在TI 的DSP 平台下优化AVS 的 IDCT 反变换的方法和代码

来源:互联网 发布:淘宝素材中心作用 编辑:程序博客网 时间:2024/04/28 14:55

 

 

一, AVS标准规定的IDCT反变换

本条定义将8´8变换系数矩阵CoeffMatrix转换为8´8残差样值矩阵ResidueMatrix的过程,步骤如下:

00001—— 首先,对变换系数矩阵进行如下水平反变换:

H¢ = CoeffMatrix ´ T8T

其中,T 8是8´8反变换矩阵,T 8TT8的转置矩阵, H¢ 表示水平反变换后的中间结果。从符合本部分的比特流中解码得到的H¢矩阵元素取值范围应为 –215215–5

 

      8  10  10   9   8   6   4   2   

      8   9   4  -2  -8 -10 -10  -6   

      8   6  -4 -10  -8   2  10   9   

      8   2 -10  -6   8   9  -4 -10 

T8 8  -2 -10   6   8  -9  -4  10 

      8  -6  -4  10  -8  -2  10  -9 

      8  -9   4   2  -8  10 -10   6

      8 -10  10  -9   8  -6   4  -2

 

00002—— 第二步,对矩阵H¢中的每个系数4右移3位,得到矩阵H¢¢

00003—— 第三步,对矩阵H¢¢进行如下垂直反变换:

H = T8 ´ H¢¢

其中,H表示反变换后的8´8矩阵。从符合本部分的比特流中解码得到的H矩阵元素取值范围应为 –215215–65

00004—— 第四步,残差样值矩阵ResidueMatrix的元素rij计算如下:

rij = (hij + 26) >> 7 i, j = 0..7

其中hijH矩阵的元素。

 

二, C语言实现

 

void idct_c_dsp(short* blk)

{

int i, j;

short* b = blk;

short  x[8];

int    r[12];

int    z[8];

 

for(i=0; i<8; i++, b+=8) // horizontal transform

{

for(j=0; j<8; j++)

{

x[j] = b[j];

}

 

r[0] = 8  * x[0] + 8  * x[4];

r[1] = 8  * x[0] - 8  * x[4];

 

r[2] = 10 * x[1] + 6   * x[5];

r[3] = 9  * x[1] - 10  * x[5];

r[4] = 6  * x[1] + 2  * x[5];

r[5] = 2  * x[1] + 9  * x[5];

 

r[6] = 10 * x[2] + 4  * x[6];

r[7] = 4  * x[2] - 10 * x[6];

 

r[8] = 9  * x[3] + 2  * x[7];

r[9] = 2  * x[3] + 6  * x[7];

r[10]= 10 * x[3] - 9  * x[7];

r[11]= 6  * x[3] + 10 * x[7]; 

 

z[0] = r[0] + r[6];

z[1] = r[2] + r[8];

 

z[2] = r[1] + r[7];

z[3] = r[3] - r[9];

 

z[4] = r[1] - r[7];

z[5] = r[4] - r[10];

 

z[6] = r[0] - r[6];

z[7] = r[5] - r[11];

 

b[0] = (short) (CLIP3(-32768, 32767, (z[0] + z[1] + 4)) >> 3);

b[1] = (short) (CLIP3(-32768, 32767, (z[2] + z[3] + 4)) >> 3);

b[2] = (short) (CLIP3(-32768, 32767, (z[4] + z[5] + 4)) >> 3);

b[3] = (short) (CLIP3(-32768, 32767, (z[6] + z[7] + 4)) >> 3);

b[4] = (short) (CLIP3(-32768, 32767, (z[6] - z[7] + 4)) >> 3);

b[5] = (short) (CLIP3(-32768, 32767, (z[4] - z[5] + 4)) >> 3);

b[6] = (short) (CLIP3(-32768, 32767, (z[2] - z[3] + 4)) >> 3);

b[7] = (short) (CLIP3(-32768, 32767, (z[0] - z[1] + 4)) >> 3);

}

 

b = blk;

for(i=0; i<8; i++, b+=1) // vertical transform

{

for(j=0; j<8; j++)

{

x[j] = b[j*8];

}

 

r[0] = 8  * x[0] + 8  * x[4]; // 0x080008

r[1] = 8  * x[0] - 8  * x[4]; // 0x080008

 

r[2] = 10 * x[1] + 6  * x[5]; // 0x0a0006

r[3] = 9  * x[1] - 10 * x[5]; // 0x09000a

r[4] = 6  * x[1] + 2  * x[5]; // 0x060002

r[5] = 2  * x[1] + 9  * x[5]; // 0x020009

 

r[6] = 10 * x[2] + 4  * x[6]; // 0x0a0004

r[7] = 4  * x[2] - 10 * x[6]; // 0x04000a

 

r[8] = 9  * x[3] + 2  * x[7]; // 0x090002

r[9] = 2  * x[3] + 6  * x[7]; // 0x020006

r[10]= 10 * x[3] - 9  * x[7]; // 0x0a0009

r[11]= 6  * x[3] + 10 * x[7]; // 0x06000a

 

z[0] = r[0] + r[6];

z[1] = r[2] + r[8];

 

z[2] = r[1] + r[7];

z[3] = r[3] - r[9];

 

z[4] = r[1] - r[7];

z[5] = r[4] - r[10];

 

z[6] = r[0] - r[6];

z[7] = r[5] - r[11];

 

b[0*8] = (short) (CLIP3(-32768, 32767, (z[0] + z[1] + 64)) >> 7);

b[1*8] = (short) (CLIP3(-32768, 32767, (z[2] + z[3] + 64)) >> 7);

b[2*8] = (short) (CLIP3(-32768, 32767, (z[4] + z[5] + 64)) >> 7);

b[3*8] = (short) (CLIP3(-32768, 32767, (z[6] + z[7] + 64)) >> 7);

b[4*8] = (short) (CLIP3(-32768, 32767, (z[6] - z[7] + 64)) >> 7);

b[5*8] = (short) (CLIP3(-32768, 32767, (z[4] - z[5] + 64)) >> 7);

b[6*8] = (short) (CLIP3(-32768, 32767, (z[2] - z[3] + 64)) >> 7);

b[7*8] = (short) (CLIP3(-32768, 32767, (z[0] - z[1] + 64)) >> 7);

}

}

 

