www.pudn.com > G711-729.rar > EXC_LBC.C


/* 
** 
** File:    exc_lbc.c 
** 
** Description: Functions that implement adaptive and fixed codebook 
**       operations. 
** 
** Functions: 
** 
**  Computing Open loop Pitch lag: 
** 
**      Estim_Pitch() 
** 
**  Harmonic noise weighting: 
** 
**      Comp_Pw() 
**      Filt_Pw() 
** 
**  Fixed Cobebook computation: 
** 
**      Find_Fcbk() 
**      Gen_Trn() 
**      Find_Best() 
**      Find_Pack() 
**      Find_Unpk() 
**      ACELP_LBC_code() 
**      Cor_h() 
**      Cor_h_X() 
**      reset_max_time() 
**      D4i64_LBC() 
**      G_code() 
**      search_T0() 
** 
**  Adaptive Cobebook computation: 
** 
**      Find_Acbk() 
**      Get_Rez() 
**      Decod_Acbk() 
** 
**  Pitch postfilter: 
**      Comp_Lpf() 
**      Find_B() 
**      Find_F() 
**      Filt_Lpf() 
** 
**  Residual interpolation: 
** 
**      Comp_Info() 
**      Regen() 
** 
*/ 
 
/* 
    ITU-T G.723 Speech Coder   ANSI-C Source Code     Version 5.00 
    copyright (c) 1995, AudioCodes, DSP Group, France Telecom, 
    Universite de Sherbrooke.  All rights reserved. 
*/ 
 
 
#include  
#include  
 
#include "typedef.h" 
#include "basop.h" 
#include "cst_lbc.h" 
#include "tab_lbc.h" 
#include "lbccodec.h" 
#include "util_lbc.h" 
#include "exc_lbc.h" 
#include "tame.h" 
#include "util_cng.h" 
 
/* 
** 
** Function:        Estim_Pitch() 
** 
** Description: Open loop pitch estimation made twice per frame (one for 
**              the first two subframes and one for the last two). 
**              The method is based on the maximization of the 
**              crosscorrelation of the speech. 
** 
** Links to text:   Section 2.9 
** 
** Arguments: 
** 
**  Word16 *Dpnt    Perceptually weighted speech 
**  Word16 Start    Starting index defining the subframes under study 
** 
** Outputs: 
** 
** Return value: 
** 
**  Word16      Open loop pitch period 
** 
*/ 
Word16   Estim_Pitch( Word16 *Dpnt, Word16 Start ) 
{ 
    int   i,j   ; 
 
    Word32   Acc0,Acc1   ; 
 
    Word16   Exp,Tmp  ; 
    Word16   Ccr,Enr  ; 
 
    Word16   Indx = (Word16) PitchMin ; 
 
    Word16   Mxp = (Word16) 30 ; 
    Word16   Mcr = (Word16) 0x4000 ; 
    Word16   Mnr = (Word16) 0x7fff ; 
 
    Word16   Pr ; 
 
    /* Init the energy estimate */ 
    Pr = Start - (Word16)PitchMin + (Word16)1 ; 
    Acc1 = (Word32) 0 ; 
    for ( j = 0 ; j < 2*SubFrLen ; j ++ ) 
        Acc1 = L_mac( Acc1, Dpnt[Pr+j], Dpnt[Pr+j] ) ; 
 
    /* Main Olp search loop */ 
    for ( i = PitchMin ; i <= PitchMax-3 ; i ++ ) { 
 
        Pr = sub( Pr, (Word16) 1 ) ; 
 
        /* Energy update */ 
        Acc1 = L_msu( Acc1, Dpnt[Pr+2*SubFrLen], Dpnt[Pr+2*SubFrLen] ) ; 
        Acc1 = L_mac( Acc1, Dpnt[Pr], Dpnt[Pr] ) ; 
 
        /*  Compute the cross */ 
        Acc0 = (Word32) 0 ; 
        for ( j = 0 ; j < 2*SubFrLen ; j ++ ) 
            Acc0 = L_mac( Acc0, Dpnt[Start+j], Dpnt[Pr+j] ) ; 
 
        if ( Acc0 > (Word32) 0 ) { 
 
            /* Compute Exp and mant of the cross */ 
            Exp = norm_l( Acc0 ) ; 
            Acc0 = L_shl( Acc0, Exp ) ; 
            Exp = shl( Exp, (Word16) 1 ) ; 
            Ccr = round( Acc0 ) ; 
            Acc0 = L_mult( Ccr, Ccr ) ; 
            Ccr = norm_l( Acc0 ) ; 
            Acc0 = L_shl( Acc0, Ccr ) ; 
            Exp = add( Exp, Ccr ) ; 
            Ccr = extract_h( Acc0 ) ; 
 
            /* Do the same with energy */ 
            Acc0 = Acc1 ; 
            Enr = norm_l( Acc0 ) ; 
            Acc0 = L_shl( Acc0, Enr ) ; 
            Exp = sub( Exp, Enr ) ; 
            Enr = round( Acc0 ) ; 
 
            if ( Ccr >= Enr ) { 
                Exp = sub( Exp, (Word16) 1 ) ; 
                Ccr = shr( Ccr, (Word16) 1 ) ; 
            } 
 
            if ( Exp <= Mxp ) { 
 
                if ( (Exp+1) < Mxp ) { 
                    Indx = (Word16) i ; 
                    Mxp = Exp ; 
                    Mcr = Ccr ; 
                    Mnr = Enr ; 
                    continue ; 
                } 
 
                if ( (Exp+1) == Mxp ) 
                    Tmp = shr( Mcr, (Word16) 1 ) ; 
                else 
                    Tmp = Mcr ; 
 
                /* Compare with equal exponents */ 
                Acc0 = L_mult( Ccr, Mnr ) ; 
                Acc0 = L_msu( Acc0, Enr, Tmp ) ; 
                if ( Acc0 > (Word32) 0 ) { 
 
                    if ( ((Word16)i - Indx) < (Word16) PitchMin ) { 
                        Indx = (Word16) i ; 
                        Mxp = Exp ; 
                        Mcr = Ccr ; 
                        Mnr = Enr ; 
                    } 
 
                    else { 
                        Acc0 = L_mult( Ccr, Mnr ) ; 
                        Acc0 = L_negate(L_shr( Acc0, (Word16) 2 ) ) ; 
                        Acc0 = L_mac( Acc0, Ccr, Mnr ) ; 
                        Acc0 = L_msu( Acc0, Enr, Tmp ) ; 
                        if ( Acc0 > (Word32) 0 ) { 
                            Indx = (Word16) i ; 
                            Mxp = Exp ; 
                            Mcr = Ccr ; 
                            Mnr = Enr ; 
                        } 
                    } 
                } 
            } 
        } 
    } 
 
    return Indx ; 
} 
 
/* 
** 
** Function:        Comp_Pw() 
** 
** Description:     Computes harmonic noise filter coefficients. 
**                  For each subframe, the optimal lag is searched around the 
**                  open loop pitch lag based on only positive correlation 
**                  maximization. 
** 
** Links to text:   Section 2.11 
** 
** Arguments: 
** 
**  Word16 *Dpnt    Formant perceptually weighted speech 
**  Word16 Start 
**  Word16 Olp      Open loop pitch lag 
** 
** Outputs:         None 
** 
** Return value: 
** 
**  PWDEF   Word16  Indx  lag of the harmonic noise shaping filter 
**          Word16  Gain  gain of the harmonic noise shaping filter 
** 
*/ 
PWDEF Comp_Pw( Word16 *Dpnt, Word16 Start, Word16 Olp ) 
{ 
 
    int   i,j   ; 
 
    Word32   Lcr[15] ; 
    Word16   Scr[15] ; 
    PWDEF    Pw ; 
 
    Word32   Acc0,Acc1   ; 
    Word16   Exp   ; 
 
    Word16   Ccr,Enr  ; 
    Word16   Mcr,Mnr  ; 
 
    /* Compute and save target energy */ 
    Lcr[0] = (Word32) 0 ; 
    for ( i = 0 ; i < SubFrLen ; i ++ ) 
        Lcr[0] = L_mac( Lcr[0], Dpnt[Start+i], Dpnt[Start+i] ) ; 
 
    /* Compute all Crosses and energys */ 
    for ( i = 0 ; i <= 2*PwRange ; i ++ ) { 
 
        Acc1 = Acc0 = (Word32) 0 ; 
        for ( j = 0 ; j < SubFrLen ; j ++ ) { 
            Acc0 = L_mac( Acc0, Dpnt[Start+j], 
                                            Dpnt[Start-(Olp-PwRange+i)+j]) ; 
            Acc1 = L_mac( Acc1, Dpnt[Start-(Olp-PwRange+i)+j], 
                                            Dpnt[Start-(Olp-PwRange+i)+j] ) ; 
        } 
 
        /* Save both */ 
        Lcr[2*i+1] = Acc1 ; 
        Lcr[2*i+2] = Acc0 ; 
    } 
 
    /* Normalize to maximum */ 
    Acc1 = (Word32) 0 ; 
    for ( i = 0 ; i < 15 ; i ++ ) { 
        Acc0 = Lcr[i] ; 
        Acc0 = L_abs( Acc0 ) ; 
        if ( Acc0 > Acc1 ) 
            Acc1 = Acc0 ; 
    } 
 
    Exp = norm_l( Acc1 ) ; 
    for ( i = 0 ; i < 15 ; i ++ ) { 
        Acc0 = L_shl( Lcr[i], Exp ) ; 
        Scr[i] = round( Acc0 ) ; 
 
    } 
 
    /* Find the best pair */ 
    Pw.Indx = (Word16) -1 ; 
    Pw.Gain = (Word16) 0  ; 
 
    Mcr = (Word16) 1 ; 
    Mnr = (Word16) 0x7fff ; 
 
    for ( i = 0 ; i <= 2*PwRange ; i ++ ) { 
 
        Enr = Scr[2*i+1] ; 
        Ccr = Scr[2*i+2] ; 
 
        if ( Ccr <= (Word16) 0 ) 
            continue ; 
 
        Exp = mult_r( Ccr, Ccr ) ; 
 
        /* Compute the cross */ 
        Acc0 = L_mult( Exp, Mnr ) ; 
        Acc0 = L_msu ( Acc0, Enr, Mcr ) ; 
 
        if ( Acc0 > (Word32) 0 ) { 
            Mcr = Exp ; 
            Mnr = Enr ; 
            Pw.Indx = (Word16)i ; 
        } 
    } 
 
    if ( Pw.Indx == -1 ) { 
        Pw.Indx = Olp ; 
        return Pw ; 
    } 
 
    /* Check the db limit */ 
    Acc0 = L_mult( Scr[0], Mnr ) ; 
    Acc1 = Acc0 ; 
    Acc0 = L_shr( Acc0, (Word16) 2 ) ; 
    Acc1 = L_shr( Acc1, (Word16) 3 ) ; 
    Acc0 = L_add( Acc0, Acc1 ) ; 
    Acc1 = L_mult( Scr[2*Pw.Indx+2], Scr[2*Pw.Indx+2] ) ; 
    Acc0 = L_sub( Acc0, Acc1 ) ; 
 
    if ( Acc0 < (Word32) 0 ) { 
 
        Exp = Scr[2*Pw.Indx + 2] ; 
 
        if ( Exp >= Mnr ) 
            Pw.Gain = PwConst ; 
        else { 
            Pw.Gain = div_s( Exp, Mnr ) ; 
            Pw.Gain = mult_r( Pw.Gain, PwConst ) ; 
        } 
    } 
 
    Pw.Indx = Olp - PwRange + Pw.Indx ; 
 
    return Pw ; 
 
} 
 
