webRTC中语音降噪模块ANS细节详解(三)
上篇(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都计算出来了,用于后面的语音噪声概率计算中。下一篇将讲基于带噪语音和特征的语音和噪声的概率计算方法和噪声估计更新以及基于维纳滤波的降噪。
webRTC中语音降噪模块ANS细节详解(三)的更多相关文章
- webRTC中语音降噪模块ANS细节详解(四)
上篇(webRTC中语音降噪模块ANS细节详解(三))讲了噪声的初始估计方法以及怎么算先验SNR和后验SNR. 本篇开始讲基于带噪语音和特征的语音和噪声的概率计算方法和噪声估计更新以及基于维纳滤波的降 ...
- webRTC中语音降噪模块ANS细节详解(二)
上篇(webRTC中语音降噪模块ANS细节详解(一))讲了维纳滤波的基本原理.本篇先给出webRTC中ANS的基本处理过程,然后讲其中两步(即时域转频域和频域转时域)中的一些处理细节. ANS的基本处 ...
- webRTC中语音降噪模块ANS细节详解(一)
ANS(adaptive noise suppression) 是webRTC中音频相关的核心模块之一,为众多公司所使用.从2015年开始,我在几个产品中使用了webRTC的3A(AEC/ANS/AG ...
- python中argparse模块用法实例详解
python中argparse模块用法实例详解 这篇文章主要介绍了python中argparse模块用法,以实例形式较为详细的分析了argparse模块解析命令行参数的使用技巧,需要的朋友可以参考下 ...
- Python中random模块生成随机数详解
Python中random模块生成随机数详解 本文给大家汇总了一下在Python中random模块中最常用的生成随机数的方法,有需要的小伙伴可以参考下 Python中的random模块用于生成随机数. ...
- Java中堆内存和栈内存详解2
Java中堆内存和栈内存详解 Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,ja ...
- angular-ngSanitize模块-$sanitize服务详解
本篇主要讲解angular中的$sanitize这个服务.此服务依赖于ngSanitize模块. 要学习这个服务,先要了解另一个指令: ng-bing-html. 顾名思义,ng-bind-html和 ...
- angular-ngSanitize模块-linky过滤器详解
本篇主要讲解angular中的linky这个过滤器.此过滤器依赖于ngSanitize模块. linky能找出文本中的链接,然后把它转换成html链接.什么意思,就是说,一段文本里有一个链接,但是这个 ...
- View绘制详解(五),draw方法细节详解之View的滚动/滑动问题
关于View绘制系列的文章已经完成了四篇了,前面四篇文章主要带小伙伴们熟悉一下View的体系的整体框架.View的测量以及布局等过程,从本篇博客开始,我们就来看看View的绘制过程.View的绘制涉及 ...
随机推荐
- 【多线程】Android多线程学习笔记——线程池
Java线程池采用了享元设计模式,在系统中维持一定数量的线程,用于处理异步或并发需求,在平时处理异步或并发任务时被广泛使用.这里基于JDK1.8和Android28来整理一些关于线程池的知识点. 一. ...
- 【PHP数据结构】二叉树的遍历及逻辑操作
上篇文章我们讲了许多理论方面的知识,虽说很枯燥,但那些都是我们今天学习的前提,一会看代码的时候你就会发现这些理论知识是多么地重要了.首先,我们还是要说明一下,我们学习的主要内容是二叉树,因为二叉树是最 ...
- TP6 前一个项目可以,第二个项目配置多域名绑定应用一直失效
之前的域名类似: www.a.com test.a.com edu.a.com ... 文件config/app.php中 'domain_bind' => [ 'test' ...
- Win7 ASP连接数据库“未找到提供程序.该程序可能未正确安装”问题
是自己装的64位Windows 7系统的原因,默认64位环境下,IIS应用程序池未启用32位应用程序,我们只需要启用一下就可以了.打开IIS 7,定位到"应用程序池",然后选择使用 ...
- Django边学边记—模型查询
查询集 两大特性 惰性执行:创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括迭代.序列化.与if合用 缓存:查询集的结果被存下来之后,再次查询时会使用之前缓存的数据 返回列 ...
- linux 修改文件名称的三中方法
一:rename "old.html" "oldd.HTML" *html参数.有什么.改为什么 ,目标文件: 二 : #!/bin/sh Dirname=&q ...
- python学习笔记(四)-文件操作
文件读写"""一.文件打开有3种方式 1.读 r #如果打开的文件的时候没有指定模式,那么默认是读 读写模式 r+,只要沾上r,文件不存在的时候,打开都会报错 2.写 w ...
- GDOI2021划水记
Day0 上午有意志行,一大早就醒了,然后走了五个小时脚痛.中午洗澡,宿舍轮流看巨人最终话然后聊了一个小时? 下午老师带着我和全爷先开溜,宿舍好像很破旧还还没得充电,领了牌牌和斐爷去吃饭. 然后六点多 ...
- P4201-[NOI2008]设计路线【结论,树形dp】
正题 题目链接:https://www.luogu.com.cn/problem/P4201 题目大意 给出\(n\)个点的一棵树开始所有边都是白色,选出若干条没有公共点的路径将上面所有边变为黑色. ...
- 解决报错:Unable to process Jar entry [org/springframework/jmx/export/annotation/*****]
情况说明:从gitub上clone的maven项目,pox.xml配置中的依赖,自己的repository都有,所以正常update project ,正常clean,install,整个过程无报错 ...