webrtc 的回声抵消(aec、aecm)算法简介_webrtc aecm-程序员宅基地

技术标签: webrtc  回声消除  AEC  

  webrtc 的回声抵消(aec、aecm)算法主要包括以下几个重要模块:1.回声时延估计 2.NLMS(归一化最小均方自适应算法) 3.NLP(非线性滤波) 4.CNG(舒适噪声产生),一般经典aec算法还应包括双端检测(DT)。考虑到webrtc使用的NLMS、NLP和CNG都属于经典算法范畴,故只做简略介绍,本文重点介绍webrtc的回声时延估计算法,这也是webrtc回声抵消算法区别一般算法(如视频会议中的算法)比较有特色的地方。

1) 回声时延估计
     回声延时长短对回声抵消器的性能有比较大的影响(此处不考虑pc上的线程同步的问题),过长的滤波器抽头也无法实际应用,因此时延估计算法就显得比较重要了。常用且容易想到的估计算法是基于相关的时延估计算法(学过通信原理的应该不会陌生),另外相关算法在语音编码中也得到广泛的应用,如 amr系列,G.729系列 ,G.718等编码器。在语音信号自相关求基音周期时,由于编码器一般按帧处理,帧长度一般是10或20ms,在该时延范围内搜索基音周期运算量较小,然而对于回声抵消的应用场合,延时搜索范围比较大,带来很高的运算复杂度。在手持终端设备上,我们需要考虑移动环境的变化对算法性能的影响,比如时延是否随机变化,反射路径线性还是非线性,以及运算量(电池)是否符合要求,则更为复杂。

     回到webrtc的回声时延估计,它采用的是gips首席科学家Bastiaan的算法。下面介绍一下该算法的主要思想:
设1表示有说话音,0表示无说话音(静音或者很弱的声音),参考端(远端)信号x(t)和接收端(近端)信号y(t)可能的组合方式有以下几种:(0,0),(0,1),(1,0),(1,1),
 (0,0)表示远端和近端都是比较弱的声音,(1,1)表示远端和近端都是比较强的声音,webrt的c代码默认其它两种情况是不可能发生的。设在时间间隔p上,即p=1,2,...,P,  频带q,q=1,2,...,Q上,输入信号x加窗(如汉宁窗)后的功率谱用Xw(p,q)来表示,对每个频带中的功率谱设定一个门限Xw(p,q)_threshold,
如果 Xw(p,q)  >= Xw(p,q)_threshold  ,   则Xw(p,q) =1;
如果 Xw(p,q) <    Xw(p,q)_threshold  ,   则Xw(p,q) =0;
同理,对于信号y(t),加窗信号功率谱Yw(p,q)和门限Yw(p,q)_threshold,
如果 Yw(p,q) >= Yw(p,q)_threshold   ,   则Yw(p,q) =1;
如果 Yw(p,q) < Yw(p,q)_threshold ,        则Yw(p,q) =0;
考虑到实际处理的方便,在webrtc的c代码中,将经过fft变换后的频域功率谱分为32个子带,这样每个特定子带 Xw(p,q)的值可以用1个比特来表示,总共需要32个比特,只用一个32位数据类型就可以表示了。
webrtc对参考信号定义了75个32位binary_far_history的数组存放历史远端参考信号,定义了16个32位binary_near_history的数组存放历史近端参考信号,最近的值都放在下标为0的数组中,使用 binary_near_history[15]的32位bit与binary_far_history数组中75个32位bit分别按位异或,得到75个32位比特数据,32位bit的物理意义是近似地使用功率谱来统计两帧信号的相关性。统计32位结果中的1的个数存于bit_counts中,接下来用对bit_counts进行平滑防止延时突变,得到mean_bit_count,可以看出  mean_bit_count 越小,则表明近端数据与该帧的远端数据越吻合,两者的时延越接近所需要的延时数值,用value_best_candidate表示。剩下的工作是对边界数值进行保护,如果value_best_candidate接近最差延时(预设),则表明数值不可靠,这时不更新延时数据;如果数据可靠,则进一步使用一阶markvo模型,比照上一次时延数据确定本次最终的更新时延last_delay.
Bastiaan的专利本身要比现有的c代码实现更为复杂,比如在异或的时候(0,0),(0,1),(1,0),(1,1)四种组合可以附加代价函数,而c代码相当于默认给(0,0),(1,1)附加权值为1,给(0,1),(1,0)附加权值为0;
另外c代码算法是按帧顺序依次对远端和近端数组异或,实际应用时也可以每隔1帧或2帧做异或,这样可以扩大搜索范围。
总的来说webrtc的时延估计算法复杂度比求相关大大简化,尤其适用于移动终端等对运算量比较敏感的场合进行回声消除。针对实际应用场合,算法还有提升的空间。

