java - 在 Macbook Pro 上生成可听见的正弦波时出现 line.open() 错误

标签 java audio runtime-error synthesizer

我在这里有这段代码,我有一个关于如何创建可听正弦波的教程:

import java.nio.ByteBuffer;
import javax.sound.sampled.*;


public class FixedFreqSine {

   //This is just an example - you would want to handle LineUnavailable properly...
   public static void main(String[] args) throws InterruptedException, LineUnavailableException 
   {
      final int SAMPLING_RATE = 44100;            // Audio sampling rate
      final int SAMPLE_SIZE = 2;                  // Audio sample size in bytes

      SourceDataLine line;
      double fFreq = 440;                         // Frequency of sine wave in hz

      //Position through the sine wave as a percentage (i.e. 0 to 1 is 0 to 2*PI)
      double fCyclePosition = 0;        

      //Open up audio output, using 44100hz sampling rate, 16 bit samples, mono, and big 
      // endian byte ordering
      AudioFormat format = new AudioFormat(SAMPLING_RATE, 16, 1, true, true);
      DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);

      if (!AudioSystem.isLineSupported(info)){
         System.out.println("Line matching " + info + " is not supported.");
         throw new LineUnavailableException();
      }

      line = (SourceDataLine)AudioSystem.getLine(info);
      line.open(format);  
      line.start();

      // Make our buffer size match audio system's buffer
      ByteBuffer cBuf = ByteBuffer.allocate(line.getBufferSize());   

      int ctSamplesTotal = SAMPLING_RATE*5;         // Output for roughly 5 seconds


      //On each pass main loop fills the available free space in the audio buffer
      //Main loop creates audio samples for sine wave, runs until we tell the thread to exit
      //Each sample is spaced 1/SAMPLING_RATE apart in time
      while (ctSamplesTotal>0) {
         double fCycleInc = fFreq/SAMPLING_RATE;  // Fraction of cycle between samples

         cBuf.clear();                            // Discard samples from previous pass

          // Figure out how many samples we can add
         int ctSamplesThisPass = line.available()/SAMPLE_SIZE;   
         for (int i=0; i < ctSamplesThisPass; i++) {
            cBuf.putShort((short)(Short.MAX_VALUE * Math.sin(2*Math.PI * fCyclePosition)));

            fCyclePosition += fCycleInc;
            if (fCyclePosition > 1)
               fCyclePosition -= 1;
         }

         //Write sine samples to the line buffer.  If the audio buffer is full, this will 
         // block until there is room (we never write more samples than buffer will hold)
         line.write(cBuf.array(), 0, cBuf.position());            
         ctSamplesTotal -= ctSamplesThisPass;     // Update total number of samples written 

         //Wait until the buffer is at least half empty  before we add more
         while (line.getBufferSize()/2 < line.available())   
            Thread.sleep(1);                                             
      }


      //Done playing the whole waveform, now wait until the queued samples finish 
      //playing, then clean up and exit
      line.drain();                                         
      line.close();
   }
}

它在 Windows 10 上运行良好,并且完美地生成了声音。但是在我的 Macbook Pro 上,我收到此错误:
2015-11-17 11:20:16.549 java[5899:9037084] Error loading /Library/Audio/Plug-Ins/HAL/SeratoVirtualAudioPlugIn.plugin/Contents/MacOS/SeratoVirtualAudioPlugIn:  dlopen(/Library/Audio/Plug-Ins/HAL/SeratoVirtualAudioPlugIn.plugin/Contents/MacOS/SeratoVirtualAudioPlugIn, 262): no suitable image found.  Did find:
    /Library/Audio/Plug-Ins/HAL/SeratoVirtualAudioPlugIn.plugin/Contents/MacOS/SeratoVirtualAudioPlugIn: mach-o, but wrong architecture
