java在通过SourceDataLine播放音频时发出一致的爆裂声
我现在正在写一个基本的synth,遇到了一个奇怪的问题。在通过SourceDataLine播放一组字节(代表16位单声道音频)时,我会听到持续的爆裂声
流行音乐以恒定的速度播放,从我所能听到的,音调。不过,pops的频率略有不同(同样,从我听到的情况来看),有些音符的pops是低通的,而另一些音符的pops是高通的。不过,POP并不是压倒性的,你仍然可以在背景中听到想要的声音
除了采样率,POP的速率、音符间距、SourceDataLine缓冲区大小、每次写入的字节数都不会改变
降低采样率会降低持久性有机污染物的检出率,反之亦然
为了测试我的程序,我打印了写入SourceDataLine的数据大约半秒,并查看了大约15个周期的正弦波,结果完全正常;没有突然的跳跃、剪断或其他任何事情
我使用采样率值的唯一两件事是一些基本的数学知识,以帮助我的采样器以正确的频率采样,每个音符只计算一次,并且在音高完美的情况下,以及在创建SourceDataLine时,它肯定起到了作用
下面是我如何启动SourceDataLine(取自main方法的多个部分):
AudioFormat format = new AudioFormat(AudioEnvironment.SAMPLE_RATE, AudioEnvironment.BIT_DEPTH, 1, true, true);
SourceDataLine line = AudioSystem.getSourceDataLine(format);
line.open(format, 8000);
line.start();
我的数据在big endian中是正确的,我在构造函数中更改endian标志并用白噪声对耳朵进行了测试
在程序设置好所有内容后,它会在这个无限循环中将数据不断写入SourceDataLine:
while (true) {
for (Channel channel : channelSystem.getChannels()) {
if (channel.pitch != 0) {
wave.sample(channel, buffer);
line.write(buffer, 0, AudioEnvironment.SUB_BUFFER_SIZE * 2);
}
}
}
(AChannel
是我创建的一个类,它包含一个音符的所有数据(尽管目前显然没有为复调正确设置程序),buffer
是一个字节数组,wave.sample()
是我将数据采样到buffer
的地方,AudioEnvironment.SUB_BUFFER_SIZE * 2
是buffer
的大小)
我不一定需要一个如何在代码中解决这个问题的例子,但是解释一下为什么会发生这种情况会很好
编辑:我可能还应该补充一点,我曾尝试在无限写循环中放入一个print语句,以打印出SourceDataLine中的可用字节数,它一直保持在500-2000左右,偶尔会达到5000左右,但从来不会接近8000,所以缓冲区永远不会耗尽数据
# 1 楼答案
事实证明,这个问题与我的想法完全无关
事实证明,我在取样器中写的一个等式是完全错误的
播放完2048个样本后,我会回到波形的开头,导致弹出
我真的不知道我为什么写这篇文章,但是,嘿,它现在起作用了