/* 
** 
** Function:        Filt_Pw() 
** 
** Description:     Applies harmonic noise shaping filter. 
**                  Lth order FIR filter on each subframe (L: lag of the filter). 
** 
** Links to text:   Section 2.11 
** 
** Arguments: 
** 
**  Word16 *DataBuff    Target vector 
**  Word16 *Dpnt        Formant perceptually weighted speech 
**  Word16 Start 
**  PWDEF   Pw          Parameters of the harmonic noise shaping filter 
** 
** Outputs: 
** 
**  Word16 *DataBuff    Target vector 
** 
** Return value:        None 
** 
*/ 
void  Filt_Pw( Word16 *DataBuff, Word16 *Dpnt, Word16 Start, PWDEF Pw ) 
{ 
    int   i  ; 
 
    Word32   Acc0 ; 
 
    /* Perform the harmonic weighting */ 
    for ( i = 0 ; i < SubFrLen ; i ++ ) { 
        Acc0 = L_deposit_h( Dpnt[PitchMax+Start+i] ) ; 
        Acc0 = L_msu( Acc0, Pw.Gain, Dpnt[PitchMax+Start-Pw.Indx+i] ) ; 
        DataBuff[Start+(Word16)i] = round( Acc0 ) ; 
    } 
 
    return; 
} 
 
/* 
** 
** Function:        Find_Fcbk() 
** 
** Description:     Fixed codebook excitation computation. 
** 
** 
** Links to text:   Sections 2.15 & 2.16 
** 
** Arguments: 
** 
**  Word16 *Dpnt    Target vector 
**  Word16 *ImpResp Impulse response of the synthesis filter 
**  LineDef *Line   Excitation parameters for one subframe 
**  Word16 Sfc      Subframe index 
** 
** Outputs: 
** 
**  Word16 *Dpnt    Excitation vector 
**  LINEDEF *Line   Fixed codebook parameters for one subframe 
** 
** Return value:        None 
** 
*/ 
void  Find_Fcbk( Word16 *Dpnt, Word16 *ImpResp, LINEDEF *Line, Word16 Sfc ) 
{ 
    int   i  ; 
    Word16 T0_acelp, gain_T0; 
    Word16   Srate ; 
 
 
    BESTDEF  Best ; 
 
    switch(WrkRate)  { 
 
        case Rate63: { 
 
            Srate = Nb_puls[(int)Sfc] ; 
            Best.MaxErr = (Word32) 0xc0000000L ; 
            Find_Best( &Best, Dpnt, ImpResp, Srate, (Word16) SubFrLen ) ; 
            if ( (*Line).Olp[Sfc>>1] < (Word16) (SubFrLen-2) ) { 
                Find_Best( &Best, Dpnt, ImpResp, Srate, (*Line).Olp[Sfc>>1]); 
            } 
 
            /* Reconstruct the excitation */ 
            for ( i = 0 ; i <  SubFrLen ; i ++ ) 
                Dpnt[i] = (Word16) 0 ; 
            for ( i = 0 ; i < Srate ; i ++ ) 
                Dpnt[Best.Ploc[i]] = Best.Pamp[i] ; 
 
            /* Code the excitation */ 
            Fcbk_Pack( Dpnt, &((*Line).Sfs[Sfc]), &Best, Srate ) ; 
 
            if ( Best.UseTrn == (Word16) 1 ) 
                Gen_Trn( Dpnt, Dpnt, (*Line).Olp[Sfc>>1] ) ; 
 
            break; 
        } 
 
        case Rate53: { 
 
            T0_acelp = search_T0( 
                    (Word16) ((*Line).Olp[Sfc>>1]-1+(*Line).Sfs[Sfc].AcLg), 
                    (*Line).Sfs[Sfc].AcGn, &gain_T0 ); 
 
            (*Line).Sfs[Sfc].Ppos = ACELP_LBC_code( 
                    Dpnt, ImpResp, T0_acelp, Dpnt, &(*Line).Sfs[Sfc].Mamp, 
                    &(*Line).Sfs[Sfc].Grid, &(*Line).Sfs[Sfc].Pamp, gain_T0 ); 
 
            (*Line).Sfs[Sfc].Tran = 0; 
 
            break; 
        } 
    } 
 
    return; 
} 
 
/* 
** 
** Function:        Gen_Trn() 
** 
** Description:     Generation of a train of Dirac functions with the period 
**                  Olp. 
** 
** Links to text:   Section 2.15 
** 
** Arguments: 
** 
**  Word16 *Dst     Fixed codebook excitation vector with  train of Dirac 
**  Word16 *Src     Fixed codebook excitation vector without train of Dirac 
**  Word16 Olp      Closed-loop pitch lag of subframe 0 (for subframes 0 & 1) 
**                  Closed-loop pitch lag of subframe 2 (for subframes 2 & 3) 
** 
** Outputs: 
** 
**  Word16 *Dst     excitation vector 
** 
** Return value:    None 
** 
*/ 
void  Gen_Trn( Word16 *Dst, Word16 *Src, Word16 Olp ) 
{ 
    int   i  ; 
 
    Word16   Tmp0,Tmp1   ; 
    Word16   Tmp[SubFrLen] ; 
 
    Tmp0 = Olp ; 
 
    for ( i = 0 ; i < SubFrLen ; i ++ ) { 
        Tmp[i] = Src[i] ; 
        Dst[i] = Src[i] ; 
    } 
 
    while ( Tmp0 < SubFrLen ) { 
        for ( i = (int) Tmp0 ; i < SubFrLen ; i ++ ) { 
            Tmp1 = add( Dst[i], Tmp[i-(int)Tmp0] ) ; 
            Dst[i] = Tmp1 ; 
        } 
        Tmp0 = add( Tmp0, Olp ) ; 
    } 
 
    return; 
} 
 
