语音通讯中提升音质的方法

语音通讯是实时通讯,影响语音质量的因素不少,大体可把这些因素分红两大类:一类是回声噪声等周围环境因素致使语音质量差,另外一类是丢包延时等网络环境因素致使语音质量差。这两类因素因为成因不同,解决方法也不同。下面就讲讲用哪些方法来提升语音质量。html

 

首先看因为周围环境因素致使语音质量差的解决方法。这类方法主要是用信号处理算法来提升音质,不一样的因素有不一样的处理算法,用回声消除算法把回声消除掉,用噪声抑制算法把噪声抑制住,用自动增益控制算法把音量调整到一个指望的值。这些都是信号处理领域比较专业的算法,好在如今webRTC已经开源,也包括这些算法(AEC/ANS/AGC)。咱们只要把这些算法用好就有很是不错的效果。这些算法的调试中AEC相对复杂一些,我在前面的文章中(音频处理之回声消除及调试经验)专门写过怎么调试,有兴趣的能够去看一看。ANS/AGC相对简单,先在Linux下作一个小应用程序验证算法的效果,有可能要调一下参数,找一个相对效果较好的值。验证算法的过程也是熟悉算法怎么使用的过程,对后面把算法应用到方案中是有好处的。web

 

再来看因为网络环境因素致使语音质量差的解决方法。网络环境因素主要包括延时、乱序、丢包、抖动等,又有多种方法来提升音质,主要有抖动缓冲区(Jitter Buffer)、丢包补偿(PLC)、前向纠错(FEC)、重传等,下面分别一一介绍。算法

 

1,Jitter Buffer缓存

Jitter Buffer主要针对乱序、抖动因素,主要功能是把乱序的包排好序,同时把包缓存一些时间(几十毫秒)来消除语音包间的抖动使播放的更平滑。我在前面的文章(音频传输之Jitter Buffer设计与实现)中专门写过Jitter Buffer 的设计和实现,有兴趣的能够去看一看。网络

 

2,FEC编码

FEC(Forward Error Correction,中文译为前向纠错)主要针对丢包这种因素。它是一种经过增长冗余数据对丢失的数据包进行恢复的信道编码算法(至于信道编码,想了解原理的朋友能够找相关文章看,这里就不讲了。再说我讲也讲很差,我掌握信源编码(语音编码就是信源编码的一种),对信道编码只是了解)。具体地说就是由发送端对原始数据包进行 FEC 编码,生成冗余数据包(原始数据包和冗余数据包的数量比例是固定的)。接收端收到后,经过冗余数据包和原始数据包来恢复出丢失或者出错的数据包。比较成熟的FEC编解码算法有RS(Reeds-Solomon) 算法、Raptor 算法和 Tornado 算法,我当时用的就是RS算法。语音上利用FEC来作补偿主要是在发端对发出的RTP包(几个为一组,称为原始包)FEC编码生成冗余包发给收端,收端收到冗余包后结合原始包用FEC解码获得原始的RTP包从而把丢掉的RTP包补上。至于生成几个冗余包,这取决于接收方反馈过来的丢包率。例如原始包5个为一组,丢包率为30%,通过FEC编码后须要生成两个冗余包,把这7个包都发给对方。对方收到原始包和冗余包的个数和只要达到5个就能够经过FEC完美复原出5个原始包,这5个原始包中丢掉的就经过这种方式补偿出来了。下图展现了这个过程,发送端有5个原始RTP包,经过FEC编码生成2个冗余RTP包。因为生成两个冗余包, 算法最多可以恢复 2 个丢失的原始包。发送端把原始包和冗余包发出去,在传输过程当中假设第 2 号和4号原始包丢失了。接收端接收到原始包和冗余包后,经过原始包一、三、5和 冗余包1 、2就能够把已经丢失的第 2 号和4号原始数据包恢复出来。设计

                                    

原始RTP包有包头和payload,冗余包中还要加上一个FEC头(在RTP头和payload中间),FEC头结构以下:调试

                                                      

