www.pudn.com > g729Decoder.rar > LPC.asm


;========================================================================== 
;  File Name 
;  ---------- 
;  LPC.ASM 
; 
;  Brief Description of the Code: 
;  ------------------------------ 
;  Find LPC coefficients. 
; 
;  Ref 
;  ------ 
;  LPC.C 
;========================================================================== 
        .mmregs 
 
        .include  ..\include\const.h 
        .include  ..\include\ld8amem.h 
 
        .text 
        .def    AutoCorr 
        .def    LagWindow 
        .def    Levinson 
 
 
        .ref    HamWindow         ; tab_ld8a.asm 
        .ref    CorrLoop1         ; tab_ld8a.asm 
 
        .ref    LagWin_l          ; tab_ld8a.asm 
        .ref    LagWin_h          ; tab_ld8a.asm 
        .ref    MPY32             ; math.asm 
 
;------------------------------------------------------------------------ 
; Function : AutoCorr 
;----------------------------------------------------------------------- 
; void Autocorr( 
;   Word16 x[],      /* (i)    : Input signal                      */ 
;   Word16 m,        /* (i)    : LPC order                         */ 
;   Word16 r_h[],    /* (o)    : Autocorrelations  (msb)           */ 
;   Word16 r_l[]     /* (o)    : Autocorrelations  (lsb)           */ 
; ) 
;----------------------------------------------------------------------- 
;  Input Registers : 
;                    AR3 -> signal[] 
; 
;  Modified Registers : BRC 
;                       A, B 
;                       AR0, AR1, AR2, AR3, AR4, AR5 
;----------------------------------------------------------------------- 
 
        .asg    "AR0", pNumCoef 
        .asg    "AR0", pLoopNum 
        .asg    "AR0", pTemp 
 
        .asg    "AR1", pCoef 
        .asg    "AR2", pWSigBase 
 
        .asg    "AR3", pWSigOffset 
        .asg    "AR3", pSignal 
 
        .asg    "AR4", pWSig1 
 
        .asg    "AR5", pWSig2 
        .asg    "AR5", pHamWindow 
 
AutoCorr: 
        RSBX    0, 10 
        STM     #Addr_wsig_buf, pWSigBase 
        STM     #L_TOTAL - 1, BRC 
        MVMM    pWSigBase, pWSig1 
        LD      #1, 15, B 
        RPTBD   #WinSig - 1 
        STM     #HamWindow, pHamWindow 
 
                MAC     *pHamWindow+, *pSignal+, B, A 
                STL     A, -16, *pWSig1+ 
WinSig: 
        MVMM    pWSigBase, pWSig1 
        LD      #1, A                           ; avoid case of all zero 
        RPT     #L_TOTAL - 1 
                SQURA   *pWSig1+, A             ; find r[0] 
 
        BC      No_AOV, ANOV              ; if overflow, make justfy, otherwise, go ahead 
        MVMM    pWSigBase, pWSig1         ; pWsig1 point to y[0] 
        STM     #L_WINDOW - 1, BRC        ; Repeat 240 times 
        RPTB    #Un_Jmp - 1               ; Two ins.  
                LD *pWSig1, -2, A         ; (y[i] >> 2) -> A 
                STL A, *pWSig1+            ; A -> y[i] 
Un_Jmp: 
	B       #WinSig                   ; Unconditionally jumping, repeat more 
No_AOV: 
 
        STM     #Addr_CorrCoef1, pCoef 
        EXP     A 
        STM     #10 - 1, BRC 
        NORM    A 
;.........for store with bit-exact with c 
        LD      A, -1, A 
        LD      A, 1, A 
;......... 
        DST     A, *pCoef+ 
 
 
        MVMM    pWSigBase, pWSigOffset 
        LDM     T, B 
        MAR     *pWSigOffset+ 
 
        RPTBD   #AutoCorrCoef - 1               ; find r[1] .. r[10] 
        STM     #CorrLoop1, pLoopNum 
 
                MVMM    pWSigBase, pWSig1 
                MVMM    pWSigOffset, pWSig2 
 
                MPY     *pWSig1+, *pWSig2+, A 
                RPT     *pLoopNum+ 
                        MAC     *pWSig1+, *pWSig2+, A 
 
                STLM    B, T 
                MAR     *pWSigOffset+ 
                NORM    A 
