comparison src/levinson.c @ 0:56410792419a

src: original EFR source from ETSI
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 03 Apr 2024 05:31:37 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:56410792419a
1 /*************************************************************************
2 *
3 * FUNCTION: Levinson()
4 *
5 * PURPOSE: Levinson-Durbin algorithm in double precision. To compute the
6 * LP filter parameters from the speech autocorrelations.
7 *
8 * DESCRIPTION:
9 * R[i] autocorrelations.
10 * A[i] filter coefficients.
11 * K reflection coefficients.
12 * Alpha prediction gain.
13 *
14 * Initialisation:
15 * A[0] = 1
16 * K = -R[1]/R[0]
17 * A[1] = K
18 * Alpha = R[0] * (1-K**2]
19 *
20 * Do for i = 2 to M
21 *
22 * S = SUM ( R[j]*A[i-j] ,j=1,i-1 ) + R[i]
23 *
24 * K = -S / Alpha
25 *
26 * An[j] = A[j] + K*A[i-j] for j=1 to i-1
27 * where An[i] = new A[i]
28 * An[i]=K
29 *
30 * Alpha=Alpha * (1-K**2)
31 *
32 * END
33 *
34 *************************************************************************/
35
36 #include "typedef.h"
37 #include "basic_op.h"
38 #include "oper_32b.h"
39 #include "count.h"
40
41 /* Lpc order == 10 */
42
43 #define M 10
44
45 /* Last A(z) for case of unstable filter */
46
47 Word16 old_A[M + 1];
48
49 void Levinson (
50 Word16 Rh[], /* (i) : Rh[m+1] Vector of autocorrelations (msb) */
51 Word16 Rl[], /* (i) : Rl[m+1] Vector of autocorrelations (lsb) */
52 Word16 A[], /* (o) : A[m] LPC coefficients (m = 10) */
53 Word16 rc[] /* (o) : rc[4] First 4 reflection coefficients */
54
55 )
56 {
57 Word16 i, j;
58 Word16 hi, lo;
59 Word16 Kh, Kl; /* reflexion coefficient; hi and lo */
60 Word16 alp_h, alp_l, alp_exp; /* Prediction gain; hi lo and exponent */
61 Word16 Ah[M + 1], Al[M + 1]; /* LPC coef. in double prec. */
62 Word16 Anh[M + 1], Anl[M + 1];/* LPC coef.for next iteration in double
63 prec. */
64 Word32 t0, t1, t2; /* temporary variable */
65
66 /* K = A[1] = -R[1] / R[0] */
67
68 t1 = L_Comp (Rh[1], Rl[1]);
69 t2 = L_abs (t1); /* abs R[1] */
70 t0 = Div_32 (t2, Rh[0], Rl[0]); /* R[1]/R[0] */
71 test ();
72 if (t1 > 0)
73 t0 = L_negate (t0); /* -R[1]/R[0] */
74 L_Extract (t0, &Kh, &Kl); /* K in DPF */
75
76 rc[0] = round (t0); move16 ();
77
78 t0 = L_shr (t0, 4); /* A[1] in */
79 L_Extract (t0, &Ah[1], &Al[1]); /* A[1] in DPF */
80
81 /* Alpha = R[0] * (1-K**2) */
82
83 t0 = Mpy_32 (Kh, Kl, Kh, Kl); /* K*K */
84 t0 = L_abs (t0); /* Some case <0 !! */
85 t0 = L_sub ((Word32) 0x7fffffffL, t0); /* 1 - K*K */
86 L_Extract (t0, &hi, &lo); /* DPF format */
87 t0 = Mpy_32 (Rh[0], Rl[0], hi, lo); /* Alpha in */
88
89 /* Normalize Alpha */
90
91 alp_exp = norm_l (t0);
92 t0 = L_shl (t0, alp_exp);
93 L_Extract (t0, &alp_h, &alp_l); /* DPF format */
94
95 /*--------------------------------------*
96 * ITERATIONS I=2 to M *
97 *--------------------------------------*/
98
99 for (i = 2; i <= M; i++)
100 {
101 /* t0 = SUM ( R[j]*A[i-j] ,j=1,i-1 ) + R[i] */
102
103 t0 = 0; move32 ();
104 for (j = 1; j < i; j++)
105 {
106 t0 = L_add (t0, Mpy_32 (Rh[j], Rl[j], Ah[i - j], Al[i - j]));
107 }
108 t0 = L_shl (t0, 4);
109
110 t1 = L_Comp (Rh[i], Rl[i]);
111 t0 = L_add (t0, t1); /* add R[i] */
112
113 /* K = -t0 / Alpha */
114
115 t1 = L_abs (t0);
116 t2 = Div_32 (t1, alp_h, alp_l); /* abs(t0)/Alpha */
117 test ();
118 if (t0 > 0)
119 t2 = L_negate (t2); /* K =-t0/Alpha */
120 t2 = L_shl (t2, alp_exp); /* denormalize; compare to Alpha */
121 L_Extract (t2, &Kh, &Kl); /* K in DPF */
122
123 test ();
124 if (sub (i, 5) < 0)
125 {
126 rc[i - 1] = round (t2); move16 ();
127 }
128 /* Test for unstable filter. If unstable keep old A(z) */
129
130 test ();
131 if (sub (abs_s (Kh), 32750) > 0)
132 {
133 for (j = 0; j <= M; j++)
134 {
135 A[j] = old_A[j]; move16 ();
136 }
137
138 for (j = 0; j < 4; j++)
139 {
140 rc[j] = 0; move16 ();
141 }
142
143 return;
144 }
145 /*------------------------------------------*
146 * Compute new LPC coeff. -> An[i] *
147 * An[j]= A[j] + K*A[i-j] , j=1 to i-1 *
148 * An[i]= K *
149 *------------------------------------------*/
150
151 for (j = 1; j < i; j++)
152 {
153 t0 = Mpy_32 (Kh, Kl, Ah[i - j], Al[i - j]);
154 t0 = L_mac (t0, Ah[j], 32767);
155 t0 = L_mac (t0, Al[j], 1);
156 L_Extract (t0, &Anh[j], &Anl[j]);
157 }
158 t2 = L_shr (t2, 4);
159 L_Extract (t2, &Anh[i], &Anl[i]);
160
161 /* Alpha = Alpha * (1-K**2) */
162
163 t0 = Mpy_32 (Kh, Kl, Kh, Kl); /* K*K */
164 t0 = L_abs (t0); /* Some case <0 !! */
165 t0 = L_sub ((Word32) 0x7fffffffL, t0); /* 1 - K*K */
166 L_Extract (t0, &hi, &lo); /* DPF format */
167 t0 = Mpy_32 (alp_h, alp_l, hi, lo);
168
169 /* Normalize Alpha */
170
171 j = norm_l (t0);
172 t0 = L_shl (t0, j);
173 L_Extract (t0, &alp_h, &alp_l); /* DPF format */
174 alp_exp = add (alp_exp, j); /* Add normalization to
175 alp_exp */
176
177 /* A[j] = An[j] */
178
179 for (j = 1; j <= i; j++)
180 {
181 Ah[j] = Anh[j]; move16 ();
182 Al[j] = Anl[j]; move16 ();
183 }
184 }
185
186 A[0] = 4096; move16 ();
187 for (i = 1; i <= M; i++)
188 {
189 t0 = L_Comp (Ah[i], Al[i]);
190 old_A[i] = A[i] = round (L_shl (t0, 1));move16 (); move16 ();
191 }
192
193 return;
194 }