【问题标题】:Consistent popping sound while playing audio through a SourceDataLine通过 SourceDataLine 播放音频时一致的爆音
【发布时间】:2020-01-24 12:29:06
【问题描述】:

我现在正在编写一个基本的合成器,但遇到了一个奇怪的问题。在通过 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 是一个字节数组,@987654325 @ 是我将数据采样到buffer 的地方,AudioEnvironment.SUB_BUFFER_SIZE * 2buffer 的大小)

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

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

【问题讨论】:

  • 你能在一个小的独立程序中重现这个(不依赖于单独的Channel 类)吗?
  • 我对你所说的流行音乐以恒定的“音高”但不同的“频率”播放感到困惑。音高不是由频率决定的吗?
  • @ruakh 在这种情况下,我认为这无关紧要;就像我上面说的,我查看了 wave.sample() 生成的数据,这很好。 Channel 目前只包含变量和构造函数。代码中唯一可能出错的部分是第一个代码 sn-p 和 line.write()。话虽如此,我会看看我是否可以编写一个小的单类程序来复制我的问题。
  • @ruakh 我想一般来说它们会有点模棱两可,但对于 midi/synths,音高通常是指音符本身(比如 C4、F#6、Gb2 等),频率会参考实际产生的声波。或者至少这是我通常看到的术语。

标签: java audio-player


【解决方案1】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-01
    • 1970-01-01
    • 2017-08-08
    • 2021-12-14
    • 1970-01-01
    相关资源
    最近更新 更多