;............for store with bit-exact with c 
                LD      A, -1, A 
                LD      A, 1, A 
;............ 
                DST     A, *pCoef+ 
AutoCorrCoef: 
        RET 
 
;----------------------------------------------------------------------- 
; Function LagWindow( 
;  Word16 m,         /* (i)     : LPC order                */ 
;  Word32 r[],       /* (i/o)   : Autocorrelations         */ 
; ) 
; 
; Lag_window on autocorrelations. 
; 
; r[i] *= LagWin[i] 
; 
; 
;----------------------------------------------------------------------- 
;  Input Registers : 
;                    AR5 -> &r[1]_hi 
; 
;  Modified Registers : BRC 
;                       A, B 
;                       AR0, AR4, AR5 
;----------------------------------------------------------------------- 
 
        .asg    "AR3", pLagWin_h 
        .asg    "AR4", pLagWin_l 
        .asg    "AR5", pWCoef 
 
LagWindow: 
 
        STM     #M - 1, BRC 
        STM     #LagWin_l, pLagWin_l 
 
        LD      #0ffffh, 16, B                  ; to be bit-exact with C code 
 
        RPTBD   #WinCoef - 1 
        STM     #LagWin_h, pLagWin_h 
 
                MPY     *pLagWin_l+, *pWCoef+, A    ; LagWin_l * WCoef_h 
                AND     B, A 
                LD      A, 1, A 
                MACSU   *pWCoef-, *pLagWin_h, A 
                LD      A, -16, A 
                MAC     *pLagWin_h+, *pWCoef, A 
 
                LD      A, -1, A 
                LD      A, 1, A 
 
                DST     A, *pWCoef+ 
WinCoef: 
        RET 
 
;----------------------------------------------------------------------- 
; 
;      LEVINSON-DURBIN algorithm in double precision 
;      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
;-------------------------------------------------------------------------- 
;  void Levinson( 
;    Word16 Rh[],      /* (i)     : Rh[M+1] Vector of autocorrelations (msb) */ 
;    Word16 Rl[],      /* (i)     : Rl[M+1] Vector of autocorrelations (lsb) */ 
;    Word16 A[],       /* (o) Q12 : A[M]    LPC coefficients  (m = 10)       */ 
;    Word16 rc[]       /* (o) Q15 : rc[M]   Reflection coefficients.         */ 
;  ) 
;-------------------------------------------------------------------------- 
; 
;  Algorithm 
; 
;       R[i]    autocorrelations. 
;       A[i]    filter coefficients. 
;       K       reflection coefficients. 
;       Alpha   prediction gain. 
; 
;       Initialization: 
;               A[0] = 1 
;               K    = -R[1]/R[0] 
;               A[1] = K 
;               Alpha = R[0] * (1-K**2) 
; 
;       Do for  i = 2 to M 
; 
;            S =  SUM ( R[j]*A[i-j] ,j=1,i-1 ) +  R[i] 
; 
;            K = -S / Alpha 
; 
;            An[j] = A[j] + K*A[i-j]   for j=1 to i-1 
;                                      where   An[i] = new A[i] 
;            An[i]=K 
; 
;            Alpha = Alpha * (1-K**2) 
; 
;       END 
; 
;----------------------------------------------------------------------- 
;  Constants : Addr_CorrCoef1 -> R 
;              Addr_LPCoefQ27 -> A 
;              Addr_RCoef -> rc 
; 
;  Modified Registers : A, B, ST0(DP), AR0 -- AR5 
; 
;  Return Value : if successfully find LPC coefficients 
;                   A = 0 
;                 else 
;                   A != 0 
;----------------------------------------------------------------------- 
 
        .asg    "AR0", AR_Counter 
        .asg    "AR1", AR_LPC_Index 
 
        .asg    "AR2", AR_Sign 
        .asg    "AR2", pLPC1Q27 
 
        .asg    "AR3", pLPCQ12 
        .asg    "AR3", pLPC2Q27 
        .asg    "AR3", pAutoCorr 
 
        .asg    "AR4", pRCoef 
        .asg    "AR5", pAlpha 
 
