音频混音算法的实现
1、线性叠加后求平均
优点:不会产生溢出,噪音较小;
缺点:衰减过大,影响通话质量;
cpp
short remix(short buffer1,short buffer2)
{
int value = buffer1 + buffer2;
return (short)(value/2);
}
2、归一化混音(自适应加权混音算法)
思路:使用更多的位数(32 bit)来表示音频数据的一个样本,混完音后在想办法降低其振幅,使其仍旧分布在16 bit所能表示的范围之内,这种方法叫做归一法;
方法:为避免发生溢出,使用一个可变的衰减因子对语音进行衰减。这个衰减因子也就代表语音的权重,衰减因子随着音频数据的变化而变化,所以称为自适应加权混音。当溢出时,衰减因子较小,使得溢出的数据在衰减后能够处于临界值以内,而在没有溢出时,又让衰减因子慢慢增大,使数据较为平缓的变化。
objectivec
void mix(char **src_data, char *mix_data, int channels, int buffer_size)
{
//归一化混音
int const MAX=32767;
int const MIN=-32768;
double f=1;
int output;
int i = 0,j = 0;
for (i=0; i < buffer_size / 2; i++)
//for (i=0; i < buffer_size; i++)
{
int temp = 0;
for (j = 0; j < channels; j++)
{
//两个文件对应音轨值相加
temp += *(short*)(src_data[j] + i * 2);
}
output = (int)(temp*f);
if (output > MAX)
{
f = (double)MAX / (double)(output);
output = MAX;
}
if (output < MIN)
{
f = (double)MIN / (double)(output);
output = MIN;
}
if (f < 1)
{
f += ((double)1 - f) / (double)32;
}
*(short*)(mix_data + i * 2) = (short)output;
}
}
3、PCM脉冲编码的音频信号的混音实现,
objectivec
#define WIDEN_TEMP_TYPE int
#define AUDIO_DATA_TYPE short
#define AUDIO_DATA_TYPE_MAX 32767 // 2^15(short)
#define AUDIO_DATA_TYPE_MIN -32768
void mix1(char **src_data, char *mix_data, int channels, int buffer_size)
{
// 初始化中间变量
WIDEN_TEMP_TYPE tempMul = 1;
WIDEN_TEMP_TYPE tempSum = 0;
WIDEN_TEMP_TYPE mixedTempData;
int howManyPointsArePos = 0;
int sz = channels;
int i = 0;
int j = 0;
for ( i = 0; i < buffer_size / 2; ++i)
{
// 复位中间变量
tempMul = 1;
tempSum = 0;
// 求中间变量
howManyPointsArePos = 0; // 统计每个点是不是都是正数
for ( j = 0; j < sz; ++j)
{
tempMul *= *(short*)(src_data[j] + i * 2);
tempSum += *(short*)(src_data[j] + i * 2);
if (*(short*)(src_data[j] + i * 2) < 0)
++howManyPointsArePos;
}
// 混音
if (howManyPointsArePos == sz)
mixedTempData = tempSum - (tempMul / -(pow(2, 16 - 1) - 1));
else
mixedTempData = tempSum - (tempMul / (pow(2, 16 - 1) - 1));
// 防止上下溢出
if (mixedTempData > AUDIO_DATA_TYPE_MAX)
mixedTempData = AUDIO_DATA_TYPE_MAX;
else if (mixedTempData < AUDIO_DATA_TYPE_MIN)
mixedTempData = AUDIO_DATA_TYPE_MIN;
*(short*)(mix_data + i * 2) = (short)mixedTempData;
}
}