webrtc4-噪声消除

433 阅读2分钟

一、背景

NS(Noise Suppression,噪声抑制),webrtc的噪声处理模块源码在“webrtc/modules/audio_processing/ns”内,包括两种方式:

  • noise_suppression.h 去噪浮点算法
  • noise_suppression_x.h 去噪定点算法,可以在性能较低的嵌入式设备上使用

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

二、注意事项

  • webrtc默认接口都是只支持输入10ms的采样数据,并且只支持8000,16000,32000的采样率,非上述类型采样率,需要重采样后才能进行处理。
  • 最新61版本,去噪模块支持输入32k的采样率,但采样个数为160,与上述不符合,需要进一步研究。

Demo

C++ code

#include <webrtc/modules/audio_processing/ns/noise_suppression.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;
    }
}

/*
**@fs 采样率
**@mode 设置噪声抑制的级别 0: Mild-轻微, 1: Medium-中等 , 2: Aggressive-积极的
*/
void TestNoiseSuppression(const char* filePathIn, const char* filePathOut, int mode, SampleConfig cfg)
{
    NsHandle *nsInst = 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数据
    float *frame_in_f = new float[samples];       //声音存储float数据

    short *frame_out_s = new short[samples];      //ns后float转short数据
    float *frame_out_f = new float[samples];      //ns后返回得到的float数据

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

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

        if (0 != WebRtcNs_Init(nsInst, cfg.sampleRate))
        {
            std::cout << "WebRtcNs_Init error" << std::endl;
            break;
        }

        //设置噪声抑制的级别 0: Mild-轻微, 1: Medium-中等 , 2: Aggressive-积极的
        if (0 != WebRtcNs_set_policy(nsInst, mode))
        {
            std::cout << "WebRtcNs_set_policy error" << std::endl;
            break;
        }

        int spanTick = GetTickCount();

        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
                    frame_in_f[i] = frame_in_s[i];//转float型接口需要
                }

                //2
                float* const p = frame_in_f;
                const float* const* spframe = &p;

                float* const q = frame_out_f;
                float* const* outframe = &q;

                //3
                WebRtcNs_Analyze(nsInst, frame_in_f);
                WebRtcNs_Process(nsInst, spframe, 1, outframe);
                for (int i = 0; i < samples; ++i)
                {
                    frame_out_s[i] = frame_out_f[i];
                }
                fwrite(frame_out_s, sizeof(short), samples, fpOut);
            }
            else
            {
                break;
            }
        }

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

    //clean
    if (nsInst) WebRtcNs_Free(nsInst);
    if (fpIn) fclose(fpIn);
    if (fpOut) fclose(fpOut);

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

测试文件

噪声测试音频:

链接: pan.baidu.com/s/15ZUkqTel… 提取码: 246d