Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java line.open()在Macbook Pro上生成可听正弦波时出错_Java_Audio_Runtime Error_Synthesizer - Fatal编程技术网

Java line.open()在Macbook Pro上生成可听正弦波时出错

Java line.open()在Macbook Pro上生成可听正弦波时出错,java,audio,runtime-error,synthesizer,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 Int

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

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();
   }
}

有人知道这个错误的原因吗?或者如何修复它

我有一个建议可以尝试一下:在两种上下文中打开带有默认设置的行,然后检查格式。例如,如果您硬编码的格式不受支持,那么您编写的代码可能会有异议

要使用默认值打开,请省略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);
}
float[]normalizedOut=float[2];
byte[]buffer=新字节[exputffersize];
int i;
玩的时候
{
i=0;
而(我<暴躁)
{
//从synth获得标准化的立体声PCM输出
normalizedOut=synth.getNextFrame();
//将标准化转换为立体声字节,“CD质量”
归一化输出[0]*=32767;
归一化输出[1]*=32767;
//此部分转换为小端点
exputffer[i++]=(字节)normalizeout[0];
exputffer[i++]=(字节)((int)normalizedOut[0]>>8);
exputffer[i++]=(字节)normalizeout[1];
exputffer[i++]=(字节)((int)normalizedOut[1]>>8);
}
行。写入(突发,0,突发);
}
我认为允许Java处理阻塞是完全可以的。除非你的“synth”算法真的很繁重,否则系统最终会在这个线程上花费大约98%的阻塞费用

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

(使用Java 8。这提醒了我,有一些旧版本的Mac OS不支持某些Java版本。我记得有一位朋友的Mac笔记本电脑无法运行Java 7程序,我想让他试试。我不知道这方面的历史。)

line = (SourceDataLine)AudioSystem.getLine(info);
      line.open(format);
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);
}