IC技术讲座是本刊2005年全新推出的技术类栏目。为了让工程师在设计开发中完善和拓展基础理论与系统知识,丰富应用经验,《世界电子元器件》和m.188betcom手机版
联合清华大学等知名院校共同创办了这个栏目,特约知名学者、教授以及著名半导体公司的应用工程师撰写,以系列讲座的方式对热点IC技术进行全面而系统的介绍,涵盖最新技术要点。最先开设的讲座将围绕三大课题:DSP、FPGA和嵌入式系统,每个课题都将连载6期。
ITU-T G.729 8kb/s CS—ACELP简介
国际电信联盟(ITU-T)于1995年11月正式通过了G.729。 ITU-T建议G.729也被称作“共轭结构代数码本激励线性预测编码方案”(CS-ACELP),它是当前较新的一种语音压缩标准。96年ITU-T又制定了G.729的简化方案G.729A,主要降低了计算的复杂度以便于实时实现,因此目前使用的都是G.729A。
G.729是由美国、法国、日本和加拿大的几家著名国际电信实体联合开发的。它需要符合一些严格的要求,比如在良好的信道条件下要达到长话质量,在有随机比特误码、发生帧丢失和多次转接等情况下要有很好的稳健性等。这种语音压缩算法可以应用在很广泛的领域中,包括IP电话、无线通信、数字卫星系统和数字专用线路。
G.729算法采用“共轭结构代数码本激励线性预测编码方案”(CS-ACELP)算法。这种算法综合了波形编码和参数编码的优点,以自适应预测编码技术为基础,采用了矢量量化、合成分析和感觉加权等技术。
图1 G.729A编码器原理图(略)
编码器(图1)对10ms长的语音帧进行处理,每帧分为两个子帧。输入语音首先要在预处理模块中经过高通滤波和幅度压缩变换,以去除低频干扰及防止在后面运算中出现溢出。每帧进行一次线性预测(LP)分析,并将LPC参数转换到线谱,对(LSP)形式进行预测式二阶段矢量量化(VQ)。然后使用分析合成法,按照合成信号和原始信号间感觉加权失真最小的准则来提取激励参数。激励参数(包括固定码本和自适应码本参数)要每子帧(5ms)计算一次。每帧要利用感觉加权语音进行一次开环整数基值基音延时估计,然后进行闭环的分数值基音分析,确定自适应码本的延时和增益,下面再进行固定码本的搜索。固定码本是使用交织单脉冲排列设计的代数码本。在搜索时使用迭代式深度优先树型搜索算法。这种算法的运算量比较小,并且具有固定的运算复杂度,比较有利于使用硬件实现。自适应码本和固定码本的增益使用预测式二阶段共轭结构码本进行矢量量化。
图2 G.729A解码器原理图(略)
图2给出了解码算法的框图。首先要从接收到的码流中提取LSP系数和两个分数基音延时、两个固定码本矢量以及两套自适应码本和固定码本增益等参数。然后,对LSP参数进行插值,并转换到线性预测滤波器系数的形式。接下来,将自适应码本和固定码本矢量分别乘以各自的增益再相加,得到激励信号。激励信号通过LPC综合滤波器后,就得到了合成语音信号。最后还要对合成语音信号进行后处理,以提高合成语音的质量。
程序的编制及调试
程序编制
DSP开发工具一般都提供C编译器,可以直接将写好的C语言程序转换成DSP汇编语言程序,但效率非常低。G.729A算法C语言程序用编译器转成汇编语言程序运行所需要的运算量超过2000个MIPS(每秒百万条指令),根本无法实时运行,因此必须手工编写汇编程序。
由于编解码的程序规模很大,又是在DSP的汇编语言级别上实现,因此保持原定点C语言程序所具有的模块化、结构化的特点对于汇编程序的编写、检查、调试和阅读都是非常有利的。所以在编程时尽量保持DSP程序与C语言程序在流程上的一致,具体是使DSP程序与C程序之间保持函数一一对应关系,保持循环、分支等结构的一一对应。只有为了避免使DSP程序产生过大的不必要开销时,才对结构进行一定的修改,但仍然要保持程序的模块化和结构化。由于C程序的结构清晰,所以要想作到这一点并不困难,只要为C程序中的if、else、for、while等结构设计出相应的结构化的DSP汇编程序结构,在编程时按照这种固定对应关系对C语言程序进行转换就可以了。
程序的调试
程序的调试也是一项很费时的工作。ITU-T针对G.729A提供了8组测试码,只要通过了这8组测试码,就可以认为程序基本正确了,这8组测试码分别针对程序中的不同位置而设定如下:
algthm - 算法中的条件部分
erasure - 帧删除恢复
fixed -固定码本搜索
lsp -LSP系数量化
overflow -合成器中的溢出检查
parity -奇偶校验
pitch -基音周期搜索
speech -一般语音文件
tame -训练过程
采用的调试步骤是首先针对测试码中最短的algthm.in的第一帧边编程边调试,也就是每编好一个函数,就将algthm.in的第一帧通过该函数后的输出数据和C语言的相应输出数据相比较,并针对出现的错误修改函数内容,由于对刚编完的函数进行调试,对函数结构和指令记忆会比较清晰。这样,当编码器完成后,algthm.in的第一帧也就基本通过了。然后再继续调试第二帧,当第二帧也通过后,程序中所剩的错误也就不多了。等到通过了第10帧,就可以开始大规模地进行仿真了。对于解码部分,由于程序比较短,就采用了先把全部程序编完,再进行调试的方法。
程序的优化
编码模块与解码模块是按照G.729编解码器的C语言定点源程序改写的,虽然定点的C语言程序已经为DSP的实现作了一定的优化,但为在一个DSP芯片上实现尽量多路的编解码,必须根据C54x芯片的功能和特点对程序进行一定的优化。在编写DSP程序时,要想提高运行效率,就要充分利用C54x
DSP芯片具有的各种硬件资源,并适当地对程序结构进行一定调整,采用的主要方法有以下几种:
充分利用各种延时
C54x芯片指令中的跳转、循环、调用子函数等指令都有延时的格式如B[D],BC[D],RPT[D],RPTB[D],CALL[D],CC[D],RET[D],RC[D]等,这些指令允许利用他们执行过程中的等待周期预先执行一两条其他指令,适当调整程序结构就可以充分利用这些等待周期,从而提高程序执行速度。
充分利用块指令循环功能
C54x DSP芯片还提供了块指令循环功能,此功能可以大大地提高执行循环的速度,但是此功能只能在一重循环中使用,因为它只提供了一个循环记数寄存器BRC,所以在遇到多重循环时就要尽量把这个功能用在最里层的循环中,最里层循环是执行次数最多的循环。
利用DSP芯片提供的各种寄存器
适当地利用各种寄存器也能显著地提高程序的执行速度。特别是当一个函数在程序中被频繁地调用,它的赋值可以减少执行时钟周期。
利用指令中的移位功能
C54x DSP在做赋值和数值运算之前可以自动对操作数进行一定位数的移位,这样就可以将移位运算和其它运算结合到一条指令中。另外,利用这种移位功能可以代替一些乘数为2的幂乘法,虽然有这样的限制,但是在许多滤波器和函数中确实有这样的运算,带立即数的乘法需要两个指令周期,而移位只需一个指令周期,并且如果条件允许还可以将其结合到其它指令中,从而大大节省运算量。
利用DELAY指令进行赋值操作
另外,在程序中有大量的赋值操作,即将一个内存变量的值赋给另一个内存变量。特别是在搜索码本的时候有大量的赋值操作,并且赋值的两个变量是固定的。一般的方法是将第一个变量读入到累加器或寄存器TREG中,再将累加器的值赋到第二个变量中。此过程要用两条单周期指令。C54x提供了一个移动缓冲区的指令DELAY,可以在一个指令周期内将内存单元的值复制到它后面的相邻的内存单元内。虽然DELAY指令一般是用来移动缓冲区的,但只要在给变量分配内存时将需要赋值的变量相邻分配,就可以在一个指令周期内完成赋值操作。
利用寄存器代替某些临时变量
程序中往往有很多的临时变量,有的临时变量应用到自始至终,但是有的临时变量只是在程序中的某段区域使用,只是暂时做数据存储之用,对这类变量就可以酌情使用寄存器代替。由于对寄存器可以直接进行操作,而不需要进行取数、存数操作,从而可以大大提高程序运行速度。
尽量利用寻址寄存器
C54x提供了八个寻址寄存器AR0-AR7,使用它们可以进行寻址操作,并且可以控制它们的值随着指令执行而增减。充分利用它们进行寻址可以显著提高运行速度。
实现结果
运算量统计
在对某一帧实际语音的处理过程中,编解码器算法的,各个部分运算量所占比例显示在表1中。运算量较大的部分是LSP系数的矢量量化与激励码本(自适应码本和随机码本)的搜索。这两个部分的运算量大约占全部编解码运算量的80%以上。
表1:运算量的分布(略)
由于G.729A算法中的LSP系数的量化、自适应码本和随机码本的搜索等运算量较大的部分的计算复杂度都是固定的,对于不同的输入所用的指令周期数目只有很小的改变,所以整个编解码器的运算量也是基本固定的,在帧与帧之间只有很小的波动,基本在15MIPS附近波动,其中编码部分约占13MIPS,解码部分约占2MIPS。
储量统计
G.729a算法所用的存储量情况见表2。
编码器和解码器的存储量是分别统计的,它们有很多的共同区域,如数据区中的表格部分和程序区的公用函数部分,所以合并后的数据区和程序区总存储量应分别为约7K字。
表2:存储量的分布(略)
结束语
本文介绍了采用TI公司TMS320VC5416实现ITU-T G.729A 8kb/s CS-ACELP语音压缩编码,所采用的设计思路、程序调试和程序优化的方法对用其它DSP芯片实现语音压缩编码算法也有参考意义。
|