Initialize Tizen 2.3
[external/opencore-amr.git] / opencore / codecs_v2 / audio / gsm_amr / amr_nb / enc / src / g_pitch.cpp
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  Filename: g_pitch.cpp
35
36 ------------------------------------------------------------------------------
37 */
38
39 /*----------------------------------------------------------------------------
40 ; INCLUDES
41 ----------------------------------------------------------------------------*/
42 #include "g_pitch.h"
43 #include "mode.h"
44 #include "cnst.h"
45 #include "basic_op.h"
46
47 /*----------------------------------------------------------------------------
48 ; MACROS
49 ; Define module specific macros here
50 ----------------------------------------------------------------------------*/
51
52
53 /*----------------------------------------------------------------------------
54 ; DEFINES
55 ; Include all pre-processor statements here. Include conditional
56 ; compile variables also.
57 ----------------------------------------------------------------------------*/
58
59 /*----------------------------------------------------------------------------
60 ; LOCAL FUNCTION DEFINITIONS
61 ; Function Prototype declaration
62 ----------------------------------------------------------------------------*/
63
64 /*----------------------------------------------------------------------------
65 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
66 ; Variable declaration - defined here and used outside this module
67 ----------------------------------------------------------------------------*/
68
69
70 /*
71 ------------------------------------------------------------------------------
72  FUNCTION NAME: G_pitch
73 ------------------------------------------------------------------------------
74  INPUT AND OUTPUT DEFINITIONS
75
76  Inputs:
77     mode = AMR mode (enum Mode)
78     xn = pointer to pitch target buffer (Word16)
79     y1 = pointer to filtered adaptive codebook buffer (Word16)
80     g_coeff  = pointer to buffer of correlations needed for gain quantization
81                (Word16)
82     L_subfr = length of subframe (Word16)
83     pOverflow = pointer to overflow flag (Flag)
84
85  Outputs:
86     g_coeff contains the mantissa and exponent of the two dot products.
87     pOverflow -> 1 if an overflow occurs
88
89  Returns:
90     gain =  ratio of dot products.(Word16)
91
92  Global Variables Used:
93     None.
94
95  Local Variables Needed:
96     None.
97
98 ------------------------------------------------------------------------------
99  FUNCTION DESCRIPTION
100
101  This function computes the pitch (adaptive codebook) gain. The adaptive
102  codebook gain is given by
103
104     g = <x[], y[]> / <y[], y[]>
105
106     where:  x[] is the target vector
107             y[] is the filtered adaptive codevector
108             <> denotes dot product.
109
110  The gain is limited to the range [0,1.2] (=0..19661 Q14)
111
112 ------------------------------------------------------------------------------
113  REQUIREMENTS
114
115  None.
116
117 ------------------------------------------------------------------------------
118  REFERENCES
119
120  g_pitch.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
121
122 ------------------------------------------------------------------------------
123  PSEUDO-CODE
124
125 Word16 G_pitch     (    // o : Gain of pitch lag saturated to 1.2
126     enum Mode mode,     // i : AMR mode
127     Word16 xn[],        // i : Pitch target.
128     Word16 y1[],        // i : Filtered adaptive codebook.
129     Word16 g_coeff[],   // i : Correlations need for gain quantization
130     Word16 L_subfr      // i : Length of subframe.
131 )
132 {
133     Word16 i;
134     Word16 xy, yy, exp_xy, exp_yy, gain;
135     Word32 s;
136
137     Word16 scaled_y1[L_SUBFR];   // Usually dynamic allocation of (L_subfr)
138
139     // divide "y1[]" by 4 to avoid overflow
140
141 // The reference ETSI code uses a global overflow Flag. However in the actual
142 // implementation a pointer to the overflow flag is passed into the function.
143
144     for (i = 0; i < L_subfr; i++)
145     {
146         scaled_y1[i] = shr (y1[i], 2);
147     }
148
149     // Compute scalar product <y1[],y1[]>
150
151     // Q12 scaling / MR122
152     Overflow = 0;
153     s = 1L; // Avoid case of all zeros
154     for (i = 0; i < L_subfr; i++)
155     {
156         s = L_mac (s, y1[i], y1[i]);
157     }
158     if (Overflow == 0)       // Test for overflow
159     {
160         exp_yy = norm_l (s);
161         yy = pv_round (L_shl (s, exp_yy));
162     }
163     else
164     {
165         s = 1L; // Avoid case of all zeros
166         for (i = 0; i < L_subfr; i++)
167         {
168             s = L_mac (s, scaled_y1[i], scaled_y1[i]);
169         }
170         exp_yy = norm_l (s);
171         yy = pv_round (L_shl (s, exp_yy));
172         exp_yy = sub (exp_yy, 4);
173     }
174
175     // Compute scalar product <xn[],y1[]>
176
177     Overflow = 0;
178     s = 1L; // Avoid case of all zeros
179
180     for (i = 0; i < L_subfr; i++)
181     {
182         s = L_mac(s, xn[i], y1[i]);
183     }
184     if (Overflow == 0)
185     {
186         exp_xy = norm_l (s);
187         xy = pv_round (L_shl (s, exp_xy));
188     }
189     else
190     {
191         s = 1L; // Avoid case of all zeros
192         for (i = 0; i < L_subfr; i++)
193         {
194             s = L_mac (s, xn[i], scaled_y1[i]);
195         }
196         exp_xy = norm_l (s);
197         xy = pv_round (L_shl (s, exp_xy));
198         exp_xy = sub (exp_xy, 2);
199     }
200
201     g_coeff[0] = yy;
202     g_coeff[1] = sub (15, exp_yy);
203     g_coeff[2] = xy;
204     g_coeff[3] = sub (15, exp_xy);
205
206     // If (xy < 4) gain = 0
207
208     i = sub (xy, 4);
209
210     if (i < 0)
211         return ((Word16) 0);
212
213     // compute gain = xy/yy
214
215     xy = shr (xy, 1);                  // Be sure xy < yy
216     gain = div_s (xy, yy);
217
218     i = sub (exp_xy, exp_yy);      // Denormalization of division
219     gain = shr (gain, i);
220
221     // if(gain >1.2) gain = 1.2
222
223     if (sub (gain, 19661) > 0)
224     {
225         gain = 19661;
226     }
227
228     if (sub(mode, MR122) == 0)
229     {
230        // clear 2 LSBits
231        gain = gain & 0xfffC;
232     }
233
234     return (gain);
235 }
236
237 ------------------------------------------------------------------------------
238  CAUTION [optional]
239  [State any special notes, constraints or cautions for users of this function]
240
241 ------------------------------------------------------------------------------
242 */
243
244 Word16 G_pitch(         /* o : Gain of pitch lag saturated to 1.2       */
245     enum Mode mode,     /* i : AMR mode                                 */
246     Word16 xn[],        /* i : Pitch target.                            Q0  */
247     Word16 y1[],        /* i : Filtered adaptive codebook.              Q12 */
248     Word16 g_coeff[],   /* i : Correlations need for gain quantization  */
249     Word16 L_subfr,     /* i : Length of subframe.                      */
250     Flag   *pOverflow   /* i/o : Overflow flag                          */
251 )
252 {
253
254     Word16 i;
255     Word16 xy;
256     Word16 yy;
257     Word16 exp_xy;
258     Word16 exp_yy;
259     Word16 gain;
260     Word16 tmp;
261     Word32 s;
262     Word32 s1;
263     Word32 L_temp;                      /* Use this as an intermediate value */
264     Word16 *p_xn = &xn[0];
265     Word16 *p_y1 = &y1[0];
266
267     /* Compute scalar product <y1[],y1[]> */
268
269     /* Q12 scaling / MR122 */
270     *pOverflow = 0;
271     s = 0;
272
273     for (i = L_subfr >> 2; i != 0; i--)
274     {
275         s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
276         p_y1++;
277         s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
278         p_y1++;
279         s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
280         p_y1++;
281         s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
282         p_y1++;
283     }
284     if ((s >= 0) & (s < 0x40000000))
285     {
286         s <<= 1;
287         s  += 1;            /* Avoid case of all zeros */
288
289         exp_yy = norm_l(s);             /* Note 0<=exp_yy <= 31 */
290         L_temp = s << exp_yy;
291         yy = pv_round(L_temp, pOverflow);
292     }
293     else
294     {
295         s = 0;                      /* Avoid case of all zeros */
296         p_y1 = &y1[0];
297         for (i = (L_subfr >> 1); i != 0; i--)
298         {
299             tmp = *(p_y1++) >> 2;
300             s = amrnb_fxp_mac_16_by_16bb((Word32) tmp, (Word32) tmp, s);
301             tmp = *(p_y1++) >> 2;
302             s = amrnb_fxp_mac_16_by_16bb((Word32) tmp, (Word32) tmp, s);
303         }
304
305         s <<= 1;
306         s  += 1;            /* Avoid case of all zeros */
307
308         exp_yy = norm_l(s);
309         L_temp = s << exp_yy;
310         yy = pv_round(L_temp, pOverflow);
311         exp_yy = exp_yy - 4;
312
313     }
314
315     /* Compute scalar product <xn[],y1[]> */
316
317     s = 0;
318     p_y1 = &y1[0];
319     *pOverflow = 0;
320
321     for (i = L_subfr; i != 0; i--)
322     {
323         L_temp = ((Word32) * (p_xn++) * *(p_y1++));
324         s1 = s;
325         s = s1 + L_temp;
326
327         if ((s1 ^ L_temp) > 0)
328         {
329             if ((s1 ^ s) < 0)
330             {
331                 *pOverflow = 1;
332                 break;
333             }
334         }
335     }
336
337     if (!(*pOverflow))
338     {
339
340         s <<= 1;
341         s  += 1;            /* Avoid case of all zeros */
342
343         exp_xy = norm_l(s);             /* Note 0<=exp_yy <= 31 */
344         L_temp = s << exp_xy;
345         xy = pv_round(L_temp, pOverflow);
346     }
347     else
348     {
349         s = 0;  /* re-initialize calculations */
350         p_y1 = &y1[0];
351         p_xn = &xn[0];
352
353         for (i = (L_subfr >> 2); i != 0; i--)
354         {
355             L_temp = (Word32)(*(p_y1++) >> 2);
356             s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
357             L_temp = (Word32)(*(p_y1++) >> 2);
358             s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
359             L_temp = (Word32)(*(p_y1++) >> 2);
360             s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
361             L_temp = (Word32)(*(p_y1++) >> 2);
362             s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
363         }
364
365         s <<= 1;
366         s  += 1;            /* Avoid case of all zeros */
367
368         exp_xy = norm_l(s);
369         L_temp = s << exp_xy;
370         xy = pv_round(L_temp, pOverflow);
371         exp_xy = exp_xy - 4;
372
373     }
374
375     g_coeff[0] = yy;
376     g_coeff[1] = 15 - exp_yy;
377     g_coeff[2] = xy;
378     g_coeff[3] = 15 - exp_xy;
379
380     /* If (xy < 4) gain = 0 */
381     if (xy < 4)
382     {
383         return ((Word16) 0);
384     }
385
386     /* compute gain = xy/yy */
387     /* Be sure xy < yy */
388
389     xy = xy >> 1;
390
391     gain = div_s(xy, yy);
392
393     i = exp_xy - exp_yy;               /* Denormalization of division */
394
395     gain = shr(gain, i, pOverflow);
396
397
398     /* if(gain >1.2) gain = 1.2 */
399     if (gain > 19661)
400     {
401         gain = 19661;
402     }
403
404     if (mode == MR122)
405     {
406         /* clear 2 LSBits */
407         gain = gain & 0xfffC;
408     }
409
410     return(gain);
411
412 }