• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
32 
33 
34  Pathname: ./audio/gsm-amr/c/src/g_pitch.c
35 
36      Date: 06/12/2000
37 
38 ------------------------------------------------------------------------------
39  REVISION HISTORY
40 
41  Description:  Placed into template and began to optimize.
42 
43  Description: Synchronized file with UMTS version 3.2.0. Updated coding
44               template. Removed unnecessary include files.
45 
46  Description: Replaced basic_op.h and oper_32b.h with the header files of the
47               math functions used in the file. Fixed typecasting issue with
48               TI compiler.
49 
50  Description: Passing in pointer to overflow flag for EPOC compatibility. .
51 
52  Description:
53               1. Eliminated unused include files.
54               2. Replaced array addressing by pointers
55               3. Eliminated math operations that unnecessary checked for
56                  saturation, in some cases this by shifting before adding and
57                  in other cases by evaluating the operands
58               4. Unrolled loops to speed up processing
59 
60  Description:  Replaced OSCL mem type functions and eliminated include
61                files that now are chosen by OSCL definitions
62 
63  Description:  Replaced "int" and/or "char" with OSCL defined types.
64 
65  Description: Changed round function name to pv_round to avoid conflict with
66               round function in C standard library.
67 
68  Description: Using inlines from fxp_arithmetic.h .
69 
70  Description: Replacing fxp_arithmetic.h with basic_op.h.
71 
72  Description:
73 
74 ------------------------------------------------------------------------------
75 */
76 
77 /*----------------------------------------------------------------------------
78 ; INCLUDES
79 ----------------------------------------------------------------------------*/
80 #include "g_pitch.h"
81 #include "mode.h"
82 #include "cnst.h"
83 #include "basic_op.h"
84 
85 /*----------------------------------------------------------------------------
86 ; MACROS
87 ; Define module specific macros here
88 ----------------------------------------------------------------------------*/
89 
90 
91 /*----------------------------------------------------------------------------
92 ; DEFINES
93 ; Include all pre-processor statements here. Include conditional
94 ; compile variables also.
95 ----------------------------------------------------------------------------*/
96 
97 /*----------------------------------------------------------------------------
98 ; LOCAL FUNCTION DEFINITIONS
99 ; Function Prototype declaration
100 ----------------------------------------------------------------------------*/
101 
102 /*----------------------------------------------------------------------------
103 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
104 ; Variable declaration - defined here and used outside this module
105 ----------------------------------------------------------------------------*/
106 
107 
108 /*
109 ------------------------------------------------------------------------------
110  FUNCTION NAME: G_pitch
111 ------------------------------------------------------------------------------
112  INPUT AND OUTPUT DEFINITIONS
113 
114  Inputs:
115     mode = AMR mode (enum Mode)
116     xn = pointer to pitch target buffer (Word16)
117     y1 = pointer to filtered adaptive codebook buffer (Word16)
118     g_coeff  = pointer to buffer of correlations needed for gain quantization
119                (Word16)
120     L_subfr = length of subframe (Word16)
121     pOverflow = pointer to overflow flag (Flag)
122 
123  Outputs:
124     g_coeff contains the mantissa and exponent of the two dot products.
125     pOverflow -> 1 if an overflow occurs
126 
127  Returns:
128     gain =  ratio of dot products.(Word16)
129 
130  Global Variables Used:
131     None.
132 
133  Local Variables Needed:
134     None.
135 
136 ------------------------------------------------------------------------------
137  FUNCTION DESCRIPTION
138 
139  This function computes the pitch (adaptive codebook) gain. The adaptive
140  codebook gain is given by
141 
142     g = <x[], y[]> / <y[], y[]>
143 
144     where:  x[] is the target vector
145             y[] is the filtered adaptive codevector
146             <> denotes dot product.
147 
148  The gain is limited to the range [0,1.2] (=0..19661 Q14)
149 
150 ------------------------------------------------------------------------------
151  REQUIREMENTS
152 
153  None.
154 
155 ------------------------------------------------------------------------------
156  REFERENCES
157 
158  g_pitch.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
159 
160 ------------------------------------------------------------------------------
161  PSEUDO-CODE
162 
163 Word16 G_pitch     (    // o : Gain of pitch lag saturated to 1.2
164     enum Mode mode,     // i : AMR mode
165     Word16 xn[],        // i : Pitch target.
166     Word16 y1[],        // i : Filtered adaptive codebook.
167     Word16 g_coeff[],   // i : Correlations need for gain quantization
168     Word16 L_subfr      // i : Length of subframe.
169 )
170 {
171     Word16 i;
172     Word16 xy, yy, exp_xy, exp_yy, gain;
173     Word32 s;
174 
175     Word16 scaled_y1[L_SUBFR];   // Usually dynamic allocation of (L_subfr)
176 
177     // divide "y1[]" by 4 to avoid overflow
178 
179 // The reference ETSI code uses a global overflow Flag. However in the actual
180 // implementation a pointer to the overflow flag is passed into the function.
181 
182     for (i = 0; i < L_subfr; i++)
183     {
184         scaled_y1[i] = shr (y1[i], 2);
185     }
186 
187     // Compute scalar product <y1[],y1[]>
188 
189     // Q12 scaling / MR122
190     Overflow = 0;
191     s = 1L; // Avoid case of all zeros
192     for (i = 0; i < L_subfr; i++)
193     {
194         s = L_mac (s, y1[i], y1[i]);
195     }
196     if (Overflow == 0)       // Test for overflow
197     {
198         exp_yy = norm_l (s);
199         yy = pv_round (L_shl (s, exp_yy));
200     }
201     else
202     {
203         s = 1L; // Avoid case of all zeros
204         for (i = 0; i < L_subfr; i++)
205         {
206             s = L_mac (s, scaled_y1[i], scaled_y1[i]);
207         }
208         exp_yy = norm_l (s);
209         yy = pv_round (L_shl (s, exp_yy));
210         exp_yy = sub (exp_yy, 4);
211     }
212 
213     // Compute scalar product <xn[],y1[]>
214 
215     Overflow = 0;
216     s = 1L; // Avoid case of all zeros
217 
218     for (i = 0; i < L_subfr; i++)
219     {
220         s = L_mac(s, xn[i], y1[i]);
221     }
222     if (Overflow == 0)
223     {
224         exp_xy = norm_l (s);
225         xy = pv_round (L_shl (s, exp_xy));
226     }
227     else
228     {
229         s = 1L; // Avoid case of all zeros
230         for (i = 0; i < L_subfr; i++)
231         {
232             s = L_mac (s, xn[i], scaled_y1[i]);
233         }
234         exp_xy = norm_l (s);
235         xy = pv_round (L_shl (s, exp_xy));
236         exp_xy = sub (exp_xy, 2);
237     }
238 
239     g_coeff[0] = yy;
240     g_coeff[1] = sub (15, exp_yy);
241     g_coeff[2] = xy;
242     g_coeff[3] = sub (15, exp_xy);
243 
244     // If (xy < 4) gain = 0
245 
246     i = sub (xy, 4);
247 
248     if (i < 0)
249         return ((Word16) 0);
250 
251     // compute gain = xy/yy
252 
253     xy = shr (xy, 1);                  // Be sure xy < yy
254     gain = div_s (xy, yy);
255 
256     i = sub (exp_xy, exp_yy);      // Denormalization of division
257     gain = shr (gain, i);
258 
259     // if(gain >1.2) gain = 1.2
260 
261     if (sub (gain, 19661) > 0)
262     {
263         gain = 19661;
264     }
265 
266     if (sub(mode, MR122) == 0)
267     {
268        // clear 2 LSBits
269        gain = gain & 0xfffC;
270     }
271 
272     return (gain);
273 }
274 
275 ------------------------------------------------------------------------------
276  RESOURCES USED [optional]
277 
278  When the code is written for a specific target processor the
279  the resources used should be documented below.
280 
281  HEAP MEMORY USED: x bytes
282 
283  STACK MEMORY USED: x bytes
284 
285  CLOCK CYCLES: (cycle count equation for this function) + (variable
286                 used to represent cycle count for each subroutine
287                 called)
288      where: (cycle count variable) = cycle count for [subroutine
289                                      name]
290 
291 ------------------------------------------------------------------------------
292  CAUTION [optional]
293  [State any special notes, constraints or cautions for users of this function]
294 
295 ------------------------------------------------------------------------------
296 */
297 
G_pitch(enum Mode mode,Word16 xn[],Word16 y1[],Word16 g_coeff[],Word16 L_subfr,Flag * pOverflow)298 Word16 G_pitch(         /* o : Gain of pitch lag saturated to 1.2       */
299     enum Mode mode,     /* i : AMR mode                                 */
300     Word16 xn[],        /* i : Pitch target.                            Q0  */
301     Word16 y1[],        /* i : Filtered adaptive codebook.              Q12 */
302     Word16 g_coeff[],   /* i : Correlations need for gain quantization  */
303     Word16 L_subfr,     /* i : Length of subframe.                      */
304     Flag   *pOverflow   /* i/o : Overflow flag                          */
305 )
306 {
307 
308     Word16 i;
309     Word16 xy;
310     Word16 yy;
311     Word16 exp_xy;
312     Word16 exp_yy;
313     Word16 gain;
314     Word16 tmp;
315     Word32 s;
316     Word32 s1;
317     Word32 L_temp;                      /* Use this as an intermediate value */
318     Word16 *p_xn = &xn[0];
319     Word16 *p_y1 = &y1[0];
320 
321     /* Compute scalar product <y1[],y1[]> */
322 
323     /* Q12 scaling / MR122 */
324     *pOverflow = 0;
325     s = 0;
326 
327     for (i = L_subfr >> 2; i != 0; i--)
328     {
329         s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
330         p_y1++;
331         s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
332         p_y1++;
333         s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
334         p_y1++;
335         s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
336         p_y1++;
337     }
338     if ((s >= 0) & (s < 0x40000000))
339     {
340         s <<= 1;
341         s  += 1;            /* Avoid case of all zeros */
342 
343         exp_yy = norm_l(s);             /* Note 0<=exp_yy <= 31 */
344         L_temp = s << exp_yy;
345         yy = pv_round(L_temp, pOverflow);
346     }
347     else
348     {
349         s = 0;                      /* Avoid case of all zeros */
350         p_y1 = &y1[0];
351         for (i = (L_subfr >> 1); i != 0; i--)
352         {
353             tmp = *(p_y1++) >> 2;
354             s = amrnb_fxp_mac_16_by_16bb((Word32) tmp, (Word32) tmp, s);
355             tmp = *(p_y1++) >> 2;
356             s = amrnb_fxp_mac_16_by_16bb((Word32) tmp, (Word32) tmp, s);
357         }
358 
359         s <<= 1;
360         s  += 1;            /* Avoid case of all zeros */
361 
362         exp_yy = norm_l(s);
363         L_temp = s << exp_yy;
364         yy = pv_round(L_temp, pOverflow);
365         exp_yy = exp_yy - 4;
366 
367     }
368 
369     /* Compute scalar product <xn[],y1[]> */
370 
371     s = 0;
372     p_y1 = &y1[0];
373     *pOverflow = 0;
374 
375     for (i = L_subfr; i != 0; i--)
376     {
377         L_temp = ((Word32) * (p_xn++) * *(p_y1++));
378         s1 = s;
379         s = s1 + L_temp;
380 
381         if ((s1 ^ L_temp) > 0)
382         {
383             if ((s1 ^ s) < 0)
384             {
385                 *pOverflow = 1;
386                 break;
387             }
388         }
389     }
390 
391     if (!(*pOverflow))
392     {
393 
394         s <<= 1;
395         s  += 1;            /* Avoid case of all zeros */
396 
397         exp_xy = norm_l(s);             /* Note 0<=exp_yy <= 31 */
398         L_temp = s << exp_xy;
399         xy = pv_round(L_temp, pOverflow);
400     }
401     else
402     {
403         s = 0;  /* re-initialize calculations */
404         p_y1 = &y1[0];
405         p_xn = &xn[0];
406         for (i = (L_subfr >> 2); i != 0; i--)
407         {
408             L_temp = (Word32)(*(p_y1++) >> 2);
409             s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
410             L_temp = (Word32)(*(p_y1++) >> 2);
411             s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
412             L_temp = (Word32)(*(p_y1++) >> 2);
413             s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
414             L_temp = (Word32)(*(p_y1++) >> 2);
415             s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
416         }
417 
418         s <<= 1;
419         s  += 1;            /* Avoid case of all zeros */
420 
421         exp_xy = norm_l(s);
422         L_temp = s << exp_xy;
423         xy = pv_round(L_temp, pOverflow);
424         exp_xy = exp_xy - 4;
425 
426     }
427 
428     g_coeff[0] = yy;
429     g_coeff[1] = 15 - exp_yy;
430     g_coeff[2] = xy;
431     g_coeff[3] = 15 - exp_xy;
432 
433     /* If (xy < 4) gain = 0 */
434     if (xy < 4)
435     {
436         return ((Word16) 0);
437     }
438 
439     /* compute gain = xy/yy */
440     /* Be sure xy < yy */
441 
442     xy = xy >> 1;
443 
444     gain = div_s(xy, yy);
445 
446     i = exp_xy - exp_yy;               /* Denormalization of division */
447 
448     gain = shr(gain, i, pOverflow);
449 
450 
451     /* if(gain >1.2) gain = 1.2 */
452     if (gain > 19661)
453     {
454         gain = 19661;
455     }
456 
457     if (mode == MR122)
458     {
459         /* clear 2 LSBits */
460         gain = gain & 0xfffC;
461     }
462 
463     return(gain);
464 
465 }
466