java - PCM 字节数组加法

标签 java audio pcm

我有一些原始 PCM 音频文件。我可以成功地从这些文件中读取字节流,并通过接受 PCM 数据作为输入的音频播放机制来播放它们。

当我从这些文件中读取数据时,我将其存储在字节[]中。这些轨道具有相同的大小并且在声音方面互补(它们在一起听起来很好)。因此,我想将几​​个包含PCM数据的byte[]添加到一个相同大小的byte[]中,代表最终的音乐。

我以一种简单、不假思索的方式尝试了它,只需这样做:

for(int i=0; i<finalbytes.length; i++)
{
   finalbytes[i] = (byte) (music1bytes[i] + music2bytes[i]);
}

其实情况并没有那么糟糕。最终的声音确实是两个音轨的叠加。问题是,当添加几首轨道时,有时在歌曲的特定部分,可以听到静态噪音的峰值。这可能是由于加法导致非钳制值或其他原因,我不知道如何解决。

那么,如何添加两个或多个 PCM 数据字节数组呢?

最佳答案

我假设这些原始音频文件的样本是 8 位签名的。

发生的情况是溢出。如果两个样本加起来大于 127 或小于 -128,您将不会得到正确的结果 - 会出现整数溢出。

您可以将每个结果样本除以 2:

finalbytes[i] = (byte) ((music1bytes[i] + music2bytes[i]) / 2);

这样,即使每个音频文件都有最大样本值,您也不会溢出。缺点是生成的文件可能有点安静。

另一个选项是剪辑:

int sample = music1bytes[i] + music2bytes[i];
sample = Math.min(sample, Byte.MAX_VALUE);
sample = Math.max(sample, Byte.MIN_VALUE);
finalbytes[i] = (byte)sample;

如果两个音频源都很大声,那么可能会有很多削波,而且听起来可能不太好。

您也可以尝试使用 SoftMixingMixer来自 JavaSound 并让它为您进行混音。实际上,这种方式可能需要做更多的工作,因为您需要定义 RAW 音频文件的音频格式,但它可能会提供最佳的声音效果。使用此选项,您需要将 openStream(AudioFormat) 与输出文件的音频格式结合使用,并告诉混音器通过线路播放 2 个 RAW 音频文件。

关于java - PCM 字节数组加法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35617388/

相关文章:

java - 不兼容的魔法值 1008813135

c# - 播放脚本中的音频源

objective-c - iOS - 访问可修改的原始音乐库数据?

java - JLayer 总是抛出 ArrayIndexOutOfBounds 异常

qt - 使用 QtMultimedia 从 MP3 文件中读取原始 PCM 样本?

c# - 将 IeeeFloat 缓冲区中的音频数据转换为缓冲区中的 PCM

Java 在泛型函数中分配对象的解决方法?

java - Java中对象的内存消耗是多少?

java - 来自 MediaPlayer 的回调

actionscript-3 - 如何消除声音