在java中,你可以像这样创建一个SourceDataLine:
AudioFormat af = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100.0, 16, 1, 2, 44100.0, false);
SourceDataLine sdl = AudioSystem.getSourceDataLine(af);
之后,您可以打开并向其写入数据:
byte[] data = new byte[1024];
fillwithsounds(data);
sdl.open()
sdl.start()
sdl.write(data, 0, 1024);
这一切都适用于单声道数据。
我想做的是能够编写立体声数据,而且我无法在线查找有关如何更改字节数据以便能够编写立体声数据的任何文档。< / p>
似乎我需要在创建AudioFormat时增加通道数量 - 使其成为立体声 - 然后我需要一半的帧速率(否则Java会抛出IllegalArgumentException)
我不明白为什么会这样,或者我提供给DataSourceLine的数据的新格式应该是什么。
也许在音频格式方面有一点经验的人可能会对这个问题有所了解。提前谢谢!
答案 0 :(得分:2)
我用于立体声的格式如下:
audioFmt = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
44100, 16, 2, 4, 44100, false);
您可能希望将每帧的字节数加倍,而不是将位编码减半。我不确定8位编码听起来像什么,但它绝对比16位编码噪音更大!
生成的文件是两倍长。然后,您可以采用制作16位采样的双字节对,并将它们复制到接下来的两个位置,以进行“单声道”播放(两个立体声通道相同)。
假设:
frame = F
little end byte = A
big end byte = B
AB = 16-bit little-endian encoding
left channel = L
right channel = R
你原来的单声道:
F1A,F1B,F2A,F2B,F3A,F3B ......
使用上述格式的立体声:
F1AL,F1BL,F1AR,F1BR,F2AL,F2BL,F2AR,F2BR,F3AL,F3BL,F3AR,F3BR ......
我很可能左右混合了。但我希望你明白这个想法!
答案 1 :(得分:0)
我刚才找到了解决方案,并找到了Andrew Thompson的评论来解释我需要的确切内容。
我认为我必须两次写每一帧,引起我的是Java不会让我只使用我的单声道通道的帧大小这一事实。 (它抛出了IllegalArgumentException)
所以我将帧速率减半以满足Java,但我不记得修改字节数组。
我实现了采用“每帧2个字节,1个通道”字节[]并将其转换为“每帧1个字节,2个通道”字节[]的代码。
private static final float LEFT = -1;
private static final float CENTER = 0;
private static final float RIGHT = 1;
private byte[] monoToStereo(byte[] data, float pan){
byte[] output = new byte[data.length];
for (int i = 0; i < (data.length - 2); i+=2){
int currentvalue = (data[i+1]*256 + data[i])/(256*2);
if (pan == LEFT || pan == CENTER){
output[i] = (byte) currentvalue;
} else {
output[i] = 0;
}
if (pan == RIGHT || pan == CENTER){
output[i+1] = (byte) currentvalue;
} else {
output[i+1] = 0;
}
}
return output;
}
使用此功能,我可以播放立体声音频(虽然有静音,我可以清楚地听到原始音轨)