Mercurial > hg > audiostuff
comparison spandsp-0.0.6pre17/src/gsm0610_lpc.c @ 4:26cd8f1ef0b1
import spandsp-0.0.6pre17
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 15:50:58 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
3:c6c5a16ce2f2 | 4:26cd8f1ef0b1 |
---|---|
1 /* | |
2 * SpanDSP - a series of DSP components for telephony | |
3 * | |
4 * gsm0610_lpc.c - GSM 06.10 full rate speech codec. | |
5 * | |
6 * Written by Steve Underwood <steveu@coppice.org> | |
7 * | |
8 * Copyright (C) 2006 Steve Underwood | |
9 * | |
10 * All rights reserved. | |
11 * | |
12 * This program is free software; you can redistribute it and/or modify | |
13 * it under the terms of the GNU Lesser General Public License version 2.1, | |
14 * as published by the Free Software Foundation. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU Lesser General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU Lesser General Public | |
22 * License along with this program; if not, write to the Free Software | |
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
24 * | |
25 * This code is based on the widely used GSM 06.10 code available from | |
26 * http://kbs.cs.tu-berlin.de/~jutta/toast.html | |
27 * | |
28 * $Id: gsm0610_lpc.c,v 1.29 2009/02/05 15:57:27 steveu Exp $ | |
29 */ | |
30 | |
31 /*! \file */ | |
32 | |
33 #if defined(HAVE_CONFIG_H) | |
34 #include "config.h" | |
35 #endif | |
36 | |
37 #include <assert.h> | |
38 #include <inttypes.h> | |
39 #if defined(HAVE_TGMATH_H) | |
40 #include <tgmath.h> | |
41 #endif | |
42 #if defined(HAVE_MATH_H) | |
43 #include <math.h> | |
44 #endif | |
45 #include "floating_fudge.h" | |
46 #include <stdlib.h> | |
47 #include <memory.h> | |
48 | |
49 #include "spandsp/telephony.h" | |
50 #include "spandsp/fast_convert.h" | |
51 #include "spandsp/bitstream.h" | |
52 #include "spandsp/bit_operations.h" | |
53 #include "spandsp/saturated.h" | |
54 #include "spandsp/vector_int.h" | |
55 #include "spandsp/gsm0610.h" | |
56 | |
57 #include "gsm0610_local.h" | |
58 | |
59 /* 4.2.4 .. 4.2.7 LPC ANALYSIS SECTION */ | |
60 | |
61 /* The number of left shifts needed to normalize the 32 bit | |
62 variable x for positive values on the interval | |
63 with minimum of | |
64 minimum of 1073741824 (01000000000000000000000000000000) and | |
65 maximum of 2147483647 (01111111111111111111111111111111) | |
66 and for negative values on the interval with | |
67 minimum of -2147483648 (-10000000000000000000000000000000) and | |
68 maximum of -1073741824 ( -1000000000000000000000000000000). | |
69 | |
70 In order to normalize the result, the following | |
71 operation must be done: norm_var1 = x << gsm0610_norm(x); | |
72 | |
73 (That's 'ffs', only from the left, not the right..) | |
74 */ | |
75 | |
76 int16_t gsm0610_norm(int32_t x) | |
77 { | |
78 assert(x != 0); | |
79 | |
80 if (x < 0) | |
81 { | |
82 if (x <= -1073741824) | |
83 return 0; | |
84 /*endif*/ | |
85 x = ~x; | |
86 } | |
87 /*endif*/ | |
88 return (int16_t) (30 - top_bit(x)); | |
89 } | |
90 /*- End of function --------------------------------------------------------*/ | |
91 | |
92 /* | |
93 (From p. 46, end of section 4.2.5) | |
94 | |
95 NOTE: The following lines gives [sic] one correct implementation | |
96 of the div(num, denum) arithmetic operation. Compute div | |
97 which is the integer division of num by denom: with | |
98 denom >= num > 0 | |
99 */ | |
100 static int16_t gsm_div(int16_t num, int16_t denom) | |
101 { | |
102 int32_t num32; | |
103 int32_t denom32; | |
104 int16_t div; | |
105 int k; | |
106 | |
107 /* The parameter num sometimes becomes zero. | |
108 Although this is explicitly guarded against in 4.2.5, | |
109 we assume that the result should then be zero as well. */ | |
110 | |
111 assert(num >= 0 && denom >= num); | |
112 if (num == 0) | |
113 return 0; | |
114 /*endif*/ | |
115 num32 = num; | |
116 denom32 = denom; | |
117 div = 0; | |
118 k = 15; | |
119 while (k--) | |
120 { | |
121 div <<= 1; | |
122 num32 <<= 1; | |
123 | |
124 if (num32 >= denom32) | |
125 { | |
126 num32 -= denom32; | |
127 div++; | |
128 } | |
129 /*endif*/ | |
130 } | |
131 /*endwhile*/ | |
132 | |
133 return div; | |
134 } | |
135 /*- End of function --------------------------------------------------------*/ | |
136 | |
137 #if defined(__GNUC__) && defined(SPANDSP_USE_MMX) | |
138 static void gsm0610_vec_vsraw(const int16_t *p, int n, int bits) | |
139 { | |
140 static const int64_t ones = 0x0001000100010001LL; | |
141 | |
142 if (n == 0) | |
143 return; | |
144 /*endif*/ | |
145 #if defined(__x86_64__) | |
146 __asm__ __volatile__( | |
147 " leaq -16(%%rsi,%%rax,2),%%rdx;\n" /* edx = top - 16 */ | |
148 " emms;\n" | |
149 " movd %%ecx,%%mm3;\n" | |
150 " movq %[ones],%%mm2;\n" | |
151 " psllw %%mm3,%%mm2;\n" | |
152 " psrlw $1,%%mm2;\n" | |
153 " cmpq %%rdx,%%rsi;" | |
154 " ja 4f;\n" | |
155 | |
156 " .p2align 2;\n" | |
157 /* 8 words per iteration */ | |
158 "6:\n" | |
159 " movq (%%rsi),%%mm0;\n" | |
160 " movq 8(%%rsi),%%mm1;\n" | |
161 " paddsw %%mm2,%%mm0;\n" | |
162 " psraw %%mm3,%%mm0;\n" | |
163 " paddsw %%mm2,%%mm1;\n" | |
164 " psraw %%mm3,%%mm1;\n" | |
165 " movq %%mm0,(%%rsi);\n" | |
166 " movq %%mm1,8(%%rsi);\n" | |
167 " addq $16,%%rsi;\n" | |
168 " cmpq %%rdx,%%rsi;\n" | |
169 " jbe 6b;\n" | |
170 | |
171 " .p2align 2;\n" | |
172 "4:\n" | |
173 " addq $12,%%rdx;\n" /* now edx = top-4 */ | |
174 " cmpq %%rdx,%%rsi;\n" | |
175 " ja 3f;\n" | |
176 | |
177 " .p2align 2;\n" | |
178 /* do up to 6 words, two per iteration */ | |
179 "5:\n" | |
180 " movd (%%rsi),%%mm0;\n" | |
181 " paddsw %%mm2,%%mm0;\n" | |
182 " psraw %%mm3,%%mm0;\n" | |
183 " movd %%mm0,(%%rsi);\n" | |
184 " addq $4,%%rsi;\n" | |
185 " cmpq %%rdx,%%rsi;\n" | |
186 " jbe 5b;\n" | |
187 | |
188 " .p2align 2;\n" | |
189 "3:\n" | |
190 " addq $2,%%rdx;\n" /* now edx = top-2 */ | |
191 " cmpq %%rdx,%%rsi;\n" | |
192 " ja 2f;\n" | |
193 | |
194 " movzwl (%%rsi),%%eax;\n" | |
195 " movd %%eax,%%mm0;\n" | |
196 " paddsw %%mm2,%%mm0;\n" | |
197 " psraw %%mm3,%%mm0;\n" | |
198 " movd %%mm0,%%eax;\n" | |
199 " movw %%ax,(%%rsi);\n" | |
200 | |
201 " .p2align 2;\n" | |
202 "2:\n" | |
203 " emms;\n" | |
204 : | |
205 : "S" (p), "a" (n), "c" (bits), [ones] "m" (ones) | |
206 : "edx" | |
207 ); | |
208 #else | |
209 __asm__ __volatile__( | |
210 " leal -16(%%esi,%%eax,2),%%edx;\n" /* edx = top - 16 */ | |
211 " emms;\n" | |
212 " movd %%ecx,%%mm3;\n" | |
213 " movq %[ones],%%mm2;\n" | |
214 " psllw %%mm3,%%mm2;\n" | |
215 " psrlw $1,%%mm2;\n" | |
216 " cmpl %%edx,%%esi;" | |
217 " ja 4f;\n" | |
218 | |
219 " .p2align 2;\n" | |
220 /* 8 words per iteration */ | |
221 "6:\n" | |
222 " movq (%%esi),%%mm0;\n" | |
223 " movq 8(%%esi),%%mm1;\n" | |
224 " paddsw %%mm2,%%mm0;\n" | |
225 " psraw %%mm3,%%mm0;\n" | |
226 " paddsw %%mm2,%%mm1;\n" | |
227 " psraw %%mm3,%%mm1;\n" | |
228 " movq %%mm0,(%%esi);\n" | |
229 " movq %%mm1,8(%%esi);\n" | |
230 " addl $16,%%esi;\n" | |
231 " cmpl %%edx,%%esi;\n" | |
232 " jbe 6b;\n" | |
233 | |
234 " .p2align 2;\n" | |
235 "4:\n" | |
236 " addl $12,%%edx;\n" /* now edx = top-4 */ | |
237 " cmpl %%edx,%%esi;\n" | |
238 " ja 3f;\n" | |
239 | |
240 " .p2align 2;\n" | |
241 /* do up to 6 words, two per iteration */ | |
242 "5:\n" | |
243 " movd (%%esi),%%mm0;\n" | |
244 " paddsw %%mm2,%%mm0;\n" | |
245 " psraw %%mm3,%%mm0;\n" | |
246 " movd %%mm0,(%%esi);\n" | |
247 " addl $4,%%esi;\n" | |
248 " cmpl %%edx,%%esi;\n" | |
249 " jbe 5b;\n" | |
250 | |
251 " .p2align 2;\n" | |
252 "3:\n" | |
253 " addl $2,%%edx;\n" /* now edx = top-2 */ | |
254 " cmpl %%edx,%%esi;\n" | |
255 " ja 2f;\n" | |
256 | |
257 " movzwl (%%esi),%%eax;\n" | |
258 " movd %%eax,%%mm0;\n" | |
259 " paddsw %%mm2,%%mm0;\n" | |
260 " psraw %%mm3,%%mm0;\n" | |
261 " movd %%mm0,%%eax;\n" | |
262 " movw %%ax,(%%esi);\n" | |
263 | |
264 " .p2align 2;\n" | |
265 "2:\n" | |
266 " emms;\n" | |
267 : | |
268 : "S" (p), "a" (n), "c" (bits), [ones] "m" (ones) | |
269 : "edx" | |
270 ); | |
271 #endif | |
272 } | |
273 /*- End of function --------------------------------------------------------*/ | |
274 #endif | |
275 | |
276 /* 4.2.4 */ | |
277 static void autocorrelation(int16_t amp[GSM0610_FRAME_LEN], int32_t L_ACF[9]) | |
278 { | |
279 int k; | |
280 int16_t smax; | |
281 int16_t scalauto; | |
282 #if !(defined(__GNUC__) && defined(SPANDSP_USE_MMX)) | |
283 int i; | |
284 int temp; | |
285 int16_t *sp; | |
286 int16_t sl; | |
287 #endif | |
288 | |
289 /* The goal is to compute the array L_ACF[k]. The signal s[i] must | |
290 be scaled in order to avoid an overflow situation. */ | |
291 | |
292 /* Dynamic scaling of the array s[0..159] */ | |
293 /* Search for the maximum. */ | |
294 #if defined(__GNUC__) && defined(SPANDSP_USE_MMX) | |
295 smax = saturate(vec_min_maxi16(amp, GSM0610_FRAME_LEN, NULL)); | |
296 #else | |
297 for (smax = 0, k = 0; k < GSM0610_FRAME_LEN; k++) | |
298 { | |
299 temp = saturated_abs16(amp[k]); | |
300 if (temp > smax) | |
301 smax = (int16_t) temp; | |
302 /*endif*/ | |
303 } | |
304 /*endfor*/ | |
305 #endif | |
306 | |
307 /* Computation of the scaling factor. */ | |
308 if (smax == 0) | |
309 { | |
310 scalauto = 0; | |
311 } | |
312 else | |
313 { | |
314 assert(smax > 0); | |
315 scalauto = (int16_t) (4 - gsm0610_norm((int32_t) smax << 16)); | |
316 } | |
317 /*endif*/ | |
318 | |
319 /* Scaling of the array s[0...159] */ | |
320 #if defined(__GNUC__) && defined(SPANDSP_USE_MMX) | |
321 if (scalauto > 0) | |
322 gsm0610_vec_vsraw(amp, GSM0610_FRAME_LEN, scalauto); | |
323 /*endif*/ | |
324 #else | |
325 if (scalauto > 0) | |
326 { | |
327 for (k = 0; k < GSM0610_FRAME_LEN; k++) | |
328 amp[k] = gsm_mult_r(amp[k], 16384 >> (scalauto - 1)); | |
329 /*endfor*/ | |
330 } | |
331 /*endif*/ | |
332 #endif | |
333 | |
334 /* Compute the L_ACF[..]. */ | |
335 #if defined(__GNUC__) && defined(SPANDSP_USE_MMX) | |
336 for (k = 0; k < 9; k++) | |
337 L_ACF[k] = vec_dot_prodi16(amp, amp + k, GSM0610_FRAME_LEN - k) << 1; | |
338 /*endfor*/ | |
339 #else | |
340 sp = amp; | |
341 sl = *sp; | |
342 L_ACF[0] = ((int32_t) sl*(int32_t) sp[0]); | |
343 sl = *++sp; | |
344 L_ACF[0] += ((int32_t) sl*(int32_t) sp[0]); | |
345 L_ACF[1] = ((int32_t) sl*(int32_t) sp[-1]); | |
346 sl = *++sp; | |
347 L_ACF[0] += ((int32_t) sl*(int32_t) sp[0]); | |
348 L_ACF[1] += ((int32_t) sl*(int32_t) sp[-1]); | |
349 L_ACF[2] = ((int32_t) sl*(int32_t) sp[-2]); | |
350 sl = *++sp; | |
351 L_ACF[0] += ((int32_t) sl*(int32_t) sp[0]); | |
352 L_ACF[1] += ((int32_t) sl*(int32_t) sp[-1]); | |
353 L_ACF[2] += ((int32_t) sl*(int32_t) sp[-2]); | |
354 L_ACF[3] = ((int32_t) sl*(int32_t) sp[-3]); | |
355 sl = *++sp; | |
356 L_ACF[0] += ((int32_t) sl*(int32_t) sp[0]); | |
357 L_ACF[1] += ((int32_t) sl*(int32_t) sp[-1]); | |
358 L_ACF[2] += ((int32_t) sl*(int32_t) sp[-2]); | |
359 L_ACF[3] += ((int32_t) sl*(int32_t) sp[-3]); | |
360 L_ACF[4] = ((int32_t) sl*(int32_t) sp[-4]); | |
361 sl = *++sp; | |
362 L_ACF[0] += ((int32_t) sl*(int32_t) sp[0]); | |
363 L_ACF[1] += ((int32_t) sl*(int32_t) sp[-1]); | |
364 L_ACF[2] += ((int32_t) sl*(int32_t) sp[-2]); | |
365 L_ACF[3] += ((int32_t) sl*(int32_t) sp[-3]); | |
366 L_ACF[4] += ((int32_t) sl*(int32_t) sp[-4]); | |
367 L_ACF[5] = ((int32_t) sl*(int32_t) sp[-5]); | |
368 sl = *++sp; | |
369 L_ACF[0] += ((int32_t) sl*(int32_t) sp[0]); | |
370 L_ACF[1] += ((int32_t) sl*(int32_t) sp[-1]); | |
371 L_ACF[2] += ((int32_t) sl*(int32_t) sp[-2]); | |
372 L_ACF[3] += ((int32_t) sl*(int32_t) sp[-3]); | |
373 L_ACF[4] += ((int32_t) sl*(int32_t) sp[-4]); | |
374 L_ACF[5] += ((int32_t) sl*(int32_t) sp[-5]); | |
375 L_ACF[6] = ((int32_t) sl*(int32_t) sp[-6]); | |
376 sl = *++sp; | |
377 L_ACF[0] += ((int32_t) sl*(int32_t) sp[0]); | |
378 L_ACF[1] += ((int32_t) sl*(int32_t) sp[-1]); | |
379 L_ACF[2] += ((int32_t) sl*(int32_t) sp[-2]); | |
380 L_ACF[3] += ((int32_t) sl*(int32_t) sp[-3]); | |
381 L_ACF[4] += ((int32_t) sl*(int32_t) sp[-4]); | |
382 L_ACF[5] += ((int32_t) sl*(int32_t) sp[-5]); | |
383 L_ACF[6] += ((int32_t) sl*(int32_t) sp[-6]); | |
384 L_ACF[7] = ((int32_t) sl*(int32_t) sp[-7]); | |
385 sl = *++sp; | |
386 L_ACF[0] += ((int32_t) sl*(int32_t) sp[0]); | |
387 L_ACF[1] += ((int32_t) sl*(int32_t) sp[-1]); | |
388 L_ACF[2] += ((int32_t) sl*(int32_t) sp[-2]); | |
389 L_ACF[3] += ((int32_t) sl*(int32_t) sp[-3]); | |
390 L_ACF[4] += ((int32_t) sl*(int32_t) sp[-4]); | |
391 L_ACF[5] += ((int32_t) sl*(int32_t) sp[-5]); | |
392 L_ACF[6] += ((int32_t) sl*(int32_t) sp[-6]); | |
393 L_ACF[7] += ((int32_t) sl*(int32_t) sp[-7]); | |
394 L_ACF[8] = ((int32_t) sl*(int32_t) sp[-8]); | |
395 for (i = 9; i < GSM0610_FRAME_LEN; i++) | |
396 { | |
397 sl = *++sp; | |
398 L_ACF[0] += ((int32_t) sl*(int32_t) sp[0]); | |
399 L_ACF[1] += ((int32_t) sl*(int32_t) sp[-1]); | |
400 L_ACF[2] += ((int32_t) sl*(int32_t) sp[-2]); | |
401 L_ACF[3] += ((int32_t) sl*(int32_t) sp[-3]); | |
402 L_ACF[4] += ((int32_t) sl*(int32_t) sp[-4]); | |
403 L_ACF[5] += ((int32_t) sl*(int32_t) sp[-5]); | |
404 L_ACF[6] += ((int32_t) sl*(int32_t) sp[-6]); | |
405 L_ACF[7] += ((int32_t) sl*(int32_t) sp[-7]); | |
406 L_ACF[8] += ((int32_t) sl*(int32_t) sp[-8]); | |
407 } | |
408 /*endfor*/ | |
409 for (k = 0; k < 9; k++) | |
410 L_ACF[k] <<= 1; | |
411 /*endfor*/ | |
412 #endif | |
413 /* Rescaling of the array s[0..159] */ | |
414 if (scalauto > 0) | |
415 { | |
416 assert(scalauto <= 4); | |
417 for (k = 0; k < GSM0610_FRAME_LEN; k++) | |
418 amp[k] <<= scalauto; | |
419 /*endfor*/ | |
420 } | |
421 /*endif*/ | |
422 } | |
423 /*- End of function --------------------------------------------------------*/ | |
424 | |
425 /* 4.2.5 */ | |
426 static void reflection_coefficients(int32_t L_ACF[9], int16_t r[8]) | |
427 { | |
428 int i; | |
429 int m; | |
430 int n; | |
431 int16_t temp; | |
432 int16_t ACF[9]; | |
433 int16_t P[9]; | |
434 int16_t K[9]; | |
435 | |
436 /* Schur recursion with 16 bits arithmetic. */ | |
437 if (L_ACF[0] == 0) | |
438 { | |
439 for (i = 8; i--; *r++ = 0) | |
440 ; | |
441 /*endfor*/ | |
442 return; | |
443 } | |
444 /*endif*/ | |
445 | |
446 assert(L_ACF[0] != 0); | |
447 temp = gsm0610_norm(L_ACF[0]); | |
448 | |
449 assert(temp >= 0 && temp < 32); | |
450 | |
451 /* ? overflow ? */ | |
452 for (i = 0; i <= 8; i++) | |
453 ACF[i] = (int16_t) ((L_ACF[i] << temp) >> 16); | |
454 /*endfor*/ | |
455 | |
456 /* Initialize array P[..] and K[..] for the recursion. */ | |
457 for (i = 1; i <= 7; i++) | |
458 K[i] = ACF[i]; | |
459 /*endfor*/ | |
460 for (i = 0; i <= 8; i++) | |
461 P[i] = ACF[i]; | |
462 /*endfor*/ | |
463 /* Compute reflection coefficients */ | |
464 for (n = 1; n <= 8; n++, r++) | |
465 { | |
466 temp = P[1]; | |
467 temp = saturated_abs16(temp); | |
468 if (P[0] < temp) | |
469 { | |
470 for (i = n; i <= 8; i++) | |
471 *r++ = 0; | |
472 /*endfor*/ | |
473 return; | |
474 } | |
475 /*endif*/ | |
476 | |
477 *r = gsm_div(temp, P[0]); | |
478 | |
479 assert(*r >= 0); | |
480 if (P[1] > 0) | |
481 *r = -*r; /* r[n] = sub(0, r[n]) */ | |
482 /*endif*/ | |
483 assert(*r != INT16_MIN); | |
484 if (n == 8) | |
485 return; | |
486 /*endif*/ | |
487 | |
488 /* Schur recursion */ | |
489 temp = gsm_mult_r(P[1], *r); | |
490 P[0] = saturated_add16(P[0], temp); | |
491 | |
492 for (m = 1; m <= 8 - n; m++) | |
493 { | |
494 temp = gsm_mult_r(K[m], *r); | |
495 P[m] = saturated_add16(P[m + 1], temp); | |
496 | |
497 temp = gsm_mult_r(P[m + 1], *r); | |
498 K[m] = saturated_add16(K[m], temp); | |
499 } | |
500 /*endfor*/ | |
501 } | |
502 /*endfor*/ | |
503 } | |
504 /*- End of function --------------------------------------------------------*/ | |
505 | |
506 /* 4.2.6 */ | |
507 static void transform_to_log_area_ratios(int16_t r[8]) | |
508 { | |
509 int16_t temp; | |
510 int i; | |
511 | |
512 /* The following scaling for r[..] and LAR[..] has been used: | |
513 | |
514 r[..] = integer (real_r[..]*32768.); -1 <= real_r < 1. | |
515 LAR[..] = integer (real_LAR[..] * 16384); | |
516 with -1.625 <= real_LAR <= 1.625 | |
517 */ | |
518 | |
519 /* Computation of the LAR[0..7] from the r[0..7] */ | |
520 for (i = 1; i <= 8; i++, r++) | |
521 { | |
522 temp = saturated_abs16(*r); | |
523 assert(temp >= 0); | |
524 | |
525 if (temp < 22118) | |
526 { | |
527 temp >>= 1; | |
528 } | |
529 else if (temp < 31130) | |
530 { | |
531 assert(temp >= 11059); | |
532 temp -= 11059; | |
533 } | |
534 else | |
535 { | |
536 assert(temp >= 26112); | |
537 temp -= 26112; | |
538 temp <<= 2; | |
539 } | |
540 /*endif*/ | |
541 | |
542 *r = (*r < 0) ? -temp : temp; | |
543 assert(*r != INT16_MIN); | |
544 } | |
545 /*endfor*/ | |
546 } | |
547 /*- End of function --------------------------------------------------------*/ | |
548 | |
549 /* 4.2.7 */ | |
550 static void quantization_and_coding(int16_t LAR[8]) | |
551 { | |
552 int16_t temp; | |
553 | |
554 /* This procedure needs four tables; the following equations | |
555 give the optimum scaling for the constants: | |
556 | |
557 A[0..7] = integer(real_A[0..7] * 1024) | |
558 B[0..7] = integer(real_B[0..7] * 512) | |
559 MAC[0..7] = maximum of the LARc[0..7] | |
560 MIC[0..7] = minimum of the LARc[0..7] */ | |
561 | |
562 #undef STEP | |
563 #define STEP(A,B,MAC,MIC) \ | |
564 temp = saturated_mul16(A, *LAR); \ | |
565 temp = saturated_add16(temp, B); \ | |
566 temp = saturated_add16(temp, 256); \ | |
567 temp >>= 9; \ | |
568 *LAR = (int16_t) ((temp > MAC) \ | |
569 ? \ | |
570 MAC - MIC \ | |
571 : \ | |
572 ((temp < MIC) ? 0 : temp - MIC)); \ | |
573 LAR++; | |
574 | |
575 STEP(20480, 0, 31, -32); | |
576 STEP(20480, 0, 31, -32); | |
577 STEP(20480, 2048, 15, -16); | |
578 STEP(20480, -2560, 15, -16); | |
579 | |
580 STEP(13964, 94, 7, -8); | |
581 STEP(15360, -1792, 7, -8); | |
582 STEP( 8534, -341, 3, -4); | |
583 STEP( 9036, -1144, 3, -4); | |
584 #undef STEP | |
585 } | |
586 /*- End of function --------------------------------------------------------*/ | |
587 | |
588 void gsm0610_lpc_analysis(gsm0610_state_t *s, | |
589 int16_t amp[GSM0610_FRAME_LEN], | |
590 int16_t LARc[8]) | |
591 { | |
592 int32_t L_ACF[9]; | |
593 | |
594 autocorrelation(amp, L_ACF); | |
595 reflection_coefficients(L_ACF, LARc); | |
596 transform_to_log_area_ratios(LARc); | |
597 quantization_and_coding(LARc); | |
598 } | |
599 /*- End of function --------------------------------------------------------*/ | |
600 /*- End of file ------------------------------------------------------------*/ |