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/****************************************************************************************
19Portions 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)
26Permission to distribute, modify and use this file under the standard license
27terms 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
197static 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
252static 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
375void 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
455void 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
508void 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