前言:
之前做个一个回声抵消的项目,要实现在windows xp平台下,一个局域网内的两个房间的通话(双方都是外接音箱的),同时要有回声抵消的功能,费了好几月的时间,走了很多弯路,但最终还是有一些成绩的,这里写几篇文章,给要接触这一方面技术的同行做个参考。
回声抵消,是个什么东西呢,介绍回声抵消的原理,这个链接讲的很好http://silversand.blog.51cto.com/820613/166095 ,这里不得不说一句,51cto真是不错的技术家园,里面的牛人很多,再往下看之前,请先看看这篇文章,要不你会不懂我再讲什么。
回声抵消有两种方式,一种是通过硬件实现,有很多手机就是这么做的,也有专业的芯片,但是只支持8khz的,如果要求高质量的音质的话,基本实现不了。二种是通过软件实现,qq,msn,很多具有通话功能的软件,现在都具有回声抵消的功能(需是比较高版本的,低版本的可能没有),但是实现代码是不对外的,开源的回声抵消的代码只有speex里面有(实际上我就是用speex的回声抵消代码)。其他还有很多voip的开源软件,例如freeswitch,也具有回声抵消的代码,但是一旦你阅读freeswitch的话,你就会知道,freeswitch也是用的speex的代码。下面我们就说一说speex的回声抵消部分。
正文:
1、speex回声抵消代码功能性验证:
如上图,示意了speex回声抵消的工作原理,如果没有回声抵消的话,那么x(n)信号通过喇叭播放出来,经过空间的多次反射,形成了y(n)信号,同时麦克将有用的语音信号v(n)和y(n)一起采集,并发送到另一端,这样另一端的人,在听到需要的v(n)信号的同时,也听到了y(n),而y(n)正是自己说的话x(n)经过反射产生的回声,所以严重影响了通话的质量,由于在windows下的通话延时较长,回声特别明显。当加入回声抵消功能后,在x(n)播放的同时,将x(n)送入滤波器,滤波器模拟出x(n)产生的回声y'(n),然后在麦克采集后的v(n) + y(n)中剪掉y(n),可以看到如果y'(n)与y(n)无限接近的话,那么就会听不到回声,而这是一个需要适应的过程,实现适应的方式是将相减的差值,送回到了回声抵消的算法中,用来更新权重系数,来使y'(n)与y(n)无限的接近。
speex回声抵消的算法实现,主要是在它的mdf.c文件里面提及。算法的原理,主要就是个自适应滤波器,将时域的信号转换为频域,然后找出频域信号的相关性,实现回声抵消(其中又涉及了收敛速度、权重等信号处理的相关知识)。speex的代码实现和原理,后面的文章我会一一提到。这里我们按着对一个陌生算法的接触过程来叙述。
首先我们验证speex回声抵消算法的可行性及技术特点,然后我们再动态的实现我们的通话程序的回声抵消功能,所以我们先进行静态的回声抵消,看其能否承担大任。为了验证其功能,我们先模拟一个产生回声的环境,找一个8k,或者16k的音频作为x(n)信号的文件,用外置的音箱或者喇叭播放它,然后同时用麦克采集回来,存成含有y(n)+v(n)信号的文件,再对这两个文件进行回声抵消处理,也就是生成e(n)信号的文件。看其是否只包含了v(n)信号,或者说在听觉上可不可以接受这样的回声抵消效果。以我的实验为例,我用cool edit生成了一个单通道、16khz、16bit精度的语音文件,存为ref.pcm,然后将其用喇叭播放出来,同时用单通道、16khz、16bit来采集存为mic.pcm,最后将ref.pcm,mic.pcm取出数据,送如回声抵消的代码,将处理后的数据存为final.pcm文件,再用cool edit打开final文件,观看其波形,和mic对比着听一听效果。附件里是我写的一个mfc程序及源码,加入了回声抵消的算法,并且我给出了几个ref.pcm和mic.pcm的例子。用我写的程序打开ref.pcm和mic.pcm,然后设置好参数,运行生成final.pcm文件,其中程序是用vs2005编译的,还有一点这里要说明,51cto上面有位大哥也提供静态的代码,用c编译的,在dos下的程序。