上篇(webRTC中语音降噪模块ANS细节详解(二))讲了ANS的处理流程和语音在时域和频域的相互转换。本篇开始讲语音降噪的核心部分,首先讲噪声的初始估计以及基于估计出来的噪声算先验信噪比和后验信噪比。
1,初始噪声估计
webRTC中ANS的初始噪声估计用的是分位数噪声估计法(QBNE,Quantile Based Noise Estimation),对应的论文为《Quantile Based Noise Estimation For Spectral Subtraction And Wiener Filtering》。 分位数噪声估计认为,即使是语音段,输入信号在某些频带分量上也可能没有信号能量,那么将某个频带上所有语音帧的能量做一个统计,设定一个分位数值,低于分位数值的认为是噪声,高于分位数值的认为是语音。算法大致步骤如下:
webRTC ANS在做初始估计时,分三个阶段,第一个阶段是前50帧,第二个阶段是51~200帧,第三个阶段是200帧以后的。50帧以后的只用分位数噪声估计法来估计噪声,而前50帧是分位数噪声估计法和噪声模型相结合,使噪声估计的更准确。先看每个阶段都有的分位数噪声估计的处理,过程如下:
1) 算出每个频点的幅度谱的自然对数值,即对数谱inst->lmagn,后续用lmagn表示
2) 更新分位数自然对数值(inst->lquantile,后续用lquantile表示)和概率密度值(inst->density,后续用density表示)。 共有三组lquantile和density值,每一帧有129个频点,所以lquantile和density的数组大小为387(129*3)。内存布局示意如图1:
图1
三组不同的lquantile和density的更新由inst->counter(后续用counter表示)来控制。counter数组有三个整数值,每个值控制一组。counter数组的初始值基于200(表示前200帧),将200一分为三,即为[66, 133, 200]。每处理完一帧counter值会加1,当值变为200时就会变为0。这样处理第二帧时counter值变为[67, 134, 0],处理第三帧时counter值变为[68, 135, 1],以此类推。当初始200帧处理完后,counter也完成了0~200的遍历。
下面看counter怎么控制lquantile和density的,对于第i组第j个频点而言,先定义变量:
更新分位数:当频点对数谱lmagn[j] > lquantile[i*129 + j]时,表示lquantile偏小,需要增大,反之则需要减小。更新数学表达式如下式1
(1)
更新概率密度:当|lmagn[j] – lquantile[i*129+j]| < WIDTH(值为0.01)时,意味着当前的噪声估计比较准确了,因此要更新概率密度。更新的数学表达式如下式2:
(2)
3) 当帧数小于200时,对最后一组(即第二组)的lquantile做自然指数运算,将其作为噪声估计值(noise[j],每个频点一个值),可以看出每帧估出的噪声是不同的。当帧数大于等于200后,只有当counter数组里的值等于200时,才会将对应的组的lquantile做自然指数运算,将其作为噪声估计值。可以看出当帧数大于等于200后每过66帧或者67帧噪声估计值才会更新。
再看前50帧利用分位数噪声估计法与噪声模型相结合来估计初始噪声。先定义如下四个变量:
需要注意的是上述4个变量定义时均没有用到前5个频点,因为i是从5开始的。再利用上面定义的变量表示白噪声(white noise)和粉红噪声(pink noise)的参数,表示如下:
其中overdrive是根据设置的降噪程度而得到的一个值(在初始化中设置)。
其中blockInd表示当前帧的index 。
这样就可以利用白噪声和粉红噪声的参数来估计模型噪声了,具体如下:
其中当频点id小于5时,usedBin = 5, 其他情况下usedBin = 频点id。
最后根据分位数估计噪声noise和模型估计噪声parametric_noise得到最终的估计噪声了。对于每个频点j来说,表达式如下式3:
(3)
至此,前50帧的结合分位数噪声估计和模型噪声估计的噪声就估计出来了。这样不管是第几帧,初始噪声都能估计出来,下面根据估计出来的初始噪声来算先验信噪比和后验信噪比。
2,算先验信噪比和后验信噪比
在webRTC中语音降噪模块ANS细节详解(一)中说过后验信噪比σ是带噪语音Y与噪声N的功率比值,先验信噪比ρ是干净语音S与噪声N的功率比值,表达式如下式4和5:
(4)
(5)
其中m表示第几帧,k表示第几个频点,即每一个频点上都有先验SNR和后验SNR。由于噪声N已通过分位数估计法估计出来,而且带噪语音Y已知,因而后验SNR可以算出来。
因为
从而
所以得到式6:
(6)
即先验SNR等于后验SNR – 1。
至于算先验SNR,用的是判决引导法(Decision-Directed,简称DD)。根据式5和式6可以得到式7:
(7)
对先验SNR的估算可以将上式递推化得到,具体如式8:
(8)
这里α为权重(或叫平滑系数),以代替上式中的1/2。从上式看出估算当前帧的先验SNR是基于上一帧的先验SNR和当前帧的后验SNR。max()用以保证估值是非负的。平滑系数α取值范围为0 < α < 1,典型取值为0.98,webRTC ANS中就是用的这个值。
在具体软件实现中,WebRTC中为了减小运算load,并未严格按照定义的公式去计算,而是采用幅度谱的比值去计算,即式9和式10中第二个等号的右边部分。
(9)
(10)
算当前帧的先验SNR时,上一帧的带噪语音Y(k, m-1)是已知的,上一帧的维纳滤波器系数的值H(k, m-1)(即inst-smooth数组里的值)也是已知的,根据维纳滤波原理,从而上一帧的估计出来的干净语音S(k, m-1) = H(k, m-1)Y(k, m-1)也是已知的,所以上一帧的先验SNR计算如式11:
(11)
将其带入式8可得当前帧的先验SNR计算表达式如式12:
(12)
这样当前帧的先验SNR和后验SNR都计算出来了,用于后面的语音噪声概率计算中。下一篇将讲基于带噪语音和特征的语音和噪声的概率计算方法和噪声估计更新以及基于维纳滤波的降噪。