我现在正在写一个基本的合成器,遇到了一个奇怪的问题。通过SourceDataLine播放表示16位单声道音频的字节数组时,我得到恒定的弹出声音。

流行音乐以恒定的速度播放,据我所知,音高是恒定的。流行音乐的频率确实略有不同(再次,据我所听到的),某些音符具有低通听起来的流行音乐,而其他音符则具有高通的声音。虽然没有流行音乐,但您仍可以在后台听到所需的声音。

除了采样率外,没有任何改变弹出声的速率,音高,音高,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);
        }
    }
}


(一个Channel是我创建的一个类,其中包含单个音符的所有数据(尽管目前该程序未正确设置复音),buffer是字节数组,wave.sample()是我将数据采样到buffer,并且AudioEnvironment.SUB_BUFFER_SIZE * 2buffer的大小)

我并不需要一个如何在代码中解决此问题的示例,但对为什么会发生这种情况的解释会很棒。

编辑:我可能还应该添加的一点是,我试图在无限写入循环中放置一条print语句以打印出SourceDataLine中的可用字节数,并且它始终保持在500-2000左右,偶尔会达到5000 ,但永远不会接近8000,因此缓冲区永远不会耗尽数据。

最佳答案

事实证明,该问题与我认为的问题完全无关。

事实证明,我在采样器中编写的一个方程式显然是错误的。

播放了2048个样本后,我会循环回到波形的开头,从而导致弹出。

老实说,我不知道为什么要写这个,但是嘿,现在可以了。

10-07 17:01