【问题标题】:How do I combine two AudioInputStream?如何组合两个 AudioInputStream?
【发布时间】:2015-12-17 21:26:15
【问题描述】:

文件格式是“PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian”,我想在放大两个文件之一的同时将它们加在一起。我打算读取两个 wav 并将它们放入两个 audioinputstream 实例中,然后将实例存储到两个 byte[] 数组中,在数组中进行操作,并作为另一个 audioinputstream 实例返回。

我做了很多研究,但没有得到好的结果。 我知道这是来自 www.jsresources.org 的一个混合两个音频输入流的类,但它不允许我在混合之前修改两个流中的任何一个,而我想在混合它们之前减少其中一个流。你觉得我应该怎么做?

【问题讨论】:

  • “我知道这是来自 www.jsresources.org 的一个混合两个音频输入流的类,但它不允许我在混合之前修改两个流中的任何一个,而我想减少一个在混合它们之前的流。" 将该源与 AmplitudeConverter 组合为其中一个流..

标签: java javasound


【解决方案1】:

为此,您可以将流转换为 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 );
}

在上面,audioBytesAaudioBytesB 是两个输入流(名称基于示例中的代码),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 中告诉我,我会修理它。

【讨论】:

    猜你喜欢
    • 2010-11-20
    • 2017-05-04
    • 2015-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-19
    • 2017-10-19
    相关资源
    最近更新 更多