/* 
** 
** Function:        Find_Best() 
** 
** Description:     Fixed codebook search for the high rate encoder. 
**                  It performs the quantization of the residual signal. 
**                  The excitation made of Np positive or negative pulses 
**                  multiplied by a gain and whose positions on the grid are 
**                  either all odd or all even, should approximate as best as 
**                  possible the residual signal (perceptual criterion). 
** 
** Links to text:   Section 2.15 
** 
** Arguments: 
** 
**  BESTDEF *Best   Parameters of the best excitation model 
**  Word16 *Tv      Target vector 
**  Word16 *ImpResp Impulse response of the combined filter 
**  Word16 Np       Number of pulses (6 for even subframes; 5 for odd subframes) 
**  Word16 Olp      Closed-loop pitch lag of subframe 0 (for subframes 0 & 1) 
**                  Closed-loop pitch lag of subframe 2 (for subframes 2 & 3) 
** 
** Outputs: 
** 
**  BESTDEF *Best 
** 
** Return value:    None 
** 
*/ 
void  Find_Best( BESTDEF *Best, Word16 *Tv, Word16 *ImpResp, Word16 Np, 
Word16 Olp ) 
{ 
 
    int   i,j,k,l  ; 
    BESTDEF  Temp  ; 
 
    Word16   Exp   ; 
    Word16   MaxAmpId ; 
    Word16   MaxAmp   ; 
    Word32   Acc0,Acc1,Acc2 ; 
 
    Word16   Imr[SubFrLen]  ; 
    Word16   OccPos[SubFrLen] ; 
    Word16   ImrCorr[SubFrLen] ; 
    Word32   ErrBlk[SubFrLen] ; 
    Word32   WrkBlk[SubFrLen] ; 
 
 
    /* Update Impulse response */ 
    if ( Olp < (Word16) (SubFrLen-2) ) { 
        Temp.UseTrn = (Word16) 1 ; 
        Gen_Trn( Imr, ImpResp, Olp ) ; 
    } 
    else { 
        Temp.UseTrn = (Word16) 0 ; 
        for ( i = 0 ; i < SubFrLen ; i ++ ) 
            Imr[i] = ImpResp[i] ; 
    } 
 
    /* Scale Imr to avoid overflow */ 
    for ( i = 0 ; i < SubFrLen ; i ++ ) 
        OccPos[i] = shr( Imr[i], (Word16) 1 ) ; 
 
    /* Compute Imr AutoCorr function */ 
    Acc0 = (Word32) 0 ; 
    for ( i = 0 ; i < SubFrLen ; i ++ ) 
        Acc0 = L_mac( Acc0, OccPos[i], OccPos[i] ) ; 
 
    Exp = norm_l( Acc0 ) ; 
    Acc0 = L_shl( Acc0, Exp ) ; 
    ImrCorr[0] = round( Acc0 ) ; 
 
    /* Compute all the other */ 
    for ( i = 1 ; i < SubFrLen ; i ++ ) { 
        Acc0 = (Word32) 0 ; 
        for ( j = i ; j < SubFrLen ; j ++ ) 
            Acc0 = L_mac( Acc0, OccPos[j], OccPos[j-i] ) ; 
        Acc0 = L_shl( Acc0, Exp ) ; 
        ImrCorr[i] = round( Acc0 ) ; 
    } 
 
    /* Cross correlation with the signal */ 
    Exp = sub( Exp, 4 ) ; 
    for ( i = 0 ; i < SubFrLen ; i ++ ) { 
        Acc0 = (Word32) 0 ; 
        for ( j = i ; j < SubFrLen ; j ++ ) 
            Acc0 = L_mac( Acc0, Tv[j], Imr[j-i] ) ; 
        ErrBlk[i] = L_shl( Acc0, Exp ) ; 
    } 
 
    /* Search for the best sequence */ 
    for ( k = 0 ; k < Sgrid ; k ++ ) { 
 
        Temp.GridId = (Word16) k ; 
 
        /* Find maximum amplitude */ 
        Acc1 = (Word32) 0 ; 
        for ( i = k ; i < SubFrLen ; i += Sgrid ) { 
            Acc0 = L_abs( ErrBlk[i] ) ; 
            if ( Acc0 >= Acc1 ) { 
                Acc1 = Acc0 ; 
                Temp.Ploc[0] = (Word16) i ; 
            } 
        } 
 
        /* Quantize the maximum amplitude */ 
        Acc2 = Acc1 ; 
        Acc1 = (Word32) 0x40000000L ; 
        MaxAmpId = (Word16) (NumOfGainLev - MlqSteps) ; 
 
        for ( i = MaxAmpId ; i >= MlqSteps ; i -- ) { 
            Acc0 = L_mult( FcbkGainTable[i], ImrCorr[0] ) ; 
            Acc0 = L_sub( Acc0, Acc2 ) ; 
            Acc0 = L_abs( Acc0 ) ; 
            if ( Acc0 < Acc1 ) { 
                Acc1 = Acc0 ; 
                MaxAmpId = (Word16) i ; 
            } 
        } 
        MaxAmpId -- ; 
 
        for ( i = 1 ; i <=2*MlqSteps ; i ++ ) { 
 
            for ( j = k ; j < SubFrLen ; j += Sgrid ) { 
                WrkBlk[j] = ErrBlk[j] ; 
                OccPos[j] = (Word16) 0 ; 
            } 
            Temp.MampId = MaxAmpId - (Word16) MlqSteps + (Word16) i ; 
 
            MaxAmp = FcbkGainTable[Temp.MampId] ; 
 
            if ( WrkBlk[Temp.Ploc[0]] >= (Word32) 0 ) 
                Temp.Pamp[0] = MaxAmp ; 
            else 
                Temp.Pamp[0] = negate(MaxAmp) ; 
 
            OccPos[Temp.Ploc[0]] = (Word16) 1 ; 
 
            for ( j = 1 ; j < Np ; j ++ ) { 
 
                Acc1 = (Word32) 0xc0000000L ; 
 
                for ( l = k ; l < SubFrLen ; l += Sgrid ) { 
 
                    if ( OccPos[l] != (Word16) 0 ) 
                        continue ; 
 
                    Acc0 = WrkBlk[l] ; 
                    Acc0 = L_msu( Acc0, Temp.Pamp[j-1], 
                            ImrCorr[abs_s((Word16)(l-Temp.Ploc[j-1]))] ) ; 
                    WrkBlk[l] = Acc0 ; 
                    Acc0 = L_abs( Acc0 ) ; 
                    if ( Acc0 > Acc1 ) { 
                        Acc1 = Acc0 ; 
                        Temp.Ploc[j] = (Word16) l ; 
                    } 
                } 
 
                if ( WrkBlk[Temp.Ploc[j]] >= (Word32) 0 ) 
                    Temp.Pamp[j] = MaxAmp ; 
                else 
                    Temp.Pamp[j] = negate(MaxAmp) ; 
 
                OccPos[Temp.Ploc[j]] = (Word16) 1 ; 
            } 
 
            /* Compute error vector */ 
            for ( j = 0 ; j < SubFrLen ; j ++ ) 
                OccPos[j] = (Word16) 0 ; 
 
            for ( j = 0 ; j < Np ; j ++ ) 
                OccPos[Temp.Ploc[j]] = Temp.Pamp[j] ; 
 
            for ( l = SubFrLen-1 ; l >= 0 ; l -- ) { 
                Acc0 = (Word32) 0 ; 
                for ( j = 0 ; j <= l ; j ++ ) 
                    Acc0 = L_mac( Acc0, OccPos[j], Imr[l-j] ) ; 
                Acc0 = L_shl( Acc0, (Word16) 2 ) ; 
                OccPos[l] = extract_h( Acc0 ) ; 
            } 
 
            /* Evaluate error */ 
            Acc1 = (Word32) 0 ; 
            for ( j = 0 ; j < SubFrLen ; j ++ ) { 
                Acc1 = L_mac( Acc1, Tv[j], OccPos[j] ) ; 
                Acc0 = L_mult( OccPos[j], OccPos[j] ) ; 
                Acc1 = L_sub( Acc1, L_shr( Acc0, (Word16) 1 ) ) ; 
            } 
 
            if ( Acc1 > (*Best).MaxErr ) { 
                (*Best).MaxErr = Acc1 ; 
                (*Best).GridId = Temp.GridId ; 
                (*Best).MampId = Temp.MampId ; 
                (*Best).UseTrn = Temp.UseTrn ; 
                for ( j = 0 ; j < Np ; j ++ ) { 
                    (*Best).Pamp[j] = Temp.Pamp[j] ; 
                    (*Best).Ploc[j] = Temp.Ploc[j] ; 
                } 
            } 
        } 
    } 
    return; 
} 
/* 
** 
** Function:        Fcbk_Pack() 
** 
** Description:     Encoding of the pulse positions and gains for the high 
**                  rate case. 
**                  Combinatorial encoding is used to transmit the optimal 
**                  combination of pulse locations. 
** 
** Links to text:   Section 2.15 
** 
** Arguments: 
** 
**  Word16 *Dpnt    Excitation vector 
**  SFSDEF *Sfs     Encoded parameters of the excitation model 
**  BESTDEF *Best   Parameters of the best excitation model 
**  Word16 Np       Number of pulses (6 for even subframes; 5 for odd subframes) 
** 
** Outputs: 
** 
**  SFSDEF *Sfs     Encoded parameters of the excitation model 
** 
** Return value:    None 
** 
*/ 
void  Fcbk_Pack( Word16 *Dpnt, SFSDEF *Sfs, BESTDEF *Best, Word16 Np ) 
{ 
    int   i,j   ; 
 
 
    /* Code the amplitudes and positions */ 
    j = MaxPulseNum - (int) Np ; 
 
    (*Sfs).Pamp = (Word16) 0 ; 
    (*Sfs).Ppos = (Word32) 0 ; 
 
    for ( i = 0 ; i < SubFrLen/Sgrid ; i ++ ) { 
 
        if ( Dpnt[(int)(*Best).GridId + Sgrid*i] == (Word16) 0 ) 
            (*Sfs).Ppos = L_add( (*Sfs).Ppos, CombinatorialTable[j][i] ) ; 
        else { 
            (*Sfs).Pamp = shl( (*Sfs).Pamp, (Word16) 1 ) ; 
            if ( Dpnt[(int)(*Best).GridId + Sgrid*i] < (Word16) 0 ) 
                (*Sfs).Pamp = add( (*Sfs).Pamp, (Word16) 1 ) ; 
 
            j ++ ; 
            /* Check for end */ 
            if ( j == MaxPulseNum ) 
                break ; 
        } 
    } 
 
    (*Sfs).Mamp = (*Best).MampId ; 
    (*Sfs).Grid = (*Best).GridId ; 
    (*Sfs).Tran = (*Best).UseTrn ; 
 
    return; 
} 
 