xOne    .set    0x60 
 
Levinson: 
        STM     #Addr_CorrCoef1 + 2, pAlpha      ; pAlpha -> R[1]_hi 
        STM     #Addr_RCoef, pRCoef              ; pRCoef -> K[] 
 
        LD      #0, DP 
 
        ;   K = -R[1]/R[0] 
        ;   A[1] = K 
 
        DLD     *pAlpha-, B                      ; pAlpha -> R[0] 
        STL     B, -16, AR_Sign 
 
        CALLD   DIV32B 
        ABS     B 
        DST     B, *pRCoef                       ; *pRCoef = numerator 
 
        LD      AR_Sign, B 
        STM     #Addr_LPCoefQ27, AR_LPC_Index    ; AR_LPC_Index -> A[1]_hi 
        XC      1, BGEQ 
                NEG     A 
 
        MVMM    AR_LPC_Index, pLPC2Q27           ; pLPC1Q27 -> A[1]_hi 
        DST     A, *pRCoef                       ; RCoef[0] = K 
        SFTA    A, -4                            ; Q31 -> Q27 
        ld      A, -1, A 
        ld      A, 1, A 
        DST     A, *pLPC2Q27                     ; A[1] = K 
 
        STM     #M-2, AR_Counter 
        LD      #0, ASM 
 
UpdateLPCoef: 
 
        ;   Alpha=Alpha * (1-K**2) 
 
        MAR     *pRCoef+                          ; pRCoef -> K_lo 
 
        LDU     *pRCoef-, A 
        SFTA    A, 15 
        MPYA    *pRCoef 
        LD      B, -16, A               ; to be bit-exact with C code 
        LD      A, 2, A 
 
        SQURA   *pRCoef, A                    ; A = k ** 2 
        ABS     A 
 
        LD      #07fffh, 16, B 
        OR      #0ffffh, B                    ; B = 0x7fffffff 
        SUB     A, B 
 
;        LD      B, A                          ; A = 1 - K ** 2 
        LD      B, -1, B 
        LD      B,  1, B 
        DST     B, *+pRCoef 
 
;        MAR     *pAlpha+ 
        LD      #0, B 
        LD      #0, A 
 
        MAC     *pRCoef+, *pAlpha, A                
        MACSU   *pRCoef-, *pAlpha+, B 
        LD      B, -16, B 
        LD      B, -1, B 
        LD      B, 1, B 
        ADD     B,  A 
        LD      #0, B 
        MACSU   *pAlpha-, *pRCoef,  B 
        LD      B, -16, B 
        LD      B, -1, B 
        LD      B, 1, B 
        ADD     A, B 
 
        LD      #31, A 
        EXP     B 
        AND     ST1, A                            ; A = ASM 
        NORM    B 
        ADD     T, A 
        DST     B, *pAlpha 
        LD      AL, ASM 
 
        ;   S = 0 
        ;   for(j=1; j<=i-1; j++) 
        ;     S += R[j] * A[i - j] 
        ;   S += R[i] 
 
        LD      #8, A 
        MVMM    pLPC2Q27, pLPC1Q27 
        SUB     AR_Counter, A 
        MAR     *pLPC1Q27+                        ; pLPC1Q27 -> A[i - 1]_lo 
        STLM    A, BRC 
        STM     #Addr_CorrCoef1 + 2, pAutoCorr    ; pAutoCorr -> R[1]_hi 
        LD      #0, B 
        RPTB    EndBlk_S - 1 
                LD      #0, A 
                MACSU   *pLPC1Q27-,  *pAutoCorr, A   ; A  = A[i - j]_lo * R[j]_hi 
                LD      A, -16, A 
                LD      A, -1, A 
                LD      A, 1, A 
                ADD     A, B 
                MAC     *pAutoCorr+, *pLPC1Q27, B    ; pLPC1Q27 -> A[i - j - 1]_lo 
                LD      #0, A 
                MACSU   *pAutoCorr+, *pLPC1Q27-, A   ; A += A[i - j]_hi * R[j]_lo 
                LD      A, -16, A 
                LD      A, -1, A 
                LD      A, 1, A 
                ADD     A, B 
