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/qgain795.c
35 Functions: MR795_gain_code_quant3
36            MR795_gain_code_quant_mod
37            MR795_gain_quant
38
39     Date: 02/04/2002
40
41------------------------------------------------------------------------------
42 REVISION HISTORY
43
44 Description: Updated template used to PV coding template.
45 Changed to accept the pOverflow flag for EPOC compatibility.
46
47 Description:
48 (1) Removed optimization -- mult(i, 3, pOverflow) is NOT the same as adding
49     i to itself 3 times.  The reason is because the mult function does a
50     right shift by 15, which will obliterate smaller numbers.
51
52 Description:  Replaced OSCL mem type functions and eliminated include
53               files that now are chosen by OSCL definitions
54
55 Description:  Replaced "int" and/or "char" with OSCL defined types.
56
57 Description: Changed round function name to pv_round to avoid conflict with
58              round function in C standard library.
59
60 Description: Added #ifdef __cplusplus around extern'ed table.
61
62 Description:
63
64------------------------------------------------------------------------------
65 MODULE DESCRIPTION
66
67
68------------------------------------------------------------------------------
69*/
70
71/*----------------------------------------------------------------------------
72; INCLUDES
73----------------------------------------------------------------------------*/
74#include "qgain795.h"
75#include "typedef.h"
76#include "basic_op.h"
77#include "cnst.h"
78#include "log2.h"
79#include "pow2.h"
80#include "sqrt_l.h"
81#include "g_adapt.h"
82#include "calc_en.h"
83#include "q_gain_p.h"
84
85
86/*--------------------------------------------------------------------------*/
87#ifdef __cplusplus
88extern "C"
89{
90#endif
91
92    /*----------------------------------------------------------------------------
93    ; MACROS
94    ; Define module specific macros here
95    ----------------------------------------------------------------------------*/
96
97    /*----------------------------------------------------------------------------
98    ; DEFINES
99    ; Include all pre-processor statements here. Include conditional
100    ; compile variables also.
101    ----------------------------------------------------------------------------*/
102#define NB_QUA_CODE 32
103
104    /*----------------------------------------------------------------------------
105    ; LOCAL FUNCTION DEFINITIONS
106    ; Function Prototype declaration
107    ----------------------------------------------------------------------------*/
108
109    /*----------------------------------------------------------------------------
110    ; LOCAL VARIABLE DEFINITIONS
111    ; Variable declaration - defined here and used outside this module
112    ----------------------------------------------------------------------------*/
113
114    /*----------------------------------------------------------------------------
115    ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
116    ; Declare variables used in this module but defined elsewhere
117    ----------------------------------------------------------------------------*/
118    extern const Word16 qua_gain_code[NB_QUA_CODE*3];
119
120
121    /*--------------------------------------------------------------------------*/
122#ifdef __cplusplus
123}
124#endif
125
126/*
127------------------------------------------------------------------------------
128 FUNCTION NAME: MR795_gain_code_quant3
129------------------------------------------------------------------------------
130 INPUT AND OUTPUT DEFINITIONS
131
132 Inputs:
133    exp_gcode0     -- Word16       -- predicted CB gain (exponent), Q0
134    gcode0         -- Word16       -- predicted CB gain (norm.)
135    g_pitch_cand[] -- Word16 array -- Pitch gain candidates (3),    Q14
136    g_pitch_cind[] -- Word16 array -- Pitch gain cand. indices (3), Q0
137    frac_coeff[]   -- Word16 array -- coefficients (5),             Q15
138    exp_coeff[]    -- Word16 array -- energy coefficients (5),      Q0
139                                      coefficients from calc_filt_ener()
140
141 Outputs:
142    gain_pit       -- Pointer to Word16 -- Pitch gain,                     Q14
143    gain_pit_ind   -- Pointer to Word16 -- Pitch gain index,               Q0
144    gain_cod       -- Pointer to Word16 -- Code gain,                      Q1
145    gain_cod_ind   -- Pointer to Word16 -- Code gain index,                Q0
146    qua_ener_MR122 -- Pointer to Word16 -- quantized energy error,         Q10
147                                          (for MR122 MA predictor update)
148
149    qua_ener -- Pointer to Word16 -- quantized energy error,       Q10
150                                     (for other MA predictor update)
151
152    pOverflow -- Pointer to Flag --  overflow indicator
153
154 Returns:
155    None
156
157 Global Variables Used:
158    None
159
160 Local Variables Needed:
161    None
162
163------------------------------------------------------------------------------
164 FUNCTION DESCRIPTION
165
166 PURPOSE: Pre-quantization of codebook gains, given three possible
167          LTP gains (using predicted codebook gain)
168------------------------------------------------------------------------------
169 REQUIREMENTS
170
171 None
172
173------------------------------------------------------------------------------
174 REFERENCES
175
176 qgain795.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
177
178------------------------------------------------------------------------------
179 PSEUDO-CODE
180
181
182------------------------------------------------------------------------------
183 RESOURCES USED [optional]
184
185 When the code is written for a specific target processor the
186 the resources used should be documented below.
187
188 HEAP MEMORY USED: x bytes
189
190 STACK MEMORY USED: x bytes
191
192 CLOCK CYCLES: (cycle count equation for this function) + (variable
193                used to represent cycle count for each subroutine
194                called)
195     where: (cycle count variable) = cycle count for [subroutine
196                                     name]
197
198------------------------------------------------------------------------------
199 CAUTION [optional]
200 [State any special notes, constraints or cautions for users of this function]
201
202------------------------------------------------------------------------------
203*/
204
205static void
206MR795_gain_code_quant3(
207    Word16 exp_gcode0,        /* i  : predicted CB gain (exponent), Q0  */
208    Word16 gcode0,            /* i  : predicted CB gain (norm.),    Q14 */
209    Word16 g_pitch_cand[],    /* i  : Pitch gain candidates (3),    Q14 */
210    Word16 g_pitch_cind[],    /* i  : Pitch gain cand. indices (3), Q0  */
211    Word16 frac_coeff[],      /* i  : coefficients (5),             Q15 */
212    Word16 exp_coeff[],       /* i  : energy coefficients (5),      Q0  */
213    /*      coefficients from calc_filt_ener()*/
214    Word16 *gain_pit,         /* o  : Pitch gain,                   Q14 */
215    Word16 *gain_pit_ind,     /* o  : Pitch gain index,             Q0  */
216    Word16 *gain_cod,         /* o  : Code gain,                    Q1  */
217    Word16 *gain_cod_ind,     /* o  : Code gain index,              Q0  */
218    Word16 *qua_ener_MR122,   /* o  : quantized energy error,       Q10 */
219    /*      (for MR122 MA predictor update)   */
220    Word16 *qua_ener,         /* o  : quantized energy error,       Q10 */
221    /*      (for other MA predictor update)   */
222    Flag   *pOverflow         /* o  : overflow indicator                */
223)
224{
225    const Word16 *p;
226    Word16 i;
227    Word16 j;
228    Word16 cod_ind;
229    Word16 pit_ind;
230    Word16 e_max;
231    Word16 exp_code;
232    Word16 g_pitch;
233    Word16 g2_pitch;
234    Word16 g_code;
235    Word16 g2_code_h;
236    Word16 g2_code_l;
237    Word16 g_pit_cod_h;
238    Word16 g_pit_cod_l;
239    Word16 coeff[5];
240    Word16 coeff_lo[5];
241    Word16 exp_max[5];
242    Word32 L_tmp;
243    Word32 L_tmp0;
244    Word32 dist_min;
245
246    /*
247     * The error energy (sum) to be minimized consists of five terms, t[0..4].
248     *
249     *                      t[0] =    gp^2  * <y1 y1>
250     *                      t[1] = -2*gp    * <xn y1>
251     *                      t[2] =    gc^2  * <y2 y2>
252     *                      t[3] = -2*gc    * <xn y2>
253     *                      t[4] =  2*gp*gc * <y1 y2>
254     *
255     */
256
257    /* determine the scaling exponent for g_code: ec = ec0 - 10 */
258    exp_code = sub(exp_gcode0, 10, pOverflow);
259
260    /* calculate exp_max[i] = s[i]-1 */
261    exp_max[0] = sub(exp_coeff[0], 13, pOverflow);
262    exp_max[1] = sub(exp_coeff[1], 14, pOverflow);
263    exp_max[2] = add(exp_coeff[2], add(15, shl(exp_code, 1, pOverflow), pOverflow), pOverflow);
264    exp_max[3] = add(exp_coeff[3], exp_code, pOverflow);
265    exp_max[4] = add(exp_coeff[4], add(exp_code, 1, pOverflow), pOverflow);
266
267
268    /*-------------------------------------------------------------------*
269     *  Find maximum exponent:                                           *
270     *  ~~~~~~~~~~~~~~~~~~~~~~                                           *
271     *                                                                   *
272     *  For the sum operation, all terms must have the same scaling;     *
273     *  that scaling should be low enough to prevent overflow. There-    *
274     *  fore, the maximum scale is determined and all coefficients are   *
275     *  re-scaled:                                                       *
276     *                                                                   *
277     *    e_max = max(exp_max[i]) + 1;                                   *
278     *    e = exp_max[i]-e_max;         e <= 0!                          *
279     *    c[i] = c[i]*2^e                                                *
280     *-------------------------------------------------------------------*/
281
282    e_max = exp_max[0];
283    for (i = 1; i < 5; i++)     /* implemented flattened */
284    {
285        if (exp_max[i] > e_max)
286        {
287            e_max = exp_max[i];
288        }
289    }
290
291    e_max = add(e_max, 1, pOverflow);      /* To avoid overflow */
292
293    for (i = 0; i < 5; i++)
294    {
295        j = sub(e_max, exp_max[i], pOverflow);
296        L_tmp = L_deposit_h(frac_coeff[i]);
297        L_tmp = L_shr(L_tmp, j, pOverflow);
298        L_Extract(L_tmp, &coeff[i], &coeff_lo[i], pOverflow);
299    }
300
301
302    /*-------------------------------------------------------------------*
303     *  Codebook search:                                                 *
304     *  ~~~~~~~~~~~~~~~~                                                 *
305     *                                                                   *
306     *  For each of the candiates LTP gains in g_pitch_cand[], the terms *
307     *  t[0..4] are calculated from the values in the table (and the     *
308     *  pitch gain candidate) and summed up; the result is the mean      *
309     *  squared error for the LPT/CB gain pair. The index for the mini-  *
310     *  mum MSE is stored and finally used to retrieve the quantized CB  *
311     *  gain                                                             *
312     *-------------------------------------------------------------------*/
313
314    /* start with "infinite" MSE */
315    dist_min = MAX_32;
316    cod_ind = 0;
317    pit_ind = 0;
318
319    /* loop through LTP gain candidates */
320    for (j = 0; j < 3; j++)
321    {
322        /* pre-calculate terms only dependent on pitch gain */
323        g_pitch = g_pitch_cand[j];
324        g2_pitch = mult(g_pitch, g_pitch, pOverflow);
325        L_tmp0 = Mpy_32_16(coeff[0], coeff_lo[0], g2_pitch, pOverflow);
326        L_tmp0 = Mac_32_16(L_tmp0, coeff[1], coeff_lo[1], g_pitch, pOverflow);
327
328        p = &qua_gain_code[0];
329        for (i = 0; i < NB_QUA_CODE; i++)
330        {
331            g_code = *p++;                   /* this is g_fac        Q11 */
332            p++;                             /* skip log2(g_fac)         */
333            p++;                             /* skip 20*log10(g_fac)     */
334
335            g_code = mult(g_code, gcode0, pOverflow);
336
337            L_tmp = L_mult(g_code, g_code, pOverflow);
338            L_Extract(L_tmp, &g2_code_h, &g2_code_l, pOverflow);
339
340            L_tmp = L_mult(g_code, g_pitch, pOverflow);
341            L_Extract(L_tmp, &g_pit_cod_h, &g_pit_cod_l, pOverflow);
342
343            L_tmp = Mac_32(L_tmp0, coeff[2], coeff_lo[2],
344                           g2_code_h, g2_code_l, pOverflow);
345            L_tmp = Mac_32_16(L_tmp, coeff[3], coeff_lo[3],
346                              g_code, pOverflow);
347            L_tmp = Mac_32(L_tmp, coeff[4], coeff_lo[4],
348                           g_pit_cod_h, g_pit_cod_l, pOverflow);
349
350            /* store table index if MSE for this index is lower
351               than the minimum MSE seen so far; also store the
352               pitch gain for this (so far) lowest MSE          */
353            if (L_tmp < dist_min)
354            {
355                dist_min = L_tmp;
356                cod_ind = i;
357                pit_ind = j;
358            }
359        }
360    }
361
362    /*------------------------------------------------------------------*
363     *  read quantized gains and new values for MA predictor memories   *
364     *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   *
365     *------------------------------------------------------------------*/
366
367    /* Read the quantized gains */
368    p = &qua_gain_code[
369            add(add(cod_ind, cod_ind, pOverflow), cod_ind, pOverflow)];
370
371    g_code = *p++;
372    *qua_ener_MR122 = *p++;
373    *qua_ener = *p;
374
375    /*------------------------------------------------------------------*
376     *  calculate final fixed codebook gain:                            *
377     *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                            *
378     *                                                                  *
379     *   gc = gc0 * g                                                   *
380     *------------------------------------------------------------------*/
381
382    L_tmp = L_mult(g_code, gcode0, pOverflow);
383    L_tmp = L_shr(L_tmp, sub(9, exp_gcode0, pOverflow), pOverflow);
384    *gain_cod = extract_h(L_tmp);
385    *gain_cod_ind = cod_ind;
386    *gain_pit = g_pitch_cand[pit_ind];
387    *gain_pit_ind = g_pitch_cind[pit_ind];
388}
389
390
391/*
392------------------------------------------------------------------------------
393 FUNCTION NAME: MR795_gain_code_quant_mod
394------------------------------------------------------------------------------
395 INPUT AND OUTPUT DEFINITIONS
396
397 Inputs:
398    gain_pit     -- Word16 -- pitch gain,                                   Q14
399    exp_gcode0   -- Word16 -- predicted CB gain (exponent),                 Q0
400    gcode0       -- Word16 -- predicted CB gain (norm.),                    Q14
401    frac_en[]    -- Word16 array -- energy coefficients (4), fraction part, Q15
402    exp_en[]     -- Word16 array -- energy coefficients (4), exponent part, Q0
403    alpha        -- Word16 -- gain adaptor factor (>0),                     Q15
404
405    gain_cod_unq -- Word16 -- Code gain (unquantized)
406                              (scaling: Q10 - exp_gcode0)
407
408    gain_cod     -- Pointer to Word16 -- Code gain (pre-/quantized),        Q1
409
410 Outputs:
411    qua_ener_MR122 -- Pointer to Word16 -- quantized energy error,       Q10
412                                           (for MR122 MA predictor update)
413    qua_ener       -- Pointer to Word16 -- quantized energy error,       Q10
414                                           (for other MA predictor update)
415    pOverflow      -- Pointer to Flag -- overflow indicator
416
417 Returns:
418    index of quantization (Word16)
419
420 Global Variables Used:
421    None
422
423 Local Variables Needed:
424    None
425
426------------------------------------------------------------------------------
427 FUNCTION DESCRIPTION
428
429 PURPOSE: Modified quantization of the MR795 codebook gain
430
431 Uses pre-computed energy coefficients in frac_en[]/exp_en[]
432
433       frac_en[0]*2^exp_en[0] = <res res>   // LP residual energy
434       frac_en[1]*2^exp_en[1] = <exc exc>   // LTP residual energy
435       frac_en[2]*2^exp_en[2] = <exc code>  // LTP/CB innovation dot product
436       frac_en[3]*2^exp_en[3] = <code code> // CB innovation energy
437------------------------------------------------------------------------------
438 REQUIREMENTS
439
440 None
441
442------------------------------------------------------------------------------
443 REFERENCES
444
445 qgain795.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
446
447------------------------------------------------------------------------------
448 PSEUDO-CODE
449
450
451------------------------------------------------------------------------------
452 RESOURCES USED [optional]
453
454 When the code is written for a specific target processor the
455 the resources used should be documented below.
456
457 HEAP MEMORY USED: x bytes
458
459 STACK MEMORY USED: x bytes
460
461 CLOCK CYCLES: (cycle count equation for this function) + (variable
462                used to represent cycle count for each subroutine
463                called)
464     where: (cycle count variable) = cycle count for [subroutine
465                                     name]
466
467------------------------------------------------------------------------------
468 CAUTION [optional]
469 [State any special notes, constraints or cautions for users of this function]
470
471------------------------------------------------------------------------------
472*/
473
474static Word16
475MR795_gain_code_quant_mod(  /* o  : index of quantization.            */
476    Word16 gain_pit,        /* i  : pitch gain,                   Q14 */
477    Word16 exp_gcode0,      /* i  : predicted CB gain (exponent), Q0  */
478    Word16 gcode0,          /* i  : predicted CB gain (norm.),    Q14 */
479    Word16 frac_en[],       /* i  : energy coefficients (4),
480                                    fraction part,                Q15 */
481    Word16 exp_en[],        /* i  : energy coefficients (4),
482                                    eponent part,                 Q0  */
483    Word16 alpha,           /* i  : gain adaptor factor (>0),     Q15 */
484    Word16 gain_cod_unq,    /* i  : Code gain (unquantized)           */
485    /*      (scaling: Q10 - exp_gcode0)       */
486    Word16 *gain_cod,       /* i/o: Code gain (pre-/quantized),   Q1  */
487    Word16 *qua_ener_MR122, /* o  : quantized energy error,       Q10 */
488    /*      (for MR122 MA predictor update)   */
489    Word16 *qua_ener,       /* o  : quantized energy error,       Q10 */
490    /*      (for other MA predictor update)   */
491    Flag   *pOverflow       /* o  : overflow indicator                */
492)
493{
494    const Word16 *p;
495    Word16 i;
496    Word16 index;
497    Word16 tmp;
498    Word16 one_alpha;
499    Word16 exp;
500    Word16 e_max;
501
502    Word16 g2_pitch;
503    Word16 g_code;
504    Word16 g2_code_h;
505    Word16 g2_code_l;
506    Word16 d2_code_h;
507    Word16 d2_code_l;
508    Word16 coeff[5];
509    Word16 coeff_lo[5];
510    Word16 exp_coeff[5];
511    Word32 L_tmp;
512    Word32 L_t0;
513    Word32 L_t1;
514    Word32 dist_min;
515    Word16 gain_code;
516
517    /*
518      Steps in calculation of the error criterion (dist):
519      ---------------------------------------------------
520
521      underlined = constant; alp = FLP value of alpha, alpha = FIP
522      ----------
523
524
525        ExEn = gp^2 * LtpEn + 2.0*gp*gc[i] * XC + gc[i]^2 * InnEn;
526               ------------   ------         --             -----
527
528        aExEn= alp * ExEn
529             = alp*gp^2*LtpEn + 2.0*alp*gp*XC* gc[i] + alp*InnEn* gc[i]^2
530               --------------   -------------          ---------
531
532             =         t[1]   +              t[2]    +          t[3]
533
534        dist = d1 + d2;
535
536          d1 = (1.0 - alp) * InnEn * (gcu - gc[i])^2 = t[4]
537               -------------------    ---
538
539          d2 =        alp  * (ResEn - 2.0 * sqrt(ResEn*ExEn) + ExEn);
540                      ---     -----   ---        -----
541
542             =        alp  * (sqrt(ExEn) - sqrt(ResEn))^2
543                      ---                  -----------
544
545             =               (sqrt(aExEn) - sqrt(alp*ResEn))^2
546                                            ---------------
547
548             =               (sqrt(aExEn) -       t[0]     )^2
549                                                  ----
550
551     */
552
553    /*
554     * calculate scalings of the constant terms
555     */
556    gain_code = shl(*gain_cod, sub(10, exp_gcode0, pOverflow), pOverflow);   /* Q1  -> Q11 (-ec0) */
557    g2_pitch = mult(gain_pit, gain_pit, pOverflow);               /* Q14 -> Q13        */
558    /* 0 < alpha <= 0.5 => 0.5 <= 1-alpha < 1, i.e one_alpha is normalized  */
559    one_alpha = add(sub(32767, alpha, pOverflow), 1, pOverflow);   /* 32768 - alpha */
560
561
562    /*  alpha <= 0.5 -> mult. by 2 to keep precision; compensate in exponent */
563    L_t1 = L_mult(alpha, frac_en[1], pOverflow);
564    L_t1 = L_shl(L_t1, 1, pOverflow);
565    tmp = extract_h(L_t1);
566
567    /* directly store in 32 bit variable because no further mult. required */
568    L_t1 = L_mult(tmp, g2_pitch, pOverflow);
569    exp_coeff[1] = sub(exp_en[1], 15, pOverflow);
570
571
572    tmp = extract_h(L_shl(L_mult(alpha, frac_en[2], pOverflow), 1, pOverflow));
573    coeff[2] = mult(tmp, gain_pit, pOverflow);
574    exp = sub(exp_gcode0, 10, pOverflow);
575    exp_coeff[2] = add(exp_en[2], exp, pOverflow);
576
577
578    /* alpha <= 0.5 -> mult. by 2 to keep precision; compensate in exponent */
579    coeff[3] = extract_h(L_shl(L_mult(alpha, frac_en[3], pOverflow), 1, pOverflow));
580    exp = sub(shl(exp_gcode0, 1, pOverflow), 7, pOverflow);
581    exp_coeff[3] = add(exp_en[3], exp, pOverflow);
582
583
584    coeff[4] = mult(one_alpha, frac_en[3], pOverflow);
585    exp_coeff[4] = add(exp_coeff[3], 1, pOverflow);
586
587
588    L_tmp = L_mult(alpha, frac_en[0], pOverflow);
589    /* sqrt_l returns normalized value and 2*exponent
590       -> result = val >> (exp/2)
591       exp_coeff holds 2*exponent for c[0]            */
592    /* directly store in 32 bit variable because no further mult. required */
593    L_t0 = sqrt_l_exp(L_tmp, &exp, pOverflow);  /* normalization included in sqrt_l_exp */
594    exp = add(exp, 47, pOverflow);
595    exp_coeff[0] = sub(exp_en[0], exp, pOverflow);
596
597    /*
598     * Determine the maximum exponent occuring in the distance calculation
599     * and adjust all fractions accordingly (including a safety margin)
600     *
601     */
602
603    /* find max(e[1..4],e[0]+31) */
604    e_max = add(exp_coeff[0], 31, pOverflow);
605    for (i = 1; i <= 4; i++)
606    {
607        if (exp_coeff[i] > e_max)
608        {
609            e_max = exp_coeff[i];
610        }
611    }
612
613    /* scale c[1]         (requires no further multiplication) */
614    tmp = sub(e_max, exp_coeff[1], pOverflow);
615    L_t1 = L_shr(L_t1, tmp, pOverflow);
616
617    /* scale c[2..4] (used in Mpy_32_16 in the quantizer loop) */
618    for (i = 2; i <= 4; i++)
619    {
620        tmp = sub(e_max, exp_coeff[i], pOverflow);
621        L_tmp = L_deposit_h(coeff[i]);
622        L_tmp = L_shr(L_tmp, tmp, pOverflow);
623        L_Extract(L_tmp, &coeff[i], &coeff_lo[i], pOverflow);
624    }
625
626    /* scale c[0]         (requires no further multiplication) */
627    exp = sub(e_max, 31, pOverflow);              /* new exponent */
628    tmp = sub(exp, exp_coeff[0], pOverflow);
629    L_t0 = L_shr(L_t0, shr(tmp, 1, pOverflow), pOverflow);
630    /* perform correction by 1/sqrt(2) if exponent difference is odd */
631    if ((tmp & 0x1) != 0)
632    {
633        L_Extract(L_t0, &coeff[0], &coeff_lo[0], pOverflow);
634        L_t0 = Mpy_32_16(coeff[0], coeff_lo[0],
635                         23170, pOverflow);                    /* 23170 Q15 = 1/sqrt(2)*/
636    }
637
638    /* search the quantizer table for the lowest value
639       of the search criterion                           */
640    dist_min = MAX_32;
641    index = 0;
642    p = &qua_gain_code[0];
643
644    for (i = 0; i < NB_QUA_CODE; i++)
645    {
646        g_code = *p++;                   /* this is g_fac (Q11)  */
647        p++;                             /* skip log2(g_fac)     */
648        p++;                             /* skip 20*log10(g_fac) */
649        g_code = mult(g_code, gcode0, pOverflow);
650
651        /* only continue if    gc[i]            < 2.0*gc
652           which is equiv. to  g_code (Q10-ec0) < gain_code (Q11-ec0) */
653
654        if (g_code >= gain_code)
655        {
656            break;
657        }
658
659        L_tmp = L_mult(g_code, g_code, pOverflow);
660        L_Extract(L_tmp, &g2_code_h, &g2_code_l, pOverflow);
661
662        tmp = sub(g_code, gain_cod_unq, pOverflow);
663        L_tmp = L_mult(tmp, tmp, pOverflow);
664        L_Extract(L_tmp, &d2_code_h, &d2_code_l, pOverflow);
665
666        /* t2, t3, t4 */
667        L_tmp = Mac_32_16(L_t1, coeff[2], coeff_lo[2], g_code, pOverflow);
668        L_tmp = Mac_32(L_tmp,    coeff[3], coeff_lo[3], g2_code_h, g2_code_l, pOverflow);
669
670        L_tmp = sqrt_l_exp(L_tmp, &exp, pOverflow);
671        L_tmp = L_shr(L_tmp, shr(exp, 1, pOverflow), pOverflow);
672
673        /* d2 */
674        tmp = pv_round(L_sub(L_tmp, L_t0, pOverflow), pOverflow);
675        L_tmp = L_mult(tmp, tmp, pOverflow);
676
677        /* dist */
678        L_tmp = Mac_32(L_tmp, coeff[4], coeff_lo[4], d2_code_h, d2_code_l, pOverflow);
679
680        /* store table index if distance measure for this
681            index is lower than the minimum seen so far   */
682        if (L_tmp < dist_min)
683        {
684            dist_min = L_tmp;
685            index = i;
686        }
687    }
688
689    /*------------------------------------------------------------------*
690     *  read quantized gains and new values for MA predictor memories   *
691     *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   *
692     *------------------------------------------------------------------*/
693
694    /* Read the quantized gains */
695    p = &qua_gain_code[add(add(index, index, pOverflow), index, pOverflow)];
696    g_code = *p++;
697    *qua_ener_MR122 = *p++;
698    *qua_ener = *p;
699
700    /*------------------------------------------------------------------*
701     *  calculate final fixed codebook gain:                            *
702     *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                            *
703     *                                                                  *
704     *   gc = gc0 * g                                                   *
705     *------------------------------------------------------------------*/
706
707    L_tmp = L_mult(g_code, gcode0, pOverflow);
708    L_tmp = L_shr(L_tmp, sub(9, exp_gcode0, pOverflow), pOverflow);
709    *gain_cod = extract_h(L_tmp);
710
711    return index;
712}
713
714/*
715------------------------------------------------------------------------------
716 FUNCTION NAME: MR795_gain_quant
717------------------------------------------------------------------------------
718 INPUT AND OUTPUT DEFINITIONS
719MR795_gain_quant(
720
721
722 Inputs:
723    adapt_st      -- Pointer to GainAdaptState -- gain adapter state structure
724    res           -- Word16 array -- LP residual,                  Q0
725    exc           -- Word16 array -- LTP excitation (unfiltered),  Q0
726    code          -- Word16 array -- CB innovation (unfiltered),   Q13
727    frac_coeff    -- Word16 array -- coefficients (5),             Q15
728    exp_coeff     -- Word16 array -- energy coefficients (5),      Q0
729                                    coefficients from calc_filt_ener()
730    exp_code_en   -- Word16 -- innovation energy (exponent), Q0
731    frac_code_en  -- Word16 -- innovation energy (fraction), Q15
732    exp_gcode0    -- Word16 -- predicted CB gain (exponent), Q0
733    frac_gcode0   -- Word16 -- predicted CB gain (fraction), Q15
734    L_subfr       -- Word16 -- Subframe length
735    cod_gain_frac -- Word16 -- opt. codebook gain (fraction),Q15
736    cod_gain_exp  -- Word16 -- opt. codebook gain (exponent), Q0
737    gp_limit      -- Word16 -- pitch gain limit
738    gain_pit      -- Pointer to Word16 -- Pitch gain,              Q14
739
740 Output
741    adapt_st       -- Pointer to GainAdaptState -- gain adapter state structure
742    gain_pit       -- Pointer to Word16 -- Pitch gain,              Q14
743
744    gain_pit       -- Pointer to Word16 -- Pitch gain,                   Q14
745    gain_cod       -- Pointer to Word16 -- Code gain,                    Q1
746    qua_ener_MR122 -- Pointer to Word16 -- quantized energy error,       Q10
747                                           (for MR122 MA predictor update)
748
749    qua_ener       -- Pointer to Word16 -- quantized energy error,       Q10
750                                           (for other MA predictor update)
751
752    anap           -- Double Pointer to Word16 -- Index of quantization
753                                           (first gain pitch, then code pitch)
754
755    pOverflow      -- Pointer to Flag -- overflow indicator
756
757 Returns:
758    None
759
760 Global Variables Used:
761    None
762
763 Local Variables Needed:
764    None
765
766------------------------------------------------------------------------------
767 FUNCTION DESCRIPTION
768
769 pitch and codebook quantization for MR795
770------------------------------------------------------------------------------
771 REQUIREMENTS
772
773 None
774
775------------------------------------------------------------------------------
776 REFERENCES
777
778 qgain795.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
779
780------------------------------------------------------------------------------
781 PSEUDO-CODE
782
783
784------------------------------------------------------------------------------
785 RESOURCES USED [optional]
786
787 When the code is written for a specific target processor the
788 the resources used should be documented below.
789
790 HEAP MEMORY USED: x bytes
791
792 STACK MEMORY USED: x bytes
793
794 CLOCK CYCLES: (cycle count equation for this function) + (variable
795                used to represent cycle count for each subroutine
796                called)
797     where: (cycle count variable) = cycle count for [subroutine
798                                     name]
799
800------------------------------------------------------------------------------
801 CAUTION [optional]
802 [State any special notes, constraints or cautions for users of this function]
803
804------------------------------------------------------------------------------
805*/
806
807void
808MR795_gain_quant(
809    GainAdaptState *adapt_st, /* i/o: gain adapter state structure       */
810    Word16 res[],             /* i  : LP residual,                  Q0   */
811    Word16 exc[],             /* i  : LTP excitation (unfiltered),  Q0   */
812    Word16 code[],            /* i  : CB innovation (unfiltered),   Q13  */
813    Word16 frac_coeff[],      /* i  : coefficients (5),             Q15  */
814    Word16 exp_coeff[],       /* i  : energy coefficients (5),      Q0   */
815    /*      coefficients from calc_filt_ener() */
816    Word16 exp_code_en,       /* i  : innovation energy (exponent), Q0   */
817    Word16 frac_code_en,      /* i  : innovation energy (fraction), Q15  */
818    Word16 exp_gcode0,        /* i  : predicted CB gain (exponent), Q0   */
819    Word16 frac_gcode0,       /* i  : predicted CB gain (fraction), Q15  */
820    Word16 L_subfr,           /* i  : Subframe length                    */
821    Word16 cod_gain_frac,     /* i  : opt. codebook gain (fraction),Q15  */
822    Word16 cod_gain_exp,      /* i  : opt. codebook gain (exponent), Q0  */
823    Word16 gp_limit,          /* i  : pitch gain limit                   */
824    Word16 *gain_pit,         /* i/o: Pitch gain,                   Q14  */
825    Word16 *gain_cod,         /* o  : Code gain,                    Q1   */
826    Word16 *qua_ener_MR122,   /* o  : quantized energy error,       Q10  */
827    /*      (for MR122 MA predictor update)    */
828    Word16 *qua_ener,         /* o  : quantized energy error,       Q10  */
829    /*      (for other MA predictor update)    */
830    Word16 **anap,            /* o  : Index of quantization              */
831    /*      (first gain pitch, then code pitch)*/
832    Flag   *pOverflow         /* o  : overflow indicator                */
833)
834{
835    Word16 frac_en[4];
836    Word16 exp_en[4];
837    Word16 ltpg, alpha, gcode0;
838    Word16 g_pitch_cand[3];      /* pitch gain candidates   Q14 */
839    Word16 g_pitch_cind[3];      /* pitch gain indices      Q0  */
840    Word16 gain_pit_index;
841    Word16 gain_cod_index;
842    Word16 exp;
843    Word16 gain_cod_unq;         /* code gain (unq.) Q(10-exp_gcode0)  */
844
845
846    /* get list of candidate quantized pitch gain values
847     * and corresponding quantization indices
848     */
849    gain_pit_index = q_gain_pitch(MR795, gp_limit, gain_pit,
850                                  g_pitch_cand, g_pitch_cind, pOverflow);
851
852    /*-------------------------------------------------------------------*
853     *  predicted codebook gain                                          *
854     *  ~~~~~~~~~~~~~~~~~~~~~~~                                          *
855     *  gc0     = 2^exp_gcode0 + 2^frac_gcode0                           *
856     *                                                                   *
857     *  gcode0 (Q14) = 2^14*2^frac_gcode0 = gc0 * 2^(14-exp_gcode0)      *
858     *-------------------------------------------------------------------*/
859    gcode0 = (Word16)(Pow2(14, frac_gcode0, pOverflow));           /* Q14 */
860
861    /* pre-quantization of codebook gain
862     * (using three pitch gain candidates);
863     * result: best guess of pitch gain and code gain
864     */
865    MR795_gain_code_quant3(
866        exp_gcode0, gcode0, g_pitch_cand, g_pitch_cind,
867        frac_coeff, exp_coeff,
868        gain_pit, &gain_pit_index, gain_cod, &gain_cod_index,
869        qua_ener_MR122, qua_ener, pOverflow);
870
871    /* calculation of energy coefficients and LTP coding gain */
872    calc_unfilt_energies(res, exc, code, *gain_pit, L_subfr,
873                         frac_en, exp_en, &ltpg, pOverflow);
874
875    /* run gain adaptor, calculate alpha factor to balance LTP/CB gain
876     * (this includes the gain adaptor update)
877     * Note: ltpg = 0 if frac_en[0] == 0, so the update is OK in that case
878     */
879    gain_adapt(adapt_st, ltpg, *gain_cod, &alpha, pOverflow);
880
881    /* if this is a very low energy signal (threshold: see
882     * calc_unfilt_energies) or alpha <= 0 then don't run the modified quantizer
883     */
884    if (frac_en[0] != 0 && alpha > 0)
885    {
886        /* innovation energy <cod cod> was already computed in gc_pred() */
887        /* (this overwrites the LtpResEn which is no longer needed)      */
888        frac_en[3] = frac_code_en;
889        exp_en[3] = exp_code_en;
890
891        /* store optimum codebook gain in Q(10-exp_gcode0) */
892        exp = add(sub(cod_gain_exp, exp_gcode0, pOverflow), 10, pOverflow);
893        gain_cod_unq = shl(cod_gain_frac, exp, pOverflow);
894
895        /* run quantization with modified criterion */
896        gain_cod_index = MR795_gain_code_quant_mod(
897                             *gain_pit, exp_gcode0, gcode0,
898                             frac_en, exp_en, alpha, gain_cod_unq,
899                             gain_cod, qua_ener_MR122, qua_ener, pOverflow); /* function result */
900    }
901
902    *(*anap)++ = gain_pit_index;
903    *(*anap)++ = gain_cod_index;
904}
905