音頻混合的方法

音頻混音算法的實現

1、線性疊加後求平均

優點:不會產生溢出,噪音較小;

缺點:衰減過大,影響通話質量;

    short  remix(short buffer1,short buffer2)  
    {  
        int value = buffer1 + buffer2;  
        return (short)(value/2);  
    }  


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;i<SIZE_AUDIO_FRAME/2;i++)  
        {  
            int temp=0;  
            for (j=0;j<number;j++)  
            {  
                temp+=*(short*)(sourseFile[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*)(objectFile+i*2)=(short)output;  
        }  
    }  


3、下面是我從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));  


4、切割時間片,重採樣算法

可以把各個通道的聲音疊到一起,讓聲音的採樣率按倍增加,如果提高聲音的播放頻率,聲音可以正常的播放,聲音實現了疊加;如果不想修改聲音的播放輸出頻率,可以通過聲音的重採樣後輸出自己想要的輸出頻率;


5、下面是上面的混音的測試代碼:

#include <stdio.h>  
#include <stdlib.h>  
#include <math.h>  
   
#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;i<SIZE_AUDIO_FRAME/2;i++)  
    {  
        int temp=0;  
        for (j=0;j<number;j++)  
        {  
            temp+=*(short*)(sourseFile[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*)(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\n");  
        }  
        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!\n");  
} 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章