EndBlk_S: 
        SFTA    B, 4 
        DADD    *pAutoCorr, B                         ; S += R[i] 
        ;   K = -S / Alpha 
 
        STL     B, -16, AR_Sign 
 
        CALLD   DIV32B 
        ABS     B 
        DST     B, *pRCoef                       ; *pRCoef = numerator 
 
 
        LD      AR_Sign, B 
        LD      A, ASM, A                       ; normalize K 
        MVMM    AR_LPC_Index, pLPC1Q27 
        XC      1, BGEQ 
                NEG     A 
 
        LD      A, -1, A 
        LD      A, 1, A 
 
        DST     A, *pRCoef 
 
        ; Test for unstable filter 
 
        SUB     #32750, 16, A 
        BC      KeepGoing, ALEQ         ; if unstable, keep old value 
                RET 
 
        ;   if(i == even) 
        ;     A [i >> 1] = An[i >> 1] = A[i >> 1] + K * A[i >> 1] 
        ; 
        ;   for(j=(i-1)>>1; j>=1; j--) 
        ;   { 
        ;     A = A[j] + K * A[i - j] 
        ;     B = A[i - j] + K * A[j] 
        ;     A[j] = An[j] = A 
        ;     A[i - j] = An[i - j] = B 
        ;   } 
KeepGoing: 
        LD      #1, A 
        AND     AR_Counter, A 
        MAR     *pRCoef+                          ; pRCoef -> K_lo 
        BCD     iOdd, ANEQ 
        MVMM    AR_LPC_Index, pLPC2Q27            ; pLPC2Q27 -> A[(i+1) >> 1] 
        DLD     *pLPC1Q27-, B                     ; pLPC1Q27 -> A[(i-1) >> 1] 
        DLD     *AR_LPC_Index+, B 
                LD      #0, A 
                LD      #0, B 
                MACSU   *pRCoef-, *pLPC2Q27, A   ; A  = K_lo * A[i >> 1]_hi 
                LD      A, -16, A 
                LD      A, -1, A 
                LD      A, 1, A 
                MAC     *pRCoef, *pLPC2Q27+, A    ; pRCoef -> K_lo 
                MACSU   *pLPC2Q27-, *pRCoef+, B   ; A += K_hi * A[i >> 1]_lo 
                LD      B, -16, B 
                LD      B, -1, B 
                LD      B, 1, B 
                ADD     B, A 
                DADD    *pLPC2Q27, A              ; A += A[i >> 1] 
                DST     A, *pLPC2Q27+ 
iOdd: 
        LD      #7, A 
        SUB     AR_Counter, A 
        BCD     NewLPCoef, ALT 
        LD      A, -1, B 
        STLM    B, BRC 
 
        NOP 
 
        RPTB    NewLPCoef - 1 
                LD      #0, A 
                LD      #0, B 
                MACSU   *pRCoef,  *pLPC2Q27+, A   ; A  = K_lo * A[i - j]_hi 
                LD      A, -16, A 
                LD      A, -1, A 
                LD      A, 1+1, A 
                LD      A, 16-1, A 
                MACSU   *pRCoef-, *pLPC1Q27+, B   ; B  = K_lo * A[j]_hi 
                LD      B, -16, B 
                LD      B, -1, B 
                LD      B, 1 +1, B 
                LD      B, 16-1, B 
 
                MACSU   *pLPC2Q27-, *pRCoef,  A   ; A += K_hi * A[i - j]_lo 
                LD      A, -16, A 
                LD      A, -1, A 
                LD      A, 1, A 
                MACSU   *pLPC1Q27-, *pRCoef,  B   ; B += K_hi * A[j]_lo 
                LD      B, -16, B 
                LD      B, -1, B 
                LD      B, 1, B 
 
                MAC     *pRCoef , *pLPC2Q27, A 
                MAC     *pRCoef+, *pLPC1Q27, B    ; pRCoef -> K_lo 
 
                DADD    *pLPC1Q27, A              ; A += A[j] 
                DADD    *pLPC2Q27, B              ; B += A[i - j] 
                DST     A, *pLPC1Q27-             ; pLPC1Q27 -> A[j - 1]_hi 
                DST     B, *pLPC2Q27+             ; pLPC2Q27 -> A[i - j + 1]_hi 