2) NLMS(归一化最小均方自适应算法
     LMS/NLMS/AP/RLS等都是经典的自适应滤波算法,此处只对webrtc中使用的NLMS算法做简略介绍。
     设远端信号为x(n),近段信号为d(n),W(n),则误差信号e(n)=d(n)-w'(n)x(n)  (此处‘表示转秩),NLMS对滤波器的系数更新使用变步长方法,即步长u=u0/(gamma+x'(n)*x(n));其中u0为更新步长因子,gamma是稳定因子,则滤波器系数更新方程为 W(n+1)=W(n)+u*e(n)*x(n);  NLMS比传统LMS算法复杂度略高,但收敛速度明显加快。LMS/NLMS性能差于AP和RLS算法。
    另外值得一提的是webrtc使用了分段块频域自适应滤波(PBFDAF)算法,这也是自适应滤波器的常用算法。
    自适应滤波的更多资料可以参考simon haykin 的《自适应滤波器原理》。

3) NLP(非线性滤波)
    webrtc采用了维纳滤波器。此处只给出传递函数的表达式,设估计的语音信号的功率谱为Ps(w),噪声信号的功率谱为Pn(w),则滤波器的传递函数为H(w)=Ps(w)/(Ps(w)+Pn(w))。

4)CNG(舒适噪声产生)
   webrtc采用的舒适噪声生成器比较简单,首先生成在[0 ,1 ]上均匀分布的随机噪声矩阵,再用噪声的功率谱开方后去调制噪声的幅度。

总的说来,webrtc的aec算法简单、实用、易于商业化,另一方面猜测c代码还有所保留。

 

由于工作需要,最近一直在研究WebRTC里的AEC算法。根据源码里面的fullaec.m文件,

总体来说,我认为该AEC算法是属于分段快频域自适应滤波算法,Partioned block frequeney domain adaPtive filter(PBFDAF)。具体可以参考Paez Borrallo J M and Otero M G

使用该AEC算法要注意两点:

1)延时要小,因为算法默认滤波器长度是分为12块,每块64点,按照8000采样率,也就是12*8ms=96ms的数据,而且超过这个长度是处理不了的。

2)延时抖动要小,因为算法是默认10块也计算一次参考数据的位置(即滤波器能量最大的那一块),所以如果抖动很大的话找参考数据时不准确的,这样回声就消除不掉了。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/audio_algorithm/article/details/78684088

智能推荐

Buffer I/O error on device mmcblk0p3 logical block /end-程序员宅基地

文章浏览阅读2.9k次。Buffer I/O error on device mmcblk0p3 logical block /end_buffer i/o error on device mmcblk0

Scala 数组、映射和集合+wordcount程序-程序员宅基地

