1e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/*
2e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Copyright 2003-2010, VisualOn, Inc.
3e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
4e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Licensed under the Apache License, Version 2.0 (the "License");
5e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** you may not use this file except in compliance with the License.
6e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** You may obtain a copy of the License at
7e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
8e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **     http://www.apache.org/licenses/LICENSE-2.0
9e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
10e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Unless required by applicable law or agreed to in writing, software
11e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** distributed under the License is distributed on an "AS IS" BASIS,
12e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** See the License for the specific language governing permissions and
14e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** limitations under the License.
15e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard */
16e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
17e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/**************************************************************************
18e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*  File: q_gain2.c                                                         *
19e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*                                                                          *
20e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*  Description:                                                            *
21e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard* Quantization of pitch and codebook gains.                                *
22e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard* MA prediction is performed on the innovation energy (in dB with mean     *
23e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard* removed).                                                                *
24e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard* An initial predicted gain, g_0, is first determined and the correction   *
25e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard* factor     alpha = gain / g_0    is quantized.                           *
26e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard* The pitch gain and the correction factor are vector quantized and the    *
27e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard* mean-squared weighted error criterion is used in the quantizer search.   *
28e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard****************************************************************************/
29e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
30e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "typedef.h"
31e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "basic_op.h"
32e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "oper_32b.h"
33e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "math_op.h"
34e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "log2.h"
35e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "acelp.h"
36e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "q_gain2.tab"
37e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
38e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#define MEAN_ENER    30
39e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#define RANGE        64
40e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#define PRED_ORDER   4
41e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
42e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
43e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/* MA prediction coeff ={0.5, 0.4, 0.3, 0.2} in Q13 */
44e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic Word16 pred[PRED_ORDER] = {4096, 3277, 2458, 1638};
45e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
46e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
47e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid Init_Q_gain2(
485d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 * mem                          /* output  :static memory (2 words)      */
495d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
50e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
515d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 i;
52e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
535d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* 4nd order quantizer energy predictor (init to -14.0 in Q10) */
545d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < PRED_ORDER; i++)
555d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
565d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        mem[i] = -14336;                     /* past_qua_en[i] */
575d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
58e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
595d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return;
60e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
61e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
62e2e838afcf03e603a41a0455846eaf9614537c16Mans RullgardWord16 Q_gain2(                            /* Return index of quantization.          */
635d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 xn[],                          /* (i) Q_xn: Target vector.               */
645d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 y1[],                          /* (i) Q_xn: Adaptive codebook.           */
655d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 Q_xn,                          /* (i)     : xn and y1 format             */
665d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 y2[],                          /* (i) Q9  : Filtered innovative vector.  */
675d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 code[],                        /* (i) Q9  : Innovative vector.           */
685d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 g_coeff[],                     /* (i)     : Correlations <xn y1> <y1 y1> */
695d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        /*           Compute in G_pitch().        */
705d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 L_subfr,                       /* (i)     : Subframe lenght.             */
715d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 nbits,                         /* (i)     : number of bits (6 or 7)      */
725d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 * gain_pit,                    /* (i/o)Q14: Pitch gain.                  */
735d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word32 * gain_cod,                    /* (o) Q16 : Code gain.                   */
745d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 gp_clip,                       /* (i)     : Gp Clipping flag             */
755d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 * mem                          /* (i/o)   : static memory (2 words)      */
765d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen          )
77e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
785d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 index, *p, min_ind, size;
795d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 exp, frac, gcode0, exp_gcode0, e_max, exp_code, qua_ener;
805d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 g_pitch, g2_pitch, g_code, g_pit_cod, g2_code, g2_code_lo;
815d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 coeff[5], coeff_lo[5], exp_coeff[5];
825d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 exp_max[5];
835d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 i, j, L_tmp, dist_min;
845d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 *past_qua_en, *t_qua_gain;
855d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
865d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    past_qua_en = mem;
875d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
885d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /*-----------------------------------------------------------------*
895d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * - Find the initial quantization pitch index                     *
905d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * - Set gains search range                                        *
915d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *-----------------------------------------------------------------*/
925d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if (nbits == 6)
935d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
945d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        t_qua_gain = t_qua_gain6b;
955d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        min_ind = 0;
965d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        size = RANGE;
975d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
985d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        if(gp_clip == 1)
995d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
1005d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            size = size - 16;          /* limit gain pitch to 1.0 */
1015d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
1025d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    } else
1035d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
1045d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        t_qua_gain = t_qua_gain7b;
1055d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1065d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        p = t_qua_gain7b + RANGE;            /* pt at 1/4th of table */
1075d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1085d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        j = nb_qua_gain7b - RANGE;
1095d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1105d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        if (gp_clip == 1)
1115d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
1125d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            j = j - 27;                /* limit gain pitch to 1.0 */
1135d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
1145d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        min_ind = 0;
1155d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        g_pitch = *gain_pit;
1165d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1175d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        for (i = 0; i < j; i++, p += 2)
1185d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
1195d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            if (g_pitch > *p)
1205d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            {
1215d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                min_ind = min_ind + 1;
1225d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            }
1235d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
1245d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        size = RANGE;
1255d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
1265d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1275d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /*------------------------------------------------------------------*
1285d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *  Compute coefficient need for the quantization.                  *
1295d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *                                                                  *
1305d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *  coeff[0] =    y1 y1                                             *
1315d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *  coeff[1] = -2 xn y1                                             *
1325d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *  coeff[2] =    y2 y2                                             *
1335d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *  coeff[3] = -2 xn y2                                             *
1345d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *  coeff[4] =  2 y1 y2                                             *
1355d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *                                                                  *
1365d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * Product <y1 y1> and <xn y1> have been compute in G_pitch() and   *
1375d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * are in vector g_coeff[].                                         *
1385d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *------------------------------------------------------------------*/
1395d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1405d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    coeff[0] = g_coeff[0];
1415d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp_coeff[0] = g_coeff[1];
1425d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    coeff[1] = negate(g_coeff[2]);                    /* coeff[1] = -2 xn y1 */
1435d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp_coeff[1] = g_coeff[3] + 1;
1445d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1455d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Compute scalar product <y2[],y2[]> */
146e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#ifdef ASM_OPT                   /* asm optimization branch */
1475d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    coeff[2] = extract_h(Dot_product12_asm(y2, y2, L_subfr, &exp));
148e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#else
1495d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    coeff[2] = extract_h(Dot_product12(y2, y2, L_subfr, &exp));
150e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#endif
1515d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp_coeff[2] = (exp - 18) + (Q_xn << 1);     /* -18 (y2 Q9) */
152e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
1535d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Compute scalar product -2*<xn[],y2[]> */
154e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#ifdef ASM_OPT                  /* asm optimization branch */
1555d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    coeff[3] = extract_h(L_negate(Dot_product12_asm(xn, y2, L_subfr, &exp)));
156e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#else
1575d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    coeff[3] = extract_h(L_negate(Dot_product12(xn, y2, L_subfr, &exp)));
158e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#endif
159e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
1605d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp_coeff[3] = (exp - 8) + Q_xn;  /* -9 (y2 Q9), +1 (2 xn y2) */
161e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
1625d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Compute scalar product 2*<y1[],y2[]> */
163e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#ifdef ASM_OPT                 /* asm optimization branch */
1645d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    coeff[4] = extract_h(Dot_product12_asm(y1, y2, L_subfr, &exp));
165e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#else
1665d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    coeff[4] = extract_h(Dot_product12(y1, y2, L_subfr, &exp));
167e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#endif
1685d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp_coeff[4] = (exp - 8) + Q_xn;  /* -9 (y2 Q9), +1 (2 y1 y2) */
1695d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1705d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /*-----------------------------------------------------------------*
1715d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *  Find energy of code and compute:                               *
1725d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *                                                                 *
1735d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *    L_tmp = MEAN_ENER - 10log10(energy of code/ L_subfr)         *
1745d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *          = MEAN_ENER - 3.0103*log2(energy of code/ L_subfr)     *
1755d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *-----------------------------------------------------------------*/
176e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#ifdef ASM_OPT                 /* asm optimization branch */
1775d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_tmp = Dot_product12_asm(code, code, L_subfr, &exp_code);
178e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#else
1795d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_tmp = Dot_product12(code, code, L_subfr, &exp_code);
180e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#endif
1815d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* exp_code: -18 (code in Q9), -6 (/L_subfr), -31 (L_tmp Q31->Q0) */
1825d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp_code = (exp_code - (18 + 6 + 31));
1835d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1845d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Log2(L_tmp, &exp, &frac);
1855d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp += exp_code;
1865d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_tmp = Mpy_32_16(exp, frac, -24660);  /* x -3.0103(Q13) -> Q14 */
1875d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1885d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_tmp += (MEAN_ENER * 8192)<<1; /* + MEAN_ENER in Q14 */
1895d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1905d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /*-----------------------------------------------------------------*
1915d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * Compute gcode0.                                                 *
1925d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *  = Sum(i=0,1) pred[i]*past_qua_en[i] + mean_ener - ener_code    *
1935d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *-----------------------------------------------------------------*/
1945d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_tmp = (L_tmp << 10);              /* From Q14 to Q24 */
1955d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_tmp += (pred[0] * past_qua_en[0])<<1;      /* Q13*Q10 -> Q24 */
1965d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_tmp += (pred[1] * past_qua_en[1])<<1;      /* Q13*Q10 -> Q24 */
1975d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_tmp += (pred[2] * past_qua_en[2])<<1;      /* Q13*Q10 -> Q24 */
1985d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_tmp += (pred[3] * past_qua_en[3])<<1;      /* Q13*Q10 -> Q24 */
1995d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2005d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    gcode0 = extract_h(L_tmp);             /* From Q24 to Q8  */
2015d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2025d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /*-----------------------------------------------------------------*
2035d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * gcode0 = pow(10.0, gcode0/20)                                   *
2045d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *        = pow(2, 3.321928*gcode0/20)                             *
2055d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *        = pow(2, 0.166096*gcode0)                                *
2065d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *-----------------------------------------------------------------*/
2075d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2085d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_tmp = vo_L_mult(gcode0, 5443);          /* *0.166096 in Q15 -> Q24     */
2095d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_tmp = L_tmp >> 8;               /* From Q24 to Q16             */
2105d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    VO_L_Extract(L_tmp, &exp_gcode0, &frac);  /* Extract exponent of gcode0  */
2115d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2125d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    gcode0 = (Word16)(Pow2(14, frac));    /* Put 14 as exponent so that  */
2135d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* output of Pow2() will be:   */
2145d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* 16384 < Pow2() <= 32767     */
2155d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp_gcode0 -= 14;
2165d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2175d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /*-------------------------------------------------------------------------*
2185d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * Find the best quantizer                                                 *
2195d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * ~~~~~~~~~~~~~~~~~~~~~~~                                                 *
2205d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * Before doing the computation we need to aling exponents of coeff[]      *
2215d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * to be sure to have the maximum precision.                               *
2225d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *                                                                         *
2235d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * In the table the pitch gains are in Q14, the code gains are in Q11 and  *
2245d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * are multiply by gcode0 which have been multiply by 2^exp_gcode0.        *
2255d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * Also when we compute g_pitch*g_pitch, g_code*g_code and g_pitch*g_code  *
2265d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * we divide by 2^15.                                                      *
2275d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * Considering all the scaling above we have:                              *
2285d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *                                                                         *
2295d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *   exp_code = exp_gcode0-11+15 = exp_gcode0+4                            *
2305d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *                                                                         *
2315d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *   g_pitch*g_pitch  = -14-14+15                                          *
2325d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *   g_pitch          = -14                                                *
2335d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *   g_code*g_code    = (2*exp_code)+15                                    *
2345d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *   g_code           = exp_code                                           *
2355d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *   g_pitch*g_code   = -14 + exp_code +15                                 *
2365d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *                                                                         *
2375d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *   g_pitch*g_pitch * coeff[0]  ;exp_max0 = exp_coeff[0] - 13             *
2385d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *   g_pitch         * coeff[1]  ;exp_max1 = exp_coeff[1] - 14             *
2395d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *   g_code*g_code   * coeff[2]  ;exp_max2 = exp_coeff[2] +15+(2*exp_code) *
2405d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *   g_code          * coeff[3]  ;exp_max3 = exp_coeff[3] + exp_code       *
2415d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *   g_pitch*g_code  * coeff[4]  ;exp_max4 = exp_coeff[4] + 1 + exp_code   *
2425d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *-------------------------------------------------------------------------*/
2435d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2445d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp_code = (exp_gcode0 + 4);
2455d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp_max[0] = (exp_coeff[0] - 13);
2465d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp_max[1] = (exp_coeff[1] - 14);
2475d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp_max[2] = (exp_coeff[2] + (15 + (exp_code << 1)));
2485d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp_max[3] = (exp_coeff[3] + exp_code);
2495d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp_max[4] = (exp_coeff[4] + (1 + exp_code));
2505d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2515d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Find maximum exponant */
2525d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2535d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    e_max = exp_max[0];
2545d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 1; i < 5; i++)
2555d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
2565d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        if(exp_max[i] > e_max)
2575d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
2585d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            e_max = exp_max[i];
2595d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
2605d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
2615d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2625d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* align coeff[] and save in special 32 bit double precision */
2635d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2645d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < 5; i++)
2655d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
2665d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        j = add1(vo_sub(e_max, exp_max[i]), 2);/* /4 to avoid overflow */
2675d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_tmp = L_deposit_h(coeff[i]);
2685d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_tmp = L_shr(L_tmp, j);
2695d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        VO_L_Extract(L_tmp, &coeff[i], &coeff_lo[i]);
2705d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        coeff_lo[i] = (coeff_lo[i] >> 3);   /* lo >> 3 */
2715d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
2725d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2735d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Codebook search */
2745d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    dist_min = MAX_32;
2755d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    p = &t_qua_gain[min_ind << 1];
2765d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2775d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    index = 0;
2785d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < size; i++)
2795d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
2805d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        g_pitch = *p++;
2815d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        g_code = *p++;
2825d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2835d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        g_code = ((g_code * gcode0) + 0x4000)>>15;
2845d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        g2_pitch = ((g_pitch * g_pitch) + 0x4000)>>15;
2855d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        g_pit_cod = ((g_code * g_pitch) + 0x4000)>>15;
2865d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_tmp = (g_code * g_code)<<1;
2875d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        VO_L_Extract(L_tmp, &g2_code, &g2_code_lo);
2885d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2895d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_tmp = (coeff[2] * g2_code_lo)<<1;
2905d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_tmp =  (L_tmp >> 3);
2915d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_tmp += (coeff_lo[0] * g2_pitch)<<1;
2925d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_tmp += (coeff_lo[1] * g_pitch)<<1;
2935d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_tmp += (coeff_lo[2] * g2_code)<<1;
2945d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_tmp += (coeff_lo[3] * g_code)<<1;
2955d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_tmp += (coeff_lo[4] * g_pit_cod)<<1;
2965d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_tmp =  (L_tmp >> 12);
2975d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_tmp += (coeff[0] * g2_pitch)<<1;
2985d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_tmp += (coeff[1] * g_pitch)<<1;
2995d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_tmp += (coeff[2] * g2_code)<<1;
3005d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_tmp += (coeff[3] * g_code)<<1;
3015d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_tmp += (coeff[4] * g_pit_cod)<<1;
3025d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3035d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        if(L_tmp < dist_min)
3045d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
3055d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            dist_min = L_tmp;
3065d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            index = i;
3075d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
3085d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
3095d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3105d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Read the quantized gains */
3115d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    index = index + min_ind;
3125d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    p = &t_qua_gain[(index + index)];
3135d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *gain_pit = *p++;                       /* selected pitch gain in Q14 */
3145d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    g_code = *p++;                          /* selected code gain in Q11  */
3155d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3165d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_tmp = vo_L_mult(g_code, gcode0);             /* Q11*Q0 -> Q12 */
3175d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_tmp = L_shl(L_tmp, (exp_gcode0 + 4));   /* Q12 -> Q16 */
3185d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3195d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *gain_cod = L_tmp;                       /* gain of code in Q16 */
3205d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3215d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /*---------------------------------------------------*
3225d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * qua_ener = 20*log10(g_code)                       *
3235d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *          = 6.0206*log2(g_code)                    *
3245d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *          = 6.0206*(log2(g_codeQ11) - 11)          *
3255d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     *---------------------------------------------------*/
3265d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3275d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_tmp = L_deposit_l(g_code);
3285d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Log2(L_tmp, &exp, &frac);
3295d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp -= 11;
3305d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_tmp = Mpy_32_16(exp, frac, 24660);   /* x 6.0206 in Q12 */
3315d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3325d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    qua_ener = (Word16)(L_tmp >> 3); /* result in Q10 */
3335d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3345d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* update table of past quantized energies */
3355d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3365d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    past_qua_en[3] = past_qua_en[2];
3375d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    past_qua_en[2] = past_qua_en[1];
3385d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    past_qua_en[1] = past_qua_en[0];
3395d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    past_qua_en[0] = qua_ener;
3405d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3415d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return (index);
342e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
343e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
344e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
345e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
346e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
347