2015-11-17 11:20:16.549 java[5899:9037084] Cannot find function pointer New_SHP_PlugIn for factory 834FC054-C1CC-11D6-BD01-00039315CD46 in CFBundle/CFPlugIn 0x7fd672c25910 </Library/Audio/Plug-Ins/HAL/SeratoVirtualAudioPlugIn.plugin> (bundle, not loaded)
2015-11-17 11:20:16.580 java[5899:9037084] 11:20:16.580 WARNING:  >compload> 472: Kickstart.component -- file://localhost/Library/Audio/Plug-Ins/Components/: trouble parsing Info.plist's AudioComponents, key (null); entry: <CFBasicHash 0x7fd67521c3f0 [0x7fff73159390]>{type = mutable dict, count = 7,
entries =>
    2 : <CFString 0x7fff730e39f0 [0x7fff73159390]>{contents = "manufacturer"} = <CFString 0x7fd675231660 [0x7fff73159390]>{contents = "CaNR"}
    7 : <CFString 0x7fff730e74b0 [0x7fff73159390]>{contents = "factoryFunction"} = <CFString 0x7fd6752319f0 [0x7fff73159390]>{contents = "KickstartAUFactory"}
    8 : <CFString 0x7fd675230f10 [0x7fff73159390]>{contents = "subtype"} = <CFString 0x7fd675230f50 [0x7fff73159390]>{contents = "CNKS"}
    9 : <CFString 0x7fff7310b6f0 [0x7fff73159390]>{contents = "description"} = <CFString 0x7fd67520fa20 [0x7fff73159390]>{contents = "Kickstart"}
    10 : <CFString 0x7fff7310a3d0 [0x7fff73159390]>{contents = "type"} = <CFString 0x7fd675231030 [0x7fff73159390]>{contents = "kAudioUnitType_Effect"}
    11 : <CFString 0x7fff73095bb0 [0x7fff73159390]>{contents = "name"} = <CFString 0x7fd675231630 [0x7fff73159390]>{contents = "Nicky Romero: Kickstart"}
    12 : <CFString 0x7fff73114370 [0x7fff73159390]>{contents = "version"} = <CFNumber 0x1000937 [0x7fff73159390]>{value = +65545, type = kCFNumberSInt64Type}
}
2015-11-17 11:20:16.586 java[5899:9037084] 11:20:16.586 WARNING:  >compload> 472: Primer.component -- file://localhost/Library/Audio/Plug-Ins/Components/: trouble parsing Info.plist's AudioComponents, key (null); entry: <CFBasicHash 0x7fd672c2dc50 [0x7fff73159390]>{type = mutable dict, count = 7,
entries =>
    2 : <CFString 0x7fff730e39f0 [0x7fff73159390]>{contents = "manufacturer"} = <CFString 0x7fd672c2e720 [0x7fff73159390]>{contents = "AudG"}
    7 : <CFString 0x7fff730e74b0 [0x7fff73159390]>{contents = "factoryFunction"} = <CFString 0x7fd672c2e8a0 [0x7fff73159390]>{contents = "PrimerAUFactory"}
    8 : <CFString 0x7fd672c2e9d0 [0x7fff73159390]>{contents = "subtype"} = <CFString 0x7fd672c2ea10 [0x7fff73159390]>{contents = "agp"}
    9 : <CFString 0x7fff7310b6f0 [0x7fff73159390]>{contents = "description"} = <CFString 0x7fd672c2c4a0 [0x7fff73159390]>{contents = "Primer"}
    10 : <CFString 0x7fff7310a3d0 [0x7fff73159390]>{contents = "type"} = <CFString 0x7fd672c2ec50 [0x7fff73159390]>{contents = "aumu"}
    11 : <CFString 0x7fff73095bb0 [0x7fff73159390]>{contents = "name"} = <CFString 0x7fd672c2e900 [0x7fff73159390]>{contents = "Audible Genius: Primer"}
    12 : <CFString 0x7fff73114370 [0x7fff73159390]>{contents = "version"} = <CFNumber 0x1010137 [0x7fff73159390]>{value = +65793, type = kCFNumberSInt64Type}
}

我根本不明白这个错误。我唯一知道的是它正在访问我的音频插件。我也知道错误发生在:
line = (SourceDataLine)AudioSystem.getLine(info);
      line.open(format);

有谁知道这个错误的原因是什么?或者如何解决?

最佳答案

我有一个尝试的建议:在两个上下文中使用默认设置打开行并检查格式。您编写的代码可能存在异议,例如,如果您硬编码的格式不受支持。

要使用默认打开,请省略 的参数。 line.open() 方法。要获取格式,请使用方法 line.getFormat() .您还可以通过在不同操作系统上播放 wav 文件来测试该行是否有效。如果 wav 可以正常播放,请在教程代码中使用相同的格式。

我建议这样做的主要原因是我很惊讶地看到 BigEndian 被用作格式的一部分。我一直使用 LittleEndian。

如果默认为立体声,您应该能够制作和使用相同的格式,唯一的区别是单声道,这样您就不必修改其余代码。

但是,我质疑的其余代码存在一些差异。我编写并使用以下基本形式将规范化的 PCM 音频数据发送到 Java 桌面:

float[] normalizedOut = float[2];
byte[] buffer = new byte[outBufferSize];
int i;

while(playing)
{
    i = 0;
    while(i < outBufferSize)
    {
        // obtain normalized, stereo PCM output from synth
        normalizedOut = synth.getNextFrame();

        // convert normalized to stereo bytes, "CD quality"
        normalizedOut[0] *= 32767;
        normalizedOut[1] *= 32767;
        // this part converts to Little Endian
        outBuffer[i++] = (byte) normalizedOut[0];
        outBuffer[i++] = (byte)((int)normalizedOut[0] >> 8);            
        outBuffer[i++] = (byte) normalizedOut[1];
        outBuffer[i++] = (byte)((int)normalizedOut[1] >> 8 );
    }
    line.write(outBuffer, 0, outBufferSize);
}

我认为允许 Java 处理阻塞是完全可以的。除非你的“合成器”算法真的很重,否则系统最终会在这个线程上花费 98%(疯狂的猜测)阻塞。

以上循环一次一帧。以更大的 block 获取正弦数据可能会更好一些,但我喜欢上面的简单性。此外,它似乎表现“足够好”。例如,您可以下载并尝试我编写的包含上述内容的实现,它使用 6 个 FM 合成器(每个都使用多个正弦波作为载波和调制器)同时播放。

circlesounds.jar demo
(使用 Java 8。这提醒了我,有一些旧版本的 Mac OS 不支持某些版本的 Java。我记得一个 friend 的 Mac 笔记本电脑无法运行 Java 7 程序,我想让他尝试一下。我我不了解这件事的历史。)

关于java - 在 Macbook Pro 上生成可听见的正弦波时出现 line.open() 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33762082/

相关文章:

c# - Umbraco 中的母版页

java - XML 序列的 JAXB 处理

android - 如何在音频文件中找到特定单词的位置?

windows - 如何在VBS 中使用MsgBox 中的计算机名环境变量?

audio - 管道转换mp3->带gstreamer的接收器

c++ - 如何处理WASAPI流中的声音数据 block 而不将它们写入文件?

程序中的 C++ 错误

java - 按元素的多个属性过滤集合 - QueryDSL

java - 无法从 teaminfo 类型对非静态方法acceptadd(String) 进行静态引用

Java boolean 值定义后返回 null