zoukankan      html  css  js  c++  java
  • 音频的编解码及其优化方法和经验

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

    1,codec 规范

    1)ITU-T

    ITU-T制定的是有线语音的codec标准,即G系列,主要有G.711、G.722、G.726、G.728、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制定的主要是音乐的编解码规范,主要有MP3、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循环、用指针替代数组等,这里就不一一说了。

  • 相关阅读:
    Nginx负载均衡+代理+ssl+压力测试
    Nginx配置文件详解
    HDU ACM 1690 Bus System (SPFA)
    HDU ACM 1224 Free DIY Tour (SPFA)
    HDU ACM 1869 六度分离(Floyd)
    HDU ACM 2066 一个人的旅行
    HDU ACM 3790 最短路径问题
    HDU ACM 1879 继续畅通工程
    HDU ACM 1856 More is better(并查集)
    HDU ACM 1325 / POJ 1308 Is It A Tree?
  • 原文地址:https://www.cnblogs.com/talkaudiodev/p/7502193.html
Copyright © 2011-2022 走看看