1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 /****************************************************************************************
19 Portions of this file are derived from the following 3GPP standard:
20
21 3GPP TS 26.073
22 ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
23 Available from http://www.3gpp.org
24
25 (C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
26 Permission to distribute, modify and use this file under the standard license
27 terms listed above has been obtained from the copyright holder.
28 ****************************************************************************************/
29 /*
30
31 Pathname: ./audio/gsm-amr/c/src/lsp_az.c
32 Funtions: Get_lsp_pol
33 Lsp_Az
34
35 ------------------------------------------------------------------------------
36 REVISION HISTORY
37
38 Description: Updated template used to PV coding template. First attempt at
39 optimizing C code.
40
41 Description: Deleted all Local stores needed/modified. Optimized Lsp_Az
42 function by getting rid of call to L_shr_r function.
43
44 Description: Updated file per comments gathered from Phase 2/3 review.
45
46 Description: Added setting of Overflow flag in the inlined code.
47
48 Description: 1. Optimized Lsp_Az function code.
49 2. Changed Input/Output definitions by adding Word type.
50
51 Description: Made changes based on review meeting.
52 1. Removed pseudocode.
53
54 Description: Synchronized file with UMTS version 3.2.0. Updated coding
55 template. Removed unnecessary include files.
56
57 Description: Replaced basic_op.h and oper_32b.h with the header files of the
58 math functions used in the file.
59
60 Description: Modified to pass overflow flag through to L_add and L_sub. The
61 flag is passed back to the calling function by pointer reference.
62
63 Description: Removed the id line since it was removed in the header file by
64 Ken.
65
66 Description: Added the write-only variable, pOverflow, to the inputs section.
67
68 Description: For lsp_az() and Get_lsp_pol()
69 1. Eliminated unused include files.
70 2. Replaced array addressing by pointers
71 3. Eliminated math operations that unnecessary checked for
72 saturation, in some cases this by shifting before adding and
73 in other cases by evaluating the operands
74 4. Unrolled loops to speed up processing
75 5. Replaced mpy_32_16 by multpilcations in place
76 6. Eliminated if-else statements for sign extension when
77 right-shifting
78
79 Description: Added casting to eliminate warnings, and eliminated include
80 files that now are chosen by OSCL definitions
81
82 Description: Replaced "int" and/or "char" with defined types.
83 Added proper casting (Word32) to some left shifting operations
84
85 Who: Date:
86 Description:
87
88 ------------------------------------------------------------------------------
89 MODULE DESCRIPTION
90
91 This file contains functions that convert line spectral pairs (LSP) to
92 linear predictive (LP) coefficients (filter order = 10). The functions
93 included in this file include Get_lsp_pol, which finds the coefficients of
94 F1(z) and F2(z), and Lsp_Az, which converts LSP to LPC by multiplying
95 F1(z) by 1+z^(-1) and F2(z) by 1-z^(-1), then calculating A(z) = (F1(z) +
96 F2(z))/2.
97
98 ------------------------------------------------------------------------------
99 */
100
101 /*----------------------------------------------------------------------------
102 ; INCLUDES
103 ----------------------------------------------------------------------------*/
104 #include "lsp_az.h"
105
106 /*----------------------------------------------------------------------------
107 ; MACROS
108 ; Define module specific macros here
109 ----------------------------------------------------------------------------*/
110
111 /*----------------------------------------------------------------------------
112 ; DEFINES
113 ; Include all pre-processor statements here. Include conditional
114 ; compile variables also.
115 ----------------------------------------------------------------------------*/
116
117 /*----------------------------------------------------------------------------
118 ; LOCAL FUNCTION DEFINITIONS
119 ; Function Prototype declaration
120 ----------------------------------------------------------------------------*/
121
122 /*----------------------------------------------------------------------------
123 ; LOCAL VARIABLE DEFINITIONS
124 ; Variable declaration - defined here and used outside this module
125 ----------------------------------------------------------------------------*/
126
127
128 /*
129 ------------------------------------------------------------------------------
130 FUNCTION NAME: Get_lsp_pol
131 ------------------------------------------------------------------------------
132 INPUT AND OUTPUT DEFINITIONS
133
134 Inputs:
135 lsp = pointer to the buffer containing the line spectral pairs (LSP)
136 of type Word16
137 f = pointer to the polynomial of type Word32 to be generated
138
139 pOverflow = pointer set in case where one of the operations overflows.
140 [data type Pointer to Flag]
141
142 Outputs:
143 buffer pointed to by f contains the polynomial generated
144
145 pOverflow = pointer set in case where one of the operations overflows.
146 [data type Pointer to Flag]
147
148 Returns:
149 None
150
151 Global Variables Used:
152 None
153
154 Local Variables Needed:
155 None
156
157 ------------------------------------------------------------------------------
158 FUNCTION DESCRIPTION
159
160 This function finds the polynomial F1(z) or F2(z) from the LSPs. If the LSP
161 vector is passed at address 0, F1(z) is computed and if it is passed at
162 address 1, F2(z) is computed.
163
164 This is performed by expanding the product polynomials:
165
166 F1(z) = product ( 1 - 2 lsp[i] z^-1 + z^-2 )
167 i=0,2,4,6,8
168 F2(z) = product ( 1 - 2 lsp[i] z^-1 + z^-2 )
169 i=1,3,5,7,9
170
171 where lsp[] is the LSP vector in the cosine domain.
172
173 The expansion is performed using the following recursion:
174
175 f[0] = 1
176 b = -2.0 * lsp[0]
177 f[1] = b
178 for i=2 to 5 do
179 b = -2.0 * lsp[2*i-2];
180 for j=i-1 down to 2 do
181 f[j] = f[j] + b*f[j-1] + f[j-2];
182 f[1] = f[1] + b;
183
184 ------------------------------------------------------------------------------
185 REQUIREMENTS
186
187 None
188
189 ------------------------------------------------------------------------------
190 REFERENCES
191
192 lsp_az.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
193
194 ------------------------------------------------------------------------------
195 PSEUDO-CODE
196
197 static void Get_lsp_pol (Word16 *lsp, Word32 *f)
198 {
199 Word16 i, j, hi, lo;
200 Word32 t0;
201
202 // f[0] = 1.0;
203 *f = L_mult (4096, 2048);
204 f++;
205 *f = L_msu ((Word32) 0, *lsp, 512); // f[1] = -2.0 * lsp[0];
206 f++;
207 lsp += 2; // Advance lsp pointer
208
209 for (i = 2; i <= 5; i++)
210 {
211 *f = f[-2];
212
213 for (j = 1; j < i; j++, f--)
214 {
215 L_Extract (f[-1], &hi, &lo);
216 t0 = Mpy_32_16 (hi, lo, *lsp); // t0 = f[-1] * lsp
217 t0 = L_shl (t0, 1);
218 *f = L_add (*f, f[-2]); // *f += f[-2]
219 *f = L_sub (*f, t0); // *f -= t0
220 }
221 *f = L_msu (*f, *lsp, 512); // *f -= lsp<<9
222 f += i; // Advance f pointer
223 lsp += 2; // Advance lsp pointer
224 }
225
226 return;
227 }
228
229 ------------------------------------------------------------------------------
230 RESOURCES USED [optional]
231
232 When the code is written for a specific target processor the
233 the resources used should be documented below.
234
235 HEAP MEMORY USED: x bytes
236
237 STACK MEMORY USED: x bytes
238
239 CLOCK CYCLES: (cycle count equation for this function) + (variable
240 used to represent cycle count for each subroutine
241 called)
242 where: (cycle count variable) = cycle count for [subroutine
243 name]
244
245 ------------------------------------------------------------------------------
246 CAUTION [optional]
247 [State any special notes, constraints or cautions for users of this function]
248
249 ------------------------------------------------------------------------------
250 */
251
Get_lsp_pol(Word16 * lsp,Word32 * f,Flag * pOverflow)252 static void Get_lsp_pol(
253 Word16 *lsp,
254 Word32 *f,
255 Flag *pOverflow)
256 {
257 Word16 i;
258 Word16 j;
259
260 Word16 hi;
261 Word16 lo;
262 Word32 t0;
263 OSCL_UNUSED_ARG(pOverflow);
264
265 /* f[0] = 1.0; */
266 *f++ = (Word32) 0x01000000;
267 *f++ = (Word32) - *(lsp++) << 10; /* f[1] = -2.0 * lsp[0]; */
268 lsp++; /* Advance lsp pointer */
269
270 for (i = 2; i <= 5; i++)
271 {
272 *f = *(f - 2);
273
274 for (j = 1; j < i; j++)
275 {
276 hi = (Word16)(*(f - 1) >> 16);
277
278 lo = (Word16)((*(f - 1) >> 1) - ((Word32) hi << 15));
279
280 t0 = ((Word32)hi * *lsp);
281 t0 += ((Word32)lo * *lsp) >> 15;
282
283 *(f) += *(f - 2); /* *f += f[-2] */
284 *(f--) -= t0 << 2; /* *f -= t0 */
285
286 }
287
288 *f -= (Word32)(*lsp++) << 10;
289
290 f += i;
291 lsp++;
292 }
293
294 return;
295 }
296
297 /****************************************************************************/
298
299
300 /*
301 ------------------------------------------------------------------------------
302 FUNCTION NAME: Get_lsp_pol_wrapper
303 ------------------------------------------------------------------------------
304 INPUT AND OUTPUT DEFINITIONS
305
306 Inputs:
307 lsp = pointer to the buffer containing the line spectral pairs (LSP)
308 of type Word16
309 f = pointer to the polynomial of type Word32 to be generated
310
311 pOverflow = pointer set in case where one of the operations overflows.
312 [data type Pointer to Flag]
313
314 Outputs:
315 buffer pointed to by f contains the polynomial generated
316
317 pOverflow = pointer set in case where one of the operations overflows.
318 [data type Pointer to Flag]
319
320 Returns:
321 None
322
323 Global Variables Used:
324 None
325
326 Local Variables Needed:
327 None
328
329 ------------------------------------------------------------------------------
330 FUNCTION DESCRIPTION
331
332 This function provides external access to the static function Get_lsp_pol.
333
334 ------------------------------------------------------------------------------
335 REQUIREMENTS
336
337 None
338
339 ------------------------------------------------------------------------------
340 REFERENCES
341
342 None
343
344 ------------------------------------------------------------------------------
345 PSEUDO-CODE
346
347 CALL Get_lsp_pol(lsp = lsp_ptr
348 f = f_ptr )
349 MODIFYING(nothing)
350 RETURNING(nothing)
351
352 ------------------------------------------------------------------------------
353 RESOURCES USED [optional]
354
355 When the code is written for a specific target processor the
356 the resources used should be documented below.
357
358 HEAP MEMORY USED: x bytes
359
360 STACK MEMORY USED: x bytes
361
362 CLOCK CYCLES: (cycle count equation for this function) + (variable
363 used to represent cycle count for each subroutine
364 called)
365 where: (cycle count variable) = cycle count for [subroutine
366 name]
367
368 ------------------------------------------------------------------------------
369 CAUTION [optional]
370 [State any special notes, constraints or cautions for users of this function]
371
372 ------------------------------------------------------------------------------
373 */
374
Get_lsp_pol_wrapper(Word16 * lsp,Word32 * f,Flag * pOverflow)375 void Get_lsp_pol_wrapper(
376 Word16 *lsp,
377 Word32 *f,
378 Flag *pOverflow)
379 {
380 /*----------------------------------------------------------------------------
381 CALL Get_lsp_pol(lsp = lsp_ptr
382 f = f_ptr )
383 ----------------------------------------------------------------------------*/
384 Get_lsp_pol(lsp, f, pOverflow);
385
386 /*----------------------------------------------------------------------------
387 MODIFYING(nothing)
388 RETURNING(nothing)
389 ----------------------------------------------------------------------------*/
390 return;
391 }
392
393 /****************************************************************************/
394
395
396 /*
397 ------------------------------------------------------------------------------
398 FUNCTION NAME: Lsp_Az
399 ------------------------------------------------------------------------------
400 INPUT AND OUTPUT DEFINITIONS
401
402 Inputs:
403 lsp = pointer to the buffer containing the line spectral pairs (LSP)
404 of type Word16
405
406 a = pointer to the buffer containing Linear Predictive (LP)
407 coefficients of type Word16 to be generated
408
409 pOverflow = pointer set in case where one of the operations overflows.
410 [data type Pointer to Flag]
411
412 Local Stores/Buffers/Pointers Needed:
413 None
414
415 Global Stores/Buffers/Pointers Needed:
416 None
417
418 Outputs:
419 pOverflow = pointer set in case where one of the operations overflows.
420 [data type Pointer to Flag]
421
422 Pointers and Buffers Modified:
423 a buffer contains the generated Linear Predictive (LP) coefficients
424
425 Local Stores Modified:
426 None
427
428 Global Stores Modified:
429 None
430
431 ------------------------------------------------------------------------------
432 FUNCTION DESCRIPTION
433
434 This function converts from the line spectral pairs (LSP) to LP coefficients
435 for a 10th order filter.
436
437 This is done by:
438 (1) Find the coefficients of F1(z) and F2(z) (see Get_lsp_pol)
439 (2) Multiply F1(z) by 1+z^{-1} and F2(z) by 1-z^{-1}
440 (3) A(z) = ( F1(z) + F2(z) ) / 2
441
442 ------------------------------------------------------------------------------
443 REQUIREMENTS
444
445 None
446
447 ------------------------------------------------------------------------------
448 REFERENCES
449
450 lsp_az.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
451
452 ------------------------------------------------------------------------------
453 PSEUDO-CODE
454
455 void Lsp_Az (
456 Word16 lsp[], // (i) : line spectral frequencies
457 Word16 a[] // (o) : predictor coefficients (order = 10)
458 )
459 {
460 Word16 i, j;
461 Word32 f1[6], f2[6];
462 Word32 t0;
463
464 Get_lsp_pol (&lsp[0], f1);
465 Get_lsp_pol (&lsp[1], f2);
466
467 for (i = 5; i > 0; i--)
468 {
469 f1[i] = L_add (f1[i], f1[i - 1]); // f1[i] += f1[i-1];
470 f2[i] = L_sub (f2[i], f2[i - 1]); // f2[i] -= f2[i-1];
471 }
472
473 a[0] = 4096;
474 for (i = 1, j = 10; i <= 5; i++, j--)
475 {
476 t0 = L_add (f1[i], f2[i]); // f1[i] + f2[i]
477 a[i] = extract_l (L_shr_r (t0, 13));
478 t0 = L_sub (f1[i], f2[i]); // f1[i] - f2[i]
479 a[j] = extract_l (L_shr_r (t0, 13));
480 }
481
482 return;
483 }
484
485 ------------------------------------------------------------------------------
486 RESOURCES USED [optional]
487
488 When the code is written for a specific target processor the
489 the resources used should be documented below.
490
491 HEAP MEMORY USED: x bytes
492
493 STACK MEMORY USED: x bytes
494
495 CLOCK CYCLES: (cycle count equation for this function) + (variable
496 used to represent cycle count for each subroutine
497 called)
498 where: (cycle count variable) = cycle count for [subroutine
499 name]
500
501 ------------------------------------------------------------------------------
502 CAUTION [optional]
503 [State any special notes, constraints or cautions for users of this function]
504
505 ------------------------------------------------------------------------------
506 */
507
Lsp_Az(Word16 lsp[],Word16 a[],Flag * pOverflow)508 void Lsp_Az(
509 Word16 lsp[], /* (i) : line spectral frequencies */
510 Word16 a[], /* (o) : predictor coefficients (order = 10) */
511 Flag *pOverflow /* (o) : overflow flag */
512 )
513 {
514 Word16 i;
515 Word16 j;
516
517 Word32 f1[6];
518 Word32 f2[6];
519 Word32 t0;
520 Word32 t1;
521 Word16 *p_a = &a[0];
522 Word32 *p_f1;
523 Word32 *p_f2;
524
525 Get_lsp_pol(&lsp[0], f1, pOverflow);
526
527 Get_lsp_pol(&lsp[1], f2, pOverflow);
528
529 p_f1 = &f1[5];
530 p_f2 = &f2[5];
531
532 for (i = 5; i > 0; i--)
533 {
534 *(p_f1--) += f1[i-1];
535 *(p_f2--) -= f2[i-1];
536 }
537
538 *(p_a++) = 4096;
539 p_f1 = &f1[1];
540 p_f2 = &f2[1];
541
542 for (i = 1, j = 10; i <= 5; i++, j--)
543 {
544 t0 = *(p_f1) + *(p_f2); /* f1[i] + f2[i] */
545 t1 = *(p_f1++) - *(p_f2++); /* f1[i] - f2[i] */
546
547 t0 = t0 + ((Word32) 1 << 12);
548 t1 = t1 + ((Word32) 1 << 12);
549
550 *(p_a++) = (Word16)(t0 >> 13);
551 a[j] = (Word16)(t1 >> 13);
552 }
553
554 return;
555 }
556