⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lpc2lsp.asm

📁 嵌入式系统开发中
💻 ASM
字号:
/*******************************************************************************
Copyright(c) 2000 - 2002 Analog Devices. All Rights Reserved.
Developed by Joint Development Software Application Team, IPDC, Bangalore, India
for Blackfin DSPs  ( Micro Signal Architecture 1.0 specification).

By using this module you agree to the terms of the Analog Devices License
Agreement for DSP Software. 
********************************************************************************
Module Name     : lpc2lsp.asm
Label name      :  __lpc2lsp
Version         :   1.3
Change History  :

                Version     Date          Author      Comments
                1.3         11/18/2002    Swarnalatha Tested with VDSP++ 3.0
                                                      compiler 6.2.2 on 
                                                      ADSP-21535 Rev.0.2
                1.2         11/13/2002    Swarnalatha Tested with VDSP++ 3.0
                                                      on ADSP-21535 Rev. 0.2
                1.1         01/22/2002    Srinivas    Modified to match silicon
                                                      cycle count
                1.0         06/19/2001    Srinivas    Original 

Description     :  Computes the LSP's from LP coefficients.

Algorithm       : (1) The sum and difference filters are computed and divided by
                   1+z^{-1}   and   1-z^{-1}, respectively.

                   f1[0] = 1.0;
                   f2[0] = 1.0;

                   for (i = 0; i< 5; i++)                                     
                   {
                       f1[i+1] = a[i+1] + a[M-i] - f1[i] ;
                       f2[i+1] = a[i+1] - a[M-i] + f2[i] ;
                   }

                (2) The roots of F1(z) and F2(z) are found using Chebyshev 
                polynomial
                evaluation. The polynomials are evaluated at 60 points regularly
                spaced in the frequency domain. The sign change interval is
                subdivided 4 times to better track the root.
                The LSPs are found in the cosine domain [1,-1].

                 nf = 0;    //number of found frequencies
                 ip = 0;    //indicator for f1 or f2
                 coef = f1;
                 xlow = grid[0];
                 ylow = Chebps (xlow, coef);
                 j = 0;

                 while ( (nf < 10) && (j < grid_points) ) 
                 {  
                    j++;
                    xhigh = xlow;
                    yhigh = ylow;
                    xlow = grid[j];
                    ylow = Chebps (xlow, coef);

                    if (ylow * yhigh) <= 0)
                    {
                            //divide 4 times the interval
                        for (i = 0; i < 4; i++)
                        {
                           xmid = (xlow + xhigh)/2
                           ymid = Chebps (xmid, coef);

                           if (ylow * ymid) <= 0)
                           {
                             yhigh = ymid;
                             xhigh = xmid; 
                           }
                           else
                           {
                             ylow = ymid; 
                             xlow = xmid;
                           }
                        }
                            //Linear interpolation
                        xint = xlow - ylow*(xhigh-xlow)/(yhigh-ylow);
                     }
                     lsp[nf] = xint;
                     xlow = xint;
                     nf++;
                     if (ip == 0)
                     {
                       ip = 1;
                       coef = f2;
                     }
                     else
                     {
                        ip = 0;
                        coef = f1;
                     }
                     ylow = Chebps (xlow, coef);
                  }

                (3) If less than 10 roots are found, the LSPs from the past 
                frame are used.

Prototype       :  void _lpc2lsp(fract16* a, fract16* lsp, fract16* old_lsp)

                  a       -> pointer to predictor coefficients i.e &a[1] , a[0] 
                             = 1.0 assumed.
                  lsp     -> pointer to line spectral pairs,
                  old_lsp -> pointer to old lsp array.

Assumptions     : (1) Order of the predictor filter = 10

Registers Used  : R0-R7, I0-I3, B0-B3, L0-L3, P0-P5, LC0, LC1.

Performance     :
                 Code Size   : 342 bytes.
                 Cycle count : 7190 (depends on data, given figure is for the
                 first set of data in lpc2lsp.h)
*******************************************************************************/
.section   L1_code;
.global    __lpc2lsp;
.align 8;
    
.extern __cheb;
.extern __divfr_16;
.extern _grid;

__lpc2lsp:

    [--SP] = (R7:4,P5:3);
    [--SP] = RETS;
    
    L0 = 0;
    L1 = 0;
    L2 = 0;
    L3 = 0;
    P1 = R0;                //ptr to lpc a[1]
    B3 = R1;                //ptr to lsp array
    I2 = R1;                //ptr to lsp array
    I3 = R2;                //ptr to old lsp
    SP += -20;              //Allocate memory in stack for 2 arrays of 5 
                            //elements each
    P4 = SP;                //ptr to f2 array
    P3 = SP;
    P3 += 10;               //ptr to f1 array
    P2 = P1;                //pointing to a[1]
    R0.H = 0X4000;          //R0 = 0.5
    R0.L = R0.L - R0.L (NS) || R1 = W[P1++](X);
                            //a[1] 
    B2 = R0;                //store 0.5
    R0 = 1024 (X);          //f1[0]= f2[0]= 1 in 6.10 format
    P2 += 18;               //pointing to a[10];
    R2 = W[P2--](X);        //a[10]
    R3 = R1 + R2, R4 = R1 - R2 (S);
                            //a[1] + a[10], a[1] - a[10] 
    R3 = R3 >>> 2;          //in 6.10
    R5 = R3 - R0(S) || R1 = W[P1++](X);
                            //f1[1] = a[1] + a[10] - f[0],, load a[2] 
    R4 = R4 >>> 2 || W[P3++] = R5 ;
                            //in 6.10, Store f1[1] 
    R7 = R4 + R0 (S)|| R2 = W[P2--](X);
                            //f2[1] = a[1] - a[10] + f[0],  load a[9] 
    P0 = 4;
    
    LSETUP(LSTART0,LEND0)LC0 = P0 ;
