webrtc5-自动增益

431 阅读2分钟

一、背景

AGC(Auto Gain Control,自动增益控制),较新的webrtc已经把原来的agc模块移动到了一个叫做legacy的文件夹。具体代码路径“webrtc/modules/audio_processing/agc/legacy”。 具有三种模式:

  • kAgcModeAdaptiveAnalog带有模拟音量调节的功能;
  • kAgcModeAdaptiveDigital是可变增益agc,但是不调节系统音量;
  • kAgcModeFixedDigital是固定增益的agc;

具体原理可以参考webrtc源码。

二、注意事项

只支持以下采样率和帧长的输入数据:

  • 8K采样率,10或者20ms长度数据,采样数为80;
  • 16K采样率,10或者20ms长度数据,采样数为160;
  • 32K采样率,5或者10ms长度数据,采样数为160;

Demo

C++ code

#include <webrtc/modules/audio_processing/agc/legacy/gain_control.h>//自动增益

struct SampleConfig
{
    int channels = 1;       //采样声道数
    int sampleRate = 44100; //采样频率
    int bitsPerSample = 16; //采样位数
};

int GetSamplesPer10ms(int fs)
{
    switch (fs)
    {
    case 8000:
        return 80;

    case 16000:
    case 32000:
        return 160;

    default:
        return -1;
    }
}

void TestAutoGainControl(const char* filePathIn, const char* filePathOut, SampleConfig cfg)
{
    void *agcInst = nullptr;

    FILE *fpIn = fopen(filePathIn, "rb");
    FILE *fpOut = fopen(filePathOut, "wb");

    int samples = GetSamplesPer10ms(cfg.sampleRate);

    char  *frame_in_c = new char[samples * 2];    //读取文件的字节
    short *frame_in_s = new short[samples];       //声音存储short数据

    short *frame_out_s = new short[samples];      //ns后float转short数据

    do
    {
        if (!fpIn || !fpOut)
        {
            std::cout << "open file" << std::endl;
            break;
        }

        agcInst = WebRtcAgc_Create();
        if (!agcInst)
        {
            std::cout << "WebRtcAgc_Create error" << std::endl;
            break;
        }

        int minLevel = 0;
        int maxLevel = 255;
        int agcMode = kAgcModeFixedDigital;
        //kAgcModeAdaptiveAnalog 带有模拟音量调节的功能
        //kAgcModeAdaptiveDigital 是可变增益agc,但是不调节系统音量
        //kAgcModeFixedDigital是固定增益的agc
        if (0 != WebRtcAgc_Init(agcInst, minLevel, maxLevel, agcMode, cfg.sampleRate))
        {
            std::cout << "WebRtcAgc_Init error" << std::endl;
            break;
        }

        WebRtcAgcConfig agcConfig;
        agcConfig.compressionGaindB = 20;
        agcConfig.limiterEnable = 1;
        agcConfig.targetLevelDbfs = 3;
        if (0 != WebRtcAgc_set_config(agcInst, agcConfig))
        {
            std::cout << "WebRtcAgc_set_config error" << std::endl;
            break;
        }

        int spanTick = GetTickCount();
        int micLevelIn = 0;
        int micLevelOut = 0;

        while (1)
        {
            if (samples == fread(frame_in_c, sizeof(char) * 2, samples, fpIn))
            {
                //1
                for (int i = 0; i < samples; ++i)
                {
                    frame_in_s[i] = (frame_in_c[i * 2 + 1] << 8) | (frame_in_c[i * 2] & 0xFF);//两个char型拼成一个short
                }

                //2
                short* const p = frame_in_s;
                const short* const* inNear = &p;

                short* const q = frame_out_s;
                short* const* outframe = &q;

                uint8_t saturationWarning = 0;

                //3
                if (0 != WebRtcAgc_Process(agcInst, inNear, 1, samples, outframe, micLevelIn, &micLevelOut, 0, &saturationWarning))
                {
                    std::cout << "WebRtcAgc_Process error" << std::endl;
                    break;
                }
                micLevelIn = micLevelOut;

                fwrite(frame_out_s, sizeof(short), samples, fpOut);
            }
            else
            {
                break;
            }
        }

        spanTick = GetTickCount() - spanTick;
        std::cout << "agc spanTick:" << spanTick << std::endl;
    } while (0);

    //clean
    if (agcInst) WebRtcAgc_Free(agcInst);
    if (fpIn) fclose(fpIn);
    if (fpOut) fclose(fpOut);

    delete[]frame_in_c;
    delete[]frame_in_s;
    delete[]frame_out_s;
}

测试文件

自动增益测试音频:

链接: pan.baidu.com/s/1c2DZSFYM… 提取码: s8ie