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