comparison intercom/gsm/lpc.c @ 2:13be24d74cd2

import intercom-0.4.1
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 09:57:52 +0200
parents
children
comparison
equal deleted inserted replaced
1:9cadc470e3da 2:13be24d74cd2
1 /*
2 * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
3 * Universitaet Berlin. See the accompanying file "COPYRIGHT" for
4 * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
5 */
6
7 /* $Header: /home/kbs/jutta/src/gsm/gsm-1.0/src/RCS/lpc.c,v 1.1 1992/10/28 00:15:50 jutta Exp $ */
8
9 #include <stdio.h>
10 #include <assert.h>
11
12 #include "private.h"
13
14 #include "gsm.h"
15 #include "proto.h"
16
17 #undef P
18
19 /*
20 * 4.2.4 .. 4.2.7 LPC ANALYSIS SECTION
21 */
22
23 /* 4.2.4 */
24
25
26 static void Autocorrelation P2((s, L_ACF), word * s, /* [0..159] IN/OUT */
27 longword * L_ACF)
28 { /* [0..8] OUT */
29 /*
30 * The goal is to compute the array L_ACF[k]. The signal s[i] must
31 * be scaled in order to avoid an overflow situation.
32 */
33 register int k, i;
34
35 word temp, smax, scalauto;
36 /* longword L_temp; */
37
38 #ifdef USE_FLOAT_MUL
39 float float_s[160];
40 /* longword L_temp2; */
41 #else
42 longword L_temp2;
43 #endif
44
45 /* Dynamic scaling of the array s[0..159]
46 */
47
48 /* Search for the maximum.
49 */
50 smax = 0;
51 for (k = 0; k <= 159; k++) {
52 temp = GSM_ABS(s[k]);
53 if (temp > smax)
54 smax = temp;
55 }
56
57 /* Computation of the scaling factor.
58 */
59 if (smax == 0)
60 scalauto = 0;
61 else {
62 assert(smax > 0);
63 scalauto = 4 - gsm_norm((longword) smax << 16); /* sub(4,..) */
64 }
65
66 /* Scaling of the array s[0...159]
67 */
68
69 if (scalauto > 0) {
70
71 # ifdef USE_FLOAT_MUL
72 # define SCALE(n) \
73 case n: for (k = 0; k <= 159; k++) \
74 float_s[k] = (float) \
75 (s[k] = GSM_MULT_R(s[k], 16384 >> (n-1)));\
76 break;
77 # else
78 # define SCALE(n) \
79 case n: for (k = 0; k <= 159; k++) \
80 s[k] = GSM_MULT_R( s[k], 16384 >> (n-1) );\
81 break;
82 # endif /* USE_FLOAT_MUL */
83
84 switch (scalauto) {
85 SCALE(1)
86 SCALE(2)
87 SCALE(3)
88 SCALE(4)
89 }
90 # undef SCALE
91 }
92 # ifdef USE_FLOAT_MUL
93 else
94 for (k = 0; k <= 159; k++)
95 float_s[k] = (float) s[k];
96 # endif
97
98 /* Compute the L_ACF[..].
99 */
100 {
101 # ifdef USE_FLOAT_MUL
102 register float *sp = float_s;
103 register float sl = *sp;
104 # else
105 word *sp = s;
106 word sl = *sp;
107 # endif
108
109 # define STEP(k) L_ACF[k] += (longword)(sl * sp[ -(k) ]);
110 # define NEXTI sl = *++sp
111
112
113 for (k = 9; k--; L_ACF[k] = 0);
114
115 STEP(0);
116 NEXTI;
117 STEP(0);
118 STEP(1);
119 NEXTI;
120 STEP(0);
121 STEP(1);
122 STEP(2);
123 NEXTI;
124 STEP(0);
125 STEP(1);
126 STEP(2);
127 STEP(3);
128 NEXTI;
129 STEP(0);
130 STEP(1);
131 STEP(2);
132 STEP(3);
133 STEP(4);
134 NEXTI;
135 STEP(0);
136 STEP(1);
137 STEP(2);
138 STEP(3);
139 STEP(4);
140 STEP(5);
141 NEXTI;
142 STEP(0);
143 STEP(1);
144 STEP(2);
145 STEP(3);
146 STEP(4);
147 STEP(5);
148 STEP(6);
149 NEXTI;
150 STEP(0);
151 STEP(1);
152 STEP(2);
153 STEP(3);
154 STEP(4);
155 STEP(5);
156 STEP(6);
157 STEP(7);
158
159 for (i = 8; i <= 159; i++) {
160
161 NEXTI;
162
163 STEP(0);
164 STEP(1);
165 STEP(2);
166 STEP(3);
167 STEP(4);
168 STEP(5);
169 STEP(6);
170 STEP(7);
171 STEP(8);
172 }
173
174 for (k = 9; k--; L_ACF[k] <<= 1);
175
176 }
177 /* Rescaling of the array s[0..159]
178 */
179 if (scalauto > 0) {
180 assert(scalauto <= 4);
181 for (k = 160; k--; *s++ <<= scalauto);
182 }
183 }
184
185 #if defined(USE_FLOAT_MUL) && defined(FAST)
186
187 static void Fast_Autocorrelation P2((s, L_ACF), word * s, /* [0..159] IN/OUT */
188 longword * L_ACF)
189 { /* [0..8] OUT */
190 register int k, i;
191 float f_L_ACF[9];
192 float scale;
193
194 float s_f[160];
195 register float *sf = s_f;
196
197 for (i = 0; i < 160; ++i)
198 sf[i] = s[i];
199 for (k = 0; k <= 8; k++) {
200 register float L_temp2 = 0;
201 register float *sfl = sf - k;
202 for (i = k; i < 160; ++i)
203 L_temp2 += sf[i] * sfl[i];
204 f_L_ACF[k] = L_temp2;
205 }
206 scale = MAX_LONGWORD / f_L_ACF[0];
207
208 for (k = 0; k <= 8; k++) {
209 L_ACF[k] = f_L_ACF[k] * scale;
210 }
211 }
212 #endif /* defined (USE_FLOAT_MUL) && defined (FAST) */
213
214 /* 4.2.5 */
215
216 static void Reflection_coefficients P2((L_ACF, r), longword * L_ACF, /* 0...8 IN */
217 register word * r /* 0...7 OUT */
218 )
219 {
220 register int i, m, n;
221 register word temp;
222 register longword ltmp;
223 word ACF[9]; /* 0..8 */
224 word P[9]; /* 0..8 */
225 word K[9]; /* 2..8 */
226
227 /* Schur recursion with 16 bits arithmetic.
228 */
229
230 if (L_ACF[0] == 0) { /* everything is the same. */
231 for (i = 8; i--; *r++ = 0);
232 return;
233 }
234
235 assert(L_ACF[0] != 0);
236 temp = gsm_norm(L_ACF[0]);
237
238 assert(temp >= 0 && temp < 32);
239
240 /* ? overflow ? */
241 for (i = 0; i <= 8; i++)
242 ACF[i] = SASR(L_ACF[i] << temp, 16);
243
244 /* Initialize array P[..] and K[..] for the recursion.
245 */
246
247 for (i = 1; i <= 7; i++)
248 K[i] = ACF[i];
249 for (i = 0; i <= 8; i++)
250 P[i] = ACF[i];
251
252 /* Compute reflection coefficients
253 */
254 for (n = 1; n <= 8; n++, r++) {
255
256 temp = P[1];
257 temp = GSM_ABS(temp);
258 if (P[0] < temp) {
259 for (i = n; i <= 8; i++)
260 *r++ = 0;
261 return;
262 }
263
264 *r = gsm_div(temp, P[0]);
265
266 assert(*r >= 0);
267 if (P[1] > 0)
268 *r = -*r; /* r[n] = sub(0, r[n]) */
269 assert(*r != MIN_WORD);
270 if (n == 8)
271 return;
272
273 /* Schur recursion
274 */
275 temp = GSM_MULT_R(P[1], *r);
276 P[0] = GSM_ADD(P[0], temp);
277
278 for (m = 1; m <= 8 - n; m++) {
279 temp = GSM_MULT_R(K[m], *r);
280 P[m] = GSM_ADD(P[m + 1], temp);
281
282 temp = GSM_MULT_R(P[m + 1], *r);
283 K[m] = GSM_ADD(K[m], temp);
284 }
285 }
286 }
287
288 /* 4.2.6 */
289
290 static void Transformation_to_Log_Area_Ratios P1((r), register word * r /* 0..7 IN/OUT */
291 )
292 /*
293 * The following scaling for r[..] and LAR[..] has been used:
294 *
295 * r[..] = integer( real_r[..]*32768. ); -1 <= real_r < 1.
296 * LAR[..] = integer( real_LAR[..] * 16384 );
297 * with -1.625 <= real_LAR <= 1.625
298 */
299 {
300 register word temp;
301 register int i;
302
303
304 /* Computation of the LAR[0..7] from the r[0..7]
305 */
306 for (i = 1; i <= 8; i++, r++) {
307
308 temp = *r;
309 temp = GSM_ABS(temp);
310 assert(temp >= 0);
311
312 if (temp < 22118) {
313 temp >>= 1;
314 } else if (temp < 31130) {
315 assert(temp >= 11059);
316 temp -= 11059;
317 } else {
318 assert(temp >= 26112);
319 temp -= 26112;
320 temp <<= 2;
321 }
322
323 *r = *r < 0 ? -temp : temp;
324 assert(*r != MIN_WORD);
325 }
326 }
327
328 /* 4.2.7 */
329
330 static void Quantization_and_coding P1((LAR), register word * LAR /* [0..7] IN/OUT */
331 )
332 {
333 register word temp;
334 longword ltmp;
335 /* ulongword utmp; reported as unused */
336
337
338 /* This procedure needs four tables; the following equations
339 * give the optimum scaling for the constants:
340 *
341 * A[0..7] = integer( real_A[0..7] * 1024 )
342 * B[0..7] = integer( real_B[0..7] * 512 )
343 * MAC[0..7] = maximum of the LARc[0..7]
344 * MIC[0..7] = minimum of the LARc[0..7]
345 */
346
347 # undef STEP
348 # define STEP( A, B, MAC, MIC ) \
349 temp = GSM_MULT( A, *LAR ); \
350 temp = GSM_ADD( temp, B ); \
351 temp = GSM_ADD( temp, 256 ); \
352 temp = SASR( temp, 9 ); \
353 *LAR = temp>MAC ? MAC - MIC : (temp<MIC ? 0 : temp - MIC); \
354 LAR++;
355
356 STEP(20480, 0, 31, -32);
357 STEP(20480, 0, 31, -32);
358 STEP(20480, 2048, 15, -16);
359 STEP(20480, -2560, 15, -16);
360
361 STEP(13964, 94, 7, -8);
362 STEP(15360, -1792, 7, -8);
363 STEP(8534, -341, 3, -4);
364 STEP(9036, -1144, 3, -4);
365
366 # undef STEP
367 }
368
369 void Gsm_LPC_Analysis P3((S, s, LARc), struct gsm_state *S, word * s, /* 0..159 signals IN/OUT */
370 word * LARc)
371 { /* 0..7 LARc's OUT */
372 longword L_ACF[9];
373
374 #if defined(USE_FLOAT_MUL) && defined(FAST)
375 if (S->fast)
376 Fast_Autocorrelation(s, L_ACF);
377 else
378 #endif
379 Autocorrelation(s, L_ACF);
380 Reflection_coefficients(L_ACF, LARc);
381 Transformation_to_Log_Area_Ratios(LARc);
382 Quantization_and_coding(LARc);
383 }

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.