LSTART0:R3 = R1 + R2 , R4 = R1 - R2 (S)  || W[P4++] = R7;
                            //a[i+1] + a[10-i], a[i+1] - a[10-i],Store f2[i+1] 
        R3 = R3 >>> 2 || R1 = W[P1++](X);
                            //in 6.10 format, load a[i+1] 
        R4 = R4 >>> 2 || R2 = W[P2--](X);
                            //in 6.10 format, load a[10-i] 
        R5 = R3 - R5 (S);   //f1[i+1] = a[i+1] + a[10-i] - f1[i]
LEND0:  R7 = R4 + R7 (S) || W[P3++] = R5;
                            //f2[i+1]= a[i+1] - a[10-i] + f2[i], Store f1[i+1] 
    
    P3 += -20;              //P3 pointing to f2 array
    B0 = P3;                //B0 pointing to f2 array
    P3 = 0;                 //nf = 0 number of found frequencies
    
    P2.L = _grid;           //pointer to grid array
    P2.H = _grid;
    
    R0 = W[P2++](X);        //xlow = grid[0]
    R4 = R0 << 0 || W[P4++] = R7;
                            //xlow, last f2, now P4 pointing to f1 
    R1 = P4;                //ptr f1
    
    CALL __cheb;
    
    R6 = R0;                //ylow
    P5 = 0;                 //j=0 number of grid points tried
    
ST_SEARCH:
    P5 += 1;                //j++
    R5 = R4;                //xhigh = xlow
    R7 = R6 << 0 || R4 = W[P2++](X);
                            //yhigh = ylow, xlow = grid[j] 
    R0 = R4;                //xlow
    R1 = P4;                //ptr to current f array
    
    CALL __cheb;            //ylow
    
    R6 = R0;                //ylow
    R2 = R0.L * R7.L;       //ylow * yhigh
    CC = R2 <= 0;           //check for the sign change
    IF !CC JUMP ST_SEARCH (BP);
                            //if root not found search in next grid interval 
    
    /* Loop for dividing the xlow-xhigh interval 4 times & searching root */
    
    P0 = 4;
    R0 = R4 + R5;           //(xlow + xhigh)

    LSETUP(LSTART1,LEND1)LC1 = P0;
                            //dividing the xlow-xhigh interval 4 times 
LSTART1:R0 = R0 >>> 1;      //xmid = (xlow + xhigh)/2
        B1 = R0;            //xmid
        R1 = P4;            //ptr to polynomial f
    
        CALL __cheb;        //R0 = ymid
    
        R2 = R0.L * R6.L;   //ymid * ylow
        CC = R2 <= 0;       //check for the sign change
        R1 = B1;            //xhigh
        IF CC R7 = R0;      //yhigh = ymid
        IF CC R5 = R1;      //xhigh = xmid
        IF !CC R6 = R0;     //ylow = ymid
        IF !CC R4 = R1;     //xlow = xmid
LEND1:  R0 = R4 + R5;       //(xlow + xhigh)
    
    R1 = R7 - R6;           //yhigh - ylow
    
    CC = R1 == 0;           //check whether (yhigh - ylow) is 0 or not
    IF CC JUMP NO_INT_POL;  //if y is 0 no need of interpolation
    
    /* Linear interpolation */
    /* xint = xlow - ylow*(xhigh-xlow)/(yhigh-ylow) */
    
    R0 = B2;                //0.5
    R3.L = SIGNBITS R1.L;   //sign bits of (yhigh - ylow)
    R2 = R5 - R4 (S);       //xhigh - xlow
    R1 = ASHIFT R1 BY R3.L; //normalise
    
    CALL __divfr_16;        //y = 0.5/(yhigh - ylow)
    
    R0 = R2.L * R0.L;       //y = (xhigh - xlow)*y
    R0 = R6.L * R0.H;       //ylow * y
    R0 = ASHIFT R0 BY R3.L; //denormalise
    R0 = R0 >>> 15;         //result in R0.L & multiplied by 2 for compensating 
                            //division by 2 in divfr_16 function
    R2 = R4 - R0;           //xint = xlow - ylow * y
    
NO_INT_POL: R4 = R2 << 0 || W[I2++] = R2.L;
                            //xlow = xint, Store lsp 
    P3 += 1;                //increment nf number of roots found
    
    P0 = P4;                //swap current & prev f array ptrs
    P4 = B0;                //current f ptr = prev f ptr
    B0 = P0;
    
    R0 = R4;                //xlow
    R1 = P4;                //ptr to polynomial f
    
    CALL __cheb;
    
    R6 = R0;                //ylow
    P0 = 10;                //required no of roots = 10
    CC = P3 == P0;          //check if no of roots found = required no of roots
    IF CC JUMP TERMINATE;   //if 10 roots found terminate
    P1 = 60;                //total no of grid pts = 60
    CC = P5 == P1;          //check if all pts are exhausted
    IF !CC JUMP ST_SEARCH (BP);
    
    P2 = B3;                //ptr to lsp array
    R0.L = W[I3++];
    LSETUP(LCP_OLD,LCP_OLD)LC0 = P0;
LCP_OLD:W[P2++] = R0 || R0.L = W[I3++] ;
                            //copy old lsp to new lsp array 
    
TERMINATE: SP += 20;        //releasing the memory
    RETS = [SP++];
    (R7:4,P5:3)=[SP++];     //restoring the register values
    RTS;
    NOP;                    //to avoid one stall if LINK or UNLINK happens to be
                            //the next instruction after RTS in the memory.
__lpc2lsp.end:                            

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -