谈谈我开发过的几套语音通讯解决方案

本人从事音频软件开发10+年,既开发过voice相关的,又开发过music相关的,但大多数仍是开发voice相关的。掐指一算到如今在通讯终端上开发过的语音解决方案共有五套,它们既有有线通讯的,又有无线通讯的;既有在上层开发的,又有在底层开发的;既有在ARM上开发的,又有在DSP上开发的,总之各有特点。但由于都是语音通讯解决方案,又有共同的地方,都要有语音的采集播放、编解码、先后处理和传输等。今天我就选取有表明性的三套方案,讲讲它们的实现。html

 

1,在嵌入式Linux上开发的有线通讯语音解决方案web

这方案是在嵌入式Linux上开发的,音频方案基于ALSA,语音通讯相关的都是在user space 作,算是一个上层的解决方案。因为是有线通讯,网络环境相对无线通讯而言不是特别恶劣,用的丢包补偿措施也不是不少,主要有PLC、RFC2198等。我在前面的文章(如何在嵌入式Linux上开发一个语音通讯解决方案)详细描述过方案是怎么作的,有兴趣的能够去看看。算法

 

2,在Android手机上开发的传统无线通讯语音解决方案微信

这方案是在Android手机上开发的,是手机上的传统语音通讯方案(相对于APP语音通讯而言)。Android是基于Linux的,因此也会用到ALSA,可是主要是作控制用,如对codec芯片的配置等。跟音频数据相关的驱动、编解码、先后处理等在Audio DSP上开发,网络侧相关的在CP(通讯处理器)上开发,算是一个底层解决方案。该方案的软件框图以下:网络

从上图看出,AP在方案中起控制做用,一是控制codec芯片上音频路径的选择(经过配置寄存器完成),二是控制Audio DSP上音频流的start/stop等。真正的音频数据处理是在Audio DSP和CP上实现的(Audio DSP和CP上的实如今两个不一样的部门作,我是在Audio DSP上作音频开发,对CP上的实现只是了解,不能详细叙述CP上的Audio实现)。语音通讯分上行和下行,先看上行。经过codec芯片采集到的语音数据由I2S送给Audio DSP。Audio DSP中有DMA IN中断,5ms发生一次,获取语音数据,而后作重采样(方案中codec芯片的采样率是48k Hz,而编解码codec的采样率是8k/16k等,须要作重采样)变成8k/16k等的语音数据并保存在buffer中。发生四次就得到了20ms的语音数据(基于20ms是由于AMR/EVS的一帧都是20ms),把这20ms数据先作前处理(AEC/ANS/AGC等),再作编码得到码流,并把码流经过IPC送给CP。CP中作些网络侧相关的处理最后经过空口发送给对方。再看下行。CP从空口收到语音数据后作网络侧处理(jitter buffer等)后将码流发给Audio DSP。Audio DSP收到码流后先解码成PCM数据并作后处理(ANS/AGC等),而后作重采样变成48k Hz的语音数据,还要作混音处理(主要是系统音,要一块儿播放出来),处理完后放在buffer里。下行也有一个DMA OUT中断,也是5ms一次,把一帧20ms的数据分四次送给codec芯片,也就是每次从上述buffer里取5ms数据,取四次buffer就取空了,而后再取下一帧的数据播放。送给codec芯片的数据就会经过外设播放出来。socket

 

因为在DSP上开发,硬件资源(DSP 频率/memory)成了瓶颈,好多时间花在load/memory的优化上。DSP频率只有300多MHZ,上下行的先后处理、编解码、重采样又是比较耗load的,不优化根本不能流畅运行,在C级别优化后一些场景仍是不能流畅运行,最后好多地方用了终极大法汇编优化,才使各类场景下都能流畅运行。Memory份内部memory (DTCM(Data Tightly Coupled Memory, 数据紧密耦合存储器,用于存data)和PTCM(Program Tightly Coupled Memory, 程序紧密耦合存储器,用于存code))和外部memory(DDR)。要想快速运行,data和code最好都放在内部memory,可是内部memory的空间又特别小,DTCM和PTCM都只有几十K Word(DSP上的基本单位是Word,一个Word是两个字节),memory不只不能随意用,在写代码时时时刻刻都要注意省内存,还要优化(常常遇到的是开发新feature,memory不够了,先优化memory,而后再开发,memory都是一点一点抠出来的),最后优化也抠不出memory了,怎么办呢?用了overlay机制,说白了就是在不一样场景下的memory复用。好比播放音乐和打电话不可能同时出现,使用的部分memory就能够复用。再好比打电话时只有一种codec在工做,而系统会同时支持多种codec,这几种codec的使用的部分memory就能够复用。函数

 

3,在Android手机上开发的APP上的语音解决方案oop

这方案也是在Android手机上开发的,可是是APP语音通讯,相似于微信语音,在Native层作,调用Android JNI提供的API,算是一个上层解决方案。该方案的软件框图以下:性能

本方案是在AP(应用处理器)上实现,语音采集和播放并无直接调用系统提供的API(AudioTrack/AudioRecorder), 而是用了开源库openSL ES,让openSL ES去调用系统的API。咱们会向openSL ES注册两个callback函数(一个用于采集语音,一个用于播放语音),这两个callback每隔20Ms被调用一次,分别得到采集到的语音以及把收到的语音送给底层播放,从底层拿到的以及送给底层的语音数据都是PCM格式,都配置成16k采样率单声道的模式。在上行方向,codec芯片采集到的语音PCM数据经过I2S送给audio DSP,audio DSP处理后把PCM数据送给AP,最终经过注册的采集callback函数把PCM数据送给上层。在上层先作前处理,包括AEC/AGC/ANS等,用的是webRTC的实现(如今APP语音内的先后处理基本上用的都是webRTC的实现),作完前处理后还要根据codec看是否须要作重采样,如codec是8k采样率的,就须要作重采样(16k转到8k), 如codec是16k采样率的,就不须要作重采样了。再以后是编码获得码流,同时用RTP打包,并用UDP socket把RTP包发给对方。在下行方向,先用UDP socket收语音RTP包,去包头获得码流放进jitter buffer中。每隔20Ms会从jitter buffer中拿一帧数据解码获得PCM,有可能还要作PLC和重采样,而后再作后处理(ANS/AGC),最终经过播放callback函数把PCM数据一层层往下送给Audio DSP,audio DSP处理后把PCM数据送给codec芯片播放出来。APP上的语音通讯属于OTT (On The Top)语音,不像传统语音通讯那样有QoS保障,要保证语音质量,必需要采起更多的补偿措施(因为无线网络环境是变化无穷的,常常会比较恶劣,会致使乱序丢包等),常见的方法有FEC(前向纠错)、重传、PLC(丢包补偿)等。补偿措施是该方案的难点,经过补偿把语音质量提升了,可是增大了时延和增长了流量。优化

 

方案的实现是上图中灰色虚线上面的部分,我之因此画出灰色虚线下面部分,是想给你们看看整个完整的语音数据流向的实现,下面的部分对APP开发人员来讲是黑盒子,他们可见的就是系统提供的API。我先是作APP上的语音通讯,后来才作手机上的传统语音通讯。作APP上的语音通讯时不清楚底层是怎么实现的,很想知道,可是没有资料可供了解。我想不少作APP语音的人跟我有同样的困惑,底层实现究竟是什么样的。后来作了手机上传统语音通讯的实现,清楚了底层是怎么作的,算是把APP语音的整个数据流向搞清楚了。本文把底层实现框图也画出来,就是想让作APP语音通讯的人也了解底层的实现。不一样手机平台上的针对APP语音的底层实现是不同的(主要是指DSP上的实现,Android Audio Framework上的实现基本是同样的),好比有的有先后处理(一般是中高端机),有的没有先后处理(一般是低端机)。中高端机在上层不作回声消除也没有回声,那是由于在底层作掉了。一样的回声消除算法在越接近硬件处作效果越好,主要是由于近远端之间的latency越靠近硬件算的越准确不变,latency准确不变回声消除才会有更好的性能。在上层算latency就会引入软件带来的时延,并且软件引入的时延有多是变化的,这就致使在上层算latency不如底层精确。在APP上层作回声消除时,机型不同,latency也就不一样(硬件不一样以及底层软件实现不一样),当时是一个机型一个机型测出来的,有一百多毫秒的,也有两百多毫秒的,差别很大。至于怎么测的,有兴趣能够看我前面写的一篇文章(音频处理之回声消除及调试经验)。在底层DSP上作回声消除时,算是最靠近硬件了,我当时算DMA OUT和DMA IN之间的delay,只有五点几毫秒,并且屡次测latency都是很稳定,偏差不超过几个采样点,这样就保证了回声消除的高性能。当时测时在硬件上把speaker和MIC的线连起来,造成一个loopback,DMA OUT的数据就彻底进入DMA IN,用特殊波形(好比正弦波)穿越,同时把DMA OUT和DMA IN的音频数据dump出来用CoolEdit看,从而获得latency的准确值。低端机在上层是必定要作回声消除的,那是由于底层没作。APP语音通讯解决方案要兼顾全部机型,因此在APP语音解决方案内回声消除是必定要有的,固然还包括其余的先后处理模块,好比ANS、AGC。

 

以上方案就是我作过的三种典型的语音通讯方案,有有线通讯,有无线通讯,也有APP语音通讯,在我看来应该是把目前通讯终端上的主要语音解决方案都囊括了。因为在不一样的平台上开发,在不一样的层次开发,从而表现出巨大的差别性,可是语音通讯的核心模块都是同样的。