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/qua_gain.c
35 Functions:
36
37     Date: 02/05/2002
38
39------------------------------------------------------------------------------
40 REVISION HISTORY
41
42 Description: Updated template used to PV coding template.
43 Changed to accept the pOverflow flag for EPOC compatibility.
44
45 Description: Changed include files to lowercase.
46
47 Description:  Replaced OSCL mem type functions and eliminated include
48               files that now are chosen by OSCL definitions
49
50 Description:  Replaced "int" and/or "char" with OSCL defined types.
51
52 Description: Added #ifdef __cplusplus around extern'ed table.
53
54 Description:
55
56------------------------------------------------------------------------------
57 MODULE DESCRIPTION
58
59    Quantization of pitch and codebook gains.
60------------------------------------------------------------------------------
61*/
62
63/*----------------------------------------------------------------------------
64; INCLUDES
65----------------------------------------------------------------------------*/
66#include "qua_gain.h"
67#include "typedef.h"
68#include "basic_op.h"
69
70#include "mode.h"
71#include "cnst.h"
72#include "pow2.h"
73#include "gc_pred.h"
74
75/*--------------------------------------------------------------------------*/
76#ifdef __cplusplus
77extern "C"
78{
79#endif
80
81    /*----------------------------------------------------------------------------
82    ; MACROS
83    ; Define module specific macros here
84    ----------------------------------------------------------------------------*/
85
86    /*----------------------------------------------------------------------------
87    ; DEFINES
88    ; Include all pre-processor statements here. Include conditional
89    ; compile variables also.
90    ----------------------------------------------------------------------------*/
91
92    /*----------------------------------------------------------------------------
93    ; LOCAL FUNCTION DEFINITIONS
94    ; Function Prototype declaration
95    ----------------------------------------------------------------------------*/
96
97    /*----------------------------------------------------------------------------
98    ; LOCAL VARIABLE DEFINITIONS
99    ; Variable declaration - defined here and used outside this module
100    ----------------------------------------------------------------------------*/
101
102    /*----------------------------------------------------------------------------
103    ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
104    ; Declare variables used in this module but defined elsewhere
105    ----------------------------------------------------------------------------*/
106    extern const Word16 table_gain_lowrates[];
107    extern const Word16 table_gain_highrates[];
108
109    /*--------------------------------------------------------------------------*/
110#ifdef __cplusplus
111}
112#endif
113
114/*
115------------------------------------------------------------------------------
116 FUNCTION NAME:
117------------------------------------------------------------------------------
118 INPUT AND OUTPUT DEFINITIONS
119
120
121 Inputs:
122    mode -- enum Mode -- AMR mode
123    Word16 exp_gcode0  -- Word16 -- predicted CB gain (exponent),       Q0
124    Word16 frac_gcode0 -- Word16 -- predicted CB gain (fraction),      Q15
125    Word16 frac_coeff -- Word16 Array -- energy coeff. (5), fraction part, Q15
126    Word16 exp_coeff  -- Word16 Array -- energy coeff. (5), exponent part,  Q0
127                                    (frac_coeff and exp_coeff computed in
128                                    calc_filt_energies())
129
130    Word16 gp_limit -- Word16 --  pitch gain limit
131
132 Outputs:
133    Word16 *gain_pit -- Pointer to Word16 -- Pitch gain,               Q14
134    Word16 *gain_cod -- Pointer to Word16 -- Code gain,                Q1
135    Word16 *qua_ener_MR122 -- Pointer to Word16 -- quantized energy error,  Q10
136                                                (for MR122 MA predictor update)
137    Word16 *qua_ener -- Pointer to Word16 -- quantized energy error,        Q10
138                                                (for other MA predictor update)
139    Flag   *pOverflow -- Pointer to Flag -- overflow indicator
140
141 Returns:
142    Word16 -- index of quantization.
143
144 Global Variables Used:
145
146
147 Local Variables Needed:
148    None
149
150------------------------------------------------------------------------------
151 FUNCTION DESCRIPTION
152
153    Quantization of pitch and codebook gains.
154------------------------------------------------------------------------------
155 REQUIREMENTS
156
157 None
158
159------------------------------------------------------------------------------
160 REFERENCES
161
162 qua_gain.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
163
164------------------------------------------------------------------------------
165 PSEUDO-CODE
166
167
168------------------------------------------------------------------------------
169 RESOURCES USED [optional]
170
171 When the code is written for a specific target processor the
172 the resources used should be documented below.
173
174 HEAP MEMORY USED: x bytes
175
176 STACK MEMORY USED: x bytes
177
178 CLOCK CYCLES: (cycle count equation for this function) + (variable
179                used to represent cycle count for each subroutine
180                called)
181     where: (cycle count variable) = cycle count for [subroutine
182                                     name]
183
184------------------------------------------------------------------------------
185 CAUTION [optional]
186 [State any special notes, constraints or cautions for users of this function]
187
188------------------------------------------------------------------------------
189*/
190
191
192Word16
193Qua_gain(                   /* o  : index of quantization.                 */
194    enum Mode mode,         /* i  : AMR mode                               */
195    Word16 exp_gcode0,      /* i  : predicted CB gain (exponent),      Q0  */
196    Word16 frac_gcode0,     /* i  : predicted CB gain (fraction),      Q15 */
197    Word16 frac_coeff[],    /* i  : energy coeff. (5), fraction part,  Q15 */
198    Word16 exp_coeff[],     /* i  : energy coeff. (5), exponent part,  Q0  */
199    /*      (frac_coeff and exp_coeff computed in  */
200    /*       calc_filt_energies())                 */
201    Word16 gp_limit,        /* i  : pitch gain limit                       */
202    Word16 *gain_pit,       /* o  : Pitch gain,                        Q14 */
203    Word16 *gain_cod,       /* o  : Code gain,                         Q1  */
204    Word16 *qua_ener_MR122, /* o  : quantized energy error,            Q10 */
205    /*      (for MR122 MA predictor update)        */
206    Word16 *qua_ener,       /* o  : quantized energy error,            Q10 */
207    /*      (for other MA predictor update)        */
208    Flag   *pOverflow       /* o  : overflow indicator                     */
209)
210{
211    const Word16 *p;
212    Word16 i;
213    Word16 j;
214    Word16 index = 0;
215    Word16 gcode0;
216    Word16 e_max;
217    Word16 temp;
218    Word16 exp_code;
219    Word16 g_pitch;
220    Word16 g2_pitch;
221    Word16 g_code;
222    Word16 g2_code;
223    Word16 g_pit_cod;
224    Word16 coeff[5];
225    Word16 coeff_lo[5];
226    Word16 exp_max[5];
227    Word32 L_tmp;
228    Word32 L_tmp2;
229    Word32 dist_min;
230    const Word16 *table_gain;
231    Word16 table_len;
232
233    if (mode == MR102 || mode == MR74 || mode == MR67)
234    {
235        table_len = VQ_SIZE_HIGHRATES;
236        table_gain = table_gain_highrates;
237    }
238    else
239    {
240        table_len = VQ_SIZE_LOWRATES;
241        table_gain = table_gain_lowrates;
242    }
243
244    /*-------------------------------------------------------------------*
245     *  predicted codebook gain                                          *
246     *  ~~~~~~~~~~~~~~~~~~~~~~~                                          *
247     *  gc0     = 2^exp_gcode0 + 2^frac_gcode0                           *
248     *                                                                   *
249     *  gcode0 (Q14) = 2^14*2^frac_gcode0 = gc0 * 2^(14-exp_gcode0)      *
250     *-------------------------------------------------------------------*/
251
252    gcode0 = (Word16)(Pow2(14, frac_gcode0, pOverflow));
253
254    /*-------------------------------------------------------------------*
255     *  Scaling considerations:                                          *
256     *  ~~~~~~~~~~~~~~~~~~~~~~~                                          *
257     *-------------------------------------------------------------------*/
258
259    /*
260     * The error energy (sum) to be minimized consists of five terms, t[0..4].
261     *
262     *                      t[0] =    gp^2  * <y1 y1>
263     *                      t[1] = -2*gp    * <xn y1>
264     *                      t[2] =    gc^2  * <y2 y2>
265     *                      t[3] = -2*gc    * <xn y2>
266     *                      t[4] =  2*gp*gc * <y1 y2>
267     *
268     */
269
270    /* determine the scaling exponent for g_code: ec = ec0 - 11 */
271    exp_code = sub(exp_gcode0, 11, pOverflow);
272
273    /* calculate exp_max[i] = s[i]-1 */
274    exp_max[0] = sub(exp_coeff[0], 13, pOverflow);
275    exp_max[1] = sub(exp_coeff[1], 14, pOverflow);
276
277    temp = shl(exp_code, 1, pOverflow);
278    temp = add(15, temp, pOverflow);
279    exp_max[2] = add(exp_coeff[2], temp, pOverflow);
280
281    exp_max[3] = add(exp_coeff[3], exp_code, pOverflow);
282
283    temp = add(1, exp_code, pOverflow);
284    exp_max[4] = add(exp_coeff[4], temp, pOverflow);
285
286
287    /*-------------------------------------------------------------------*
288     *  Find maximum exponent:                                           *
289     *  ~~~~~~~~~~~~~~~~~~~~~~                                           *
290     *                                                                   *
291     *  For the sum operation, all terms must have the same scaling;     *
292     *  that scaling should be low enough to prevent overflow. There-    *
293     *  fore, the maximum scale is determined and all coefficients are   *
294     *  re-scaled:                                                       *
295     *                                                                   *
296     *    e_max = max(exp_max[i]) + 1;                                   *
297     *    e = exp_max[i]-e_max;         e <= 0!                          *
298     *    c[i] = c[i]*2^e                                                *
299     *-------------------------------------------------------------------*/
300
301    e_max = exp_max[0];
302    for (i = 1; i < 5; i++)
303    {
304        if (exp_max[i] > e_max)
305        {
306            e_max = exp_max[i];
307        }
308    }
309
310    e_max = add(e_max, 1, pOverflow);      /* To avoid overflow */
311
312    for (i = 0; i < 5; i++)
313    {
314        j = sub(e_max, exp_max[i], pOverflow);
315        L_tmp = L_deposit_h(frac_coeff[i]);
316        L_tmp = L_shr(L_tmp, j, pOverflow);
317        L_Extract(L_tmp, &coeff[i], &coeff_lo[i], pOverflow);
318    }
319
320
321    /*-------------------------------------------------------------------*
322     *  Codebook search:                                                 *
323     *  ~~~~~~~~~~~~~~~~                                                 *
324     *                                                                   *
325     *  For each pair (g_pitch, g_fac) in the table calculate the        *
326     *  terms t[0..4] and sum them up; the result is the mean squared    *
327     *  error for the quantized gains from the table. The index for the  *
328     *  minimum MSE is stored and finally used to retrieve the quantized *
329     *  gains                                                            *
330     *-------------------------------------------------------------------*/
331
332    /* start with "infinite" MSE */
333    dist_min = MAX_32;
334
335    p = &table_gain[0];
336
337    for (i = 0; i < table_len; i++)
338    {
339        g_pitch = *p++;
340        g_code = *p++;                   /* this is g_fac        */
341        p++;                             /* skip log2(g_fac)     */
342        p++;                             /* skip 20*log10(g_fac) */
343
344        if (g_pitch <= gp_limit)
345        {
346            g_code = mult(g_code, gcode0, pOverflow);
347            g2_pitch = mult(g_pitch, g_pitch, pOverflow);
348            g2_code = mult(g_code, g_code, pOverflow);
349            g_pit_cod = mult(g_code, g_pitch, pOverflow);
350
351            L_tmp = Mpy_32_16(coeff[0], coeff_lo[0], g2_pitch, pOverflow);
352            L_tmp2 = Mpy_32_16(coeff[1], coeff_lo[1], g_pitch, pOverflow);
353            L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
354
355            L_tmp2 = Mpy_32_16(coeff[2], coeff_lo[2], g2_code, pOverflow);
356            L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
357
358            L_tmp2 =  Mpy_32_16(coeff[3], coeff_lo[3], g_code, pOverflow);
359            L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
360
361            L_tmp2 = Mpy_32_16(coeff[4], coeff_lo[4], g_pit_cod, pOverflow);
362            L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
363
364            /* store table index if MSE for this index is lower
365               than the minimum MSE seen so far */
366            if (L_tmp < dist_min)
367            {
368                dist_min = L_tmp;
369                index = i;
370            }
371        }
372    }
373
374    /*------------------------------------------------------------------*
375     *  read quantized gains and new values for MA predictor memories   *
376     *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   *
377     *------------------------------------------------------------------*/
378
379    /* Read the quantized gains */
380    p = &table_gain[shl(index, 2, pOverflow)];
381    *gain_pit = *p++;
382    g_code = *p++;
383    *qua_ener_MR122 = *p++;
384    *qua_ener = *p;
385
386    /*------------------------------------------------------------------*
387     *  calculate final fixed codebook gain:                            *
388     *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                            *
389     *                                                                  *
390     *   gc = gc0 * g                                                   *
391     *------------------------------------------------------------------*/
392
393    L_tmp = L_mult(g_code, gcode0, pOverflow);
394    temp  = sub(10, exp_gcode0, pOverflow);
395    L_tmp = L_shr(L_tmp, temp, pOverflow);
396
397    *gain_cod = extract_h(L_tmp);
398
399    return index;
400}
401