如何将.wav文件转换为浮点数组(编辑浮点数组,例如添加两个信号),然后又转换回.wav文件,而不会产生白噪声

时间:2019-05-19 12:43:15

标签: java audio processing signal-processing wav

我正在尝试在处理过程中通过Ray-Tracing对听觉进行编程。要编辑来自Ray Tracer的信息的样本,我需要将.wav文件(文件格式:PCM签名,16位,立体声,2字节/帧,小字节序)转换为Float数组。

我通过audioInputStream和DataInputStream转换了音频,然后将音频加载到字节数组中。

然后我将字节数组转换为这样的浮点数组。

byte[] samples;
float[] audio_data = float(samples); 

当我将浮点数组转换回.wav文件时,我得到了原始音频文件的声音。

但是当我向原始信号添加另一个Float Array并将其转换回a时。通过上面的方法的wav文件(即使我添加相同的信号),我得到的是白噪声信号而不是有用信号(我可以在调制的白噪声下听到原始信号,但是非常安静)。

我以前读过这个问题,从浮点数组到字节数组的转换可能会出现问题。这是因为float是32位数据类型,而字节(在Java中)仅为16位,并且字节以某种方式混合在一起是错误的,因此产生了白噪声。在“处理”中,有一种数据类型为带符号的16位整数(名称为“ short”),但是我无法再修改幅度,因为因此我需要浮点值,因此无法将其转换为short。

我还尝试通过将信号从16位值(-32768/32767)调制为-1/1的值并将信号混合(添加)后再次返回来处理浮点数组中的溢出(幅度)。结果给了我白噪声。当我添加两个以上的信号时,它什么也没有给我(听不到)。

我要解决的具体问题是以浮点数组的形式添加许多信号(超过1000个信号,并产生适当的延迟以产生一种混响)。然后,我想将它们组合到一个浮点数组中,然后将其另存为音频文件而不会产生白噪声。

我希望你们能帮助我。

1 个答案:

答案 0 :(得分:0)

如果您具有真正的PCM数据点,那么使用简单的加法运算就不会有问题。唯一的问题是,在极少数情况下(假设您的音频不太热),这些值将超出范围。这会产生严重的失真,而不是白噪声。出现白噪声的事实向我表明,也许您没有将PCM总和正确转换回所输出格式的字节。

这是我在AudioCue中使用的一些代码,用于将PCM转换回字节。假定格式为16位,44100 fps,立体声,小端。我正在使用PCM作为标准化浮点。该算法一次转换缓冲区的数据量。

for (int i = 0, n = buffer.length; i < n; i++)
    {
        buffer[i] *= 32767;

        audioBytes[i*2] = (byte) buffer[i];
        audioBytes[i*2 + 1] = (byte)((int)buffer[i] >> 8 );
    }

有时,使用Math.min(Math.max(audioval,-1),1)或Math.min(Math.max(audioval,-32767),32767)之类的函数将值保持在范围内。更复杂的限制器或压缩器算法将缩放音量以适合。但是,如果不进行处理,结果应该是失真,而不是白噪声。

如果错误发生在另一个阶段,我们将需要查看您的更多代码。

所有这些,希望您能拥有1000点回声阵列混响的运气。我还没有听说过这种方法有效。也许现在有处理器可以处理计算负荷? (您是否尝试实时执行此操作?)我对编码实时混响的唯一成功是使用Schroeder方法,从CCMRA Freeberb插入结构和值,从Craig Lindley的代码中删除了代码。古代(2001年版权所有)的“ Java数字音频”一书。那本书的大部分内容都处理过时的GUI代码(pre-Swing!),但是他为AllPass和Comb过滤器提供的代码仍然有效。

我回想起当我从事此工作时,我找到了一个更好的混响来尝试编码,但是我必须做一些真正的挖掘才能找到我的笔记。当时我感到不安,因为算法是通过框图而不是细节或伪代码来表示的。不过,我想再次进行处理,以获得比Shroeder型更好的混响效果。 Schoeder对于不太敲击的声音还是可以通过的。

获得实时射线追踪解决方案将是一项宝贵的成就。 AR / VR和游戏中的许多应用程序。