文章浏览阅读74次。数组1、定长数组和变长数组package cn.gec.scala import scala.collection.mutable.ArrayBuffer object ArrayDemo { def main(args: Array[String]) { //初始化一个长度为8的定长数组,其所有元素均为0 val arr1 = n..._scala array[long] wordcount

代码:灰度重心法提取线激光条纹中心线(CPP+OpenCV)_灰度中心法-程序员宅基地

文章浏览阅读2.1k次。灰度重心法是根据每行光条纹横截面内的灰度分布特征逐行进行处理,通过在行坐标的方向上,逐行计算提取光条纹区域的灰度重心点,并将该点用来代表该截面的光条纹中心点位置,最后将所有中心点拟合形成光条纹中心线。灰度重心法计算光条纹中心点的公式(光条纹第v列的灰度重心坐标):图像包含U行、V列的图像中坐标(u, v)处的像素灰度值为I(u,v),其中u=1,2,3,…,U; v=1,2,3…,V。灰度重心法提取光条纹中心线时运算速度快,实时性好。但是易受图像中的噪点干扰,导致中心线坐标偏移。#include._灰度中心法

论文查重系统的比较和选择_千万级和亿级查重哪个好-程序员宅基地

文章浏览阅读2k次。又到了毕业季,一般学校都会对毕业生的论文进行查重检测,看看大家的重复率。这个对大家的毕业是十分重要的,如果查重不过,可能会被延期毕业。所以很多学生也会自己事先查重,然后自己多次修改,达到学校的要求。可是很多学生不知道如何选择检测系统,下面我就给大家介绍一下主流的几种系统: 1.万方检测,特点是检测结果粗放,不是很令人满意,但是价格足够便宜,非常适合大家前期修改论文。 _千万级和亿级查重哪个好

FX PLC-程序员宅基地

文章浏览阅读75次。该协议实际上适用于PLC编程端口以及 FX-232AW 模块的通信。通讯格式:命令 命令码 目标设备DEVICE READ CMD "0" X,Y,M,S,T,C,DDEVICE WRITE CMD "1" X,Y,M,S,T,C,DFORCE ON CMD " 7" X,Y,M,S,T,CFORCE OFF CMD "8" X,Y,M,S,T,C传输格式: R..._fxplc一次性最多读写多少字节

DOM与虚拟DOM_dom和虚拟dom-程序员宅基地

文章浏览阅读1.8k次,点赞4次,收藏9次。1. DOM(Document Object Model)2018年通用版本是 DOM 3DOM的作用:对Html文档进行增删改查DOM文档树:(Object =&amp;amp;amp;amp;gt;)祖先 Node =&amp;amp;amp;amp;gt;Document创建Html标签;Text 创建文本;Element 创建其他元素标签;Comment 创建注释…2. Node 接口2. 1 属性childNodes //获取的..._dom和虚拟dom

随便推点

windows10系统下kafka+zookeeper安装启动步骤_kafka zookeeper在window上安装-程序员宅基地

文章浏览阅读566次。1.首先电脑上要安装好jdk,并且配置好jdk环境变量等。我的是jdk1.82.下载zookeeper以及kafka安装包zookeeper:http://zookeeper.apache.org/releases.html(apache-zookeeper-3.5.5-bin.tar.gz )kafka:http://kafka.apache.org/downloads.html(kafka_2.11-2.1.1.tgz)3.安装zookeeper:(1)解压,D:\software._kafka zookeeper在window上安装

LightOJ - 1138 N - Trailing Zeroes (III)_you task is to find minimal natural number n so th-程序员宅基地

文章浏览阅读538次。You task is to find minimal natural number N, so that N! contains exactly Q zeroes on the trail in decimal notation. As you know N! = 1*2*...*N. For example, 5! = 120, 120 contains one zero on the tr..._you task is to find minimal natural number n so that n! contains exactly q

/sys/devices/ 下的设备name就是bios中定义的HID_acpi hardware_id-程序员宅基地

文章浏览阅读1.8k次。ACPI scan的时候会调用到acpi_bus_check_add->acpi_add_single_objectstatic int acpi_add_single_object(struct acpi_device **child, acpi_handle handle, int type, unsigned long long sta){ int result_acpi hardware_id

杭电oj-2067 小兔的棋盘(卡特兰数)-程序员宅基地

文章浏览阅读241次。杭电oj-2067 小兔的棋盘(卡特兰数)Problem Description小兔的叔叔从外面旅游回来给她带来了一个礼物,小兔高兴地跑回自己的房间,拆开一看是一个棋盘,小兔有所失望。不过没过几天发现了棋盘的好玩之处。从起点(0,0)走到终点(n,n)的最短路径数是C(2n,n),现在小兔又想如果不穿越对角线(但可接触对角线上的格点),这样的路径数有多少?小兔想了很长时间都没想出来,现在想请你帮助小兔解决这个问题,对于你来说应该不难吧!Input每次输入一个数n(1<=n<=35),当n

Petya勒索软件变种Nyetya全球爆发,思科Talos率先响应-程序员宅基地

文章浏览阅读102次。自2017年5月份经历勒索软件WannaCry的大规模爆发后,思科Talos团队在6月27日发现了最新的勒索软件变种,暂命名为Nyetya。目前已经在多个国家发现了这个勒索软件的感染事件,思科Talos团队正在积极分析并不断更新最新的防护信息。原文链接:http://blog.talosintelligence.com/2017/06/worldwid...

springboot项目中自定义注解的使用总结、java自定义注解实战(常用注解DEMO)_springboot自定义注解加载字段上怎么使用-程序员宅基地

文章浏览阅读2.4w次,点赞142次,收藏1k次。初学spring的时候使用注解总觉得使用注解很神奇,加一个注解就能实现想要的功能,很好奇,也想自己根据需要写一些自己实现的自定义注解。问题来了,自定义注解到底是什么?肯定会有人和我一样有这个疑惑,我根据自己的理解总结一下。看完下面的几个使用自定义注解的实战demo,小伙伴大概就懂怎么用了。其实注解一点也不神奇,注解就是一种标志,单独使用注解,就相当于在类、方法、参数和包上加上一个装饰,什么功能也没有,仅仅是一个标志,然后这个标志可以加上一些自己定义的参数。_springboot自定义注解加载字段上怎么使用