音频混音算法的实现

来源:互联网 发布:mac pro截屏快捷键 编辑:程序博客网 时间:2024/06/01 21:35

音频混音算法的实现

1、线性叠加后求平均

优点:不会产生溢出,噪音较小;

缺点:衰减过大,影响通话质量;

[cpp] view plaincopy
  1. short  remix(short buffer1,short buffer2)  
  2. {  
  3.     int value = buffer1 + buffer2;  
  4.     return (short)(value/2);  
  5. }  

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

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

方法:为避免发生溢出,使用一个可变的衰减因子对语音进行衰减。这个衰减因子也就代表语音的权重,衰减因子随着音频数据的变化而变化,所以称为自适应加权混音。当溢出时,衰减因子较小,使得溢出的数据在衰减后能够处于临界值以内,而在没有溢出时,又让衰减因子慢慢增大,使数据较为平缓的变化。

[cpp] view plaincopy
  1. void Mix(char sourseFile[10][SIZE_AUDIO_FRAME],int number,char *objectFile)  
  2. {  
  3.     //归一化混音  
  4.     int const MAX=32767;  
  5.     int const MIN=-32768;  
  6.    
  7.     double f=1;  
  8.     int output;  
  9.     int i = 0,j = 0;  
  10.     for (i=0;i<SIZE_AUDIO_FRAME/2;i++)  
  11.     {  
  12.         int temp=0;  
  13.         for (j=0;j<number;j++)  
  14.         {  
  15.             temp+=*(short*)(sourseFile[j]+i*2);  
  16.         }                  
  17.         output=(int)(temp*f);  
  18.         if (output>MAX)  
  19.         {  
  20.             f=(double)MAX/(double)(output);  
  21.             output=MAX;  
  22.         }  
  23.         if (output<MIN)  
  24.         {  
  25.             f=(double)MIN/(double)(output);  
  26.             output=MIN;  
  27.         }  
  28.         if (f<1)  
  29.         {  
  30.             f+=((double)1-f)/(double)32;  
  31.         }  
  32.         *(short*)(objectFile+i*2)=(short)output;  
  33.     }  
  34. }  
3、下面是我从newlc上找到的一个关于PCM脉冲编码的音频信号的混音实现,其中包含了一个关键的混音算法!

[cpp] view plaincopy
  1. if( data1 < 0 && data2 < 0)  
  2.     date_mix = data1+data2 - (data1 * data2 / -(pow(2,16-1)-1));  
  3. else  
  4.     date_mix = data1+data2 - (data1 * data2 / (pow(2,16-1)-1));  

4、切割时间片,重采样算法

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


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

[cpp] view plaincopy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <math.h>  
  4.    
  5. #define IN_FILE1 "1.wav"  
  6. #define IN_FILE2 "2.wav"  
  7. #define OUT_FILE "remix.pcm"  
  8.    
  9. #define SIZE_AUDIO_FRAME (2)  
  10.    
  11. void Mix(char sourseFile[10][SIZE_AUDIO_FRAME],int number,char *objectFile)  
  12. {  
  13.     //归一化混音  
  14.     int const MAX=32767;  
  15.     int const MIN=-32768;  
  16.    
  17.     double f=1;  
  18.     int output;  
  19.     int i = 0,j = 0;  
  20.     for (i=0;i<SIZE_AUDIO_FRAME/2;i++)  
  21.     {  
  22.         int temp=0;  
  23.         for (j=0;j<number;j++)  
  24.         {  
  25.             temp+=*(short*)(sourseFile[j]+i*2);  
  26.         }                  
  27.         output=(int)(temp*f);  
  28.         if (output>MAX)  
  29.         {  
  30.             f=(double)MAX/(double)(output);  
  31.             output=MAX;  
  32.         }  
  33.         if (output<MIN)  
  34.         {  
  35.             f=(double)MIN/(double)(output);  
  36.             output=MIN;  
  37.         }  
  38.         if (f<1)  
  39.         {  
  40.             f+=((double)1-f)/(double)32;  
  41.         }  
  42.         *(short*)(objectFile+i*2)=(short)output;  
  43.     }  
  44. }  
  45.    
  46. int main()  
  47. {  
  48.     FILE * fp1,*fp2,*fpm;  
  49.     fp1 = fopen(IN_FILE1,"rb");  
  50.     fp2 = fopen(IN_FILE2,"rb");  
  51.     fpm = fopen(OUT_FILE,"wb");  
  52.        
  53.     short data1,data2,date_mix;  
  54.     int ret1,ret2;  
  55.     char sourseFile[10][2];  
  56.    
  57.     while(1)  
  58.     {  
  59.         ret1 = fread(&data1,2,1,fp1);  
  60.         ret2 = fread(&data2,2,1,fp2);  
  61.         *(short*) sourseFile[0] = data1;  
  62.         *(short*) sourseFile[1] = data2;  
  63.            
  64.         if(ret1>0 && ret2>0)  
  65.         {  
  66.             Mix(sourseFile,2,(char *)&date_mix);  
  67.             /* 
  68.             if( data1 < 0 && data2 < 0) 
  69.                 date_mix = data1+data2 - (data1 * data2 / -(pow(2,16-1)-1)); 
  70.             else 
  71.                 date_mix = data1+data2 - (data1 * data2 / (pow(2,16-1)-1));*/  
  72.                    
  73.             if(date_mix > pow(2,16-1) || date_mix < -pow(2,16-1))  
  74.                 printf("mix error\n");  
  75.         }  
  76.         else if( (ret1 > 0) && (ret2==0))  
  77.         {  
  78.             date_mix = data1;  
  79.         }  
  80.         else if( (ret2 > 0) && (ret1==0))  
  81.         {  
  82.             date_mix = data2;  
  83.         }  
  84.         else if( (ret1 == 0) && (ret2 == 0))  
  85.         {  
  86.             break;  
  87.         }  
  88.         fwrite(&date_mix,2,1,fpm);  
  89.     }  
  90.     fclose(fp1);  
  91.     fclose(fp2);  
  92.     fclose(fpm);  
  93.     printf("Done!\n");  


0 0
原创粉丝点击