一个频域语音降噪算法实现及改进方法
来自: http://www.cnblogs.com/icoolmedia/p/weiner_audio_ns.html
发现很多朋友想进入语音降噪处理的大门,却很容易被铺天盖地的理论弄的很迷惑,不知道从哪里开始比较好。网上给出的参考文章大多干说理论,没有代码实现。很不利于学习。于是打算写这篇语音降噪的文章,并给出相应的实现代码方便交流和进一步的学习。
一. 算法核心思想与流程概要
本文给出的降噪算法的核心流程很简单,主要是两个步骤:
- 环境噪声的假设与估计
- 频域维纳滤波降噪
这里简单说一下语音相位问题,通常在语音的降噪算法中,是不考虑纯净语音的相位问题的,这是因为理论上可以证明:带噪语音相位就是纯净语音相位的最优估计!
二. 环境噪声估计
首先我们假设环境噪声为随机平稳加性噪声、且与语音信号不相关。要注意这个假设对我们很重要,要记住这个算法的前提条件。这里介绍的噪声估计算法叫做连续谱最小值跟踪,资料出处为“语音增强-理论与实践”一书中第九章中的一部分内容。此算法利用了带噪语音信号在单个频带的功率通常会衰减到噪声的功率水平。即使在语音活动期间也是如此。
算法主要分为两个步骤:
- 对各频点带噪语音功率谱进行平滑处理。短时平滑方式为:
这里, 为平滑后的第k帧、 频点的语音信号功率谱, 为平滑因子(通常取值为: )。
2.对各频点带噪语音功率最小值进行非线性跟踪。
If
else
end
这里,算法中的非线性跟踪会连续对噪声功率进行估计,这主要是由于上式中的第二项实现了一个一阶差分运算,是在离散情况下对求导的一种近似。当带噪语音功率 增加时,导数值也会增加,因此差分值 为正,当带噪语音功率下降的时候,导数为负,噪声估计减小。算法唯一要注意的是:当语音谱上出现很窄的峰值时,可能会导致在语音活动期音对噪声的过估计,进而可能抑制语音。
三. 频域维纳滤波
使用维纳滤波进行语音降噪的过程,其实是把降噪过程视为一个线性时不变系统,当带噪语音通过这个系统时,在均方误差最小化准则下,使得系统的输出与期望的纯净语音信号最接近的过程。系统我们用下面的卷积过程来表示:
其中y(n)为输入信号, 为输出信号,如果我们转换到频域,表示为: ,则频率 处的估计误差为:
在频域使其均方误差 最小化:
这里 为输入信号的功率谱, 是输入信号y(n)与期望信号d(n)的互功率谱,为了得到最优的滤波器 ,我们对均方误差 求关于 的复导数,并令其等于0,可得:
由于 ,求解 ,得到维纳滤波的通用形式:
再由于我们假设噪声为加性噪声,且与语音信号不相关,可得:
将上面两个式子代入维纳滤波器的通用形式,得到频域维纳滤波器:
其中 为频率 处的先验SNR。下面的算法实现中将会用到这个结论。当然,如果想使用平方根维纳滤波器,也可以对 再进行一次开方,这个就不再多说了。
四. 可能的改进方法
总的说来,这是一个降噪算法的小实现,可以改进的地方真的是太多了:
l 结合对先验信噪比与后验信噪比的调整算法(如:判决引导法)
l 结合语音存在的概率进行调整
l 使用超几何增益,而不是维纳增益
l 结合盲信号处理与阵列方向信息
这里不再一一列举,实现代码请到音视频算法讨论QQ群(374737122)中自行下载(TestNs),欢迎就其它改进方法一起讨论!