NewLPCoef: 
; _________ An[i]=K __________ 
        MAR     *pRCoef-                          ; 
        DLD     *pRCoef, A 
        SFTA    A, -4                             ; Q31 -> Q27 
;1998/11/20 
        LD      A, -1, A 
        LD      A, 1, A 
;1998/11/20 
        DST     A, *pLPC2Q27 
 
        BANZ    UpdateLPCoef, *AR_Counter- 
 
        STM     #M - 1, BRC 
        STM     #Addr_LPCoefQ27, pLPC1Q27 
        LD      #1, 14, B 
 
        RPTBD   EndUpdateCoef - 1 
        STM     Addr_lpc_coefQ12, pLPCQ12 
 
                DADD    *pLPC1Q27+, B, A 
                STL     A, -15, *pLPCQ12+ 
EndUpdateCoef: 
 
        LD      #0, A 
        RET 
 
 
;---------------------------------------------------- 
;  DIV32B : 32 bit fractional division 
;          abs(NUMER)<=abs(DENOM), DENOM>0, NUMER>=0 
; 
;       input : 
;                NUMER(32) = | Nhi(16) | Nlo(16) | 
;                DENOM(32) = | Dhi(16) | Dlo(16) | 
; 
;                AR4 -> Nhi 
;                AR5 -> Dhi 
; 
;       output : 
;                if  ((DENOM>0) && (NUMER>0)) 
;                      A = QUOT(32) 
;                else  A = 0 
; 
;       Modified Registers : AR3, AR5 
;---------------------------------------------------- 
                .def     DIV32B 
 
                .asg     "Addr_local_buf1 + 128", L_32 
 
                .asg     "AR3", pB 
                .asg     "AR3", pL_32 
                .asg     "AR4", pNum 
                .asg     "AR5", pDen 
 
 
DIV32B: 
        DLD     *pDen, B 
        LD      #0, A 
        RC      BLEQ 
 
;DIV16 
        LD      #03fffh, 16, B    ; approx = div_s( (Word16)0x3fff, denom_hi); 
        RPT     #15-1 
                SUBC    *pDen, B        ; BL = approx 
        STLM    B, T                    ; T = approx >= 0 since Den > 0 
 
        RSBX    FRCT                    ; to be bit-exact with C code 
 
;MPY32_16 
        MAR     *pDen+          ; L_32 = Mpy_32_16(denom, approx) 
        MPYU    *pDen-, A 
        LD      A, -16, A 
        MAC     *pDen, A 
 
        LD      #04000h, 16, B 
        SUB     #1, B 
        SUB     A, B                 ; Q29 
 
        SSBX    FRCT                 ; to be bit-exact with C code 
 
        STM     #BL, pB 
 
;MPY32_16 
        MPYU    *pB+, A 
        LD      A, -16, A 
        MAC     *pB-, A       ; A = L_32 
 
        LD      A, 1, A       ; Q28 -> Q29, to be bit-exact with C code 
 
        STM     #L_32, pL_32 
        DST     A, *pL_32 
        MAR     *pL_32+ 
 
;MPY32 
        LD      #0, A 
        LD      #0, B 
        MACSU   *pL_32-, *pNum+, A 
        LD      A, -16, A 
        LD      A,  -1, A                ; to be bit-exact with C code 
        Ld      A,   1, A 
 
        MACSU   *pNum-, *pL_32 , B 
        LD      B, -16, B 
        LD      B,  -1, B                ; to be bit-exact with C code 
        Ld      B,   1, B 
        ADD     B , A 
 
        RETD 
        MAC     *pL_32, *pNum, A 
        LD      A, 2, A