Exemple #1
0
/*
 * The decimation-in-time complex FFT is implemented below.
 * The input complex numbers are presented as real part followed by
 * imaginary part for each sample.  The counters are therefore
 * incremented by two to access the complex valued samples.
 */
void r_fft(Word16 * farray_ptr, Flag *pOverflow)
{

    Word16 ftmp1_real;
    Word16 ftmp1_imag;
    Word16 ftmp2_real;
    Word16 ftmp2_imag;
    Word32 Lftmp1_real;
    Word32 Lftmp1_imag;
    Word16 i;
    Word16 j;
    Word32 Ltmp1;

    /* Perform the complex FFT */
    c_fft(farray_ptr, pOverflow);

    /* First, handle the DC and foldover frequencies */
    ftmp1_real = *farray_ptr;
    ftmp2_real = *(farray_ptr + 1);
    *farray_ptr = add(ftmp1_real, ftmp2_real, pOverflow);
    *(farray_ptr + 1) = sub(ftmp1_real, ftmp2_real, pOverflow);

    /* Now, handle the remaining positive frequencies */
    for (i = 2, j = SIZE - i; i <= SIZE_BY_TWO; i = i + 2, j = SIZE - i)
    {
        ftmp1_real = add(*(farray_ptr + i), *(farray_ptr + j), pOverflow);
        ftmp1_imag = sub(*(farray_ptr + i + 1),
                         *(farray_ptr + j + 1), pOverflow);
        ftmp2_real = add(*(farray_ptr + i + 1),
                         *(farray_ptr + j + 1), pOverflow);
        ftmp2_imag = sub(*(farray_ptr + j),
                         *(farray_ptr + i), pOverflow);

        Lftmp1_real = L_deposit_h(ftmp1_real);
        Lftmp1_imag = L_deposit_h(ftmp1_imag);

        Ltmp1 = L_mac(Lftmp1_real, ftmp2_real, phs_tbl[i], pOverflow);
        Ltmp1 = L_msu(Ltmp1, ftmp2_imag, phs_tbl[i + 1], pOverflow);
        *(farray_ptr + i) = pv_round(L_shr(Ltmp1, 1, pOverflow), pOverflow);

        Ltmp1 = L_mac(Lftmp1_imag, ftmp2_imag, phs_tbl[i], pOverflow);
        Ltmp1 = L_mac(Ltmp1, ftmp2_real, phs_tbl[i + 1], pOverflow);
        *(farray_ptr + i + 1) = pv_round(L_shr(Ltmp1, 1, pOverflow), pOverflow);

        Ltmp1 = L_mac(Lftmp1_real, ftmp2_real, phs_tbl[j], pOverflow);
        Ltmp1 = L_mac(Ltmp1, ftmp2_imag, phs_tbl[j + 1], pOverflow);
        *(farray_ptr + j) = pv_round(L_shr(Ltmp1, 1, pOverflow), pOverflow);

        Ltmp1 = L_negate(Lftmp1_imag);
        Ltmp1 = L_msu(Ltmp1, ftmp2_imag, phs_tbl[j], pOverflow);
        Ltmp1 = L_mac(Ltmp1, ftmp2_real, phs_tbl[j + 1], pOverflow);
        *(farray_ptr + j + 1) = pv_round(L_shr(Ltmp1, 1, pOverflow), pOverflow);

    }
}                               /* end r_fft () */
void Post_Process(
    Post_ProcessState *st,  /* i/o : post process state                   */
    Word16 signal[],        /* i/o : signal                               */
    Word16 lg,              /* i   : length of signal                     */
    Flag   *pOverflow
)
{
    Word16 i, x2;
    Word32 L_tmp;

    Word16 *p_signal;
    Word16 c_a1 = a[1];
    Word16 c_a2 = a[2];
    Word16 c_b0 = b[0];
    Word16 c_b1 = b[1];
    Word16 c_b2 = b[2];

    p_signal = &signal[0];

    for (i = 0; i < lg; i++)
    {
        x2 = st->x1;
        st->x1 = st->x0;
        st->x0 = *(p_signal);

        /*  y[i] = b[0]*x[i]*2 + b[1]*x[i-1]*2 + b140[2]*x[i-2]/2  */
        /*                     + a[1]*y[i-1] + a[2] * y[i-2];      */

        L_tmp = ((Word32) st->y1_hi) * c_a1;
        L_tmp += (((Word32) st->y1_lo) * c_a1) >> 15;
        L_tmp += ((Word32) st->y2_hi) * c_a2;
        L_tmp += (((Word32) st->y2_lo) * c_a2) >> 15;
        L_tmp += ((Word32) st->x0) * c_b0;
        L_tmp += ((Word32) st->x1) * c_b1;
        L_tmp += ((Word32) x2) * c_b2;
        L_tmp <<= 3;


        /* Multiplication by two of output speech with saturation. */

        *(p_signal++) = pv_round(L_shl(L_tmp, 1, pOverflow), pOverflow);

        st->y2_hi = st->y1_hi;
        st->y2_lo = st->y1_lo;

        st->y1_hi = (Word16)(L_tmp >> 16);
        st->y1_lo = (Word16)((L_tmp >> 1) - ((Word32) st->y1_hi << 15));

    }

    return;
}
Exemple #3
0
/*
------------------------------------------------------------------------------
 FUNCTION NAME: build_code
------------------------------------------------------------------------------
 INPUT AND OUTPUT DEFINITIONS

 Inputs:
    codvec,  position of pulses, array of type Word16
    dn_sign, sign of pulses, array of type Word16
    h,       impulse response of weighted synthesis filter, Word16 array

 Outputs:

    cod,       innovative code vector, array of type Word16
    y[],       filtered innovative code, array of type Word16
    sign[],    sign of 2 pulses, array of type Word16
    pOverflow, Flag set when overflow occurs, pointer of type Flag *

 Returns:

 Global Variables Used:
    None

 Local Variables Needed:
    None

------------------------------------------------------------------------------
 FUNCTION DESCRIPTION

 Builds the codeword, the filtered codeword and index of the
 codevector, based on the signs and positions of 2 pulses.

------------------------------------------------------------------------------
 REQUIREMENTS

 None

------------------------------------------------------------------------------
 REFERENCES

 c2_11pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001

------------------------------------------------------------------------------
 PSEUDO-CODE

------------------------------------------------------------------------------
 CAUTION [optional]
 [State any special notes, constraints or cautions for users of this function]

------------------------------------------------------------------------------
*/
static Word16 build_code(
    Word16 codvec[],    /* i : position of pulses                            */
    Word16 dn_sign[],   /* i : sign of pulses                                */
    Word16 cod[],       /* o : innovative code vector                        */
    Word16 h[],         /* i : impulse response of weighted synthesis filter */
    Word16 y[],         /* o : filtered innovative code                      */
    Word16 sign[],      /* o : sign of 2 pulses                              */
    Flag   * pOverflow  /* o : Flag set when overflow occurs                 */
)
{
    Word16 i;
    Word16 j;
    Word16 k;
    Word16 track;
    Word16 index;
    Word16 _sign[NB_PULSE];
    Word16 indx;
    Word16 rsign;
    Word16 tempWord;

    Word16 *p0;
    Word16 *p1;

    Word32 s;

    for (i = 0; i < L_CODE; i++)
    {
        cod[i] = 0;
    }

    indx = 0;
    rsign = 0;

    for (k = 0; k < NB_PULSE; k++)
    {
        i = codvec[k];      /* read pulse position */
        j = dn_sign[i];     /* read sign           */

        /* index = pos/5 */
        /* index = mult(i, 6554, pOverflow); */
        index = (Word16)(((Word32) i * 6554) >> 15);

        /* track = pos%5 */
        /* tempWord =
            L_mult(
            index,
            5,
            pOverflow); */
        tempWord = (index << 3) + (index << 1);

        /* tempWord =
            L_shr(
            tempWord,
            1,
            pOverflow); */
        tempWord >>= 1;


        /* track =
            sub(
            i,
            tempWord,
            pOverflow); */
        track = i - tempWord;

        tempWord = track;

        if (tempWord == 0)
        {
            track = 1;

            /* index =
                shl(
                index,
                6,
                pOverflow); */
            index <<= 6;
        }
        else if (track == 1)
        {
            tempWord = k;

            if (tempWord == 0)
            {
                track = 0;
                /* index =
                    shl(
                    index,
                    1,
                    pOverflow); */
                index <<= 1;
            }
            else
            {
                track = 1;

                /* tempWord =
                    shl(
                    index,
                    6,
                    pOverflow); */
                tempWord = index << 6;

                /* index =
                    add(
                    tempWord,
                    16,
                    pOverflow); */
                index = tempWord + 16;
            }
        }
        else if (track == 2)
        {
            track = 1;

            /* tempWord =
                shl(
                index,
                6,
                pOverflow); */
            tempWord = index << 6;

            /* index =
                add(
                tempWord,
                32,
                pOverflow); */
            index = tempWord + 32;
        }
        else if (track == 3)
        {
            track = 0;

            /* tempWord =
                shl(
                index,
                1,
                pOverflow); */
            tempWord = index << 1;

            /* index =
                add(
                tempWord,
                1,
                pOverflow); */
            index = tempWord + 1;
        }
        else if (track == 4)
        {
            track = 1;

            /* tempWord =
                shl(
                index,
                6,
                pOverflow); */
            tempWord = index << 6;

            /* index =
                add(
                tempWord,
                48,
                pOverflow); */
            index = tempWord + 48;
        }

        if (j > 0)
        {
            cod[i] = 8191;
            _sign[k] = 32767;

            tempWord =
                shl(
                    1,
                    track,
                    pOverflow);

            rsign =
                add_16(
                    rsign,
                    tempWord,
                    pOverflow);
        }
        else
        {
            cod[i] = -8192;
            _sign[k] = (Word16) - 32768L;
        }

        indx =
            add_16(
                indx,
                index,
                pOverflow);
    }
    *sign = rsign;

    p0 = h - codvec[0];
    p1 = h - codvec[1];

    for (i = 0; i < L_CODE; i++)
    {
        s = 0;

        s =
            L_mac(
                s,
                *p0++,
                _sign[0],
                pOverflow);

        s =
            L_mac(
                s,
                *p1++,
                _sign[1],
                pOverflow);

        y[i] =
            pv_round(
                s,
                pOverflow);
    }

    return indx;
}
static Word16 Lag_max(  /* o : lag found                               */
    vadState *vadSt,    /* i/o : VAD state struct                      */
    Word32 corr[],      /* i   : correlation vector.                   */
    Word16 scal_sig[],  /* i : scaled signal.                          */
    Word16 L_frame,     /* i : length of frame to compute pitch        */
    Word16 lag_max,     /* i : maximum lag                             */
    Word16 lag_min,     /* i : minimum lag                             */
    Word16 old_lag,     /* i : old open-loop lag                       */
    Word16 *cor_max,    /* o : normalized correlation of selected lag  */
    Word16 wght_flg,    /* i : is weighting function used              */
    Word16 *gain_flg,   /* o : open-loop flag                          */
    Flag dtx,           /* i : dtx flag; use dtx=1, do not use dtx=0   */
    Flag   *pOverflow   /* o : overflow flag                           */
)
{
    Word16 i;
    Word16 j;
    Word16 *p;
    Word16 *p1;
    Word32 max;
    Word32 t0;
    Word16 t0_h;
    Word16 t0_l;
    Word16 p_max;
    const Word16 *ww;
    const Word16 *we;
    Word32 t1;
    Word16 temp;

    ww = &corrweight[250];
    we = &corrweight[123 + lag_max - old_lag];

    max = MIN_32;
    p_max = lag_max;

    for (i = lag_max; i >= lag_min; i--)
    {
        t0 = corr[-i];

        /* Weighting of the correlation function.   */
        L_Extract(corr[-i], &t0_h, &t0_l, pOverflow);
        t0 = Mpy_32_16(t0_h, t0_l, *ww, pOverflow);
        ww--;
        if (wght_flg > 0)
        {
            /* Weight the neighbourhood of the old lag. */
            L_Extract(t0, &t0_h, &t0_l, pOverflow);
            t0 = Mpy_32_16(t0_h, t0_l, *we, pOverflow);
            we--;
        }

        /*       if (L_sub (t0, max) >= 0) */
        if (t0 >= max)
        {
            max = t0;
            p_max = i;
        }
    }
    p  = &scal_sig[0];
    p1 = &scal_sig[-p_max];
    t0 = 0;
    t1 = 0;

    for (j = 0; j < L_frame; j++, p++, p1++)
    {
        t0 = L_mac(t0, *p, *p1, pOverflow);
        t1 = L_mac(t1, *p1, *p1, pOverflow);
    }

    if (dtx)
    {   /* no test() call since this if is only in simulation env */
#ifdef VAD2
        /* Save max correlation */
        vadSt->L_Rmax = L_add(vadSt->L_Rmax, t0, pOverflow);
        /* Save max energy */
        vadSt->L_R0 =   L_add(vadSt->L_R0, t1, pOverflow);
#else
        /* update and detect tone */
        vad_tone_detection_update(vadSt, 0, pOverflow);
        vad_tone_detection(vadSt, t0, t1, pOverflow);
#endif
    }

    /* gain flag is set according to the open_loop gain */
    /* is t2/t1 > 0.4 ? */
    temp = pv_round(t1, pOverflow);
    t1 = L_msu(t0, temp, 13107, pOverflow);
    *gain_flg = pv_round(t1, pOverflow);

    *cor_max = 0;

    return (p_max);
}
Exemple #5
0
void c_fft(Word16 * farray_ptr, Flag *pOverflow)
{

    Word16 i;
    Word16 j;
    Word16 k;
    Word16 ii;
    Word16 jj;
    Word16 kk;
    Word16 ji;
    Word16 kj;
    Word16 ii2;
    Word32 ftmp;
    Word32 ftmp_real;
    Word32 ftmp_imag;
    Word16 tmp;
    Word16 tmp1;
    Word16 tmp2;

    /* Rearrange the input array in bit reversed order */
    for (i = 0, j = 0; i < SIZE - 2; i = i + 2)
    {
        if (j > i)
        {
            ftmp = *(farray_ptr + i);
            *(farray_ptr + i) = *(farray_ptr + j);
            *(farray_ptr + j) = (Word16)ftmp;

            ftmp = *(farray_ptr + i + 1);
            *(farray_ptr + i + 1) = *(farray_ptr + j + 1);
            *(farray_ptr + j + 1) = (Word16)ftmp;
        }

        k = SIZE_BY_TWO;
        while (j >= k)
        {
            j = sub(j, k, pOverflow);
            k = shr(k, 1, pOverflow);
        }
        j = add(j, k, pOverflow);
    }

    /* The FFT part */
    for (i = 0; i < NUM_STAGE; i++)
    {               /* i is stage counter */
        jj = shl(2, i, pOverflow);     /* FFT size */
        kk = shl(jj, 1, pOverflow);    /* 2 * FFT size */
        ii = ii_table[i];   /* 2 * number of FFT's */
        ii2 = shl(ii, 1, pOverflow);
        ji = 0;         /* ji is phase table index */

        for (j = 0; j < jj; j = j + 2)
        {                   /* j is sample counter */

            for (k = j; k < SIZE; k = k + kk)
            {               /* k is butterfly top */
                kj = add(k, jj, pOverflow);    /* kj is butterfly bottom */

                /* Butterfly computations */
                ftmp_real = L_mult(*(farray_ptr + kj), phs_tbl[ji], pOverflow);
                ftmp_real = L_msu(ftmp_real, *(farray_ptr + kj + 1),
                                  phs_tbl[ji + 1], pOverflow);

                ftmp_imag = L_mult(*(farray_ptr + kj + 1),
                                   phs_tbl[ji], pOverflow);
                ftmp_imag = L_mac(ftmp_imag, *(farray_ptr + kj),
                                  phs_tbl[ji + 1], pOverflow);

                tmp1 = pv_round(ftmp_real, pOverflow);
                tmp2 = pv_round(ftmp_imag, pOverflow);

                tmp = sub(*(farray_ptr + k), tmp1, pOverflow);
                *(farray_ptr + kj) = shr(tmp, 1, pOverflow);

                tmp = sub(*(farray_ptr + k + 1), tmp2, pOverflow);
                *(farray_ptr + kj + 1) = shr(tmp, 1, pOverflow);

                tmp = add(*(farray_ptr + k), tmp1, pOverflow);
                *(farray_ptr + k) = shr(tmp, 1, pOverflow);

                tmp = add(*(farray_ptr + k + 1), tmp2, pOverflow);
                *(farray_ptr + k + 1) = shr(tmp, 1, pOverflow);
            }

            ji =  add(ji, ii2, pOverflow);
        }
    }
}                               /* end of c_fft () */
//=============================================================================
//函数名称:Dec_gain
//函数功能:解码的音调和码书增益
//=============================================================================
void Dec_gain(
    gc_predState *pred_state, /* i/o: MA predictor state           */
    enum Mode mode,           /* i  : AMR mode                     */
    Word16 index,             /* i  : index of quantization.       */
    Word16 code[],            /* i  : Innovative vector.           */
    Word16 evenSubfr,         /* i  : Flag for even subframes      */
    Word16 * gain_pit,        /* o  : Pitch gain.                  */
    Word16 * gain_cod,        /* o  : Code gain.                   */
    Flag   * pOverflow
)
{
    const Word16 *p;
    Word16 frac;
    Word16 gcode0;
    Word16 exp;
    Word16 qua_ener;
    Word16 qua_ener_MR122;
    Word16 g_code;
    Word32 L_tmp;
    Word16 temp1;
    Word16 temp2;

    /* Read the quantized gains (table depends on mode) */
    //阅读量化收益(表取决于模式)
    index = shl(index, 2, pOverflow);

    if (mode == MR102 || mode == MR74 || mode == MR67)
    {
        p = &table_gain_highrates[index];

        *gain_pit = *p++;
        g_code = *p++;
        qua_ener_MR122 = *p++;
        qua_ener = *p;
    }
    else
    {
        if (mode == MR475)
        {
            index += (1 ^ evenSubfr) << 1; /* evenSubfr is 0 or 1 */

            if (index > (MR475_VQ_SIZE*4 - 2))
            {
                index = (MR475_VQ_SIZE * 4 - 2); /* avoid possible buffer overflow */
            }

            p = &table_gain_MR475[index];

            *gain_pit = *p++;
            g_code = *p++;

            /*---------------------------------------------------------*
             *  calculate predictor update values (not stored in 4.75  *
             *  quantizer table to save space):                        *
             *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  *
             *                                                         *
             *   qua_ener       = log2(g)                              *
             *   qua_ener_MR122 = 20*log10(g)                          *
             *---------------------------------------------------------*/
            //计算预测更新值(不存储在4.75量化表,以节省空间)

            /* Log2(x Q12) = log2(x) + 12 */
            temp1 = (Word16) L_deposit_l(g_code);
            Log2(temp1, &exp, &frac, pOverflow);
            exp = sub(exp, 12, pOverflow);

            temp1 = shr_r(frac, 5, pOverflow);
            temp2 = shl(exp, 10, pOverflow);
            qua_ener_MR122 = add(temp1, temp2, pOverflow);

            /* 24660 Q12 ~= 6.0206 = 20*log10(2) */
            L_tmp = Mpy_32_16(exp, frac, 24660, pOverflow);
            L_tmp = L_shl(L_tmp, 13, pOverflow);
            qua_ener = pv_round(L_tmp, pOverflow);
            /* Q12 * Q0 = Q13 -> Q10 */
        }
        else
        {
            p = &table_gain_lowrates[index];

            *gain_pit = *p++;
            g_code = *p++;
            qua_ener_MR122 = *p++;
            qua_ener = *p;
        }
    }

    /*-------------------------------------------------------------------*
     *  predict codebook gain                                            *
     *  ~~~~~~~~~~~~~~~~~~~~~                                            *
     *  gc0     = Pow2(int(d)+frac(d))                                   *
     *          = 2^exp + 2^frac                                         *
     *                                                                   *
     *  gcode0 (Q14) = 2^14*2^frac = gc0 * 2^(14-exp)                    *
     *-------------------------------------------------------------------*/

    gc_pred(pred_state, mode, code, &exp, &frac, NULL, NULL, pOverflow);

    gcode0 = (Word16) Pow2(14, frac, pOverflow);

    /*------------------------------------------------------------------*
     *  read quantized gains, update table of past quantized energies   *
     *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   *
     *  st->past_qua_en(Q10) = 20 * Log10(g_fac) / constant             *
     *                       = Log2(g_fac)                              *
     *                       = qua_ener                                 *
     *                                           constant = 20*Log10(2) *
     *------------------------------------------------------------------*/

    L_tmp = L_mult(g_code, gcode0, pOverflow);
    temp1 = sub(10, exp, pOverflow);
    L_tmp = L_shr(L_tmp, temp1, pOverflow);
    *gain_cod = extract_h(L_tmp);

    /* update table of past quantized energies */
    //过去的量化能量表更新

    gc_pred_update(pred_state, qua_ener_MR122, qua_ener);

    return;
}
Word16 Cb_gain_average(
    Cb_gain_averageState *st, /* i/o : State variables for CB gain averaging */
    enum Mode mode,           /* i   : AMR mode                              */
    Word16 gain_code,         /* i   : CB gain                            Q1 */
    Word16 lsp[],             /* i   : The LSP for the current frame     Q15 */
    Word16 lspAver[],         /* i   : The average of LSP for 8 frames   Q15 */
    Word16 bfi,               /* i   : bad frame indication flag             */
    Word16 prev_bf,           /* i   : previous bad frame indication flag    */
    Word16 pdfi,              /* i   : potential degraded bad frame ind flag */
    Word16 prev_pdf,          /* i   : prev pot. degraded bad frame ind flag */
    Word16 inBackgroundNoise, /* i   : background noise decision             */
    Word16 voicedHangover,    /* i   : # of frames after last voiced frame   */
    Flag   *pOverflow
)
{
    Word16 i;
    Word16 cbGainMix;
    Word16 diff;
    Word16 tmp_diff;
    Word16 bgMix;
    Word16 cbGainMean;
    Word32 L_sum;
    Word16 tmp[M];
    Word16 tmp1;
    Word16 tmp2;
    Word16 shift1;
    Word16 shift2;
    Word16 shift;

    /*---------------------------------------------------------*
     * Compute mixed cb gain, used to make cb gain more        *
     * smooth in background noise for modes 5.15, 5.9 and 6.7  *
     * states that needs to be updated by all                  *
     *---------------------------------------------------------*/

    /* set correct cbGainMix for MR74, MR795, MR122 */
    cbGainMix = gain_code;

    /*-------------------------------------------------------*
     *   Store list of CB gain needed in the CB gain         *
     *   averaging                                           *
     *-------------------------------------------------------*/
    for (i = 0; i < (L_CBGAINHIST - 1); i++)
    {
        st->cbGainHistory[i] = st->cbGainHistory[i+1];
    }
    st->cbGainHistory[L_CBGAINHIST-1] = gain_code;

    diff = 0;

    /* compute lsp difference */
    for (i = 0; i < M; i++)
    {
        tmp1 = abs_s(sub(*(lspAver + i), *(lsp + i), pOverflow));
        /* Q15      */
        shift1 = sub(norm_s(tmp1), 1, pOverflow);       /* Qn       */
        tmp1 = shl(tmp1, shift1, pOverflow);            /* Q15+Qn   */
        shift2 = norm_s(*(lspAver + i));                /* Qm       */
        tmp2 = shl(*(lspAver + i), shift2, pOverflow);  /* Q15+Qm   */
        tmp[i] = div_s(tmp1, tmp2);        /* Q15+(Q15+Qn)-(Q15+Qm) */

        shift = 2 + shift1 - shift2;

        if (shift >= 0)
        {
            *(tmp + i) = shr(*(tmp + i), shift, pOverflow);
            /* Q15+Qn-Qm-Qx=Q13 */
        }
        else
        {
            *(tmp + i) = shl(*(tmp + i), negate(shift), pOverflow);
            /* Q15+Qn-Qm-Qx=Q13 */
        }

        diff = add(diff, *(tmp + i), pOverflow);           /* Q13 */
    }

    /* Compute hangover */

    if (diff > 5325)                /* 0.65 in Q11 */
    {
        st->hangVar += 1;
    }
    else
    {
        st->hangVar = 0;
    }


    if (st->hangVar > 10)
    {
        /* Speech period, reset hangover variable */
        st->hangCount = 0;
    }

    /* Compute mix constant (bgMix) */
    bgMix = 8192;    /* 1 in Q13 */

    if ((mode <= MR67) || (mode == MR102))
        /* MR475, MR515, MR59, MR67, MR102 */
    {
        /* if errors and presumed noise make smoothing probability stronger */

        if (((((pdfi != 0) && (prev_pdf != 0)) || (bfi != 0) ||
                (prev_bf != 0))
                && (voicedHangover > 1)
                && (inBackgroundNoise != 0)
                && ((mode == MR475) || (mode == MR515) ||
                    (mode == MR59))))
        {
            /* bgMix = min(0.25, max(0.0, diff-0.55)) / 0.25; */
            tmp_diff = sub(diff, 4506, pOverflow);   /* 0.55 in Q13 */
        }
        else
        {
            /* bgMix = min(0.25, max(0.0, diff-0.40)) / 0.25; */
            tmp_diff = sub(diff, 3277, pOverflow); /* 0.4 in Q13 */
        }

        /* max(0.0, diff-0.55)  or  */
        /* max(0.0, diff-0.40) */
        if (tmp_diff > 0)
        {
            tmp1 = tmp_diff;
        }
        else
        {
            tmp1 = 0;
        }

        /* min(0.25, tmp1) */
        if (2048 < tmp1)
        {
            bgMix = 8192;
        }
        else
        {
            bgMix = shl(tmp1, 2, pOverflow);
        }

        if ((st->hangCount < 40) || (diff > 5325)) /* 0.65 in Q13 */
        {
            /* disable mix if too short time since */
            bgMix = 8192;
        }

        /* Smoothen the cb gain trajectory  */
        /* smoothing depends on mix constant bgMix */
        L_sum = L_mult(6554, st->cbGainHistory[2], pOverflow);
        /* 0.2 in Q15; L_sum in Q17 */

        for (i = 3; i < L_CBGAINHIST; i++)
        {
            L_sum = L_mac(L_sum, 6554, st->cbGainHistory[i], pOverflow);
        }
        cbGainMean = pv_round(L_sum, pOverflow);               /* Q1 */

        /* more smoothing in error and bg noise (NB no DFI used here) */

        if (((bfi != 0) || (prev_bf != 0)) && (inBackgroundNoise != 0)
                && ((mode == MR475) || (mode == MR515)
                    || (mode == MR59)))
        {
            /* 0.143 in Q15; L_sum in Q17    */
            L_sum = L_mult(4681, st->cbGainHistory[0], pOverflow);
            for (i = 1; i < L_CBGAINHIST; i++)
            {
                L_sum =
                    L_mac(L_sum, 4681, st->cbGainHistory[i], pOverflow);
            }
            cbGainMean = pv_round(L_sum, pOverflow);              /* Q1 */
        }

        /* cbGainMix = bgMix*cbGainMix + (1-bgMix)*cbGainMean; */
        /* L_sum in Q15 */
        L_sum = L_mult(bgMix, cbGainMix, pOverflow);
        L_sum = L_mac(L_sum, 8192, cbGainMean, pOverflow);
        L_sum = L_msu(L_sum, bgMix, cbGainMean, pOverflow);
        cbGainMix = pv_round(L_shl(L_sum, 2, pOverflow), pOverflow);  /* Q1 */
    }

    st->hangCount += 1;

    return (cbGainMix);
}
void gc_pred(
    gc_predState *st,   /* i/o: State struct                           */
    enum Mode mode,     /* i  : AMR mode                               */
    Word16 *code,       /* i  : innovative codebook vector (L_SUBFR)   */
    /*      MR122: Q12, other modes: Q13           */
    Word16 *exp_gcode0, /* o  : exponent of predicted gain factor, Q0  */
    Word16 *frac_gcode0,/* o  : fraction of predicted gain factor  Q15 */
    Word16 *exp_en,     /* o  : exponent of innovation energy,     Q0  */
    /*      (only calculated for MR795)            */
    Word16 *frac_en,    /* o  : fraction of innovation energy,     Q15 */
    /*      (only calculated for MR795)            */
    Flag   *pOverflow
)
{
    register Word16 i;
    register Word32 L_temp1, L_temp2;
    register Word32 L_tmp;
    Word32 ener_code;
    Word32 ener;
    Word16 exp, frac;
    Word16 exp_code, gcode0;
    Word16 tmp;
    Word16 *p_code = &code[0];

    /*-------------------------------------------------------------------*
     *  energy of code:                                                  *
     *  ~~~~~~~~~~~~~~~                                                  *
     *  ener_code = sum(code[i]^2)                                       *
     *-------------------------------------------------------------------*/
    ener_code = 0;

    /* MR122:  Q12*Q12 -> Q25 */
    /* others: Q13*Q13 -> Q27 */

    for (i = L_SUBFR >> 2; i != 0; i--)
    {
        tmp = *(p_code++);
        ener_code += ((Word32) tmp * tmp) >> 3;
        tmp = *(p_code++);
        ener_code += ((Word32) tmp * tmp) >> 3;
        tmp = *(p_code++);
        ener_code += ((Word32) tmp * tmp) >> 3;
        tmp = *(p_code++);
        ener_code += ((Word32) tmp * tmp) >> 3;
    }

    ener_code <<= 4;

    if (ener_code < 0)      /*  Check for saturation */
    {
        ener_code = MAX_32;
    }

    if (mode == MR122)
    {
        /* ener_code = ener_code / lcode; lcode = 40; 1/40 = 26214 Q20 */
        /* Q9  * Q20 -> Q30 */

        ener_code = ((Word32)(pv_round(ener_code, pOverflow) * 26214)) << 1;

        /*-------------------------------------------------------------*
         *  energy of code:                                            *
         *  ~~~~~~~~~~~~~~~                                            *
         *  ener_code(Q17) = 10 * Log10(energy) / constant             *
         *                 = 1/2 * Log2(energy)                        *
         *  constant = 20*Log10(2)                                     *
         *-------------------------------------------------------------*/
        /* ener_code = 1/2 * Log2(ener_code); Note: Log2=log2+30 */
        Log2(ener_code, &exp, &frac, pOverflow);

        /* Q16 for log()    */
        /* ->Q17 for 1/2 log()*/

        L_temp1 = (Word32)(exp - 30) << 16;
        ener_code = L_temp1 + ((Word32)frac << 1);

        /*-------------------------------------------------------------*
         *  predicted energy:                                          *
         *  ~~~~~~~~~~~~~~~~~                                          *
         *  ener(Q24) = (Emean + sum{pred[i]*past_en[i]})/constant     *
         *            = MEAN_ENER + sum(pred[i]*past_qua_en[i])        *
         *  constant = 20*Log10(2)                                     *
         *-------------------------------------------------------------*/

        ener = MEAN_ENER_MR122;                   /* Q24 (Q17) */
        for (i = 0; i < NPRED; i++)
        {
            L_temp1 = (((Word32) st->past_qua_en_MR122[i]) *
                       pred_MR122[i]) << 1;
            ener = L_add(ener, L_temp1, pOverflow);

            /* Q10 * Q13 -> Q24 */
            /* Q10 * Q6  -> Q17 */
        }

        /*---------------------------------------------------------------*
         *  predicted codebook gain                                      *
         *  ~~~~~~~~~~~~~~~~~~~~~~~                                      *
         *  gc0     = Pow10( (ener*constant - ener_code*constant) / 20 ) *
         *          = Pow2(ener-ener_code)                               *
         *          = Pow2(int(d)+frac(d))                               *
         *                                                               *
         *  (store exp and frac for pow2())                              *
         *---------------------------------------------------------------*/
        /* Q16 */

        L_temp1 = L_sub(ener, ener_code, pOverflow);


        *exp_gcode0 = (Word16)(L_temp1 >> 17);

        L_temp2 = (Word32) * exp_gcode0 << 15;
        L_temp1 >>= 2;

        *frac_gcode0 = (Word16)(L_temp1 - L_temp2);

    }
Exemple #9
0
void A_Refl(
    Word16 a[],        /* i   : Directform coefficients */
    Word16 refl[],     /* o   : Reflection coefficients */
    Flag   *pOverflow
)
{
    /* local variables */
    Word16 i;
    Word16 j;
    Word16 aState[M];
    Word16 bState[M];
    Word16 normShift;
    Word16 normProd;
    Word32 L_acc;
    Word16 scale;
    Word32 L_temp;
    Word16 temp;
    Word16 mult;

    /* initialize states */
    for (i = 0; i < M; i++)
    {
        aState[i] = a[i];
    }

    /* backward Levinson recursion */
    for (i = M - 1; i >= 0; i--)
    {
        if (abs_s(aState[i]) >= 4096)
        {
            for (i = 0; i < M; i++)
            {
                refl[i] = 0;
            }
            break;
        }

        refl[i] = shl(aState[i], 3, pOverflow);

        L_temp = L_mult(refl[i], refl[i], pOverflow);
        L_acc = L_sub(MAX_32, L_temp, pOverflow);

        normShift = norm_l(L_acc);
        scale = sub(15, normShift, pOverflow);

        L_acc = L_shl(L_acc, normShift, pOverflow);
        normProd = pv_round(L_acc, pOverflow);

        mult = div_s(16384, normProd);

        for (j = 0; j < i; j++)
        {
            L_acc = L_deposit_h(aState[j]);
            L_acc = L_msu(L_acc, refl[i], aState[i-j-1], pOverflow);

            temp = pv_round(L_acc, pOverflow);
            L_temp = L_mult(mult, temp, pOverflow);
            L_temp = L_shr_r(L_temp, scale, pOverflow);

            if (L_abs(L_temp) > 32767)
            {
                for (i = 0; i < M; i++)
                {
                    refl[i] = 0;
                }
                break;
            }

            bState[j] = extract_l(L_temp);
        }

        for (j = 0; j < i; j++)
        {
            aState[j] = bState[j];
        }
    }
    return;
}
    static Word16 build_code(
        Word16 subNr,     /* i : subframe number                            */
        Word16 codvec[],  /* i : position of pulses                         */
        Word16 dn_sign[], /* i : sign of pulses                             */
        Word16 cod[],     /* o : innovative code vector                     */
        Word16 h[],       /* i : impulse response of weighted synthesis     */
        /*     filter                                     */
        Word16 y[],       /* o : filtered innovative code                   */
        Word16 sign[],    /* o : sign of 2 pulses                           */
        Flag  *pOverflow  /* o : Flag set when overflow occurs              */
    )
    {
        register Word16 i;
        register Word16 j;
        register Word16 k;
        register Word16 track;
        register Word16 first;
        register Word16 index;
        register Word16 rsign;
        Word16 indx;
        Word16 _sign[NB_PULSE];
        Word16 *p0;
        Word16 *p1;

        const Word16 *pt;

        Word32 s;

        pt = trackTable + subNr + (subNr << 2);

        for (i = 0; i < L_CODE; i++)
        {
            *(cod + i) = 0;
        }

        indx = 0;
        rsign = 0;

        for (k = 0; k < NB_PULSE; k++)
        {
            i = *(codvec + k);  /* read pulse position */
            j = *(dn_sign + i); /* read sign           */

            s = ((Word32)(i * 6554)) >> 15;
            index = (Word16) s; /* index = pos/5 */

            track = i - (5 * index);    /* track = pos%5 */

            first = *(pt + track);


            if (k == 0)
            {
                track = 0;

                if (first != 0)
                {
                    index += 64;  /* table bit is MSB */
                }
            }
            else
            {
                track = 1;
                index <<= 3;
            }

            if (j > 0)
            {
                *(cod + i) = 8191;
                *(_sign + k) = 32767;
                rsign += (1 << track);
            }
            else
            {
                *(cod + i) = ~(8192) + 1;
                *(_sign + k) = (Word16)(~(32768) + 1);
            }

            indx += index;
        }

        *sign = rsign;

        p0 = h - *codvec;
        p1 = h - *(codvec + 1);

        for (i = 0; i < L_CODE; i++)
        {
            s = 0;
            s =
                L_mult(
                    *p0++,
                    *_sign,
                    pOverflow);

            s =
                L_mac(
                    s,
                    *p1++,
                    *(_sign + 1),
                    pOverflow);

            *(y + i) =
                pv_round(
                    s,
                    pOverflow);
        }

        return(indx);
    }
Exemple #11
0
void set_sign12k2(
    Word16 dn[],        /* i/o : correlation between target and h[]         */
    Word16 cn[],        /* i   : residual after long term prediction        */
    Word16 sign[],      /* o   : sign of d[n]                               */
    Word16 pos_max[],   /* o   : position of maximum correlation            */
    Word16 nb_track,    /* i   : number of tracks tracks                    */
    Word16 ipos[],      /* o   : starting position for each pulse           */
    Word16 step,        /* i   : the step size in the tracks                */
    Flag   *pOverflow   /* i/o: overflow flag                               */
)
{
    Word16 i, j;
    Word16 val;
    Word16 cor;
    Word16 k_cn;
    Word16 k_dn;
    Word16 max;
    Word16 max_of_all;
    Word16 pos = 0; /* initialization only needed to keep gcc silent */
    Word16 en[L_CODE];                  /* correlation vector */
    Word32 s;
    Word32 t;
    Word32 L_temp;
    Word16 *p_cn;
    Word16 *p_dn;
    Word16 *p_sign;
    Word16 *p_en;

    /* calculate energy for normalization of cn[] and dn[] */

    s = 256;
    t = 256;
    p_cn = cn;
    p_dn = dn;      /* crosscorrelation values do not have strong peaks, so
                       scaling applied in cor_h_x (sf=2) guaranteed that the
                       mac of the energy for this vector will not overflow */

    for (i = L_CODE; i != 0; i--)
    {
        val = *(p_cn++);
        s = L_mac(s, val, val, pOverflow);
        val = *(p_dn++);
        t += ((Word32) val * val) << 1;
    }
    s = Inv_sqrt(s, pOverflow);
    k_cn = (Word16)((L_shl(s, 5, pOverflow)) >> 16);

    t = Inv_sqrt(t, pOverflow);
    k_dn = (Word16)(t >> 11);

    p_cn   = &cn[L_CODE-1];
    p_sign = &sign[L_CODE-1];
    p_en   = &en[L_CODE-1];

    for (i = L_CODE - 1; i >= 0; i--)
    {
        L_temp = ((Word32)k_cn * *(p_cn--)) << 1;
        val = dn[i];
        s = L_mac(L_temp, k_dn, val, pOverflow);
        L_temp = L_shl(s, 10, pOverflow);
        cor = pv_round(L_temp, pOverflow);

        if (cor >= 0)
        {
            *(p_sign--) = 32767;                      /* sign = +1 */
        }
        else
        {
            *(p_sign--) = -32767;                     /* sign = -1 */
            cor = - (cor);

            /* modify dn[] according to the fixed sign */
            dn[i] = - val;
        }

        *(p_en--) = cor;
    }

    max_of_all = -1;
    for (i = 0; i < nb_track; i++)
    {
        max = -1;

        for (j = i; j < L_CODE; j += step)
        {
            cor = en[j];
            if (cor > max)
            {
                max = cor;
                pos = j;
            }
        }
        /* store maximum correlation position */
        pos_max[i] = pos;
        if (max > max_of_all)
        {
            max_of_all = max;
            /* starting position for i0 */
            ipos[0] = i;
        }
    }

    /*----------------------------------------------------------------*
     *     Set starting position of each pulse.                       *
     *----------------------------------------------------------------*/

    pos = ipos[0];
    ipos[nb_track] = pos;

    for (i = 1; i < nb_track; i++)
    {
        pos++;

        if (pos >= nb_track)
        {
            pos = 0;
        }
        ipos[ i] = pos;
        ipos[ i + nb_track] = pos;
    }

    return;
}
Exemple #12
0
static Word16
MR795_gain_code_quant_mod(  /* o  : index of quantization.            */
    Word16 gain_pit,        /* i  : pitch gain,                   Q14 */
    Word16 exp_gcode0,      /* i  : predicted CB gain (exponent), Q0  */
    Word16 gcode0,          /* i  : predicted CB gain (norm.),    Q14 */
    Word16 frac_en[],       /* i  : energy coefficients (4),
                                    fraction part,                Q15 */
    Word16 exp_en[],        /* i  : energy coefficients (4),
                                    eponent part,                 Q0  */
    Word16 alpha,           /* i  : gain adaptor factor (>0),     Q15 */
    Word16 gain_cod_unq,    /* i  : Code gain (unquantized)           */
    /*      (scaling: Q10 - exp_gcode0)       */
    Word16 *gain_cod,       /* i/o: Code gain (pre-/quantized),   Q1  */
    Word16 *qua_ener_MR122, /* o  : quantized energy error,       Q10 */
    /*      (for MR122 MA predictor update)   */
    Word16 *qua_ener,       /* o  : quantized energy error,       Q10 */
    /*      (for other MA predictor update)   */
    const Word16* qua_gain_code_ptr, /* i : ptr to read-only ptr      */
    Flag   *pOverflow       /* o  : overflow indicator                */
)
{
    const Word16 *p;
    Word16 i;
    Word16 index;
    Word16 tmp;
    Word16 one_alpha;
    Word16 exp;
    Word16 e_max;

    Word16 g2_pitch;
    Word16 g_code;
    Word16 g2_code_h;
    Word16 g2_code_l;
    Word16 d2_code_h;
    Word16 d2_code_l;
    Word16 coeff[5];
    Word16 coeff_lo[5];
    Word16 exp_coeff[5];
    Word32 L_tmp;
    Word32 L_t0;
    Word32 L_t1;
    Word32 dist_min;
    Word16 gain_code;

    /*
      Steps in calculation of the error criterion (dist):
      ---------------------------------------------------

      underlined = constant; alp = FLP value of alpha, alpha = FIP
      ----------


        ExEn = gp^2 * LtpEn + 2.0*gp*gc[i] * XC + gc[i]^2 * InnEn;
               ------------   ------         --             -----

        aExEn= alp * ExEn
             = alp*gp^2*LtpEn + 2.0*alp*gp*XC* gc[i] + alp*InnEn* gc[i]^2
               --------------   -------------          ---------

             =         t[1]   +              t[2]    +          t[3]

        dist = d1 + d2;

          d1 = (1.0 - alp) * InnEn * (gcu - gc[i])^2 = t[4]
               -------------------    ---

          d2 =        alp  * (ResEn - 2.0 * sqrt(ResEn*ExEn) + ExEn);
                      ---     -----   ---        -----

             =        alp  * (sqrt(ExEn) - sqrt(ResEn))^2
                      ---                  -----------

             =               (sqrt(aExEn) - sqrt(alp*ResEn))^2
                                            ---------------

             =               (sqrt(aExEn) -       t[0]     )^2
                                                  ----

     */

    /*
     * calculate scalings of the constant terms
     */
    gain_code = shl(*gain_cod, (10 - exp_gcode0), pOverflow);   /* Q1  -> Q11 (-ec0) */
    g2_pitch = mult(gain_pit, gain_pit, pOverflow);               /* Q14 -> Q13        */
    /* 0 < alpha <= 0.5 => 0.5 <= 1-alpha < 1, i.e one_alpha is normalized  */
    one_alpha = add_16((32767 - alpha), 1, pOverflow);   /* 32768 - alpha */


    /*  alpha <= 0.5 -> mult. by 2 to keep precision; compensate in exponent */
    L_t1 = L_mult(alpha, frac_en[1], pOverflow);
    L_t1 = L_shl(L_t1, 1, pOverflow);
    tmp = (Word16)(L_t1 >> 16);

    /* directly store in 32 bit variable because no further mult. required */
    L_t1 = L_mult(tmp, g2_pitch, pOverflow);
    exp_coeff[1] = exp_en[1] - 15;


    tmp = (Word16)(L_shl(L_mult(alpha, frac_en[2], pOverflow), 1, pOverflow) >> 16);
    coeff[2] = mult(tmp, gain_pit, pOverflow);
    exp = exp_gcode0 - 10;
    exp_coeff[2] = add_16(exp_en[2], exp, pOverflow);


    /* alpha <= 0.5 -> mult. by 2 to keep precision; compensate in exponent */
    coeff[3] = (Word16)(L_shl(L_mult(alpha, frac_en[3], pOverflow), 1, pOverflow) >> 16);
    exp = shl(exp_gcode0, 1, pOverflow) - 7;
    exp_coeff[3] = add_16(exp_en[3], exp, pOverflow);


    coeff[4] = mult(one_alpha, frac_en[3], pOverflow);
    exp_coeff[4] = add_16(exp_coeff[3], 1, pOverflow);


    L_tmp = L_mult(alpha, frac_en[0], pOverflow);
    /* sqrt_l returns normalized value and 2*exponent
       -> result = val >> (exp/2)
       exp_coeff holds 2*exponent for c[0]            */
    /* directly store in 32 bit variable because no further mult. required */
    L_t0 = sqrt_l_exp(L_tmp, &exp, pOverflow);  /* normalization included in sqrt_l_exp */
    exp += 47;
    exp_coeff[0] = exp_en[0] - exp;

    /*
     * Determine the maximum exponent occuring in the distance calculation
     * and adjust all fractions accordingly (including a safety margin)
     *
     */

    /* find max(e[1..4],e[0]+31) */
    e_max = exp_coeff[0] + 31;
    for (i = 1; i <= 4; i++)
    {
        if (exp_coeff[i] > e_max)
        {
            e_max = exp_coeff[i];
        }
    }

    /* scale c[1]         (requires no further multiplication) */
    tmp = e_max - exp_coeff[1];
    L_t1 = L_shr(L_t1, tmp, pOverflow);

    /* scale c[2..4] (used in Mpy_32_16 in the quantizer loop) */
    for (i = 2; i <= 4; i++)
    {
        tmp = e_max - exp_coeff[i];
        L_tmp = ((Word32)coeff[i] << 16);
        L_tmp = L_shr(L_tmp, tmp, pOverflow);
        L_Extract(L_tmp, &coeff[i], &coeff_lo[i], pOverflow);
    }

    /* scale c[0]         (requires no further multiplication) */
    exp = e_max - 31;              /* new exponent */
    tmp = exp - exp_coeff[0];
    L_t0 = L_shr(L_t0, shr(tmp, 1, pOverflow), pOverflow);
    /* perform correction by 1/sqrt(2) if exponent difference is odd */
    if ((tmp & 0x1) != 0)
    {
        L_Extract(L_t0, &coeff[0], &coeff_lo[0], pOverflow);
        L_t0 = Mpy_32_16(coeff[0], coeff_lo[0],
                         23170, pOverflow);                    /* 23170 Q15 = 1/sqrt(2)*/
    }

    /* search the quantizer table for the lowest value
       of the search criterion                           */
    dist_min = MAX_32;
    index = 0;
    p = &qua_gain_code_ptr[0];

    for (i = 0; i < NB_QUA_CODE; i++)
    {
        g_code = *p++;                   /* this is g_fac (Q11)  */
        p++;                             /* skip log2(g_fac)     */
        p++;                             /* skip 20*log10(g_fac) */
        g_code = mult(g_code, gcode0, pOverflow);

        /* only continue if    gc[i]            < 2.0*gc
           which is equiv. to  g_code (Q10-ec0) < gain_code (Q11-ec0) */

        if (g_code >= gain_code)
        {
            break;
        }

        L_tmp = L_mult(g_code, g_code, pOverflow);
        L_Extract(L_tmp, &g2_code_h, &g2_code_l, pOverflow);

        tmp = sub(g_code, gain_cod_unq, pOverflow);
        L_tmp = L_mult(tmp, tmp, pOverflow);
        L_Extract(L_tmp, &d2_code_h, &d2_code_l, pOverflow);

        /* t2, t3, t4 */
        L_tmp = Mac_32_16(L_t1, coeff[2], coeff_lo[2], g_code, pOverflow);
        L_tmp = Mac_32(L_tmp,    coeff[3], coeff_lo[3], g2_code_h, g2_code_l, pOverflow);

        L_tmp = sqrt_l_exp(L_tmp, &exp, pOverflow);
        L_tmp = L_shr(L_tmp, shr(exp, 1, pOverflow), pOverflow);

        /* d2 */
        tmp = pv_round(L_sub(L_tmp, L_t0, pOverflow), pOverflow);
        L_tmp = L_mult(tmp, tmp, pOverflow);

        /* dist */
        L_tmp = Mac_32(L_tmp, coeff[4], coeff_lo[4], d2_code_h, d2_code_l, pOverflow);

        /* store table index if distance measure for this
            index is lower than the minimum seen so far   */
        if (L_tmp < dist_min)
        {
            dist_min = L_tmp;
            index = i;
        }
    }

    /*------------------------------------------------------------------*
     *  read quantized gains and new values for MA predictor memories   *
     *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   *
     *------------------------------------------------------------------*/

    /* Read the quantized gains */
    p = &qua_gain_code_ptr[(index<<2) - index];
    g_code = *p++;
    *qua_ener_MR122 = *p++;
    *qua_ener = *p;

    /*------------------------------------------------------------------*
     *  calculate final fixed codebook gain:                            *
     *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                            *
     *                                                                  *
     *   gc = gc0 * g                                                   *
     *------------------------------------------------------------------*/

    L_tmp = L_mult(g_code, gcode0, pOverflow);
    L_tmp = L_shr(L_tmp, 9 - exp_gcode0, pOverflow);
    *gain_cod = (Word16)(L_tmp >> 16);

    return index;
}