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