📄 lpc2lsp.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 + -