音频的编解码及其优化方法和经验

音频的编解码(codec)根据应用场景的不一样主要由几大技术组织制定,分别是ITU-T、3GPP、MPEG。固然也有一些公司或者公司的联合体等制定,如微软的WMA。他们不只制定了codec的规范,同时还提供软件实现的reference code,这样便于普及制定的codec的使用。本文先谈谈这些codec,而后讲怎么样根据reference code去优化codec(主要是减小CPU load)。web

 

1,codec 规范算法

1)ITU-T编程

ITU-T制定的是有线语音的codec标准,即G系列,主要有G.7十一、G.72二、G.72六、G.72八、G.729等。采样率窄带是8KHz,宽带是16KHz。码率从64kbps到8kbps不等。下表列出了具体的采样率和码率。数组

                                                          

2)3GPP网络

3GPP制定的是移动语音的codec标准,主要是AMR(adaptive multi-rate,自适应多码率)系列等,能根据网络情况自适应的调整码率。采样率窄带是8KHz,宽带是16KHz。近年来为了应对互联网的竞争(互联网公司提出了涵盖语音和音乐的OPUS codec),3GPP出台了EVS(enhanced voice service)音频编解码规范。EVS也涵盖了语音和音乐,能在二者之间灵活切换,支持多种采样率和码率。具体以下表。函数

                                       

3)MPEG工具

MPEG制定的主要是音乐的编解码规范,主要有MP三、AAC等。MP3你们都很熟悉,是近二十年来听音乐的最主要的格式,AAC是MP3的继承者,下一代的最主要的音乐编解码规范。音乐中采样率通常是44100HZ,也有的用48000HZ。码率在一个范围内,码率越大,音质越好。测试

 

4)公司或公司联合体优化

一些公司或者公司联合体根据须要制定音频的编解码规范,好比微软的WMA,Skype的SILK,GIPS(GIPS在2011年被谷歌收购,谷歌基于GIPS的音视频解决方案推出了webRTC并开源出来,影响巨大)的ILBC等。还有一个不得不提的就是OPUS,它是由非盈利的Xiph.org 基金会、Skype 和Mozilla 等共同主导开发的,全频段(8kHZ到48kHZ),支持语音和音乐(语音用SILK, 音乐用CELT),已被IETF接纳成为网络上的声音编解码标准(RFC6716)。指针

 

我用过的codec从语音到音乐分别有G.711/G.722/G.726/G.728/G.729/AMR-NB/AMR-WB/ILBC/OPUS/MP3/AAC/WMA/APE/Vorbis/ALAC/FLAC等。

 

2,codec的优化

这里讲的优化主要是指CPU load的优化,即优化后运行codec占用更少的CPU,在具体的硬件平台上运行的更流畅。优化到什么程度算结束这依赖需求而定。若是优化后给所在项目用,就要看项目给你多长时间优化以及项目能接受的优化后的CPU load,通常状况下项目用上优化后的codec后在最复杂的场景下能流畅运行又不影响其余功能就能够了,由于项目上要腾出人手作其余事情,毕竟项目进度和质量是最重要的。若是优化后做为库卖给客户用,就要尽可能优化到极致,由于这是用户选择用哪家公司库的重要指标,是卖点,这种状况下就会有更多的优化方法和技巧。我作过的优化都是给项目用,没有做为库给客户用,于是技巧不是特别多。

1)优化前的准备工做

a)    通读一下要优化的codec的代码,尽可能读懂,即便没懂也要搞清楚函数是干什么的,这有利于后面优化。

b)    准备好profiling工具,profiling工具就是测量运行某个函数花了多少clock。有现成的profiling工具最好,若是没有就根据具体OS和硬件平台(ARM/MIPS等)本身作工具。

c)    准备好test vector,即测试的音源,通常codec制定的官方会提供,一般是多个vector, 对应于不一样的场景。优化的原则是在减小CPU load的同时算法运算结果不被改变,因此在作优化时每优化一些就要用test vector跑一下,看结果有没有改变,若是改变了,就要退回到上一个版本。我作优化时天天至少保留一个版本,有时两个或者三个,就是为了出问题时好回溯,尽快查出哪一个地方的优化出了问题。

 

2)优化步骤与方法

a)    将编译器的优化选项从-o0改成-o3

b)    给代码中那些常常被调用的又短小的函数加上inline

一般状况下作完a,b后load会下来一大截,如同挤泡沫同样,会挤掉很大一部分。

c)     ITU-T或者3GPP的codec reference code中有好多基本运算(加减乘除)的函数,这些函数都写的特别严谨,同时调用的频次又很是高,于是加大了运算复杂度。这些函数中有些在保证正确的前提下能够简化(如一些防饱和就能够不要),这样处理后load会降下来一些。

d)    用profiling工具一步步排查看到底哪一个函数花的load多,明白这个函数是干什么的,而后具体问题具体分析,看怎么样来优化。

e)    有些函数就是一个小算法,reference code中写的比较复杂,调用频次又比较高。要去找有没有简单的实现能够替代,有的话替代了load就会降下来一些。好比codec中常常有求平方根的计算,reference code中一般写的比较复杂。咱们知道用牛顿迭代法也能够求平方根,就能够用牛顿迭代法去替换将load降下来。

f)     用汇编优化。若是在C级别能解决问题就不要用汇编了。各个处理器都有本身的汇编指令集,须要去学而且掌握其中的思想和技巧。一般是用的频次较高的又比较占load的函数用汇编去写,即用C和汇编混合编程。汇编优化花的时间会相对长一些。

固然还有一些小的技巧好比展开for循环、用指针替代数组等,这里就不一一说了。

相关文章
相关标签/搜索