如何混合两个 PCM 音频文件

Posted

技术标签:

【中文标题】如何混合两个 PCM 音频文件【英文标题】:How can I mix two PCM audio files 【发布时间】:2018-02-18 08:18:51 【问题描述】:

我确实测试了混合两个 PCM 音频文件。 但没有得到真正的音频文件。

我用过这个example 所以,我的代码:

  private void mixSound() throws IOException 

byte[] music1 = null;
music1 = new byte[in1.available()];
music1 = convertStreamToByteArray(in1);
in1.close();


byte[] music2 = null;
music2 = new byte[in2.available()];
music2 = convertStreamToByteArray(in2);
in2.close();

byte[] output = new byte[music1.length];

for (int i = 0; i < output.length; i++) 

samplef1 = music1[i] / 128.0f; 
samplef2 = music2[i] / 128.0f;

float mixed = samplef1 + samplef2;
// reduce the volume a bit:
mixed *= 0.8;
// hard clipping
if (mixed > 1.0f) mixed = 1.0f;

if (mixed < -1.0f) mixed = -1.0f;

byte outputSample = (byte) (mixed * 128.0f);
output[i] = outputSample;

 //for loop

save = openFileOutput(filename, Context.MODE_PRIVATE);
save.write(output);
save.flush();
save.close();


public byte[] convertStreamToByteArray(InputStream is) throws IOException 

ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buff = new byte[8000];
int i;
while ((i = is.read(buff, 0, buff.length)) > 0) 
baos.write(buff, 0, i);


return baos.toByteArray(); // be sure to close InputStream in calling function


2 个比特率 64000 & 采样率 16000 GH & sterio 的音频文件

in1 = getResources().openRawResource(R.raw.a_2);
in2 = getResources().openRawResource(R.raw.a_diz_2);

也尝试转换 bytes array to short array -&gt; then calculate-&gt; then convert short to byte 使用转换方法 比如 bytes2Shorts(byte[] buf) 和 shorts2Bytes(short[] s)。 但是钢铁有一个失败的结果。

谁能说我哪里错了?

【问题讨论】:

【参考方案1】:

这里有很多问题,我会尝试解决其中的一些问题

首先,使用byte[] 表明您的PCM wave data formatAudioFormat.ENCODING_PCM_8BIT(或者如果它已经不是这种格式,它应该是这种格式)。此格式使用8-bit (1 byte) unsigned,表示声音 样本存储在[0, 255] 范围内(不在[-127, +128] or [-128,+127] 范围内)。

这意味着负值在[0, 127]范围内,正样本在[128,255]范围内。

混合值时,最好从一开始就阻止clipping,所以我会使用

byte mixed = (music1[i] + music2[i])/2; //this ensures that mixed remains within the `correct range` for your PCM format

您还可以将样本除以 128(如果您想将它们转换为浮点值)

float samplef1 = (((float)music1[i]-127)/128 ; //converting samples to [-1, +1] range -- -1 corresponds a sample value of 0 and +1 to 255

float samplef2 = (((float)music2[i]-127)/128;

float mixed = (samplef1+samplef2)/2;

请注意,您现在有 2 个选项来播放以这种方式生成的数据(样本)。要么将floats 转换回bytes,要么使用AudioFormat.ENCODING_PCM_FLOAT 格式。

比特率 64000 & 采样率 16000 GH & sterio 的音频文件

这不可能是正确的。典型的采样率为4000Hz, 8000Hz, 11000Hz, 16000Hz, 22050Hz or 44100Hz。对于位深度,音频通常使用8 bits, 16 bits or 32 bits

例如,CD 质量的音频使用44100Hz, 16bit, stereo 格式。

【讨论】:

嗨!我同意,现在也这么想。我会试试的,非常感谢

以上是关于如何混合两个 PCM 音频文件的主要内容,如果未能解决你的问题,请参考以下文章

如何将 PCM 音频流转换为在线播放

如何将两个 m4a 音频文件“混合/叠加”在一起

如何使用 ALSA 混合多个 PCM 流

使用 NAudio 混合两个音频文件

混合 PCM 音频样本

NAudio 使用 WaveMixerStream32() 混合 2 两个音频->如何让第二个音频稍后开始