/* 
** 
** Function:        Fcbk_Unpk() 
** 
** Description:     Decoding of the fixed codebook excitation for both rates. 
**                  Gains, pulse positions, grid position (odd or even), signs 
**                  are decoded and used to reconstruct the excitation. 
** 
** Links to text:   Section 2.17 & 3.5 
** 
** Arguments: 
** 
**  Word16 *Tv      Decoded excitation vector 
**  SFSDEF Sfs      Encoded parameters of the excitation (for one subframe) 
**  Word16 Olp      Closed loop adaptive pitch lag 
**  Word16 Sfc      Subframe index 
** 
** Outputs: 
** 
**  Word16 *Tv      Decoded excitation vector 
** 
** Return value:    None 
** 
*/ 
void  Fcbk_Unpk( Word16 *Tv, SFSDEF Sfs, Word16 Olp, Word16 Sfc ) 
{ 
    int   i,j   ; 
 
    Word32   Acc0  ; 
    Word16   Np ; 
    Word16 Tv_tmp[SubFrLen+4]; 
    Word16 acelp_gain, acelp_sign, acelp_shift, acelp_pos; 
    Word16 offset, ipos, T0_acelp, gain_T0; 
 
 
 
    switch(WrkRate)  { 
        case Rate63: { 
 
            Np = Nb_puls[(int)Sfc] ; 
 
            for ( i = 0 ; i < SubFrLen ; i ++ ) 
                Tv[i] = (Word16) 0 ; 
 
            if ( Sfs.Ppos >= MaxPosTable[Sfc] ) 
                return ; 
 
            /* Decode the amplitudes and positions */ 
            j = MaxPulseNum - (int) Np ; 
 
            Acc0 = Sfs.Ppos ; 
 
            for ( i = 0 ; i < SubFrLen/Sgrid ; i ++ )  { 
 
                Acc0 = L_sub( Acc0, CombinatorialTable[j][i] ) ; 
 
                if ( Acc0 < (Word32) 0 ) { 
                    Acc0 = L_add( Acc0, CombinatorialTable[j][i] ) ; 
                    j ++ ; 
                    if ( (Sfs.Pamp & (1 << (MaxPulseNum-j) )) != (Word16) 0 ) 
                        Tv[(int)Sfs.Grid + Sgrid*i] = -FcbkGainTable[Sfs.Mamp] ; 
                    else 
                        Tv[(int)Sfs.Grid + Sgrid*i] =  FcbkGainTable[Sfs.Mamp] ; 
 
                    if ( j == MaxPulseNum ) 
                        break ; 
                } 
            } 
 
            if ( Sfs.Tran == (Word16) 1 ) 
                Gen_Trn( Tv, Tv, Olp ) ; 
            break; 
        } 
 
        case Rate53: { 
            for ( i = 0 ; i < SubFrLen+4 ; i ++ ) 
                Tv_tmp[i] = (Word16) 0 ; 
 
            /* decoding gain */ 
            acelp_gain = FcbkGainTable[Sfs.Mamp]; 
            /* decoding grid */ 
            acelp_shift = Sfs.Grid; 
            /* decoding Sign */ 
            acelp_sign = Sfs.Pamp; 
            /* decoding Pos */ 
            acelp_pos = (short) Sfs.Ppos; 
 
            offset  = 0; 
            for(i=0; i<4; i++) { 
                ipos = (acelp_pos & (Word16)0x0007) ; 
                ipos = shl(ipos,3) + acelp_shift + offset; 
                if( (acelp_sign & 1 )== 1) { 
                    Tv_tmp[ipos] = acelp_gain; 
                } 
                else { 
                    Tv_tmp[ipos] = -acelp_gain; 
                } 
                offset = add(offset,2); 
                acelp_pos = shr(acelp_pos, 3); 
                acelp_sign = shr(acelp_sign,1); 
            } 
            for (i = 0; i < SubFrLen; i++) Tv[i] = Tv_tmp[i]; 
            T0_acelp = search_T0( (Word16) (Olp-1+Sfs.AcLg), Sfs.AcGn, 
                                                            &gain_T0); 
            if(T0_acelp  (Word16) (PitchMax-5) ) 
            Olp = (Word16)(PitchMax-5) ; 
    } 
 
    lPnt = CorBuf ; 
    for ( k = 0 ; k < (int) Hb ; k ++ ) { 
 
        /* Get residual from the excitation buffer */ 
        Get_Rez( RezBuf, PrevExc, (Word16)(Olp-(Word16)Pstep+k) ) ; 
 
        /* Filter the last one using the impulse response */ 
        for ( i = 0 ; i < SubFrLen ; i ++ ) { 
            Acc0 = (Word32) 0 ; 
            for ( j = 0 ; j <= i ; j ++ ) 
                Acc0 = L_mac( Acc0, RezBuf[ClPitchOrd-1+j], ImpResp[i-j] ) ; 
            FltBuf[ClPitchOrd-1][i] = round( Acc0 ) ; 
        } 
 
        /* Update all the others */ 
        for ( i = ClPitchOrd-2 ; i >= 0 ; i -- ) { 
            FltBuf[i][0] = mult_r( RezBuf[i], (Word16) 0x2000 ) ; 
            for ( j = 1 ; j < SubFrLen ; j ++ ) { 
                Acc0 = L_deposit_h( FltBuf[i+1][j-1] ) ; 
                Acc0 = L_mac( Acc0, RezBuf[i], ImpResp[j] ) ; 
                FltBuf[i][j] = round( Acc0 ) ; 
            } 
        } 
 
        /* Compute the cross with the signal */ 
        for ( i = 0 ; i < ClPitchOrd ; i ++ ) { 
            Acc1 = (Word32) 0 ; 
            for ( j = 0 ; j < SubFrLen ; j ++ ) { 
                Acc0 = L_mult( Tv[j], FltBuf[i][j] ) ; 
                Acc1 = L_add( Acc1, L_shr( Acc0, (Word16) 1 ) ) ; 
            } 
            *lPnt ++ = L_shl( Acc1, (Word16) 1 ) ; 
        } 
 
        /* Compute the energies */ 
        for ( i = 0 ; i < ClPitchOrd ; i ++ ) { 
            Acc1 = (Word32) 0 ; 
            for ( j = 0 ; j < SubFrLen ; j ++ ) 
                Acc1 = L_mac( Acc1, FltBuf[i][j], FltBuf[i][j] ) ; 
            *lPnt ++ = Acc1 ; 
        } 
 
        /* Compute the between crosses */ 
        for ( i = 1 ; i < ClPitchOrd ; i ++ ) { 
            for ( j = 0 ; j < i ; j ++ ) { 
                Acc1 = (Word32) 0 ; 
                for ( l = 0 ; l < SubFrLen ; l ++ ) { 
                    Acc0 = L_mult( FltBuf[i][l], FltBuf[j][l] ) ; 
                    Acc1 = L_add( Acc1, L_shr( Acc0, (Word16) 1 ) ) ; 
                } 
                *lPnt ++ = L_shl( Acc1, (Word16) 2 ) ; 
            } 
        } 
    } 
 
 
    /* Find Max and normalize */ 
    Acc1 = (Word32) 0 ; 
    for ( i = 0 ; i < Hb*20 ; i ++ ) { 
        Acc0 = L_abs(CorBuf[i]) ; 
        if ( Acc0 > Acc1 ) 
            Acc1 = Acc0 ; 
    } 
 
    Exp = norm_l( Acc1 ) ; 
    /* Convert to shorts */ 
    for ( i = 0 ; i < Hb*20 ; i ++ ) { 
        Acc0 = L_shl( CorBuf[i], Exp ) ; 
        CorVct[i] = round( Acc0 ) ; 
    } 
 
    /* Test potential error */ 
    Lag1 = Olp-(Word16)Pstep; 
    Lag2 = Olp-(Word16)Pstep+ Hb -(Word16)1; 
    off_filt = Test_Err(Lag1, Lag2); 
    Bound[0] =  NbFilt085_min + shl(off_filt,2); 
    if(Bound[0] > NbFilt085) Bound[0] = NbFilt085; 
    Bound[1] =  NbFilt170_min + shl(off_filt,3); 
    if(Bound[1] > NbFilt170) Bound[1] = NbFilt170; 
 
    /* Init the search loop */ 
    Acc1 = (Word32) 0 ; 
 
    for ( k = 0 ; k < (int) Hb ; k ++ ) { 
 
        /* Select Quantization tables */ 
        l = 0 ; 
        if ( WrkRate == Rate63 ){ 
            if ( (Sfc & (Word16) 1) == (Word16) 0 ) { 
                if ( (int)Olp-Pstep+k >= SubFrLen-2 )l ++ ; 
            } 
            else { 
                if ( (int)Olp >= SubFrLen-2 ) l ++ ; 
            } 
        } 
        else { 
            l = 1; 
        } 
 
 
        sPnt = AcbkGainTablePtr[l] ; 
 
        for ( i = 0 ; i < (int) Bound[l] ; i ++ ) { 
 
            Acc0 = (Word32) 0 ; 
            for ( j = 0 ; j < 20 ; j ++ ) 
                Acc0 = L_add( Acc0, L_shr( L_mult(CorVct[k*20+j], *sPnt ++), 
(Word16) 1 ) ) ; 
 
            if ( Acc0 > Acc1 ) { 
                Acc1 = Acc0 ; 
                Gid = (Word16) i ; 
                Lid = (Word16) k ; 
            } 
        } 
    } 
 
    /* Modify Olp for even sub frames */ 
    if ( (Sfc & (Word16) 1 ) == (Word16) 0 ) { 
        Olp = Olp - (Word16) Pstep + Lid ; 
        Lid = (Word16) Pstep ; 
    } 
 
    /* Save Gains and Olp */ 
    (*Line).Sfs[Sfc].AcLg = Lid ; 
    (*Line).Sfs[Sfc].AcGn = Gid ; 
    (*Line).Olp[shr(Sfc, (Word16) 1)] = Olp ; 
 
    /* Decode the Acbk contribution and subtract it */ 
    Decod_Acbk( RezBuf, PrevExc, Olp, Lid, Gid ) ; 
 
    for ( i = 0 ; i < SubFrLen ; i ++ ) { 
        Acc0 = L_deposit_h( Tv[i] ) ; 
        Acc0 = L_shr( Acc0, (Word16) 1 ) ; 
 
        for ( j = 0 ; j <= i ; j ++ ) 
            Acc0 = L_msu( Acc0, RezBuf[j], ImpResp[i-j] ) ; 
        Acc0 = L_shl( Acc0, (Word16) 1 ) ; 
        Tv[i] = round( Acc0 ) ; 
    } 
 
    return; 
} 
 
/* 
** 
** Function:        Get_Rez() 
** 
** Description:     Gets delayed contribution from the previous excitation 
**                  vector. 
** 
** Links to text:   Sections 2.14, 2.18 & 3.4 
** 
** Arguments: 
** 
**  Word16 *Tv      delayed excitation 
**  Word16 *PrevExc Previous excitation vector 
**  Word16 Lag      Closed loop pitch lag 
** 
** Outputs: 
** 
**  Word16 *Tv      delayed excitation 
** 
** Return value:    None 
** 
*/ 
void  Get_Rez( Word16 *Tv, Word16 *PrevExc, Word16 Lag ) 
{ 
    int   i  ; 
 
    for ( i = 0 ; i < ClPitchOrd/2 ; i ++ ) 
        Tv[i] = PrevExc[PitchMax - (int) Lag - ClPitchOrd/2 + i] ; 
 
    for ( i = 0 ; i < SubFrLen+ClPitchOrd/2 ; i ++ ) 
        Tv[ClPitchOrd/2+i] = PrevExc[PitchMax - (int)Lag + i%(int)Lag] ; 
 
    return; 
} 
 
/* 
** 
** Function:        Decod_Acbk() 
** 
** Description:     Computes the adaptive codebook contribution from the previous 
**                  excitation vector. 
**                  With the gain index, the closed loop pitch lag, the jitter 
**                  which when added to this pitch lag gives the actual closed 
**                  loop value, and after having selected the proper codebook, 
**                  the pitch contribution is reconstructed using the previous 
**                  excitation buffer. 
** 
** Links to text:   Sections 2.14, 2.18 & 3.4 
** 
** Arguments: 
** 
**  Word16 *Tv      Reconstructed excitation vector 
**  Word16 *PrevExc Previous excitation vector 
**  Word16 Olp      closed-loop pitch period 
**  Word16 Lid      Jitter around pitch period 
**  Word16 Gid      Gain vector index in 5- dimensional 
**                      adaptive gain vector codebook 
** 
** Outputs: 
** 
**  Word16 *Tv      Reconstructed excitation vector 
** 
** Return value:    None 
** 
*/ 
void  Decod_Acbk( Word16 *Tv, Word16 *PrevExc, Word16 Olp, Word16 Lid, 
Word16 Gid ) 
{ 
    int   i,j   ; 
 
    Word32   Acc0  ; 
    Word16   RezBuf[SubFrLen+ClPitchOrd-1] ; 
    Word16  *sPnt ; 
 
    Get_Rez( RezBuf, PrevExc, (Word16)(Olp - (Word16)Pstep + Lid) ) ; 
 
    /* Select Quantization tables */ 
    i = 0 ; 
    if ( WrkRate == Rate63 ) { 
        if ( Olp >= (Word16) (SubFrLen-2) ) i ++ ; 
    } 
    else { 
        i = 1; 
    } 
    sPnt = AcbkGainTablePtr[i] ; 
 
    sPnt += (int)Gid*20 ; 
 
    for ( i = 0 ; i < SubFrLen ; i ++ ) { 
        Acc0 = (Word32) 0 ; 
        for ( j = 0 ; j < ClPitchOrd ; j ++ ) 
            Acc0 = L_mac( Acc0, RezBuf[i+j], sPnt[j] ) ; 
        Acc0 = L_shl( Acc0, (Word16) 1 ) ; 
        Tv[i] = round( Acc0 ) ; 
    } 
 
    return; 
} 
 
/* 
** 
** Function:        Comp_Info() 
** 
** Description:     Voiced/unvoiced classifier. 
**                  It is based on a cross correlation maximization over the 
**                  last 120 samples of the frame and with an index varying 
**                  around the decoded pitch lag (from L-3 to L+3). Then the 
**                  prediction gain is tested to declare the frame voiced or 
**                  unvoiced. 
** 
** Links to text:   Section 3.10.2 
** 
** Arguments: 
** 
**  Word16 *Buff  decoded excitation 
**  Word16 Olp    Decoded pitch lag 
** 
** Outputs: None 
** 
** Return value: 
** 
**      Word16   Estimated pitch value 
*/ 
Word16   Comp_Info( Word16 *Buff, Word16 Olp, Word16 *Gain, Word16 *ShGain) 
{ 
    int   i,j   ; 
 
    Word32   Acc0,Acc1 ; 
 
    Word16   Tenr ; 
    Word16   Ccr,Enr ; 
    Word16   Indx ; 
 
    /* Normalize the excitation */ 
    *ShGain = Vec_Norm( Buff, (Word16) (PitchMax+Frame) ) ; 
 
    if ( Olp > (Word16) (PitchMax-3) ) 
        Olp = (Word16) (PitchMax-3) ; 
 
    Indx = Olp ; 
 
    Acc1 = (Word32) 0 ; 
 
    for ( i = (int)Olp-3 ; i <= (int)Olp+3 ; i ++ ) { 
 
        Acc0 = (Word32) 0 ; 
        for ( j = 0 ; j < 2*SubFrLen ; j ++ ) 
            Acc0 = L_mac( Acc0, Buff[PitchMax+Frame-2*SubFrLen+j], 
                                    Buff[PitchMax+Frame-2*SubFrLen-i+j] ) ; 
 
        if ( Acc0 > Acc1 ) { 
            Acc1 = Acc0 ; 
            Indx = (Word16) i ; 
        } 
    } 
 
    /* Compute target energy */ 
    Acc0 = (Word32) 0 ; 
    for ( j = 0 ; j < 2*SubFrLen ; j ++ ) 
        Acc0 = L_mac( Acc0, Buff[PitchMax+Frame-2*SubFrLen+j], 
                                    Buff[PitchMax+Frame-2*SubFrLen+j] ) ; 
    Tenr = round( Acc0 ) ; 
    *Gain = Tenr; 
 
    /* Compute best energy */ 
    Acc0 = (Word32) 0 ; 
    for ( j = 0 ; j < 2*SubFrLen ; j ++ ) 
        Acc0 = L_mac( Acc0, Buff[PitchMax+Frame-2*SubFrLen-(int)Indx+j], 
                            Buff[PitchMax+Frame-2*SubFrLen-(int)Indx+j] ) ; 
 
    Ccr = round( Acc1 ) ; 
 
    if ( Ccr <= (Word16) 0 ) 
        return (Word16) 0 ; 
 
    Enr = round( Acc0 ) ; 
 
    Acc0 = L_mult( Enr, Tenr ) ; 
    Acc0 = L_shr( Acc0, (Word16) 3 ) ; 
 
    Acc0 = L_msu( Acc0, Ccr, Ccr ) ; 
 
    if ( Acc0 < (Word32) 0 ) 
        return Indx ; 
    else 
        return (Word16) 0 ; 
} 
 
/* 
** 
** Function:        Regen() 
** 
** Description:     Performs residual interpolation depending of the frame 
**                  classification. 
**                  If the frame is previously declared unvoiced, the excitation 
**                  is regenerated using a random number generator. Otherwise 
**                  a periodic excitation is generated with the period 
**                  previously found. 
** 
** Links to text:   Section 3.10.2 
** 
** Arguments: 
** 
**  Word16 *DataBuff  current subframe decoded excitation 
**  Word16 *Buff     past decoded excitation 
**  Word16 Lag       Decoded pitch lag from previous frame 
**  Word16 Gain      Interpolated gain from previous frames 
**  Word16 Ecount    Number of erased frames 
**  Word16 *Sd       Random number used in unvoiced cases 
** 
** Outputs: 
** 
**  Word16 *DataBuff current subframe decoded excitation 
**  Word16 *Buff     updated past excitation 
** 
** Return value:    None 
** 
*/ 
void     Regen( Word16 *DataBuff, Word16 *Buff, Word16 Lag, Word16 Gain, 
Word16 Ecount, Word16 *Sd ) 
{ 
    int   i  ; 
 
    /* Test for clearing */ 
    if ( Ecount >= (Word16) ErrMaxNum ) { 
        for ( i = 0 ; i < Frame ; i ++ ) 
            DataBuff[i] = (Word16) 0 ; 
        for ( i = 0 ; i < Frame+PitchMax ; i ++ ) 
            Buff[i] = (Word16) 0 ; 
    } 
    else { 
        /* Interpolate accordingly to the voicing estimation */ 
        if ( Lag != (Word16) 0 ) { 
            /* Voiced case */ 
            for ( i = 0 ; i < Frame ; i ++ ) 
                Buff[PitchMax+i] = Buff[PitchMax-(int)Lag+i] ; 
            for ( i = 0 ; i < Frame ; i ++ ) 
                DataBuff[i] = Buff[PitchMax+i] = mult( Buff[PitchMax+i], 
                            (Word16) 0x6000 ) ; 
        } 
        else { 
            /* Unvoiced case */ 
            for ( i = 0 ; i < Frame ; i ++ ) 
                DataBuff[i] = mult( Gain, Rand_lbc( Sd ) ) ; 
            /* Clear buffer to reset memory */ 
            for ( i = 0 ; i < Frame+PitchMax ; i ++ ) 
                Buff[i] = (Word16) 0 ; 
        } 
    } 
 
    return; 
} 
 
/* 
** 
** Function:        Comp_Lpf() 
** 
** Description:     Computes pitch postfilter parameters. 
**                  The pitch postfilter lag is first derived (Find_B 
**                  and Find_F). Then, the one that gives the largest 
**                  contribution is used to calculate the gains (Get_Ind). 
** 
** 
** Links to text:   Section 3.6 
** 
** Arguments: 
** 
**  Word16 *Buff    decoded excitation 
**  Word16 Olp      Decoded pitch lag 
**  Word16 Sfc      Subframe index 
** 
** Outputs: 
** 
** 
** Return value: 
** 
**  PFDEF       Pitch postfilter parameters: PF.Gain    Pitch Postfilter gain 
**                                           PF.ScGn    Pitch Postfilter scaling gain 
**                                           PF.Indx    Pitch postfilter lag 
*/ 
PFDEF Comp_Lpf( Word16 *Buff, Word16 Olp, Word16 Sfc ) 
{ 
    int   i,j   ; 
 
    PFDEF Pf    ; 
    Word32   Lcr[5] ; 
    Word16   Scr[5] ; 
    Word16   Bindx, Findx ; 
    Word16   Exp ; 
 
    Word32   Acc0,Acc1 ; 
 
    /* Initialize */ 
    Pf.Indx = (Word16) 0 ; 
    Pf.Gain = (Word16) 0 ; 
    Pf.ScGn = (Word16) 0x7fff ; 
 
    /* Find both indices */ 
    Bindx = Find_B( Buff, Olp, Sfc ) ; 
    Findx = Find_F( Buff, Olp, Sfc ) ; 
 
    /* Combine the results */ 
    if ( (Bindx == (Word16) 0) && (Findx == (Word16) 0) ) 
        return Pf ; 
 
    /* Compute target energy */ 
    Acc0 = (Word32) 0 ; 
    for ( j = 0 ; j < SubFrLen ; j ++ ) 
        Acc0 = L_mac( Acc0, Buff[PitchMax+(int)Sfc*SubFrLen+j], 
                                    Buff[PitchMax+(int)Sfc*SubFrLen+j] ) ; 
    Lcr[0] = Acc0 ; 
 
    if ( Bindx != (Word16) 0 ) { 
        Acc0 = (Word32) 0 ; 
        Acc1 = (Word32) 0 ; 
        for ( j = 0 ; j < SubFrLen ; j ++ ) { 
            Acc0 = L_mac( Acc0, Buff[PitchMax+(int)Sfc*SubFrLen+j], 
                        Buff[PitchMax+(int)Sfc*SubFrLen+(int)Bindx+j] ) ; 
            Acc1 = L_mac( Acc1, Buff[PitchMax+(int)Sfc*SubFrLen+(int)Bindx+j], 
                        Buff[PitchMax+(int)Sfc*SubFrLen+(int)Bindx+j] ) ; 
        } 
        Lcr[1] = Acc0 ; 
        Lcr[2] = Acc1 ; 
    } 
    else { 
        Lcr[1] = (Word32) 0 ; 
        Lcr[2] = (Word32) 0 ; 
    } 
 
    if ( Findx != (Word16) 0 ) { 
        Acc0 = (Word32) 0 ; 
        Acc1 = (Word32) 0 ; 
        for ( j = 0 ; j < SubFrLen ; j ++ ) { 
            Acc0 = L_mac( Acc0, Buff[PitchMax+(int)Sfc*SubFrLen+j], 
                        Buff[PitchMax+(int)Sfc*SubFrLen+(int)Findx+j] ) ; 
            Acc1 = L_mac( Acc1, Buff[PitchMax+(int)Sfc*SubFrLen+(int)Findx+j], 
                        Buff[PitchMax+(int)Sfc*SubFrLen+(int)Findx+j] ) ; 
        } 
        Lcr[3] = Acc0 ; 
        Lcr[4] = Acc1 ; 
    } 
    else { 
        Lcr[3] = (Word32) 0 ; 
        Lcr[4] = (Word32) 0 ; 
    } 
 
    /* Normalize and convert to shorts */ 
    Acc1 = 0L ; 
    for ( i = 0 ; i < 5 ; i ++ ) { 
        Acc0 = Lcr[i] ; 
        if ( Acc0 > Acc1 ) 
            Acc1 = Acc0 ; 
    } 
 
    Exp = norm_l( Acc1 ) ; 
    for ( i = 0 ; i < 5 ; i ++ ) { 
        Acc0 = L_shl( Lcr[i], Exp ) ; 
        Scr[i] = extract_h( Acc0 ) ; 
    } 
 
    /* Select the best pair */ 
    if ( (Bindx != (Word16) 0) && ( Findx == (Word16) 0) ) 
        Pf = Get_Ind( Bindx, Scr[0], Scr[1], Scr[2] ) ; 
 
    if ( (Bindx == (Word16) 0) && ( Findx != (Word16) 0) ) 
        Pf = Get_Ind( Findx, Scr[0], Scr[3], Scr[4] ) ; 
 
    if ( (Bindx != (Word16) 0) && ( Findx != (Word16) 0) ) { 
        Exp = mult_r( Scr[1], Scr[1] ) ; 
        Acc0 = L_mult( Exp, Scr[4] ) ; 
        Exp = mult_r( Scr[3], Scr[3] ) ; 
        Acc1 = L_mult( Exp, Scr[2] ) ; 
        if ( Acc0 > Acc1 ) 
            Pf = Get_Ind( Bindx, Scr[0], Scr[1], Scr[2] ) ; 
        else 
            Pf = Get_Ind( Findx, Scr[0], Scr[3], Scr[4] ) ; 
    } 
 
    return Pf ; 
} 
 
/* 
** 
** Function:        Find_B() 
** 
** Description:     Computes best pitch postfilter backward lag by 
**                  backward cross correlation maximization around the 
**                  decoded pitch lag 
**                  of the subframe 0 (for subframes 0 & 1) 
**                  of the subframe 2 (for subframes 2 & 3) 
** 
** Links to text:   Section 3.6 
** 
** Arguments: 
** 
**  Word16 *Buff    decoded excitation 
**  Word16 Olp      Decoded pitch lag 
**  Word16 Sfc      Subframe index 
** 
** Outputs:     None 
** 
** Return value: 
** 
**  Word16   Pitch postfilter backward lag 
*/ 
Word16   Find_B( Word16 *Buff, Word16 Olp, Word16 Sfc ) 
{ 
    int   i,j   ; 
 
    Word16   Indx = 0 ; 
 
    Word32   Acc0,Acc1 ; 
 
    if ( Olp > (Word16) (PitchMax-3) ) 
        Olp = (Word16) (PitchMax-3) ; 
 
    Acc1 = (Word32) 0 ; 
 
    for ( i = (int)Olp-3 ; i <= (int)Olp+3 ; i ++ ) { 
 
        Acc0 = (Word32) 0 ; 
        for ( j = 0 ; j < SubFrLen ; j ++ ) 
            Acc0 = L_mac( Acc0, Buff[PitchMax+(int)Sfc*SubFrLen+j], 
                                    Buff[PitchMax+(int)Sfc*SubFrLen-i+j] ) ; 
        if ( Acc0 > Acc1 ) { 
            Acc1 = Acc0 ; 
            Indx = -(Word16) i ; 
        } 
    } 
    return Indx ; 
} 
 
/* 
** 
** Function:        Find_F() 
** 
** Description:     Computes best pitch postfilter forward lag by 
**                  forward cross correlation maximization around the 
**                  decoded pitch lag 
**                  of the subframe 0 (for subframes 0 & 1) 
**                  of the subframe 2 (for subframes 2 & 3) 
** 
** Links to text:   Section 3.6 
** 
** Arguments: 
** 
**  Word16 *Buff    decoded excitation 
**  Word16 Olp      Decoded pitch lag 
**  Word16 Sfc      Subframe index 
** 
** Outputs:     None 
** 
** Return value: 
** 
**  Word16    Pitch postfilter forward lag 
*/ 
Word16   Find_F( Word16 *Buff, Word16 Olp, Word16 Sfc ) 
{ 
    int   i,j   ; 
 
    Word16   Indx = 0 ; 
 
    Word32   Acc0,Acc1 ; 
 
    if ( Olp > (Word16) (PitchMax-3) ) 
        Olp = (Word16) (PitchMax-3) ; 
 
    Acc1 = (Word32) 0 ; 
 
    for ( i = Olp-3 ; i <= Olp+3 ; i ++ ) { 
 
        Acc0 = (Word32) 0 ; 
        if ( ((int)Sfc*SubFrLen+SubFrLen+i) <= Frame ) { 
            for ( j = 0 ; j < SubFrLen ; j ++ ) 
                Acc0 = L_mac( Acc0, Buff[PitchMax+(int)Sfc*SubFrLen+j], 
                            Buff[PitchMax+(int)Sfc*SubFrLen+i+j] ) ; 
        } 
 
 
        if ( Acc0 > Acc1 ) { 
            Acc1 = Acc0 ; 
            Indx = (Word16) i ; 
        } 
    } 
 
    return Indx ; 
} 
 
/* 
** 
** Function:        Get_Ind() 
** 
** Description:     Computes gains of the pitch postfilter. 
**                  The gains are calculated using the cross correlation 
**                  (forward or backward, the one with the greatest contribution) 
**                  and the energy of the signal. Also, a test is performed on 
**                  the prediction gain to see whether the pitch postfilter 
**                  should be used or not. 
** 
** 
** 
** Links to text:   Section 3.6 
** 
** Arguments: 
** 
**  Word16 Ind      Pitch postfilter lag 
**  Word16 Ten      energy of the current subframe excitation vector 
**  Word16 Ccr      Crosscorrelation of the excitation 
**  Word16 Enr      Energy of the (backward or forward) "delayed" excitation 
** 
** Outputs:     None 
** 
** Return value: 
** 
**  PFDEF 
**         Word16   Indx    Pitch postfilter lag 
**         Word16   Gain    Pitch postfilter gain 
**         Word16   ScGn    Pitch postfilter scaling gain 
** 
*/ 
PFDEF Get_Ind( Word16 Ind, Word16 Ten, Word16 Ccr, Word16 Enr ) 
{ 
    Word32   Acc0,Acc1 ; 
    Word16   Exp   ; 
 
    PFDEF Pf ; 
 
 
    Pf.Indx = Ind ; 
 
    /* Check valid gain */ 
    Acc0 = L_mult( Ten, Enr ) ; 
    Acc0 = L_shr( Acc0, (Word16) 2 ) ; 
    Acc1 = L_mult( Ccr, Ccr ) ; 
 
    if ( Acc1 > Acc0 ) { 
 
        if ( Ccr >= Enr ) 
            Pf.Gain = LpfConstTable[(int)WrkRate] ; 
        else { 
            Pf.Gain = div_s( Ccr, Enr ) ; 
            Pf.Gain = mult( Pf.Gain, LpfConstTable[(int)WrkRate] ) ; 
        } 
        /* Compute scaling gain */ 
        Acc0 = L_deposit_h( Ten ) ; 
        Acc0 = L_shr( Acc0, (Word16) 1 ) ; 
        Acc0 = L_mac( Acc0, Ccr, Pf.Gain ) ; 
        Exp  = mult( Pf.Gain, Pf.Gain ) ; 
        Acc1 = L_mult( Enr, Exp ) ; 
        Acc1 = L_shr( Acc1, (Word16) 1 ) ; 
        Acc0 = L_add( Acc0, Acc1 ) ; 
        Exp = round( Acc0 ) ; 
 
        Acc1 = L_deposit_h( Ten ) ; 
        Acc0 = L_deposit_h( Exp ) ; 
        Acc1 = L_shr( Acc1, (Word16) 1 ) ; 
 
        if ( Acc1 >= Acc0 ) 
            Exp = (Word16) 0x7fff ; 
        else 
            Exp = div_l( Acc1, Exp ) ; 
 
        Acc0 = L_deposit_h( Exp ) ; 
        Pf.ScGn = Sqrt_lbc( Acc0 ) ; 
    } 
    else { 
        Pf.Gain = (Word16) 0 ; 
        Pf.ScGn = (Word16) 0x7fff ; 
    } 
 
    Pf.Gain = mult( Pf.Gain, Pf.ScGn ) ; 
 
    return Pf ; 
} 
 
/* 
** 
** Function:        Filt_Lpf() 
** 
** Description:     Applies the pitch postfilter for each subframe. 
** 
** Links to text:   Section 3.6 
** 
** Arguments: 
** 
**  Word16 *Tv      Pitch postfiltered excitation 
**  Word16 *Buff    decoded excitation 
**  PFDEF Pf        Pitch postfilter parameters 
**  Word16 Sfc      Subframe index 
** 
** Outputs: 
** 
**  Word16 *Tv      Pitch postfiltered excitation 
** 
** Return value: None 
** 
*/ 
void  Filt_Lpf( Word16 *Tv, Word16 *Buff, PFDEF Pf, Word16 Sfc ) 
{ 
    int   i  ; 
 
    Word32   Acc0 ; 
 
    for ( i = 0 ; i < SubFrLen ; i ++ ) { 
        Acc0 = L_mult( Buff[PitchMax+(int)Sfc*SubFrLen+i], Pf.ScGn ) ; 
        Acc0 = L_mac( Acc0, Buff[PitchMax+(int)Sfc*SubFrLen+(int)Pf.Indx+i], 
                                                                Pf.Gain ) ; 
        Tv[(int)Sfc*SubFrLen+i] = round( Acc0 ) ; 
    } 
 
    return; 
} 
 
/* 
** 
** Function:        ACELP_LBC_code() 
** 
** Description:     Find Algebraic codebook for low bit rate LBC encoder 
** 
** Links to text:   Section 2.16 
** 
** Arguments: 
** 
**   Word16 X[]              Target vector.     (in Q0) 
**   Word16 h[]              Impulse response.  (in Q12) 
**   Word16 T0               Pitch period. 
**   Word16 code[]           Innovative vector.        (in Q12) 
**   Word16 gain             Innovative vector gain.   (in Q0) 
**   Word16 sign             Signs of the 4 pulses. 
**   Word16 shift            Shift of the innovative vector 
**   Word16 gain_T0          Gain for pitch synchronous fiter 
** 
** Inputs : 
** 
**   Word16 X[]              Target vector.     (in Q0) 
**   Word16 h[]              Impulse response.  (in Q12) 
**   Word16 T0               Pitch period. 
**   Word16 gain_T0          Gain for pitch synchronous fiter 
** 
** Outputs: 
** 
**   Word16 code[]           Innovative vector.        (in Q12) 
**   Word16 gain             Innovative vector gain.   (in Q0) 
**   Word16 sign             Signs of the 4 pulses. 
**   Word16 shift            Shift of the innovative vector. 
** 
** Return value: 
** 
**   Word16 index            Innovative codebook index 
** 
*/ 
Word16  ACELP_LBC_code(Word16 X[], Word16 h[], Word16 T0, Word16 code[], 
        Word16 *ind_gain, Word16 *shift, Word16 *sign, Word16 gain_T0) 
{ 
    Word16 i, index, gain_q; 
    Word16 Dn[SubFrLen2], tmp_code[SubFrLen2]; 
    Word16 rr[DIM_RR]; 
 
 /* 
  * Include fixed-gain pitch contribution into impulse resp. h[] 
  * Find correlations of h[] needed for the codebook search. 
 */ 
    for (i = 0; i < SubFrLen; i++)    /* Q13 -->  Q12*/ 
        h[i] = shr(h[i], 1); 
 
    if (T0 < SubFrLen-2) { 
        for (i = T0; i < SubFrLen; i++)    /* h[i] += gain_T0*h[i-T0] */ 
        h[i] = add(h[i], mult(h[i-T0], gain_T0)); 
    } 
 
    Cor_h(h, rr); 
 
 /* 
  * Compute correlation of target vector with impulse response. 
  */ 
 
    Cor_h_X(h, X, Dn); 
 
 /* 
  * Find innovative codebook. 
  * rr input matrix autocorrelation 
  *    output filtered codeword 
  */ 
 
    index = D4i64_LBC(Dn, rr, h, tmp_code, rr, shift, sign); 
 
 /* 
  * Compute innovation vector gain. 
  * Include fixed-gain pitch contribution into code[]. 
  */ 
 
    *ind_gain = G_code(X, rr, &gain_q); 
 
    for (i = 0; i < SubFrLen; i++)   { 
        code[i] = i_mult(tmp_code[i], gain_q); 
    } 
 
    if(T0 < SubFrLen-2) 
        for (i = T0; i < SubFrLen; i++)    /* code[i] += gain_T0*code[i-T0] */ 
            code[i] = add(code[i], mult(code[i-T0], gain_T0)); 
 
 
    return index; 
} 
 
/* 
** 
** Function:        Cor_h() 
** 
** Description:     Compute correlations of h[] needed for the codebook search. 
** 
** Links to text:   Section 2.16 
** 
** Arguments: 
** 
**  Word16 h[]              Impulse response. 
**  Word16 rr[]             Correlations. 
** 
**  Outputs: 
** 
**  Word16 rr[]             Correlations. 
** 
**  Return value :          None 
*/ 
void Cor_h(Word16 *H, Word16 *rr) 
{ 
    Word16 *rri0i0, *rri1i1, *rri2i2, *rri3i3; 
    Word16 *rri0i1, *rri0i2, *rri0i3; 
    Word16 *rri1i2, *rri1i3, *rri2i3; 
 
    Word16 *p0, *p1, *p2, *p3; 
 
    Word16 *ptr_hd, *ptr_hf, *ptr_h1, *ptr_h2; 
    Word32 cor; 
    Word16 i, k, ldec, l_fin_sup, l_fin_inf; 
    Word16 h[SubFrLen2]; 
 
    /* Scaling for maximum precision */ 
 
    cor = 0; 
    for(i=0; i 32000 ) { 
        for(i=0; i max) max = s; 
    } 
 
    /* 
     * Find the number of right shifts to do on y32[] 
     * so that maximum is on 13 bits 
     */ 
 
    j = norm_l(max); 
    if( sub(j,16) > 0) j = 16; 
 
    j = sub(18, j); 
 
    for(i=0; i 17 bits; 4 pulses in a frame of 60 samples 
** 
**                     The code length is 60, containing 4 nonzero pulses 
**                     i0, i1, i2, i3. Each pulse can have 8 possible 
**                     positions (positive or negative): 
** 
**                     i0 (+-1) : 0, 8,  16, 24, 32, 40, 48, 56 
**                     i1 (+-1) : 2, 10, 18, 26, 34, 42, 50, 58 
**                     i2 (+-1) : 4, 12, 20, 28, 36, 44, 52, (60) 
**                     i3 (+-1) : 6, 14, 22, 30, 38, 46, 54, (62) 
** 
**                     All the pulse can be shifted by one. 
**                     The last position of the last 2 pulses falls outside the 
**                     frame and signifies that the pulse is not present. 
**                     The threshold controls if a section of the innovative 
**                     codebook should be searched or not. 
** 
**  Links to the text: Section 2.16 
** 
**  Input arguments: 
** 
**      Word16 Dn[]       Correlation between target vector and impulse response h[] 
**      Word16 rr[]       Correlations of impulse response h[] 
**      Word16 h[]        Impulse response of filters 
** 
**  Output arguments: 
** 
**      Word16 cod[]      Selected algebraic codeword 
**      Word16 y[]        Filtered codeword 
**      Word16 code_shift Shift of the codeword 
**      Word16 sign       Signs of the 4 pulses. 
** 
**  Return value: 
** 
**      Word16   Index of selected codevector 
** 
*/ 
Word16 D4i64_LBC(Word16 Dn[], Word16 rr[], Word16 h[], Word16 cod[], 
                 Word16 y[], Word16 *code_shift, Word16 *sign) 
{ 
    Word16  i0, i1, i2, i3, ip0, ip1, ip2, ip3; 
    Word16  i, j, time; 
    Word16  shif, shift; 
    Word16  ps0, ps1, ps2, ps3, alp, alp0; 
    Word32  alp1, alp2, alp3, L32; 
    Word16  ps0a, ps1a, ps2a; 
    Word16  ps3c, psc, alpha; 
    Word16  means, max0, max1, max2, thres; 
 
    Word16  *rri0i0, *rri1i1, *rri2i2, *rri3i3; 
    Word16  *rri0i1, *rri0i2, *rri0i3; 
    Word16  *rri1i2, *rri1i3, *rri2i3; 
 
    Word16  *ptr_ri0i0, *ptr_ri1i1, *ptr_ri2i2, *ptr_ri3i3; 
    Word16  *ptr_ri0i1, *ptr_ri0i2, *ptr_ri0i3; 
    Word16  *ptr_ri1i2, *ptr_ri1i3, *ptr_ri2i3; 
 
    Word16  *ptr1_ri0i1, *ptr1_ri0i2, *ptr1_ri0i3; 
    Word16  *ptr1_ri1i2, *ptr1_ri1i3, *ptr1_ri2i3; 
 
    Word16  p_sign[SubFrLen2/2]; 
 
    /* Init pointers */ 
 
    rri0i0 = rr; 
    rri1i1 = rri0i0 + NB_POS; 
    rri2i2 = rri1i1 + NB_POS; 
    rri3i3 = rri2i2 + NB_POS; 
 
    rri0i1 = rri3i3 + NB_POS; 
    rri0i2 = rri0i1 + MSIZE; 
    rri0i3 = rri0i2 + MSIZE; 
    rri1i2 = rri0i3 + MSIZE; 
    rri1i3 = rri1i2 + MSIZE; 
    rri2i3 = rri1i3 + MSIZE; 
 
 /* 
  * Extend the backward filtered target vector by zeros 
  */ 
 
    for (i = SubFrLen; i < SubFrLen2; i++) Dn[i] = 0; 
 
 /* 
  * Chose the sign of the impulse. 
  */ 
 
    for (i=0; i= 0) { 
            p_sign[i/2] = 1; 
        } 
        else { 
            p_sign[i/2] = -1; 
            Dn[i] = -Dn[i]; 
            Dn[i+1] = -Dn[i+1]; 
        } 
    } 
    p_sign[30] = p_sign[31] = 1; 
 
 /* 
  *   Compute the search threshold after three pulses 
  */ 
 
    /* odd positions */ 
    /* Find maximum of Dn[i0]+Dn[i1]+Dn[i2] */ 
 
    max0 = Dn[0]; 
    max1 = Dn[2]; 
    max2 = Dn[4]; 
    for (i = 8; i < SubFrLen; i+=STEP) { 
        if (Dn[i]   > max0) max0 = Dn[i]; 
        if (Dn[i+2] > max1) max1 = Dn[i+2]; 
        if (Dn[i+4] > max2) max2 = Dn[i+4]; 
    } 
    max0 = add(max0, max1); 
    max0 = add(max0, max2); 
 
    /* Find means of Dn[i0]+Dn[i1]+Dn[i2] */ 
 
    L32 = 0; 
    for (i = 0; i < SubFrLen; i+=STEP) { 
        L32 = L_mac(L32, Dn[i], 1); 
        L32 = L_mac(L32, Dn[i+2], 1); 
        L32 = L_mac(L32, Dn[i+4], 1); 
    } 
    means =extract_l( L_shr(L32, 4)); 
 
    /* thres = means + (max0-means)*threshold; */ 
 
    thres = sub(max0, means); 
    thres = mult(thres, threshold); 
    thres = add(thres, means); 
 
    /* even positions */ 
    /* Find maximum of Dn[i0]+Dn[i1]+Dn[i2] */ 
 
    max0 = Dn[1]; 
    max1 = Dn[3]; 
    max2 = Dn[5]; 
    for (i = 9; i < SubFrLen; i+=STEP) { 
        if (Dn[i]   > max0) max0 = Dn[i]; 
        if (Dn[i+2] > max1) max1 = Dn[i+2]; 
        if (Dn[i+4] > max2) max2 = Dn[i+4]; 
    } 
    max0 = add(max0, max1); 
    max0 = add(max0, max2); 
 
    /* Find means of Dn[i0]+Dn[i1]+Dn[i2] */ 
 
    L32 = 0; 
    for (i = 1; i < SubFrLen; i+=STEP) { 
        L32 = L_mac(L32, Dn[i], 1); 
        L32 = L_mac(L32, Dn[i+2], 1); 
        L32 = L_mac(L32, Dn[i+4], 1); 
    } 
    means =extract_l( L_shr(L32, 4)); 
 
 
    /* max1 = means + (max0-means)*threshold */ 
 
    max1 = sub(max0, means); 
    max1 = mult(max1, threshold); 
    max1 = add(max1, means); 
 
    /* Keep maximum threshold between odd and even position */ 
 
    if(max1 > thres) thres = max1; 
 
 /* 
  * Modification of rrixiy[] to take signs into account. 
  */ 
 
    ptr_ri0i1 = rri0i1; 
    ptr_ri0i2 = rri0i2; 
    ptr_ri0i3 = rri0i3; 
    ptr1_ri0i1 = rri0i1; 
    ptr1_ri0i2 = rri0i2; 
    ptr1_ri0i3 = rri0i3; 
 
    for(i0=0; i0 ps2) { 
                    shift = 1; 
                    ps2   = ps2a; 
                } 
 
                /* Test threshold */ 
 
                if ( ps2 > thres) { 
 
                    /* Init. pointers that depend on 4th loop */ 
                    ptr_ri3i3 = rri3i3; 
 
                    /* 4th pulse loop */ 
                    for (i3 = 6; i3 < SubFrLen2; i3 += STEP) { 
 
                        ps3 = add(ps2, Dn[i3+shift]); 
 
                        /* alp3 = alp2 + (*ptr_ri3i3++) + 
                                         2 x ( (*ptr_ri0i3++) + 
                                               (*ptr_ri1i3++) + 
                                               (*ptr_ri2i3++) ) */ 
 
                        alp3 = L_mac(alp2, *ptr_ri3i3++, 1); 
                        alp3 = L_mac(alp3, *ptr_ri0i3++, 2); 
                        alp3 = L_mac(alp3, *ptr_ri1i3++, 2); 
                        alp3 = L_mac(alp3, *ptr_ri2i3++, 2); 
                        alp  = extract_l(L_shr(alp3, 5)); 
 
                        ps3c = mult(ps3, ps3); 
                        if( L_mult(ps3c, alpha) > L_mult(psc, alp) ) { 
                            psc = ps3c; 
                            alpha = alp; 
                            ip0 = i0; 
                            ip1 = i1; 
                            ip2 = i2; 
                            ip3 = i3; 
                            shif = shift; 
                        } 
                    }  /*  end of for i3 = */ 
 
                    time --; 
                    if(time <= 0 ) goto end_search;   /* Max time finish */ 
                    ptr_ri0i3 -= NB_POS; 
                    ptr_ri1i3 -= NB_POS; 
 
                }  /* end of if >thres */ 
 
                else { 
                    ptr_ri2i3 += NB_POS; 
                } 
 
            } /* end of for i2 = */ 
 
            ptr_ri0i2 -= NB_POS; 
            ptr_ri1i3 += NB_POS; 
 
        } /* end of for i1 = */ 
 
        ptr_ri0i2 += NB_POS; 
        ptr_ri0i3 += NB_POS; 
 
    } /* end of for i0 = */ 
 
