原因:由于APM中涉及到去噪模块,故在此进行简单调用和原理分析
概况:通过对信号的初始噪声估计得出一个语音/噪声概率函数,然后通过该函数估计出每帧数据的噪声,然后使用维纳滤波器将噪声进行抑制。故重点为噪声估计的准确性。而噪声估计依赖于语音/噪声概率函数,而语音/噪声概率函数是通过使用映射函数将每帧的信号分类特征映射到一个概率值而得出。每帧的分类特征包括:频谱平坦度,频谱差异,LRT均值特征。
伪代码实现如下:
首先设置提取特征的参数信息
// Initialize state. int WebRtcNs_InitCore(NoiseSuppressionC* self, uint32_t fs) { set_feature_extraction_parameters(self); }针对每帧进行特征值的提取并映射得出语音/噪声概率函数.
void WebRtcNs_AnalyzeCore(NoiseSuppressionC* self, const float* speechFrame) { // Quantile noise estimate. NoiseEstimation(self, magn, noise);噪声估计 // Post and prior SNR needed for SpeechNoiseProb. ComputeSnr(self, magn, noise, snrLocPrior, snrLocPost);计算信噪比 FeatureUpdate(self, magn, updateParsFlag);更新特征值 SpeechNoiseProb(self, self->speechProb, snrLocPrior, snrLocPost);计算语音/噪声概率 UpdateNoiseEstimate(self, magn, snrLocPrior, snrLocPost, noise);更新噪声估计 } static void FeatureUpdate(NoiseSuppressionC* self, const float* magn, int updateParsFlag) { // Compute spectral flatness on input spectrum. ComputeSpectralFlatness(self, magn);计算谱平坦度 // Compute difference of input spectrum with learned/estimated noise spectrum. ComputeSpectralDifference(self, magn);计算谱差异 }根据估计出的语音/噪声概率函数估计当前帧噪声,并进行维纳滤波进行抑制
void WebRtcNs_ProcessCore(NoiseSuppressionC* self, const float* const* speechFrame, size_t num_bands, float* const* outFrame) { ComputeDdBasedWienerFilter(self, magn, theFilter); }测试伪代码如下
NsHandle *phandle = WebRtcNs_Create(); int ir = WebRtcNs_Init(phandle, iSampleRate); ir = WebRtcNs_set_policy(phandle, 0); while (iR) { WebRtcNs_Analyze(phandle, pbuff); WebRtcNs_Process(phandle, &pbuff, 1, &pbout); }波形对比:明显看出降噪后能量值也被衰减.
测试工程地址:https://github.com/quanwstone/WebRTC
总结:通过测试流程和源码可以得知noise_suppression的实现原理.具体实现细节算法未完待续。