我在这里有这个代码,我有一个关于如何创建可听正弦波的教程:
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);
有谁知道这个错误的原因是什么?或者如何解决?
答案 0 :(得分:0)
我有建议尝试:在两个上下文中打开默认设置的行并检查格式。您编写的代码可能是反对的,例如,如果您不支持硬编码的格式。
要使用默认值打开,请省略 line.open()方法的参数。要获取格式,请使用 line.getFormat()方法。您还可以通过在不同操作系统上播放wav文件来测试该线路的工作原理。如果wavs回放正常,请在教程代码中使用相同的格式。
我建议这一点的主要原因是我很惊讶地看到 BigEndian 被用作格式的一部分。我一直使用 LittleEndian 。
如果默认为立体声,您应该能够制作和使用相同的格式,而mono是唯一的区别,因此您无需修改其余代码。
但是,我对其他代码存在一些差异。我编写并使用以下基本表单将标准化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处理阻塞是完全可以的。除非你的&#34; synth&#34;系统最终会在这个帖子上花费98%(疯狂猜测)阻塞。算法很重要。
以上一次循环一帧。在较大的块中获得正弦数据可能会更好一点,但我喜欢上面的简单性。而且,它似乎表现得足够好。&#34;例如,您可以下载并尝试我编写的实现,其中包括上面使用6个FM合成器(每个使用多个正弦作为载波和调制器)都可以同时播放。
circlesounds.jar demo (使用Java 8.这让我想起,有一些旧版本的Mac OS不支持某些版本的Java。我记得有一台Mac笔记本电脑的朋友无法运行Java 7程序我希望他试用我不了解这个历史。)