end_search: 
 
    extra = time; 
 
    /* Set the sign of impulses */ 
 
    i0 = p_sign[shr(ip0, 1)]; 
    i1 = p_sign[shr(ip1, 1)]; 
    i2 = p_sign[shr(ip2, 1)]; 
    i3 = p_sign[shr(ip3, 1)]; 
 
    /* Find the codeword corresponding to the selected positions */ 
 
    for(i=0; i 0) { 
        ip0 = add(ip0 ,1); 
        ip1 = add(ip1 ,1); 
        ip2 = add(ip2 ,1); 
        ip3 = add(ip3 ,1); 
    } 
 
    cod[ip0] =  i0; 
    cod[ip1] =  i1; 
    if(ip2 0) 
        for(i=ip0, j=0; i 0) 
        for(i=ip1, j=0; i 0) 
            for(i=ip2, j=0; i 0) 
            for(i=ip3, j=0; i 0) *sign = add(*sign, 1); 
    if(i1 > 0) *sign = add(*sign, 2); 
    if(i2 > 0) *sign = add(*sign, 4); 
    if(i3 > 0) *sign = add(*sign, 8); 
 
    i = shr(ip0, 3); 
    i = add(i, shl(shr(ip1, 3), 3)); 
    i = add(i, shl(shr(ip2, 3), 6)); 
    i = add(i, shl(shr(ip3, 3), 9)); 
 
    return i; 
} 
 
/* 
** 
**  Function:  G_code() 
** 
**  Description: Compute the gain of innovative code. 
** 
** 
**  Links to the text: Section 2.16 
** 
** Input arguments: 
** 
**      Word16 X[]        Code target.  (in Q0) 
**      Word16 Y[]        Filtered innovation code. (in Q12) 
** 
** Output: 
** 
**      Word16 *gain_q    Gain of innovation code.  (in Q0) 
** 
**  Return value: 
** 
**      Word16  index of innovation code gain 
** 
*/ 
Word16 G_code(Word16 X[], Word16 Y[], Word16 *gain_q) 
{ 
    Word16 i; 
    Word16 xy, yy, exp_xy, exp_yy, gain, gain_nq; 
    Word32 L_xy, L_yy; 
    Word16 dist, dist_min; 
 
 
    /* Scale down Y[] by 8 to avoid overflow */ 
    for(i=0; i */ 
    L_xy = 0L; 
    for(i=0; i */ 
    L_yy = 0L; 
    for(i=0; i