通过SourceDataLine播放音频时持续弹出声音

问题描述 投票:1回答:1

我现在正在写一个基本的合成器,遇到了一个奇怪的问题。通过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的大小)

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

编辑:我还可能要补充的一点是,我已经尝试将打印语句放入无限写入循环中,以打印出SourceDataLine中的可用字节数,并且该值始终保持在500-2000左右,偶尔会上升到大约5000,但永远不会接近8000,因此缓冲区永远不会耗尽数据。

java audio-player
1个回答
0
投票

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

结果是,我在采样器中编写的一个方程式显然是错误的。

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

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

© www.soinside.com 2019 - 2024. All rights reserved.