为此,您可以将流转换为 PCM 数据,将您希望更改音量的通道乘以所需因子,将结果中的 PCM 数据相加,然后再转换回字节。
要按字节访问音频流,请查看Using Files and Format Converters 上 Java 教程部分的第一个扩展代码片段。这显示了如何获取声音字节数据数组。有一条评论写道:
// Here, do something useful with the audio data that's
// now in the audioBytes array...
此时,遍历字节,转换为 PCM。一组基于以下内容的命令应该可以工作:
for (int i = 0; i < numBytes; i += 2)
{
pcmA[i/2] = audioBytesA[i] & 0xff ) | ( audioBytesA[i + 1] << 8 );
pcmB[i/2] = audioBytesB[i] & 0xff ) | ( audioBytesB[i + 1] << 8 );
}
在上面,audioBytesA 和 audioBytesB 是两个输入流(名称基于示例中的代码),pcmA 和 pcmB 可以是 int 数组或 short 数组,包含适合 short 范围内的值。最好制作 pcm 数组 floats,因为您将进行一些会产生分数的数学运算。在下面的示例中使用 floats 只会增加一个位置的准确性(比使用 int 时更好的舍入),并且 int 会执行得更快。我认为如果音频数据被标准化以用于额外的处理,则更经常使用浮点数。
从那里开始,更改音量的最佳方法是将每个 PCM 值乘以相同的数量。例如,要将音量增加 25%,
pcmA[i] = pcmA[i] * 1.25f;
然后,添加 pcmA 和 pcmB,并转换回字节。您可能还需要输入 min 或 max 函数以确保音量和合并不超过可以适合格式的 16 位的值。
我使用以下转换回字节:
for (int i = 0; i < numBytes; i++)
{
outBuffer[i*2] = (byte) pcmCombined[i];
outBuffer[(i*2) + 1] = (byte)((int)pcmCombined[i] >> 8 );
}
以上假设 pcmCombined[] 是一个浮点数组。如果是 short[] 或 int[] 数组,转换代码可以简单一些。
我从我为发布在my website 的程序所做的开发工作中剪切并粘贴了上面的内容,并针对您的场景对其进行了编辑,因此如果出现拼写错误或错误,请在 cmets 中告诉我,我会修理它。