我有 2 个文件。曾经是一个 mp3 被解码为 pcm 进入一个流,我也有一个 wav 被读入 pcm。样本以短数据类型保存。
音频统计:44,100 个样本 * 每个样本 16 位 * 2 个 channel = 1,411,200 位/秒
我需要在 mp3 pcm 数据的开头应用 X 秒的静音,我是这样做的:
private short[] mp3Buffer = null;
private short[] wavBuffer = null;
private short[] mixedBuffer = null;
double silenceSamples = (audioInfo.rate * padding) * 2;
for (int i = 0; i < minBufferSize; i++){
if (silenceSamples > 0 ){
mp3Buffer[i] = 0; //Add 0 to the buffer as silence
mixedBuffer[i] = (short)((mp3Buffer[i] + stereoWavBuffer[i])/2);
silenceSamples = silenceSamples - 0.5;
}
else
mixedBuffer[i] = (short)((mp3Buffer[i] + stereoWavBuffer[i])/2);
}
音频始终关闭。有时太快一两秒,有时太慢一两秒。我不认为这是一个时间问题,因为我先启动 audiorecord(wav),然后设置启动计时器-> 启动媒体播放器(已经准备好)-> 结束计时器并将差异设置为“填充”变量。从 wav header 中我也跳过了 44kb。
如有任何帮助,我们将不胜感激。
最佳答案
我假设您希望通过在其中一个流的开头插入填充来以某种方式对齐两个音频源?这里有一些问题。
mp3Buffer[i] = 0; //Add 0 to the buffer as silence
这并不是在开头添加静音,只是将数组中 offest [i] 处的条目设置为 0。下一行:
mixedBuffer[i] = (short)((mp3Buffer[i] + stereoWavBuffer[i])/2);
然后只是覆盖这个值。
如果你想以某种方式对齐流,最好的方法是不要在任何一个流的开头插入静音,而是在一个流中从另一个流开始混合.另外,最好将它们混合成 32 位 float 然后归一化。像这样的东西:
int silenceSamples = (audioInfo.rate * padding) * 2;
float[] mixedBuffer = new float[minBufferSize + silenceSamples]
for (int i = 0; i < minBufferSize + silenceSamples; i++){
if (i < silenceSamples )
{
mixedBuffer[i] = (float) stereoWavBuffer[i];
}
else if(i < minBufferSize)
{
mixedBuffer[i] = (float) (stereoWavBuffer[i] + mp3Buffer[i-silenceSamples]);
}
else
{
mixedBuffer[i] = (float) (mp3Buffer[i-silenceSamples]);
}
要规范化数据,您需要遍历 mixedBuffer 并找到绝对最大值 Math.abs(...)
,然后将数组中的所有值乘以 32,767/largestValue -这将为您提供一个缓冲区,其中最大值适合短而不剪裁。然后遍历 float 组,将每个值移回短数组。
我不确定您的 minBufferSize
是多少 - 这需要足够大才能混合所有数据。
关于java - Android/Java 混音和静音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10727510/