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
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
163Word16 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
298Word16 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