刘品
学以致用---博主简介:专注语音、视频数字信号处理方面的研究以及算法在手机平台上面的移植和优化。涉及语音/音频编解码,语音增强,语音识别,语音音质客观评估,VOIP语音引擎 Qos算法模块和声音变速不变调和变调不变速等功能实现。熟悉ARM 各个系列的CPU,用ARMv4,ARMv5,ARMv6 and Cortex Neon 汇编优化相关算法代码,争取perforamance 最优。目前主要Windows mobile and Android platform上做相关speech/audio算法以及应用开发, HEVC 编解码器PC 和手机上的开发与应用。(交流Email:liupin.2008@gmail.com)

 十六 提高专业技能之 “Codec定点化”

                                   Write by Liupin 2010-4-1

  1. 基本理论

1)     为什么要定点化

Since the Core is an integer process,all floating point operations must be simulated using integer arithmetic. 现在大多数嵌入式CPU都是定点的,当然在这些CPU platform上是能跑浮点数的程序,但效果很低,原因是内部是调用floating 处理的库或专用的硬件处理单元。另一点,由于浮点数的处理单元功耗更高,这就限制在移动devices上的应用。

 

结论:定点化处理在移动应用上开发往往是必不可少的一步。现在很多算法实现,往往开始是在相关的平台上进行算法仿真,然后就C语言浮点实现,里面有很多float, double型的数据,然后就是定点化的,提高算法的效率。

2)     定点化的方法

首先要选择Q的数值,如short型的,往往用Q15, int型的,往往用Q31.这也是有前提的,要保证在所有运算过程中,最大值不会大于1。 如出现了,应该调整Q值,如用Q14或Q30.

 

其次就是一些基本运算时,注意一定要保持Q值的统一,如不统一那得要通过左移或右移来实现。

In signal processing the data oftenconsists of fractional values, in the range -1 to +1. This example uses exponentq and 32-bit integer mantissas (so that each value can be held in a single ARMregister). In order to be able to multiply two numbers without overflow, youneed , or . In practice q=14 is often chosen as this allows multiplication withseveral accumulates without risk of overflow。

 

Fig16.1     Q=14  Basic operations

 

从Fig16.1中可以看,在计算前要统一各参与运算变量的Q值。 如 X + a, X是Q14, 而且a是一整数,所以在运算时要统一到Q14, so a<<14.  运算有时会改变Q的值,所以在运算后往往要对结果进行Q值的调整。如 xy

X: Q14, Y :Q14, So XY: Q28, in order tonormal the Q value to 14, so the result have to right shift 14: (X*Y) >>14.

 

Example1:

To calculate the distance from theorigin, d = sqrt(x^2 + y^2 + z^2), in q=8 form. If you apply the above formulaedirectly and keep all intermediate answers in q=8 form, you arrive at thefollowing code:

x = (x*x)>>8 square x

y = (y*y)>>8 square y

z = (z*z)>>8 square z

s = x+y+z sum of squares

d = sqrt(s<<8)the distance in q=8 form

Alternatively, if you keep theintermediate answers in q=16 form, the number of shifts is reduced and theaccuracy increased:

x = x*x square of x in q=16 form

y = y*y square of y in q=16 form

z = z*z square of z in q=16 form

s = x+y+x sum of squares in q=16 form

d = sqrt(s) distance d in q=8 form

 

 

Conclusion:

(1)  If you add two numbers in Q-form, the stay in Q-form

(2)  If you multiply two numbers in Q-form, the answer is 2Q-from

(3) If you take the square root of a number in q form the answer isin q/2-form.

(4) To convert from q-formto r-form you shift left by (r-q) or right by (q-r),depending on which of q andr is greater

(5) To get the bestprecision results, choose q to be the largest number such that the intermediatecalculations cannot overflow.

 

  1. 深入探究

定点化过程中,最难把握的是数度问题,如Q值太小,往往达不到技术要求的精度。但Q值定得太大,如Q31,这样又比较容易出现溢出,同时也会增加一些常量表的size. 在实际运行中,往往也会影响代码的效率,因为会导致register不够用。如都是Q15,那样一个数就是2bytes,这样一个32bits register就能load二个数值。

一个方法往往是先估计一下,在运算中,最大的数值是多少,这个往往好估计的,然后根据这个值来尽量取大的Q值。原则是先满足精度要求下进行定点化,当定点化完成后,再考虑用小点的Q值来定点化。尽量提高时间性能参数。

 

  1. 工程实战

以AC3decoder project 定点化来说明,代码定点化过程。

往往大家,拿到一工程代码,由于文件很多,且各个文件有相关参数的传递,这样搞得大家不知道怎么下手来做定点化的工作。

其实我们可以采用化整为零的方法,通过做法是以每个function为单位进行定点化。

例如:

AC3 Decoder---idctsc() function

做法是,在进行idctsc后,对输入的数据进行定点化,然后参与定点化的运算,定点化的运算无非就是上面列举的basic operations, 然后在function结束前,做与开始相反的运算,恢复输出buffer里的数据成floating data.

void idctsc(DEC_PARAM *p_decparam, BUFF_PARAM *p_buff)

{

       //DSPfract*fftrptr, *fftiptr, *fftrptr2, *fftiptr2;

       //DSPfract*tcrptr, *tciptr, *cosptr, *sinptr;

       //DSPfractar, ai, cr, ci;

       int     *fftrptr, *fftiptr, *fftrptr2, *fftiptr2;

       int     *tcrptr,*tciptr;

       int     ar, ai, i;

       int     fftbuf_fx[N], tcbuf_fx[N];

       short   *cosptr, *sinptr;

    short   cr, ci;

 

   //对输入buffer里的数据进行Q31的定点化处理

    for(i=0;i<N; i++)

    {

           fftbuf_fx[i]= (int)(p_buff->fftbuf[i] * 2147483647);

           tcbuf_fx[i]  = (int)(p_aublk->tcbuf[i] * 2147483647);

           fprintf(fdebug,"idctsc1: 0x%08x\n", fftbuf_fx[i]);

           fprintf(fdebug,"idctsc2: 0x%08x\n", tcbuf_fx[i]);

    }

……

 

    进行相关运算

……

 

 

 

  //恢复outputbuffer floating data, in order to the next function run.

    for(i=0;i<N; i++)

    {

           p_buff->fftbuf[i]= (double)(fftbuf_fx[i]/2147483647.0);

    }

}

 

用这个方法,fixed AC3 project codec function by function.当然了,有时并不是整个project用统一的Q值,可能这个function 是Q30,另一个function 由于一些值的累加,用Q30时会产生溢出,这时可能会用Q28. 有不同Q值时,特别要注意利用左右移位,保证最后数据的正确性。

 

 

  1. 参考文献

[1]. ARM Document, ApplicationNote 33 --- Fixed point Arithmetic on the ARM

posted on 2010-07-30 15:37  liupin  阅读(4136)  评论(4编辑  收藏  举报

-->