DSP

音频混音算法的实现

2019-07-13 15:24发布

转自:http://blog.csdn.net/iflychenyang/article/details/11680449

线性叠加后求平均

优点:不会产生溢出,噪音较小;
缺点:衰减过大,影响通话质量; short remix(short buffer1,short buffer2) { int value = buffer1 + buffer2; return (short)(value/2); }

归一化混音(自适应加权混音算法)

思路:

使用更多的位数(32 bit)来表示音频数据的一个样本,混完音后在想办法降低其振幅,使其仍旧分布在16 bit所能表示的范围之内,这种方法叫做归一法.

方法:

为避免发生溢出,使用一个可变的衰减因子对语音进行衰减。这个衰减因子也就代表语音的权重,衰减因子随着音频数据的变化而变化,所以称为自适应加权混音。当溢出时,衰减因子较小,使得溢出的数据在衰减后能够处于临界值以内,而在没有溢出时,又让衰减因子慢慢增大,使数据较为平缓的变化.
代码: void Mix(char sourseFile[10][SIZE_AUDIO_FRAME],int number,char *objectFile) { //归一化混音 int const MAX=32767; int const MIN=-32768; double f=1; int output; int i = 0,j = 0; for (i=0;i2;i++) { int temp=0; for (j=0;jshort*)(sourseFile[j]+i*2); } output=(int)(temp*f); if (output>MAX) { f=(double)MAX/(double)(output); output=MAX; } if (outputdouble)MIN/(double)(output); output=MIN; } if (f<1) { f+=((double)1-f)/(double)32; } *(short*)(objectFile+i*2)=(short)output; } }

下面是我从newlc上找到的一个关于PCM脉冲编码的音频信号的混音实现,其中包含了一个关键的混音算法!

if( data1 < 0 && data2 < 0) date_mix = data1+data2 - (data1 * data2 / -(pow(2,16-1)-1)); else date_mix = data1+data2 - (data1 * data2 / (pow(2,16-1)-1));

切割时间片,重采样算法

可以把各个通道的声音叠到一起,让声音的采样率按倍增加,如果提高声音的播放频率,声音可以正常的播放,声音实现了叠加;如果不想修改声音的播放输出频率,可以通过声音的重采样后输出自己想要的输出频率;

下面是上面的混音的测试代码:

#include #include #include #define IN_FILE1 "1.wav" #define IN_FILE2 "2.wav" #define OUT_FILE "remix.pcm" #define SIZE_AUDIO_FRAME (2) void Mix(char sourseFile[10][SIZE_AUDIO_FRAME],int number,char *objectFile) { //归一化混音 int const MAX=32767; int const MIN=-32768; double f=1; int output; int i = 0,j = 0; for (i=0;i2;i++) { int temp=0; for (j=0;jshort*)(sourseFile[j]+i*2); } output=(int)(temp*f); if (output>MAX) { f=(double)MAX/(double)(output); output=MAX; } if (outputdouble)MIN/(double)(output); output=MIN; } if (f<1) { f+=((double)1-f)/(double)32; } *(short*)(objectFile+i*2)=(short)output; } } int main() { FILE * fp1,*fp2,*fpm; fp1 = fopen(IN_FILE1,"rb"); fp2 = fopen(IN_FILE2,"rb"); fpm = fopen(OUT_FILE,"wb"); short data1,data2,date_mix; int ret1,ret2; char sourseFile[10][2]; while(1) { ret1 = fread(&data1,2,1,fp1); ret2 = fread(&data2,2,1,fp2); *(short*) sourseFile[0] = data1; *(short*) sourseFile[1] = data2; if(ret1>0 && ret2>0) { Mix(sourseFile,2,(char *)&date_mix); /* if( data1 < 0 && data2 < 0) date_mix = data1+data2 - (data1 * data2 / -(pow(2,16-1)-1)); else date_mix = data1+data2 - (data1 * data2 / (pow(2,16-1)-1));*/ if(date_mix > pow(2,16-1) || date_mix < -pow(2,16-1)) printf("mix error "); } else if( (ret1 > 0) && (ret2==0)) { date_mix = data1; } else if( (ret2 > 0) && (ret1==0)) { date_mix = data2; } else if( (ret1 == 0) && (ret2 == 0)) { break; } fwrite(&date_mix,2,1,fpm); } fclose(fp1); fclose(fp2); fclose(fpm); printf("Done! "); }