Audio 混音算法

1、  输入两路16bit 音频,分别0.5倍增益后混音。

2、  左声道audio 1sample 乘以 0.5 倍增益,右声道 audio 1 sample 乘以 0.5倍增益

左声道audio 2 sample 乘以 0.5 倍增益,右声道 audio 2 sample 乘以 0.5倍增益

3、  控制每个经过增益处理的的sample值不超过 S16范围(-32767 ,32767),因为增益可能是N倍,可能增益处理后超出S16范围。

4、  Output audio  左声道sample =audio 1 增益后的左声道sample + audio 2 增益后的左声道sample

Output audio  右声道sample =audio 1 增益后的右声道sample + audio 2 增益后的右声道sample

5、  如果outputaudio > MAX(32767),则gain = MAX/output

如果output audio < MIN(-32767),则gain = MIN/output

其他 gain = 1;

6、  Output audio sample乘以gain,得到混合后的sample值


样例代码

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

#define SAMPLE_SIZE 4
#define SAMPLE_GAIN (2147483647.0f)

#define CHECK_MAX_VALUE(value) ((value > 32767) ? 32767 : value)
#define CHECK_MIN_VALUE(value) ((value < -32767) ? -32767 : value)

int MixAudio2(short* sourceData1, short* sourceData2, float fBackgroundGain, float fWordsGain, short *outputData) {
    int const MAX = 32767;
    int const MIN = -32767;


    double f = 1.0;


    float fLeftValue1 = 0;
    float fRightValue1 = 0;
    float fLeftValue2 = 0;
    float fRightValue2 = 0;
    float fLeftValue = 0;
    float fRightValue = 0;
    int output = 0;
    int iIndex = 0;


    /*audio source 1 left channel sample*/
    fLeftValue1 = (float)(sourceData1[0]);


    /*audio source 1 right channel sample*/
    fRightValue1 = (float)(sourceData1[1]);


    /*audio source 2 left channel sample*/
    fLeftValue2 = (float)(sourceData2[0]);


    /*audio source 2 right channel sample*/
    fRightValue2 = (float)(sourceData2[1]);


    //fprintf(stderr,"sample (%f,%f)(%f,%f).\n",
    //    fLeftValue1,fRightValue1,fLeftValue2,fRightValue2);


    if((fLeftValue1 > 32767)||(fLeftValue1 < -32767))
        fprintf(stderr,"sample (%f).\n",fLeftValue1);


    if((fRightValue1 > 32767)||(fRightValue1 < -32767))
        fprintf(stderr,"sample (%f).\n",fRightValue1);


    if((fLeftValue2 > 32767)||(fLeftValue2 < -32767))
        fprintf(stderr,"sample (%f).\n",fLeftValue2);


    if((fRightValue2 > 32767)||(fRightValue2 < -32767))
        fprintf(stderr,"sample (%f).\n",fRightValue2);


    /*sample * gain*/
    fLeftValue1 = fLeftValue1*fBackgroundGain;
    fRightValue1 = fRightValue1*fBackgroundGain;
    fLeftValue2 = fLeftValue2*fWordsGain;
    fRightValue2 = fRightValue2*fWordsGain;


    /*source sample domain(-32767,32767)*/
    /*(sample * gain) may beyond this S16 domain*/
    /*limit  limit sample value in domain (-32767,32767)*/
    fLeftValue1 = CHECK_MAX_VALUE(fLeftValue1);
    fLeftValue1 = CHECK_MIN_VALUE(fLeftValue1);
    fRightValue1 = CHECK_MAX_VALUE(fRightValue1);
    fRightValue1 = CHECK_MIN_VALUE(fRightValue1);
    fLeftValue2 = CHECK_MAX_VALUE(fLeftValue2);
    fLeftValue2 = CHECK_MIN_VALUE(fLeftValue2);
    fRightValue2 = CHECK_MAX_VALUE(fRightValue2);
    fRightValue2 = CHECK_MIN_VALUE(fRightValue2);


    /*mix source 1 and source 2 left channel sample*/
    fLeftValue = fLeftValue1 + fLeftValue2;
    /*mix source 1 and source 2 right channel sample*/
    fRightValue = fRightValue1 + fRightValue2;


    for (iIndex = 0; iIndex < 2; iIndex++)
    {
        /*multiply gain f*/
        if (iIndex == 0) {
            output = (int)(fLeftValue*f);
        }
        else {
            output = (int)(fRightValue*f);
        }
        if (output>MAX)
        {
            /*change gain if mix sample is beyond S16 domain*/
            f = (double)MAX / (double)(output);
            output = MAX;
        }
        if (output         {
            /*change gain if mix sample is beyond S16 domain*/
            f = (double)MIN / (double)(output);
            output = MIN;
        }
        if (f<1)
        {
            f += ((double)1 - f) / (double)32;
        }
        outputData[iIndex] = (short)output;
    }
    return 1;
}

你可能感兴趣的:(多媒体编程)