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/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
77 extern "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 
192 Word16
Qua_gain(enum Mode mode,Word16 exp_gcode0,Word16 frac_gcode0,Word16 frac_coeff[],Word16 exp_coeff[],Word16 gp_limit,Word16 * gain_pit,Word16 * gain_cod,Word16 * qua_ener_MR122,Word16 * qua_ener,Flag * pOverflow)193 Qua_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