三,C语言实现的算法分析

 

仔细分析系数矩阵可以看到特点:偶数列上的上四行和下四行是对称的,奇数列上的上四行和下四行是反对称的。这样就可以得出十二个基本项,就是c代码中的r[12],进而得到8个值z[8],最后得到反变换的值。仔细阅读代码就会清楚的明白了。

需要注意的是,CLIP3函数实际是用来求16位的有符号数的饱和计算。在理想情况下系数矩阵经过变换后是不会出现超出16位可表示的数值的,但在实际中还是会出现极少数情况超出,为了优化又需要在16位之内计算,因此,采用折中的办法将超出进行饱和处理,保证IDCT的精度损失较小。

 

四,基于TI 的6000系列DSP优化

 

1,利用dsp的乘加指令和32位加载伪指令进行初步优化,代码实现如下

 

void idct_intrinsic_dsp(short* blk)

{

int i;

short* b = blk;

int    x[4];

int    r[12];

int    z[8];

 

_nassert(((int)(blk) & 0x03) == 0);

for(i=0; i<8; i++, b+=8) // horizontal transform

{

x[0] = _mem4(&b[0]); // b[1] b[0] , little endian

x[1] = _mem4(&b[2]); // b[3] b[2]

x[2] = _mem4(&b[4]); // b[5] b[4]

x[3] = _mem4(&b[6]); // b[7] b[6]

 

r[0] = x[0]; // save x[0]

r[1] = x[1]; // save x[1]

 

x[0] = _pack2 (r[0], x[2]); // b[0] b[4] 

x[1] = _packh2(r[0], x[2]); // b[1] b[5] 

x[2] = _pack2 (r[1], x[3]); // b[2] b[6] 

x[3] = _packh2(r[1], x[3]); // b[3] b[7] 

 

r[0] = _dotp2 (0x080008, x[0]); // r[0] = 8  * x[0] + 8  * x[4]; // 0x080008

r[1] = _dotpn2(0x080008, x[0]); // r[1] = 8  * x[0] - 8  * x[4]; // 0x08fff8

r[2] = _dotp2 (0x0a0006, x[1]); // r[2] = 10 * x[1] + 6  * x[5]; // 0x0a0006

r[3] = _dotpn2(0x09000a, x[1]); // r[3] = 9  * x[1] - 10 * x[5]; // 0x09000a

r[4] = _dotp2 (0x060002, x[1]); // r[4] = 6  * x[1] + 2  * x[5]; // 0x060002

r[5] = _dotp2 (0x020009, x[1]); // r[5] = 2  * x[1] + 9  * x[5]; // 0x020009

r[6] = _dotp2 (0x0a0004, x[2]); // r[6] = 10 * x[2] + 4  * x[6]; // 0x0a0004

r[7] = _dotpn2(0x04000a, x[2]); // r[7] = 4  * x[2] - 10 * x[6]; // 0x04000a

r[8] = _dotp2 (0x090002, x[3]); // r[8] = 9  * x[3] + 2  * x[7]; // 0x090002

r[9] = _dotp2 (0x020006, x[3]); // r[9] = 2  * x[3] + 6  * x[7]; // 0x020006

r[10]= _dotpn2(0x0a0009, x[3]); // r[10]= 10 * x[3] - 9  * x[7]; // 0x0a0009

r[11]= _dotp2 (0x06000a, x[3]); // r[11]= 6  * x[3] + 10 * x[7]; // 0x06000a

 

z[0] = r[0] + r[6];

z[1] = r[2] + r[8];

z[2] = r[1] + r[7];

z[3] = r[3] - r[9];

z[4] = r[1] - r[7];

z[5] = r[4] - r[10];

z[6] = r[0] - r[6];

z[7] = r[5] - r[11];

 

b[0] = (short)(CLIP3(-32768, 32767, (z[0] + z[1] + 4)) >> 3);

b[1] = (short)(CLIP3(-32768, 32767, (z[2] + z[3] + 4)) >> 3);

b[2] = (short)(CLIP3(-32768, 32767, (z[4] + z[5] + 4)) >> 3);

b[3] = (short)(CLIP3(-32768, 32767, (z[6] + z[7] + 4)) >> 3);

b[4] = (short)(CLIP3(-32768, 32767, (z[6] - z[7] + 4)) >> 3);

b[5] = (short)(CLIP3(-32768, 32767, (z[4] - z[5] + 4)) >> 3);

b[6] = (short)(CLIP3(-32768, 32767, (z[2] - z[3] + 4)) >> 3);

b[7] = (short)(CLIP3(-32768, 32767, (z[0] - z[1] + 4)) >> 3);

}

 

b = blk;

for(i=0; i<8; i++, b+=1) // horizontal transform

{

short* p = (short*)x;

p[0] = b[4*8];

p[1] = b[0*8];

p[2] = b[5*8];

p[3] = b[1*8];

p[4] = b[6*8];

p[5] = b[2*8];

p[6] = b[7*8];

p[7] = b[3*8];

 

r[0] = _dotp2 (0x080008, x[0]); // r[0] = 8  * x[0] + 8  * x[4]; // 0x080008

r[1] = _dotpn2(0x080008, x[0]); // r[1] = 8  * x[0] - 8  * x[4]; // 0x08fff8

r[2] = _dotp2 (0x0a0006, x[1]); // r[2] = 10 * x[1] + 6  * x[5]; // 0x0a0006

r[3] = _dotpn2(0x09000a, x[1]); // r[3] = 9  * x[1] - 10 * x[5]; // 0x09000a

r[4] = _dotp2 (0x060002, x[1]); // r[4] = 6  * x[1] + 2  * x[5]; // 0x060002

r[5] = _dotp2 (0x020009, x[1]); // r[5] = 2  * x[1] + 9  * x[5]; // 0x020009

r[6] = _dotp2 (0x0a0004, x[2]); // r[6] = 10 * x[2] + 4  * x[6]; // 0x0a0004

r[7] = _dotpn2(0x04000a, x[2]); // r[7] = 4  * x[2] - 10 * x[6]; // 0x04000a

r[8] = _dotp2 (0x090002, x[3]); // r[8] = 9  * x[3] + 2  * x[7]; // 0x090002

r[9] = _dotp2 (0x020006, x[3]); // r[9] = 2  * x[3] + 6  * x[7]; // 0x020006

r[10]= _dotpn2(0x0a0009, x[3]); // r[10]= 10 * x[3] - 9  * x[7]; // 0x0a0009

r[11]= _dotp2 (0x06000a, x[3]); // r[11]= 6  * x[3] + 10 * x[7]; // 0x06000a

 

z[0] = r[0] + r[6];

z[1] = r[2] + r[8];

z[2] = r[1] + r[7];

z[3] = r[3] - r[9];

z[4] = r[1] - r[7];

z[5] = r[4] - r[10];

z[6] = r[0] - r[6];

z[7] = r[5] - r[11];

 

b[0*8] = (short)(CLIP3(-32768, 32767, (z[0] + z[1] + 64)) >> 7);

b[1*8] = (short)(CLIP3(-32768, 32767, (z[2] + z[3] + 64)) >> 7);

b[2*8] = (short)(CLIP3(-32768, 32767, (z[4] + z[5] + 64)) >> 7);

b[3*8] = (short)(CLIP3(-32768, 32767, (z[6] + z[7] + 64)) >> 7);

b[4*8] = (short)(CLIP3(-32768, 32767, (z[6] - z[7] + 64)) >> 7);

b[5*8] = (short)(CLIP3(-32768, 32767, (z[4] - z[5] + 64)) >> 7);

b[6*8] = (short)(CLIP3(-32768, 32767, (z[2] - z[3] + 64)) >> 7);

b[7*8] = (short)(CLIP3(-32768, 32767, (z[0] - z[1] + 64)) >> 7);

}

 

从代码实现可以看出利用dsp的乘加指令实现求r数组的12个基本值比较简洁,但是,注意到,关键的内存加载部分代码优化效果一般,而存储部分还没有改变。下面,着重说明该部分的优化方法。

 

2,存储优化分析

 

注意:由于语言表达不太清楚,请仔细看矩阵的行列坐标,和代码就很容易理解这样做的好处了。

 

CoeffMatrix 为, 其中,x01 代表第0行,第1列的元素, 以此类推,以下的矩阵推导中都是用x表示的,只是为了写起来方便,实际上每次变换后,值都是改变的。

                 x00  x01  x02  x03  x04  x05  x06  x07  

                 x10  x11  x12  x13  x14  x15  x16  x17  

                 x20  x21  x22  x23  x24  x25  x26  x27  

                 x30  x31  x32  x33  x34  x35  x36  x37  

                 x40  x41  x42  x43  x44  x45  x46  x47  

                x50  x51  x52  x53  x54  x55  x56  x57  

                x60  x61  x62  x63  x64  x65  x66  x67  

                x70  x71  x72  x73  x74  x75  x76  x77  

 

通过改变frame或者field的扫描矩阵改变CoeffMatrix 的存储方式,这样做是为了加载和计算时快捷,改变后如下,

 

x04  x00  x05  x01  x06  x02  x07  x03  

x44  x40  x45  x41  x46  x42  x47  x43  

x14  x10  x15  x11  x16  x12  x17  x13  

x54  x50  x55  x51  x56  x52  x57  x53  

x24  x20  x25  x21  x26  x22  x27  x23  

x64  x60  x65  x61  x66  x62  x67  x63  

x34  x30  x35  x31  x36  x32  x37  x33  

x74  x70  x75  x71  x76  x72  x77  x73  

 

对上面的矩阵0,1两行,2,3两行,4,5两行,6,7两行,同时进行行变换,之后进行饱和及压缩,存储, 得到的矩阵如下,

 

x40   x00   x50   x10    x60    x20   x70    x30  

x41  x01  x51  x11  x61  x21  x71  x31

x42   x02   x52   x12    x62   x22    x72    x32

x43   x03   x53    x13   x63   x23    x73    x33

x44  x04  x54  x14  x64  x24  x74  x34  

x45  x05  x55  x15  x65  x25  x75  x35

x46  x06  x56  x16  x66  x26  x76  x36

x47  x07  x57  x17  x67  x27  x77  x37

 

进行完上面的行变换后,进行列变换,上面矩阵的每一行,就是原来的要变换的列,而且也已经是按4 0 5 1 6 2 7 3的顺序排列的,同时对两行  进行变换,也就是原来的列变换,或者说是垂直变换也行。把变换后的值存储在原来的残差矩阵的对应位置,

 

x00  x01  x02  x03  x04  x05  x06  x07  

              x10  x11  x12  x13  x14  x15  x16  x17  

              x20  x21  x22  x23  x24  x25  x26  x27  

              x30  x31  x32  x33  x34  x35  x36  x37  

              x40  x41  x42  x43  x44  x45  x46  x47  

              x50  x51  x52  x53  x54  x55  x56  x57  

              x60  x61  x62  x63  x64  x65  x66  x67  

              x70  x71  x72  x73  x74  x75  x76  x77  

 

通过以上变换方法,就实现了加载和存储全都是按整数进行的,并减少了原来要调整数据进行的_pack2和_packh2操作来。

用到的dsp内联指令有,_pack2, _packh2, _amemd8_const, _dotp2, _dotpn2, _spack2, _shr2等。

 

3, 按照上述想法,优化的代码如下

 

void idct_intrinsic_dsp(short* blk)
{
    int    i;
    int    x[4] , n[4] ;
    int    r[12], p[12];
    int    z[8] , m[8] ;
    int    t[8][4];
    short* b = blk;

    _nassert(((int)(blk) & 0x03) == 0);

    for(i=0; i<4; i++, b+=16) // horizontal transform
    {
        // 取第0行的系数值,假定原始系数值是按 b[4] b[0] b[5] b[1] b[6] b[2] b[7] b[3] 排列的

                                                               // high | low    
        x[0] = _lo(_amemd8_const(b));     // b[0]   b[4]   
        x[1] = _hi(_amemd8_const(b));     // b[1]   b[5]   
        x[2] = _lo(_amemd8_const(b+4)); // b[2]   b[6]   
        x[3] = _hi(_amemd8_const(b+4)); // b[3]   b[7]   
        // 取第1行的系数值                               
        n[0] = _lo(_amemd8_const(b+8)); // b[0]   b[4]   
        n[1] = _hi(_amemd8_const(b+8)); // b[1]   b[5]   
        n[2] = _lo(_amemd8_const(b+12));// b[2]   b[6]   
        n[3] = _hi(_amemd8_const(b+12));// b[3]   b[7]                              

        r[0] = _dotp2 (0x080008, x[0]); // r[0] = 8  * x[0] + 8  * x[4]; // 0x080008
        r[1] = _dotpn2(0x080008, x[0]); // r[1] = 8  * x[0] - 8  * x[4]; // 0x08fff8
        r[2] = _dotp2 (0x0a0006, x[1]); // r[2] = 10 * x[1] + 6  * x[5]; // 0x0a0006
        r[3] = _dotpn2(0x09000a, x[1]); // r[3] = 9  * x[1] - 10 * x[5]; // 0x09000a
        r[4] = _dotp2 (0x060002, x[1]); // r[4] = 6  * x[1] + 2  * x[5]; // 0x060002
        r[5] = _dotp2 (0x020009, x[1]); // r[5] = 2  * x[1] + 9  * x[5]; // 0x020009
        r[6] = _dotp2 (0x0a0004, x[2]); // r[6] = 10 * x[2] + 4  * x[6]; // 0x0a0004
        r[7] = _dotpn2(0x04000a, x[2]); // r[7] = 4  * x[2] - 10 * x[6]; // 0x04000a
        r[8] = _dotp2 (0x090002, x[3]); // r[8] = 9  * x[3] + 2  * x[7]; // 0x090002
        r[9] = _dotp2 (0x020006, x[3]); // r[9] = 2  * x[3] + 6  * x[7]; // 0x020006
        r[10]= _dotpn2(0x0a0009, x[3]); // r[10]= 10 * x[3] - 9  * x[7]; // 0x0a0009
        r[11]= _dotp2 (0x06000a, x[3]); // r[11]= 6  * x[3] + 10 * x[7]; // 0x06000a

        p[0] = _dotp2 (0x080008, n[0]); // r[0] = 8  * x[0] + 8  * x[4]; // 0x080008
        p[1] = _dotpn2(0x080008, n[0]); // r[1] = 8  * x[0] - 8  * x[4]; // 0x08fff8
        p[2] = _dotp2 (0x0a0006, n[1]); // r[2] = 10 * x[1] + 6  * x[5]; // 0x0a0006
        p[3] = _dotpn2(0x09000a, n[1]); // r[3] = 9  * x[1] - 10 * x[5]; // 0x09000a
        p[4] = _dotp2 (0x060002, n[1]); // r[4] = 6  * x[1] + 2  * x[5]; // 0x060002
        p[5] = _dotp2 (0x020009, n[1]); // r[5] = 2  * x[1] + 9  * x[5]; // 0x020009
        p[6] = _dotp2 (0x0a0004, n[2]); // r[6] = 10 * x[2] + 4  * x[6]; // 0x0a0004
        p[7] = _dotpn2(0x04000a, n[2]); // r[7] = 4  * x[2] - 10 * x[6]; // 0x04000a
        p[8] = _dotp2 (0x090002, n[3]); // r[8] = 9  * x[3] + 2  * x[7]; // 0x090002
        p[9] = _dotp2 (0x020006, n[3]); // r[9] = 2  * x[3] + 6  * x[7]; // 0x020006
        p[10]= _dotpn2(0x0a0009, n[3]); // r[10]= 10 * x[3] - 9  * x[7]; // 0x0a0009
        p[11]= _dotp2 (0x06000a, n[3]); // r[11]= 6  * x[3] + 10 * x[7]; // 0x06000a

        z[0] = r[0] + r[6];
        z[1] = r[2] + r[8];
        z[2] = r[1] + r[7];
        z[3] = r[3] - r[9];
        z[4] = r[1] - r[7];
        z[5] = r[4] - r[10];
        z[6] = r[0] - r[6];
        z[7] = r[5] - r[11];

        m[0] = p[0] + p[6];
        m[1] = p[2] + p[8];
        m[2] = p[1] + p[7];
        m[3] = p[3] - p[9];
        m[4] = p[1] - p[7];
        m[5] = p[4] - p[10];
        m[6] = p[0] - p[6];
        m[7] = p[5] - p[11];
                                                                                                // high | low
        t[0][i] = _shr2(_spack2(z[0]+z[1]+4, m[0]+m[1]+4), 3); // x00    x40
        t[1][i] = _shr2(_spack2(z[2]+z[3]+4, m[2]+m[3]+4), 3); // x01    x41
        t[2][i] = _shr2(_spack2(z[4]+z[5]+4, m[4]+m[5]+4), 3); // x02    x42
        t[3][i] = _shr2(_spack2(z[6]+z[7]+4, m[6]+m[7]+4), 3); // x03    x43
        t[4][i] = _shr2(_spack2(z[6] -z[7]+4, m[6] -m[7]+4), 3); // x04    x44
        t[5][i] = _shr2(_spack2(z[2] -z[3]+4, m[2] -m[3]+4), 3); // x05    x45
        t[6][i] = _shr2(_spack2(z[4] -z[5]+4, m[4] -m[5]+4), 3); // x46    x46
        t[7][i] = _shr2(_spack2(z[0] -z[1]+4, m[0] -m[1]+4), 3); // x47    x47
    }    

    b = blk;

    for(i=0; i<4; i++, b+=2) // horizontal transform
    {                
        // 取第0行的系数值                                          // high | low
        x[0] = _lo(_amemd8_const(&t[2*i+0][0])); // b[0]   b[4]
        x[1] = _hi(_amemd8_const(&t[2*i+0][0])); // b[1]   b[5]
        x[2] = _lo(_amemd8_const(&t[2*i+0][2])); // b[2]   b[6]
        x[3] = _hi(_amemd8_const(&t[2*i+0][2])); // b[3]   b[7]
        // 取第1行的系数值
        n[0] = _lo(_amemd8_const(&t[2*i+1][0])); // b[0]   b[4]
        n[1] = _hi(_amemd8_const(&t[2*i+1][0])); // b[1]   b[5]
        n[2] = _lo(_amemd8_const(&t[2*i+1][2])); // b[2]   b[6]
        n[3] = _hi(_amemd8_const(&t[2*i+1][2])); // b[3]   b[7]

        r[0] = _dotp2 (0x080008, x[0]); // r[0] = 8  * x[0] + 8  * x[4]; // 0x080008
        r[1] = _dotpn2(0x080008, x[0]); // r[1] = 8  * x[0] - 8  * x[4]; // 0x08fff8
        r[2] = _dotp2 (0x0a0006, x[1]); // r[2] = 10 * x[1] + 6  * x[5]; // 0x0a0006
        r[3] = _dotpn2(0x09000a, x[1]); // r[3] = 9  * x[1] - 10 * x[5]; // 0x09000a
        r[4] = _dotp2 (0x060002, x[1]); // r[4] = 6  * x[1] + 2  * x[5]; // 0x060002
        r[5] = _dotp2 (0x020009, x[1]); // r[5] = 2  * x[1] + 9  * x[5]; // 0x020009
        r[6] = _dotp2 (0x0a0004, x[2]); // r[6] = 10 * x[2] + 4  * x[6]; // 0x0a0004
        r[7] = _dotpn2(0x04000a, x[2]); // r[7] = 4  * x[2] - 10 * x[6]; // 0x04000a
        r[8] = _dotp2 (0x090002, x[3]); // r[8] = 9  * x[3] + 2  * x[7]; // 0x090002
        r[9] = _dotp2 (0x020006, x[3]); // r[9] = 2  * x[3] + 6  * x[7]; // 0x020006
        r[10]= _dotpn2(0x0a0009, x[3]); // r[10]= 10 * x[3] - 9  * x[7]; // 0x0a0009
        r[11]= _dotp2 (0x06000a, x[3]); // r[11]= 6  * x[3] + 10 * x[7]; // 0x06000a

        p[0] = _dotp2 (0x080008, n[0]); // r[0] = 8  * x[0] + 8  * x[4]; // 0x080008
        p[1] = _dotpn2(0x080008, n[0]); // r[1] = 8  * x[0] - 8  * x[4]; // 0x08fff8
        p[2] = _dotp2 (0x0a0006, n[1]); // r[2] = 10 * x[1] + 6  * x[5]; // 0x0a0006
        p[3] = _dotpn2(0x09000a, n[1]); // r[3] = 9  * x[1] - 10 * x[5]; // 0x09000a
        p[4] = _dotp2 (0x060002, n[1]); // r[4] = 6  * x[1] + 2  * x[5]; // 0x060002
        p[5] = _dotp2 (0x020009, n[1]); // r[5] = 2  * x[1] + 9  * x[5]; // 0x020009
        p[6] = _dotp2 (0x0a0004, n[2]); // r[6] = 10 * x[2] + 4  * x[6]; // 0x0a0004
        p[7] = _dotpn2(0x04000a, n[2]); // r[7] = 4  * x[2] - 10 * x[6]; // 0x04000a
        p[8] = _dotp2 (0x090002, n[3]); // r[8] = 9  * x[3] + 2  * x[7]; // 0x090002
        p[9] = _dotp2 (0x020006, n[3]); // r[9] = 2  * x[3] + 6  * x[7]; // 0x020006
        p[10]= _dotpn2(0x0a0009, n[3]); // r[10]= 10 * x[3] - 9  * x[7]; // 0x0a0009
        p[11]= _dotp2 (0x06000a, n[3]); // r[11]= 6  * x[3] + 10 * x[7]; // 0x06000a

        z[0] = r[0] + r[6];
        z[1] = r[2] + r[8];
        z[2] = r[1] + r[7];
        z[3] = r[3] - r[9];
        z[4] = r[1] - r[7];
        z[5] = r[4] - r[10];
        z[6] = r[0] - r[6];
        z[7] = r[5] - r[11];

        m[0] = p[0] + p[6];
        m[1] = p[2] + p[8];
        m[2] = p[1] + p[7];
        m[3] = p[3] - p[9];
        m[4] = p[1] - p[7];
        m[5] = p[4] - p[10];
        m[6] = p[0] - p[6];
        m[7] = p[5] - p[11];

        _amem4(&b[0*8])    = _shr2(_spack2(m[0]+m[1]+64, z[0]+z[1]+64), 7); // x10    x00
        _amem4(&b[1*8])    = _shr2(_spack2(m[2]+m[3]+64, z[2]+z[3]+64), 7); // x11    x01
        _amem4(&b[2*8])    = _shr2(_spack2(m[4]+m[5]+64, z[4]+z[5]+64), 7); // x12    x02
        _amem4(&b[3*8])    = _shr2(_spack2(m[6]+m[7]+64, z[6]+z[7]+64), 7); // x13    x03
        _amem4(&b[4*8])    = _shr2(_spack2(m[6]- m[7]+64,  z[6]-z[7]+64), 7); // x14    x04
        _amem4(&b[5*8])    = _shr2(_spack2(m[4]- m[5]+64,  z[4]-z[5]+64), 7); // x15    x05
        _amem4(&b[6*8])    = _shr2(_spack2(m[2]- m[3]+64,  z[2]-z[3]+64), 7); // x16    x06
        _amem4(&b[7*8])    = _shr2(_spack2(m[0]- m[1]+64,  z[0]-z[1]+64), 7); // x17    x07
    }    
}

 

五,结果对比

优化效果显著!!!

 

 

        望对dsp优化有经验的的大侠多多指点,看看有没有更好的方法进行优化,及代码写法方面的问题。

 

 

刘春龙:欢迎转载!