深入探究音视频开源库 WebRTC 中 NetEQ 音频抗网络延时与抗丢包的实现机制 | 主赛道
音视频软件随着应用场景和使用环境的变化,对音频的质量要求越来越高,要实现高质量的音频效果,可以借鉴音视频领域一些成熟的解决方案。WebRTC 正是目前解决话音质量最先进的语音引擎之一,其中 NetEQ 网络均衡器模块很好地解决了音频数据在低带宽下出现的延迟、抖动与丢包问题。本文将详细分析 WebRTC 中 NetEQ 网络均衡器的实现原理、处理流程以及丢包补偿处理机制。
1、引言
由于 IP 网络主要用于数据传输业务,与传统的电话占用独立的逻辑或物理线路不同,因此没有服务质量(Qos)保证,存在包乱序到达、延迟、丢包和抖动等问题。对于丢包,业务上可以采用重传或者多倍发送机制,但音视频软件都是实时业务,对带宽、时延和抖动有严格的要求,所以必须有一定的 Qos 保证。
音视频软件中影响音频质量主要有两个因素:时延抖动和丢包处理。一般通过抖动缓冲区来消除网络传输所带来的不良影响,抖动缓冲区技术直接影响丢包处理。接收缓冲区可以用来消除时延抖动,但如果发生丢包,会卡顿或者填静音或者插值补偿,但在时延大、抖动大、丢包严重的网络中,效果都不理想。
如何借用 WebRTC 中的 NetEQ 网络均衡器的技术来提高软件的音频质量,首先需要分析分解 NetEQ 的原理和处理流程,其次是了解丢包补偿算法的原理和使用场景,然后就是将之有效到应用到软件产品的设计中去。
2、WebRTC 简介
在详细介绍 WebRTC 中的 NetEQ 网络均衡器之前,我们先来大概地了解以下 WebRTC。
WebRTC(Web Real-Time Communication)是一个由 Google 发起的实时音视频通讯 C++开源库,其提供了音视频采集、编码、网络传输,解码显示等一整套音视频解决方案,我们可以通过该开源库快速地构建出一个音视频通讯应用。
一个实时音视频应用软件一般都会包括这样几个环节:音视频采集、音视频编码(压缩)、前后处理(美颜、滤镜、回声消除、噪声抑制等)、网络传输、解码渲染(音视频播放)等。其中每一个细分环节,还有更细分的技术模块。
虽然其名为 WebRTC,但是实际上它不光支持 Web 之间的音视频通讯,还支持 Windows、Android 以及 iOS 等移动平台。WebRTC 底层是用 C/C++开发的,具有良好的跨平台性能。
l WebRTC 主要使用 C++开发实现,代码中大量使用了 C++11 及以上的新特性,在阅读源码之前需要大概地了解 C++的这些新特性。
l 学习 C++11 新特性很有必要,不仅在 C++开源代码中会频繁地使用到新特性,在跳槽时的笔试面试时也会经常被问到。
l 推荐大家仔细研读一下新版的、免费公开的《Google 开源项目风格指南(zh-google-styleguide) 》,它不仅仅是 Googe 的编码规范,它不仅告诉你编码时要怎么做,还告诉你为什么要这么做!对于学习 C++11 及以上的新特性也很有好处!这本项目风格指南,我们项目大组去年系统地研读过,收获很大,很有参考价值!
WebRTC 因为其较好的音视频效果及良好的网络适应性,目前已被广泛的应用到视频会议、实时音视频直播等领域中。在视频会议领域,腾讯会议、华为 WeLink、字节飞书、阿里钉钉、小鱼易连、厦门亿联等国产厂商均提供了基于 WebRTC 方案的视频会议。
大家熟知的音视频专业服务商声网(Agora),更是基于开源 WebRTC 库,提供了社交直播、教育、游戏电竞、IoT、AR/VR、金融、保险、医疗、企业协作等多个行业的音视频互动解决方案。使用声网服务的企业包括小米、陌陌、斗鱼、哔哩哔哩、新东方、小红书、HTC VIVE 、The Meet Group、Bunch、Yalla 等遍布全球的巨头、独角兽及创业企业。除了头部公司声网之外,也陆续有多家公司基于开源的 WebRTC,开发出了多个音视频应用,提供了多个领域的音视频通信解决方案。
3、什么是 NetEQ?
NetEQ 本质上就是一个音频的 JitterBuffer(抖动缓冲器),全称是 Network Equalizer(网络均衡器)。
GIPS 语音引擎的两大核心技术之一就是包含丢包隐藏算法的高级自适应抖动缓冲器技术,称作 NetEQ。2010 年谷歌公司以 6820 万美元收购 Global IP Solutions 公司而获得的这项技术,另一个核心技术就是 3A 算法。随后,谷歌在 2011 年将其集成到 WebRTC 中对外开源发布。
NetEQ 集成了自适应抖动控制算法和语音丢包隐藏算法,并且与解码器进行集成,所以 NetEQ 能够在较高的丢包环境下始终能够保持较好的语音质量。
4、NetEQ 技术详解
4.1、NetEQ 概述
NetEQ 处理中包括了自适应抖动控制算法和语音丢包补偿算法。自适应抖动算法能够快速适应不断变化的网络环境,而语音丢包补偿算法能够保证一定的音质和清晰度且缓冲延迟最小,另外对 NetEQ 算法的模拟测试有助于评估音质效果和如何与现有软件设计的有机结合。
NetEQ 处理中包括了自适应抖动控制算法和语音丢包补偿算法。自适应抖动算法能够快速适应不断变化的网络环境,而语音丢包补偿算法能够保证一定的音质和清晰度且缓冲延迟最小,另外对 NetEQ 算法的模拟测试有助于评估音质效果和如何与现有软件设计的有机结合。
NetEQ 的模块概要图如下所示:
从上图可以看出,NetEQ 分为 4 部分:自适应缓冲(Adaptive packet buffer)、语音解码器(Speech decoder)、抖动控制和丢包补偿(Jitter control and error concealment)和播放(Play out)。其中抖动控制和丢包补偿模块是 NetEQ 的核心算法,既控制着自适应缓冲,又控制着解码器和丢包补偿算法,并且将最终的计算结果交给声卡去播放。
首先,NetEQ 是目前最为完善的抖动消除技术。与固定抖动缓冲和传统的自适应抖动缓冲相比,NetEQ 能够快速适应不断变化的网络环境,因此保证了更小的延迟和更少的丢包。NetEQ 自适应抖动算法性能比较如下图所示:
其次,抖动控制和和丢包补偿模块由三大操作所组成,即 Expansion、Normal 和 Accelerate:
Expansion:扩展操作,即对语音时长的拉伸,其中包括 expand 和 preemptive_expand 两种模式。前者为 NetEQ 的丢包补偿处理,其作用是等待延迟包并补偿丢包;后者为优先扩展,即在原有数据的基础上拉伸语音时长,其作用是实现减速播放。
Normal:正常播放操作,即网络环境正常且相对平稳时的操作。
Accelerate:加速操作,即实现快速播放。
综上所述,本文主要讨论 NetEQ 的抖动消除和丢包补偿技术,并结合模拟测试和产品设计分析来进一步提高视频会议产品的通话音质。NetEQ 性能列表如下所示:
4.2、抖动消除技术
有两种抖动的定义:
l 抖动定义 1:指由于各种延迟的变化导致网络中的数据分组到达速率的变化。具体地说,可将抖动定义为数据流在发送端发送间隔与接收端接收间隔之差,适用于可变码率场景。
l 抖动定义 2:接收端某个数据包到达间隔与平均数据包达到间隔之差定义为该数据包的延时抖动,使用于恒定码率场景。
抖动是一个零均值的随机序列,是由排队 IP 包的延迟时间差构成的。数据包堆积时意味着数据包提前到达,虽然保证了语音的完整性,但是容易造成接收端缓存溢出并且会增大端到端延迟。数据包超时时意味着数据包经过网络传输后,一段时间后仍未到达接收端,说明数据包可能会延迟到达或者丢包。由于溢出和超时均可导致丢包,会增加端到端的丢包概率。因此,必须对抖动进行有效的控制,以减少由此引起的丢包。
抖动通常采用抖动缓冲技术来消除,即在接收方建立一个缓冲区,语音包到达接收端时首先进入缓冲区暂存,随后系统再以平稳的速率将语音包从缓冲区提取出来,经解压后从音频端口播放。抖动消除的理想状态为:每个数据包在网络传输中的延迟与缓冲区中的所有缓冲数据的延迟应该相等,而缓冲区的大小应该与每个数据包提前到达的抖动加上缓冲数据的延迟之和相等。
抖动缓冲控制算法包括静态抖动缓冲和自适应缓冲抖动控制算法两类:
l 静态抖动控制算法:缓冲区的延时和大小在语音通话建立后一直到通话结束,均为固定值,对于超时和抖动超出缓冲区大小的数据将会被丢弃。该算法模型简单,易于实现;但网络延时大、抖动大时,丢包率较高,而网络延时和抖动小时,语音延迟较大,不能根据网络状况动态改变缓冲区的延时和大小,而且初始值限定了适用的网络状况。
l 自适应抖动控制算法:缓冲区的延时和大小随着实际网络的抖动情况而变化。接收端将当前收到的数据包的延迟与算法中保存的延迟信息相比较,得到当前网络的最大抖动,从而选择恰当的缓冲区延时和大小。该算法的优点是:网络抖动大时丢包率小,网络抖动小时延时小;缺点是算法多样且相对复杂。
考虑到当前网络的复杂多变,一般采用自适应抖动算法,NetEQ 的抖动消除也属于这类算法。
4.3、丢包补偿技术
丢包补偿又称为丢包隐藏,即 Packet Loss Concealment,简称为 PLC,可以分为两类:基于发送端补偿和基于接收端补偿。丢包补偿技术构成如下:
基于发送端的补偿也称为丢包恢复,即 Packet Loss Recovery。一般来说,基于发送端的补偿要比基于接收端的补偿效果要好,但会增加网络带宽和时延。
FEC(Forward Error Correction,前向纠错技术)是目前最看好的一种改善 VoIP 语音质量的冗余编码技术,目的在于提高语音数据传输时的可靠性。为此 FEC 不仅要传输原始数据,同时还要根据相关性,传输一些冗余数据,以便使解码端根据数据之间的相关性重构丢失的数据包。在 VoIP 中最简单是奇偶校验码。这种方法是每个 n-1 个数据包就传输一个包含前面 n 个数据包的异或操作的校验码,当网络每 n 个数据包只丢失一个包时,可从别的 n-1 个数据包重构丢失的数据包。基于奇偶校验包的 FEC 如下所示:
当发生连续丢包时,FEC 等各种补偿技术的效果都不理想。为了抵抗大段的突发连续语音丢失,可采用交织(interleaving)技术。交织技术不是真正的丢包恢复技术,因为它不能恢复已经丢失的数据包,但是这种技术能够减少丢包带来的损失。交织技术是通过把原始数据分成若干个比 IP 包小的单元,在发送前,重新排序这些单元的顺序,使得每个 IP 包中的数据来自不同的语音帧,当发生丢帧时,只是每一帧的一部分数据丢失,不会出现一帧数据全部丢失现象,在接收端这些单元再重新排序。交织技术利用了人脑能够利用听觉感知自动恢复丢失的一部分数据的功能。当每帧数据只丢失少量数据时,对人耳听觉的影响较小,从而提高音质。由于没有输出额外的信息,所以不会增加带宽,但是由于需要在接收端重新排序,所以会增加时延,达到一定程度也会让人无法忍受。GSM 系统就采用了交织技术。
交织技术如下:
低比特率冗余编码(Low-rate Redundant Coding)是一种冗余技术,每个数据包除了包含自身的数据外,还包含前一帧数据经过压缩后的复制,该复制质量低,占用比特数少。当接收端丢包后,可从后面的数据包利用这个复制快速重构丢失包。不像 FEC 增加的比特数与前后帧具有相关性,它只是简单的在后续包中一份复制,所以也会增加带宽和时延,但是在网络拥塞时与 FEC 一样,对于连续丢包不适用,会导致丢包更严重。G.729A 就采用了冗余编码技术。冗余编码恢复丢包示意图如下:
接收端丢包补偿技术的基本原理是产生一个与丢失的语音包相似的替代语音,这种技术的可行性是基于语音的短时相似性和人耳的掩蔽效应,可以处理较小的丢包率(<15%)和较小的语音包(4~40ms)。接收端的丢包补偿无法替代发送端的补偿,因为不能精确恢复丢失数据。因此网络丢包率较大的时候需要依赖发送端补偿技术,但是丢包率过大的时候只能优化网络。
基于插入的方法是指在丢包处插入一个简单的波形隐藏丢包的方法,这个波形通常与丢失的波形没有相关性,包括静音、白噪声和复制等。
静音替代使用范围非常有限,在丢包率低于 2%且语音帧小于 4ms 时效果较好。白噪声或者舒适噪声利用了人脑下意识用正确语音修复丢失波形的能力,比静音效果好。
复制是 GSM 系统采用的方法,在发生连续丢包时,补偿的波形用上一帧数据通过逐渐衰减来生成,由于没有考虑语音的前后帧相关性,效果也不是很理想。插值技术是指在丢包时用相似的波形来补偿,这种技术相对复杂,利用丢包前后的数据对丢失数据进行估计,然后用最相似的波形替代丢失波形,所以效果比插入技术更好。
帧间插值技术是一种传统的误码隐藏技术。对于变换编码或线性预测编码的语音编码器,解码器可以基于语音信号的短时平稳性和相邻帧间参数的相关性,根据上一帧的参数进行插值来补偿。G.723.1 就采用了参数插值技术,对 LSP 系数和激励信号分别进行帧间插值来补偿丢失帧;G.729 也是利用上一帧的参数进行插值来隐藏错误帧的,利用上一帧的线性预测系数(LPC)和增益衰减系数来补偿丢失帧。
基于重构的补偿技术是通过丢包前后的解码信息来重构产生一个补偿包,计算量最大,效果最好。在接收端完成,不需要发送端的参与和额外的比特流,所以能够满足实时传输的要求,在现代网络传输中更具有有效性和实用性。
基于基音检测的波形替代技术是通过计算基音周期,然后根据基音周期对该帧进行清浊音判断,如果是清音,则用丢包前最近的波形替代,否则用丢包之前长度为基音周期的一段合适的波形来替代,再结合短时能量和过零率来恢复丢失语音,效果由于插入技术,但相对复杂。
数字语音信号处理的基本单位是基音,基音指物体振动时所发出的频率最低的音,其余为泛音。也就是发声体振动时,携带语音中的大部分能量,这种声带振动的频率称为基频,相应的周期为基音周期。基音周期的估计称为基音检测,其目的是得出和声带振动频率完全一致的基音周期长度。
采用波形编码的 G.711 编码器中没有使用丢包补偿技术,但为了提高语音质量,G.711 协议附录中增加了基于基音检测的波形替代技术来补偿丢帧,它利用解码的上一帧数据来估计当前语音信号的基音周期,将最近的一个基音周期和它之前的 1/4 基音周期的数据用于补偿丢失数据。其中前 1/4 基音周期的数据用于与丢帧前的语音信号进行重叠相加,保证原始信号和补偿信号之间平滑过渡。若下一帧数据没有丢失,为了保证平滑过渡,则再拓展 1/4 基音周期数据与正常解码数据进行重叠相加。若下一帧仍然丢失,则多提取一个基音周期的数据用于补偿,最多可提取 3 个基音周期。丢帧越多,补偿语音与实际语音相差越大。因此,除第一帧外,连续丢帧补偿时,要以 20%的速度逐帧衰减。由于语音信号是准平稳的时间序列,尤其是浊音信号,具有一定的周期性,因此采用丢帧前的语音数据重构丢帧数据效果更好。
时域修正技术采用缺口两侧的波形向切口方向延展来填充缺口,在缺口的任一侧找到基音周期的交叠矢量,偏移它们来覆盖缺口,交叠部分求均值。这种方式避免了缺口边界相位不连续的现象,在丢包结合处听不到爆破音,主观效果优于基音检测的波形替代。
WebRTC 中 NetEQ 的丢包补偿技术是采用融合了 iLBC 算法的丢包补偿技术。iLBC 全称为 Internet Low Bit rate Codec,是 GIPS 开发的一种专为包交换网络通信设计的编解码算法,采样率为 8khz,有 20ms 和 30ms 两种编码时长,码率分别为 15.2kbps 和 13.3kbps,在丢包时具有强大健壮性。iLBC 的丢包补偿只在解码端进行处理,采用基于模型恢复法产生补偿包,其具体步骤为:
l 重建线性预测系数(LPC) ,即采用最后一帧的 LPC 系统来重建。因为无论空间上还是时间上,最后一帧都与当前丢失帧的 LPC 具有最相关性,但是这种简单的复制在处理连续丢帧时,显然会引入更大的失真。
l 重建残差信号。残差信号通常可以分为两部分:准周期成分和类噪声成分。其中准周期成分可以根据上一帧的基音周期来近似得到,而类噪声成分则可以通过产生随机噪声得到,二者的能量比例也可以借鉴上一帧的比例关系。因此,首先要对上一帧进行基音检测,然后以基音同步的方式重建丢失帧的话音信号,接着利用相关性得到类噪声增益,最后进行混合以重建整个残差信号。
l 在连续丢帧的情况下,PLC 所补偿的各个语音帧具有相同的频谱特性(相同的 LPC)和基音频率,为了减少各个补偿帧之间的相关性,会将能量进行逐帧递减。
OPUS 的丢包补偿分为两种模式:CELT 和 SILK。OPUS 编解码器是由互联网工程任务组(IETF)设计用于互联网的交互式语音和音频输出的,融合了 Skype 的 SILK(与 Skype 现有 SILK 算法不兼容)和 Xiph.Org 的 CELT 技术。其中 CELT 模式的丢包补偿与 iLBC 的类似。
SILK 编码器模块框架如下所示:
4.4、NetEQ 概要设计
NetEQ 模块主要包括 MCU 和 DSP 两大处理单元,其中 MCU(Micro Control Unit)模块是抖动缓冲区的控制单元,由于抖动缓冲区的作用是暂存接收数据,所以 MCU 主要作用是负责数据包的插入和控制数据包的输出。抖动消除技术包含在 MCU 控制模块中。
NetEQ 概要设计如下:
抖动缓冲区中设置 240 个插槽,每个从网络中传输过来的原始数据包都会在抖动缓冲区中选择一个合适的插槽进行放置,主要存储数据包的时间戳、序列号、数据类型等信息,而真正的数据载体存放于一个内存缓冲区中。当有新的数据包到达后,才在内存缓冲区中分配空间存放其载体,从而实现抖动消除。
DSP 模块主要负责对从 MCU 中读取的数据包进行算法处理,包括解码、信号处理、数据输出等,丢包补偿技术包含在 DSP 模块中。
语音缓冲区中存储的是经过解码及信号处理的待播放数据,可以存储 565 个样本,curPosition 表示待播放数据的起点,sampleLefe 为待播放样本数。
共享内存、解码缓冲区和算法缓冲区都是临时数据缓冲区,其中共享内存用于暂存从抖动缓冲区中读取的待解码数据,并且存储样本丢失数量及 MCU 控制命令;解码缓冲区暂存解码后的数据;NetEQ 算法缓冲区暂存 DSP 算法处理后的数据,用于补充语音缓冲区的新数据;播放缓冲区是播放驱动的数据缓冲区,用于从语音缓冲区中读取数据并播放。
4.5、NetEQ 的命令机制
NetEQ 的处理流程由各种命令来进行控制,根据接收数据包的状况,来决定采用什么命令:
l 上一帧和当前帧都正常接收:这时数据包进入正常的处理流程,并将解码后的数据按照是否有抖动消除的需要来选择 Normal、Accelerate 或者 Preemptive Expand。
l 仅当前帧丢包或超时:如果当前帧丢包或超时,那么进入 PLC 处理重建 LPC 和残差信号,即 Expand 操作。NetEQ 最多会为超时、丢包帧等待 100ms,超过该时间则直接提取播放下一帧。
l 连续多帧超时或丢包:如果连续多帧丢包,那么就需要多次进行 PLC 操作,这时越靠后的数据越难以准确重建补偿包,所以对连续丢包的补偿能量增益采取逐帧减少的方式,以避免引入更大的失真。
l 上一帧丢失,当前帧正常:上一帧丢失,那么播放的上一帧数据是 PLC 补偿的。为了使经过 PLC 补偿的帧与正常解码的帧保持语音连续,需要根据前后帧的相关性进行平滑,这时选择 Normal 或者 Merge。
此外,当 NetEQ 第一次接收到数据包或者整个 NetEQ 重置之后,会重置解码器。另一方面,当 NetEQ 接收超过延迟超过 3.75s 的数据包时,不会将其视为超时包丢弃,而是将其插入抖动缓冲区,并重置缓冲区状态。
4.6、NetEQ 的播放机制
WebRTC 的语音引擎运行时启动两个线程:一个线程接收数据包并插入抖动缓冲区;另一个线程每隔 10ms 从语音缓冲区中读取 10ms 数据进行播放。
NetEQ 会结合语音缓冲区中的数据存量和抖动缓冲区中的数据存量来决定是否从抖动缓冲区中读取数据:
l 控制命令为 Normal、Expand、解码器重置或者 packet buffer 状态重置,且 SampleLeft 大于等于 10ms 时,则不从抖动缓冲区读取数据,DSP 进行 Normal 操作。
l 控制命令为 Normal、解码器重置或者 packet buffer 状态重置,且 SampleLeft 小于 10ms 时,从抖动缓冲区读取数据后,DSP 进行 Normal 操作。
l 控制命令为 Expand 且 SampleLeft 小于 10ms 时,则不从抖动缓冲区读取数据,DSP 进行 Expand 操作。
l 控制命令为 Merge 时,从抖动缓冲区读取数据后,DSP 进行 Merge 操作。
l 控制命令为 Accelerate 时,当 SampleLeft 大于等于 30ms,不从抖动缓冲区读取数据,DSP 进行 Accelerate 操作;当 SampleLeft 大于等于 10ms 且小于 30ms 时,不同抖动缓冲区读取数据,DSP 进行 Normal 操作;当 SampleLeft 小于 10ms 时,从抖动缓冲区读取数据后,DSP 进行 Accelerate 操作。
l 控制命令为 Preemptive Expand 时,当 SampleLeft 大于等于 10ms 时,不从抖动缓冲区读取数据,DSP 进行 Preemptive Expand 操作;当 SampleLeft 小于 10ms 时,从抖动缓冲读取数据后,DSP 进行 Preemptive Expand 操作。
上面的命令处理中,由于考虑到防止在语音缓冲区中增加额外的通话延迟,因此 SampleLeft 大于等于 10ms 时不需要从抖动缓冲区读取数据,只有在其小于等于 10ms 时才会读取数据,保持语音缓冲区中适量的数据;当控制命令为 Merge 时,任何时候都需要从抖动缓冲区读取数据,这是为了保证前后数据的连贯性;当控制命令为 Expand 时,丢包补偿会产生一定量的数据,因此任何都是都不需要从抖动缓冲区读取数据,但 SampleLeft 大于等于 10ms 时也不进行 Expand 操作,因为语音缓冲区中有足够的数据用于播放,只进行 Normal 操作。
4.7、MCU 的控制机制
NetEQ 的抖动算法中用 Blo(optBufferLevel)基于遗忘因子算法来计算预测网络的抖动,用 BLc(bufferLevelFit)基于自适应平均算法来计算预测抖动缓冲区的抖动。MCU 的控制机制根据已播放数据的时间戳(playedOutTS,记为 TSplay)、待读取数据包的时间戳(availableTS,记为 TSavail)、Blo 和 Blc 的关系来选择操作命令。TSplay 和 TSavail 的关系来判断网络数据是否正常。
Blo 和 Blc 的比较如下所示:
上图中 Blo 和 Blc 的关系来判断选择 Accelerate、Preemptive Expand、Expand 和 Merge 操作。
简而言之,NetEQ 中抖动消除主要由网络延迟和抖动缓冲区延迟的关系发送不同的命令通知 DSP 执行对应的操作来完成。
4.8、DSP 的算法处理
DSP 模块是 NetEQ 中的语音信号处理模块,其操作命令受 MCU 控制。WebRTC 中采用自相关函数法,由于语音信号是非平稳信号,所以对信号的处理都使用短时自相关函数。短时自相关函数法的基因检测主要是利用短时自相关函数在信号周期处最大的特点,通过比较原始信号和它位移后的信号之间的相似性来确定基音周期,如果位移距离等于基音周期,那么两个信号便具有最大相似性。经典的短时自相关函数进行基音检测时,使用一个窗函数,窗不动,语音信号移动。窗长度至少要大于基音周期的两倍,窗长度越长,得出的基音周期越准确,但计算量也会相应的增加。
WebRTC 中加速和减速操作基于 WSOLA 算法来实现语音时长的调整,就是要在不改变语音的音调并保证良好音质的前提下,使语音在时间轴上被压缩或者拉伸,即通常所说的变速不变调。语音时长调整算法分为时域和频率两类,时域以重叠区波形相似性(WSOLA)算法为代表,对于语音信号来说可以获得较高的语音质量,且相对频率算法运算量较小。而对于频率变化剧烈的音频,如音乐信号,时域算法则通常难以获得较高的语音质量,此时通常采用计算量较大的频率算法,如子带 WSOLA 算法。由于 GIPS 针对 VoIP 业务设计的 NetEQ,所以数据以语音信号为主,频域变化较小,因此采用时域算法 WSOLA。
DSP 处理是实现抖动消除、丢包补偿并使得播放的语音实现低时延和较好音质的关键,下面分别介绍 DSP 的各个操作:
1)加速:将一个语音包的样本数减少,减少的数据是根据语音样本的相关性所得到的基音周期。将两个样本周期的语音数据经过平滑处理,转变为一个基音周期的数据。加速操作以 30ms 为一帧,只有相关性非常强(>0.9)或者为信号能量很低时才会加速,算法与减速处理类似。如下图所示:
2)减速:将一个语音包的样本数增加,增加的数据是根据语音样本的相关性所得到的基音周期。将两个样本周期的语音数据经过平滑处理,插入两个样本周期之间。减速操作以 30ms 为一帧,且待播放数据至少有 0.625ms,否则重复播放上一帧;当解码后数据缓存不足 30ms 时,直接拷贝至播放缓存。基音周期的范围为 2.5ms 至 15ms,所以最多延长 15ms。如下图所示:
3)插帧:采用 iLBC 的丢包补偿算法,即重建线性预测系统、重建残差信号和将补偿帧能量逐帧递减。插帧操作时待播放缓存要小于播放读取时长(10ms)。如下图所示:
4)融合:上一帧丢包之后会进行插帧操作,当新的数据解码后,为了提高语音数据的连贯,对新的解码数据和插帧数据进行平滑处理,能量渐强。融合操作生成的数据中间数据较大,需要预留最大空间。如下图所示:
5)正常:这时新的解码数据正常输出播放,但如果上一帧数据是插帧数据,需要先插帧再平滑。
4.9、DSP 算法的模拟测试
针对以上 DSP 算法操作,本文分别对间断的语音信号(Test1)、连续的语音信号(Test2)和音乐信号(Test3)在不同丢包率下进行了模拟测试,并采用 ITU-T P563 客观测量标准进行 MOS 值估计,LostData 为丢包时填补静音,Expand 为丢包时插帧,Expand+Merge 为丢包时先插帧再融合。
间断话音信号对丢包率的变化不是很敏感,因为丢包的时候没有丢失太多语音时 MOS 值就会比较好,丢包时产生的爆破音在丢包补偿之后都有明显改善,主观感受良好。
连续话音信号跟随丢包率呈现出逐渐下降的趋势,丢包补偿的效果与 Test1 相近,爆破音明显改善,主观感受良好。
音乐信号选取的是久石让的《天空之城》,整个频谱变化较大,丢包率较小时补偿效果不错,丢包率越大补偿的主观效果越差。
加速、减速和正常操作就不一一对比了,其中加速和减速操作在不丢包时对消除抖动的音质效果非常好,保持语音信号的完整性。
上图中动态模拟的初始值为 37 个样本,即初始时待播放样本为 37 个。Expand 之后 Merge 得到的 MOS 值下降,有两个可能的原因:1、Expand 前待播放字节数较少,导致插帧数据音质不高;2、Merge 前 Expand 补偿的数据较多影响 Merge 后的音质,理想情况应该是 Expand 和 Merge 一一对应。
上图中固定模拟的固定值为 500 个样本,即待播放样本保持为 500 个。这时 Expand 得到的 MOS 值有较大提升,之后每次都进行 Merge 操作,帮助提高 MOS 值。
上图中动态模拟的初始值为 0,即初始时待播放样本为 0 个。这时 Expand 之前待播放样本减少导致 Expand 插帧数据的 MOS 值降低,之后虽然不是 Expand 和 Merge 一一对应,但是每次 Merge 之前待播放数据较少,所以需要平滑的数据就会更少,帮助提高 MOS 值。
P563 标准的几个重要参数为:信噪比(SNR)、静音间隔和平均基音周期等,没有参考相位变化,但是相位变化对听觉的主观影响很大,比如在插帧数据之后相位不连续的波形有可能会产生爆音,这时会影响音质,所以插帧与融合虽然采用 P563 的 MOS 值估计有时相差无几,但是融合的主观感受要明显好于插帧。
5、参考文档
《GIPS NetEQ》,Global IP Solutions
《WebRTC 语音引擎中 NetEQ 技术的研究》,吴江锐
《WebRTC 语音引擎中分组缓存技术研究》,肖洪亮
《VoIP 丢包处理技术的研究发展》,李如玮,鲍长春
《ITU-T P.563 Single-ended method for objective speech quality assessment in narrow-band telephony application》,国际电联 ITU(International Telecommunication Union)
评论