其中Group first Sequence number是指这一组原始包中第一个的sequence number,original count是指一组原始包的个数,redundant count是指生成的冗余包的个数,Redundant index是指第几个冗余包。冗余包有本身的payload type 和sequence number,要在SIP的SDP中告诉对方冗余包的payload type是多少,对方收到这个payload type的包后就作冗余包处理。code

 

FEC不依赖与语音包内的payload,对于丢失的包能精确的复原出来。可是它也有缺点,一是它要累积到指定数量的包才能精确的复原,这就增长了时延;二是它要产生冗余包发送给对方,增长了流量。htm

 

3,PLC

PLC也主要针对丢包因素。它本质上是一种信号处理方法,利用前面收到的一个或者几个包来近似的产生出当前丢的包。产生补偿包的技术有不少种,好比基音波形复制(G711 Appendix A PLC用的就是这种技术)、波形类似叠加技术(WSOLA)、基音同步叠加(PSOLA)技术等,这些都很专业,有兴趣能够找相关的文章看看。对codec而言,若是支持PLC功能,如G729,就不须要再在外部加PLC功能了,只须要对codec作相应的配置,让它的PLC功能使能。若是不支持PLC功能,如G711,就须要在外部实现PLC。

 

PLC对小的丢包率(< 15%)有比较好的效果,大的丢包率效果就很差了,尤为是连续丢包,第一个丢的包补偿效果还不错,越到后面丢的包效果越差。

 

把Jitter Buffer、FEC、PLC结合起来就能够获得以下的接收侧针对网络环境因素的提升音质方案:

                                                            

从网络收到的RTP包如是原始包不只要PUT进JB,还要PUT进FEC。如是冗余包则只PUT进FEC,在FEC中若是一组包中原始包的个数加上冗余包的个数达到指定值就开始作FEC解码获得丢失的原始包,并把那些丢失的原始包PUT进JB。在须要的时候把语音帧从JB中GET出解码并有可能作PLC。

 

4,重传

重传也主要针对丢包这种因素,把丢掉的包再从新传给对方,通常都是采用按需重传的方法。我在用重传的方法时是这样作的:接收方把收到的包排好序后放在buffer里,若是收到RTP包头中的sequence number能被5整除(即模5),就统计一下这个包前面未被播放的包有哪些没收到(即buffer里相应位置为空), 采用比特位的方式记录下来(当前能被5整除的包的前一个包用比特位0表示,丢包置1,不丢包置0,比特位共16位(short型),因此作多能够看到前16个包是否有丢包),而后组成一个控制包(控制包的payload有两方面信息:当前能被5整除的包的sequence number(short型)以及上面组成的16位的比特位)发给对方,让对方重发这些包。接收方收到这个控制包后就能解析出哪些包丢了,而后重传这些包。在控制包的payload里面也能够把每一个丢了的包的sequence number发给对方,这里用比特位主要是减少payload大小,省流量。

 

在实际使用中重传起的效果不大,主要是由于常常重传包来的太迟,已经错过了播放窗口而只能主动丢弃了。它是这些方法中效果最差的一个。

 

5,RFC2198

RFC2198是RTP Payload for Redundant Audio Data(用于冗余音频数据的RTP负载格式),用了它后在当前RTP包中不只能够承载当前语音的payload,还能够承载前几个包的payload,承载之前包的个数越多,在高丢包率的状况下效果越好,可是延时也就越大,同时消耗的流量也就越多。相比于FEC,它消耗的流量更多,由于FEC用一组RTP包编码生一个或多个成冗余包,而它一个RTP包就带一个或多个之前包的payload。在有线网络或者WIFI下能够用,在蜂窝网络下建议慎用。

 

以上就是我用过的提升音质的方法。还有其余方法,我没实践过,就不写了,写出来也是纸上谈兵。欢迎你们补充其余的方法。

相关文章
相关标签/搜索