数字广播调幅系统DRM(Digital Radio Mondiale)采用先进音频编码AAC(Advanced Audio Coding)作为其主要的信源编码方式[1],在与模拟调幅广播同样的带宽(9 kHz或10 kHz)下实现了调频的音质。DRM不仅解决了模拟调幅广播抗干扰能力差等缺点,而且在音频业务的基础上又增加了文本、图像、数据等附加业务,丰富了调幅广播的内容,大大提高了调幅广播的市场竞争力,成为调幅广播发展的必然趋势。
信源编码是DRM系统的关键技术,其压缩节目音频源信号,只需较少的传输带宽就可保证接收端的重建音频信号有较好的音质。DRM音频解码器的实现和优化决定了系统能否正确实现音频解码,并完成音频的实时播放,使用户得到良好音质。本文中AAC音频解码程序在DSP硬件平台上运行,由于硬件平台性能有限,要求音解码器不仅要能确保音频质量,还要不能占用DSP系统太多的资源。因此研究DRM音频解码器在高性能DSP平台上的实现及其优化具有非常重要的现实意义。
1 DRM音频解码流程
通用MPEG-4 AAC音频编解码器的原理和实现技术已经很成熟,不再详述。DRM系统的信源编码方案中所采用的频带恢复技术(SBR)提供了类似于MPEG-4 AAC中感知噪声整形(PNS)模块的功能,故DRM系统采用的音频编码方案不包括PNS模块,同时也去除了长期预测(LTP)、采样率可分级(SSR)等复杂的模块,降低了算法复杂度,对处理器的处理能力要求也相对较低,适合应用于嵌入式开发平台上。AAC的采样率有12 kHz和24 kHz两种,5个(12 kHz采样频率)或10个(24 kHz采样频率)音频帧组成一个持续时间固定为400 ms的音频超级帧。本文优化之前首先在PC机的VC++6.0环境下实现了DRM广播信号的正确解码和实时播放,测试信号为单声道、48 kHz采样,采用AAC音频编码的wav格式的DRM广播信号源,其中AAC的采样率为24 kHz,即一个音频超帧包含10个子帧。在VC++6.0环境下运行整个工程,经同步、解调和信道解码后获得DRM信号源中的AAC音频编码数据,在每次AAC子帧解码前将每子帧数据输出到一个文件。在DSP上测试音频解码程序时,可以直接提取AAC数据进行解码,解码流程如图 1所示。解码过程如下:
(1)对传来的AAC子帧数据进行比特流分解,根据DRM系统中音频子帧结构获取语法单元、霍夫曼码字等各部分的数据。
(2)进行霍夫曼解码,这部分用到了一系列的霍夫曼码书进行查询解码。频域数据和比例因子的获得都在这一步。该过程需要在将顺序打乱的码字重新组合在一起的同时,进行霍夫曼解码,并将解码之后的数据放置到正确的位置上,准备进行下一步的反量化。
(3)对解码后的频域数据进行反量化。
(4)将反量化的结果乘以(2)中生成的比例因子。
(5)滤波器组部分。这部分在解码时采用了逆改进离散余弦变换(IMDCT)[2],还包括一个加窗的过程和叠加的过程。功能模块的输出为信号的时域值。
2 TMS320C6416的DSP开发平台
TMS320C6416(简称C6416)[3]是一种高性能的32 bit定点DSP芯片。本文使用的C6416的工作频率达到600 MHz。其特点包括:具有8个功能单元的高级超长指令体系结构的CPU;所有指令有条件执行;支持8/16/32 bit可变长度数据访问;支持常用算术运算的饱和与归一化操作;两级高速缓存(Cache)存储器结构及丰富的片内外设,如增强型直接存储器访问EDMA控制器、多通道缓冲串口McBSP等。C6416开发板上除C6416 DSP芯片外,还带有外扩的512 K×8 bit的FLASH。
开发环境采用DSP集成开发环境CCS(Code Composer Studio),它集成了代码编辑、编译、工程管理、代码生成与调试、代码性能剖析、数据查看、绘制数据图像、DSP/BIOS参数设置,以及提供各种优化建议等工具模块。
3 音频解码程序的优化
本文优化之前先在PC机VC++6.0环境下实现了DRM广播信号的正确解码和实时播放,但移植到DSP平台之后不能实时播放。本文单独将音频解码部分的程序移植到DSP开发平台CCS3.1开发环境中,测试数据为前文中存储的AAC解码前每子帧的数据。优化前,不带有SBR解码的情况下,音频解码程序中一个音频超帧里每个子帧解码所花费的周期数,即运行效率如下:
子帧1:1 901 300 子帧2:3 667 994
子帧3:3 469 783 子帧4:3 397 752
子帧5:1 745 753 子帧6:3 416 357
子帧7:3 439 464 子帧8:3 331 484
子帧9:1 721 339 子帧10:1 764 605
(共计27 855 831周期)
在DSP上单独测试音频解码的效率,计算所花费的时钟周期数的语句如下:
st=cLOCk( ); aac_frame_decode(, , , ); end=clock(); printf("clock cost %dn",end - st);
其中aac_frame_decode( )是信道解码与音频解码的接口函数,该函数调用AAC解码程序,在此,其参数与返回值已省略。在CCS环境下,运行程序前点击Profile剖析菜单下Clock选项中的Enable,就打开了CCS的程序运行周期计数功能。两次clock函数调用返回值之差就是解码函数花费的周期数。表1是利用CCS3.1中Profile工具分别计算的程序优化前后一个超帧解码过程中每个函数所花费的周期数。
优化的本质是提高程序的运行效率,同时保持程序原有功能准确无误。本文针对本课题中的具体问题,提出以下对应的优化措施:
(1)去除原程序中用不到的函数。最初的音频解码程序是针对所有MPEG-4 AAC标准使用的,其中包含了很多功能模块,如MP4解码、PNS解码、LTP解码等。这些功能在DRM系统的音频编码标准AAC中是用不到的,所以应当将它们去除,否则其生成的代码不仅无用,而且会占用大量存储空间。在CCS3.1中点击Profile菜单下的Analysis Toolkit选项中的Code coverage and Exclusive Profiler,按照提示运行程序,可以得到一个Excel文件。该文件将代码覆盖程度、每个函数调用次数以及执行函数CPU所花费的周期数等展示出来,从而可以方便地找到每个文件中一直没有运行的函数,去除这些函数可节省大量存储空间且保证程序功能无误。
(2)循环体优化。原始的音频解码程序已经采用了一些常用的算法级别的优化,如IMDCT的快速算法[4]、霍夫曼解码的查表快速算法等,但仍没有达到最理想的速度。主要原因是for循环和定点化的问题。在AAC解码器中,循环体几乎占用了60%的资源,因此它的优化非常重要。要想充分发挥C6416 DSP处理器的8个功能单元并行执行指令的功能,需要让编译器尽可能多地生成由2条以上指令组成的超长指令。C/C++编译器可以对代码进行不同级别的优化。高级优化由专门的优化器完成,与目标DSP有关的低级优化由代码生成器完成。图2是编译器、优化器和代码生成器的执行图。