上篇(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细节详解(三)的更多相关文章

  1. webRTC中语音降噪模块ANS细节详解(四)

    上篇(webRTC中语音降噪模块ANS细节详解(三))讲了噪声的初始估计方法以及怎么算先验SNR和后验SNR. 本篇开始讲基于带噪语音和特征的语音和噪声的概率计算方法和噪声估计更新以及基于维纳滤波的降 ...

  2. webRTC中语音降噪模块ANS细节详解(二)

    上篇(webRTC中语音降噪模块ANS细节详解(一))讲了维纳滤波的基本原理.本篇先给出webRTC中ANS的基本处理过程,然后讲其中两步(即时域转频域和频域转时域)中的一些处理细节. ANS的基本处 ...

  3. webRTC中语音降噪模块ANS细节详解(一)

    ANS(adaptive noise suppression) 是webRTC中音频相关的核心模块之一,为众多公司所使用.从2015年开始,我在几个产品中使用了webRTC的3A(AEC/ANS/AG ...

  4. python中argparse模块用法实例详解

    python中argparse模块用法实例详解 这篇文章主要介绍了python中argparse模块用法,以实例形式较为详细的分析了argparse模块解析命令行参数的使用技巧,需要的朋友可以参考下 ...

  5. Python中random模块生成随机数详解

    Python中random模块生成随机数详解 本文给大家汇总了一下在Python中random模块中最常用的生成随机数的方法,有需要的小伙伴可以参考下 Python中的random模块用于生成随机数. ...

  6. Java中堆内存和栈内存详解2

    Java中堆内存和栈内存详解   Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,ja ...

  7. angular-ngSanitize模块-$sanitize服务详解

    本篇主要讲解angular中的$sanitize这个服务.此服务依赖于ngSanitize模块. 要学习这个服务,先要了解另一个指令: ng-bing-html. 顾名思义,ng-bind-html和 ...

  8. angular-ngSanitize模块-linky过滤器详解

    本篇主要讲解angular中的linky这个过滤器.此过滤器依赖于ngSanitize模块. linky能找出文本中的链接,然后把它转换成html链接.什么意思,就是说,一段文本里有一个链接,但是这个 ...

  9. View绘制详解(五),draw方法细节详解之View的滚动/滑动问题

    关于View绘制系列的文章已经完成了四篇了,前面四篇文章主要带小伙伴们熟悉一下View的体系的整体框架.View的测量以及布局等过程,从本篇博客开始,我们就来看看View的绘制过程.View的绘制涉及 ...

随机推荐

  1. 数据结构逆向分析-List

    数据结构逆向分析-List 首先STL中的List就是一个链表,但是肯定C++用了很多封装,所以这里我们来一探究竟. 开始 首先先写一些简单的分析的源代码: #include<iostream& ...

  2. 使用python3中的2to3.py执行数据迁移

    1.在python默认安装的位置找到Tools\scripts 2.找到2to3.py 3.在所在文件夹shift+右键打开终端 4.执行命令python 2to3.py -w 需要做数据迁移的数据路 ...

  3. P6222-「P6156 简单题」加强版【莫比乌斯反演】

    正题 题目链接:https://www.luogu.com.cn/problem/P6222 题目大意 给出\(k\),\(T\)组询问给出\(n\)求 \[\sum_{i=1}^n\sum_{j=1 ...

  4. P6672-[清华集训2016]你的生命已如风中残烛【结论】

    正题 题目链接:https://www.luogu.com.cn/problem/P6672 题目大意 长度为\(m\)的序列\(a\),有\(n\)个数字不是\(0\),其他\(m-n\)个是\(0 ...

  5. Spring,IOC源码分析

    有错勿喷 1.首先是Spring,IOC的基本概念 IOC是一个容器 容器启动的时候创建所有单实例对象 我们可以直接从容器中获取到这个对象 2.调试流程 ioc容器的启动过程?启动期间都做了什么(什么 ...

  6. 单机百万连接调优和Netty应用级别调优

    作者:Grey 原文地址:单机百万连接调优和Netty应用级别调优 说明 本文为深度解析Netty源码的学习笔记. 单机百万连接调优 准备两台Linux服务器,一个充当服务端,一个充当客户端. 服务端 ...

  7. dubbo-admin的使用

    目录 了解 dubbo-admin 下载 dubbo-admin 使用 dubbo-admin 1.dubbo-admin是什么 dubbo-admin是一个监控程序,可以通过web很方便的管理监控众 ...

  8. PAT (Basic Level) Practice (中文)1076 Wifi密码 (15分)

    1076 Wifi密码 (15分) 下面是微博上流传的一张照片:"各位亲爱的同学们,鉴于大家有时需要使用 wifi,又怕耽误亲们的学习,现将 wifi 密码设置为下列数学题答案:A-1:B- ...

  9. IEEE754浮点数的转换

    将十进制数转换为单精度浮点数 如何将十进制数转换为单精度浮点数参考 首先要知道 IEEE浮点标准:V=(-1)^s * M * 2^E 1.符号(sign)s决定这个数是负数(s=1)还是正数,0(s ...

  10. WeakMap与Map,使用WeakMap实现深拷贝循环引用问题

    1.Map可以使用任意类型的key值,不限字符串,对象等. 2.WeakMap只能使用对象作为key值,是弱引用,当从WeakMap中移除时,会自动垃圾回收 3.Object只能用基本类型作为key值 ...