Java 通过SourceDataLine播放音频时发出一致的爆裂声

Java 通过SourceDataLine播放音频时发出一致的爆裂声,java,audio-player,Java,Audio Player,我现在正在写一个基本的synth,遇到了一个奇怪的问题。通过SourceDataLine播放一组字节(代表16位单声道音频)时,我会听到持续的爆裂声 流行音乐以恒定的速度播放,从我所能听到的,音调。虽然这些流行音乐的频率略有不同(同样,从我听到的情况来看),但有些音符的声音很低,而另一些音符的声音很高。虽然POP并不是最重要的,但你仍然可以在背景中听到想要的声音 除了采样率外,POP的速率、音符间距、SourceDataLine缓冲区大小、每次写入的字节数都不会改变 降低采样率会降低持久性有机污

我现在正在写一个基本的synth,遇到了一个奇怪的问题。通过SourceDataLine播放一组字节(代表16位单声道音频)时,我会听到持续的爆裂声

流行音乐以恒定的速度播放,从我所能听到的,音调。虽然这些流行音乐的频率略有不同(同样,从我听到的情况来看),但有些音符的声音很低,而另一些音符的声音很高。虽然POP并不是最重要的,但你仍然可以在背景中听到想要的声音

除了采样率外,POP的速率、音符间距、SourceDataLine缓冲区大小、每次写入的字节数都不会改变

降低采样率会降低持久性有机污染物的采样率,反之亦然

为了测试我这方面的程序,我打印了写入SourceDataLine的数据约半秒,并查看了大约15个周期的正弦波,结果非常好;没有突然的跳跃、剪断或其他任何动作

我使用采样率值的唯一两件事是一些基本的数学,以帮助我的采样器以正确的频率采样,每个音符只计算一次,并且在音高完美的情况下以及在创建SourceDataLine时,确实起到了作用

下面是我如何启动SourceDataLine(取自主方法的多个部分):

我的数据正确地使用了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);
        }
    }
}
(一个
频道
是我创建的一个类,它包含一个音符的所有数据(尽管显然该程序目前没有正确设置复调),
缓冲区
是一个字节数组,
wave.sample()
是我将数据采样到
缓冲区的地方,
AudioEnvironment.SUB\u buffer\u SIZE*2
缓冲区的大小

我不一定需要一个如何在代码中解决这个问题的例子,但是解释一下为什么会发生这种情况会很好


编辑:我还应该补充一点,我曾尝试在无限写循环中放入一个print语句,以打印出SourceDataLine中的可用字节数,它一直保持在500-2000左右,偶尔会达到5000左右,但从未接近8000,所以缓冲区永远不会耗尽数据。

事实证明,这个问题与我所想的完全无关

结果发现,我在取样器中写的一个方程式是完全错误的

播放完2048个样本后,我会回到波形的开头,导致弹出


老实说,我不知道我为什么要写这篇文章,但是,嘿,它现在起作用了。

事实证明,这个问题与我所想的完全无关

结果发现,我在取样器中写的一个方程式是完全错误的

播放完2048个样本后,我会回到波形的开头,导致弹出


我真的不知道为什么我在中写了这个,但是,嘿,它现在起作用了。

你能在一个小的独立程序中重现这个吗(它不依赖于单独的
频道
类)?我对你的说法感到困惑,你说流行音乐以恒定的“音高”播放,但“频率”不同。音调不是由频率决定的吗?@ruakh在这种情况下,我认为这不重要;正如我上面所说,我已经查看了wave.sample()生成的数据,结果很好。通道目前只包含变量和构造函数。代码中唯一可能出错的部分是第一个代码段和行。write()。也就是说,我会看看是否可以编写一个小型的单类程序来复制我的问题。@ruakh我想一般来说,它们会有点模棱两可,但对于midi/Synth,音高通常指音符本身(比如C4、F#6、Gb2等),频率指的是实际产生的声波。或者至少这是我通常看到的术语。你能在一个小的独立程序(不依赖于单独的
频道
类)中重现这一点吗?我被你的说法弄糊涂了,你说流行音乐以恒定的“音高”播放,但“频率”不同。音调不是由频率决定的吗?@ruakh在这种情况下,我认为这不重要;正如我上面所说,我已经查看了wave.sample()生成的数据,结果很好。通道目前只包含变量和构造函数。代码中唯一可能出错的部分是第一个代码段和行。write()。也就是说,我会看看是否可以编写一个小型的单类程序来复制我的问题。@ruakh我想一般来说,它们会有点模棱两可,但对于midi/Synth,音高通常指音符本身(比如C4、F#6、Gb2等),频率指的是实际产生的声波。或者至少这是我通常看到的术语用法。
while (true) {              
    for (Channel channel : channelSystem.getChannels()) {
        if (channel.pitch != 0) {
            wave.sample(channel, buffer);

            line.write(buffer, 0, AudioEnvironment.SUB_BUFFER_SIZE * 2);
        }
    }
}