www.pudn.com > p_voice.rar > ACELP_CP.C


/* 
   ITU-T G.729 Annex C+ - Reference C code for floating point 
                         implementation of G.729 Annex C+ 
                         (integration of Annexes B, D and E) 
                         Version 2.1 of October 1999 
*/ 
 
/* 
 File : ACELP_CP.C 
*/ 
 
/*****************************************************************************/ 
/* fixed codebook encoding routines  for 11.8, 8 and 6.4 kbit/s              */ 
/*****************************************************************************/ 
#include  
 
#include "typedef.h" 
#include "ld8k.h" 
#include "ld8cp.h" 
#include "tabld8cp.h" 
 
/* prototypes of local functions */ 
static void cor_h_cp( 
    FLOAT *H,         /* (i)     :Impulse response of filters */ 
    FLOAT *rr,        /* (o)     :Correlations of H[]         */ 
    int   rate 
); 
static int d4i40_17(   /* (o)    : Index of pulses positions.               */ 
    FLOAT Dn[],          /* (i)    : Correlations between h[] and Xn[].       */ 
    FLOAT rr[],          /* (i)    : Correlations of impulse response h[].    */ 
    FLOAT h[],           /* (i)    : Impulse response of filters.             */ 
    FLOAT cod[],         /* (o)    : Selected algebraic codeword.             */ 
    FLOAT y[],           /* (o)    : Filtered algebraic codeword.             */ 
    int   *sign,         /* (o)    : Signs of 4 pulses.                       */ 
    int   i_subfr        /* (i)    : subframe flag                            */ 
); 
static void cor_h_vec( 
    FLOAT h[],           /* (i) scaled impulse response */ 
    FLOAT vec[],         /* (i) vector to correlate with h[] */ 
    int track,         /* (i) track to use */ 
    FLOAT sign[],        /* (i) sign vector */ 
    FLOAT rrixix[][NB_POS],  /* (i) correlation of h[x] with h[x] */ 
    FLOAT cor[]          /* (o) result of correlation (NB_POS elements) */ 
); 
 
static void search_ixiy( 
    int track_x,       /* (i) track of pulse 1 */ 
    int track_y,       /* (i) track of pulse 2 */ 
    FLOAT *ps,           /* (i/o) correlation of all fixed pulses */ 
    FLOAT *alp,          /* (i/o) energy of all fixed pulses */ 
    int *ix,           /* (o) position of pulse 1 */ 
    int *iy,           /* (o) position of pulse 2 */ 
    FLOAT dn[],          /* (i) corr. between target and h[] */ 
    FLOAT cor_x[],       /* (i) corr. of pulse 1 with fixed pulses */ 
    FLOAT cor_y[],       /* (i) corr. of pulse 2 with fixed pulses */ 
    FLOAT rrixiy[][MSIZE]  /* (i) corr. of pulse 1 with pulse 2 */ 
); 
 
static void set_sign( 
    FLOAT cn[],       /* (i) : residual after long term prediction    */ 
    FLOAT dn[],       /* (i) : correlation between target and h[]     */ 
    FLOAT sign[],     /* (o) : sign vector (sign of each position)    */ 
    FLOAT inv_sign[], /* (o) : inverse of sign[]                      */ 
    int pos_max[],    /* (o) : pos of max of correlation              */ 
    FLOAT corr[]      /* (o) : correlation of each track              */ 
); 
 
static void cor_h_e( 
    FLOAT sign[],           /* (i) : sign vector                 */ 
    FLOAT inv_sign[],       /* (i) : inverse of sign[]           */ 
    FLOAT h[],              /* (o) : scaled h[]                 */ 
    FLOAT h_inv[],          /* (o) : inverse of scaled h[]      */ 
    FLOAT rrixix[][NB_POS], /* (o) energy of h[].                   */ 
    FLOAT rrixiy[][MSIZE]   /* (o) correlation between 2 pulses.    */ 
); 
 
static void build_code( 
    int codvec[],      /* (i)  : positions of each pulse */ 
    FLOAT sign[],      /* (i)  : sign vector             */ 
    int nb_of_pulse,   /* (i)  : number of pulses        */ 
    FLOAT h[],         /* (i)  : impulse response of weighted synthesis filter */ 
    FLOAT code[],      /* (o)  : algebraic (fixed) codebook excitation         */ 
    FLOAT y[],         /* (o)  : filtered fixed codebook excitation            */ 
    int indx[]         /* (o)  : index of pulses (5 words, 1 per track).       */ 
); 
 
static int pack3(int index1, int index2, int index3); 
 
 
int ACELP_codebook(     /* (o)     :index of pulses positions    */ 
    FLOAT x[],            /* (i)     :Target vector                */ 
    FLOAT h[],            /* (i)     :Impulse response of filters  */ 
    int   t0,             /* (i)     :Pitch lag                    */ 
    FLOAT pitch_sharp,    /* (i)     :Last quantized pitch gain    */ 
    int i_subfr,          /* (i)     :Indicator of 1st subframe,   */ 
    FLOAT code[],         /* (o)     :Innovative codebook          */ 
    FLOAT y[],            /* (o)     :Filtered innovative codebook */ 
    int *sign             /* (o)     :Signs of 4 pulses            */ 
) 
{ 
    int i, index; 
    FLOAT dn[L_SUBFR]; 
    FLOAT rr[DIM_RR]; 
     
    /*----------------------------------------------------------------* 
    * Include fixed-gain pitch contribution into impulse resp. h[]    * 
    * Find correlations of h[] needed for the codebook search.        * 
    *-----------------------------------------------------------------*/ 
     
    if(t0 < L_SUBFR) { 
        for (i = t0; i < L_SUBFR; i++) 
            h[i] += pitch_sharp * h[i-t0]; 
    }        
    cor_h_cp(h, rr, G729); 
     
    /*----------------------------------------------------------------* 
    * Compute correlation of target vector with impulse response.     * 
    *-----------------------------------------------------------------*/ 
     
    cor_h_x(h, x, dn);      /* backward filtered target vector dn */ 
     
                            /*----------------------------------------------------------------* 
                            * Find innovative codebook.                                       * 
    *-----------------------------------------------------------------*/ 
     
    index = d4i40_17(dn, rr, h, code, y, sign, i_subfr); 
     
    /*------------------------------------------------------* 
    * - Add the fixed-gain pitch contribution to code[].    * 
    *-------------------------------------------------------*/ 
     
    if(t0 < L_SUBFR) { 
        for (i = t0; i < L_SUBFR; i++) 
            code[i] += pitch_sharp * code[i-t0]; 
    } 
    return index; 
} 
 
 
int ACELP_codebook64(   /* (o)     :Index of pulses positions    */ 
                     FLOAT x[],            /* (i)     :Target vector                */ 
                     FLOAT h[],            /* (i)     :Impulse response of filters  */ 
                     int   t0,             /* (i)     :Pitch lag                    */ 
                     FLOAT pitch_sharp,    /* (i)     :Last quantized pitch gain    */ 
                     FLOAT code[],         /* (o)     :Innovative codebook          */ 
                     FLOAT y[],            /* (o)     :Filtered innovative codebook */ 
                     int *sign             /* (o)     :Signs of 4 pulses            */ 
                     ) 
{ 
    int i, j; 
 
    int posIndex[NB_PULSES_6K];            /* position index of last constructed vector */ 
    int signIndex[NB_PULSES_6K];           /* sign index of last constructed vector */ 
    /* (1=positive, 0=negative) */ 
     
    FLOAT dn[L_SUBFR]; 
     
    FLOAT Csq_best; 
    FLOAT E_best; 
    FLOAT C; 
    FLOAT Csq; 
    FLOAT E; 
    int m0_bestIndex; 
    int m1_bestIndex; 
    int m0_bestPos; 
    int m1_bestPos; 
    int index; 
    int m0, m1, pulse0, pulse1; 
     
    FLOAT *ptr1, *ptr2, *ptr3; 
    FLOAT C0; 
     
    FLOAT rr[DIM_RR]; 
    int p_sign[L_SUBFR]; 
     
    int   i0, i1, i2, i3; 
    FLOAT *rri0i0, *rri1i1, *rri2i2, *rri3i3, *rri4i4; 
    FLOAT *rri0i1, *rri0i2, *rri0i3, *rri0i4; 
    FLOAT *rri1i2, *rri1i3, *rri1i4; 
    FLOAT *rri2i3, *rri2i4; 
     
    FLOAT *ptr_ri0i1, *ptr_ri0i2, *ptr_ri0i3, *ptr_ri0i4; 
    FLOAT *ptr_ri1i2, *ptr_ri1i3, *ptr_ri1i4; 
    FLOAT *ptr_ri2i3, *ptr_ri2i4; 
     
    /*----------------------------------------------------------------* 
    * Include fixed-gain pitch contribution into impulse resp. h[]    * 
    * Find correlations of h[] needed for the codebook search.        * 
    *-----------------------------------------------------------------*/ 
    if(t0 < L_SUBFR) { 
        for (i = t0; i < L_SUBFR; i++) 
            h[i] += pitch_sharp * h[i-t0]; 
    } 
    cor_h_x(h, x, dn); /* backward filtered target vector dn */ 
 
    cor_h_cp(h, rr, G729D); 
 
    /* approximate sign by using ltpResidual and target */ 
    for ( i = 0; i < L_SUBFR; i++) { 
        if (dn[i] >= 0) { 
            p_sign[i] = 1; 
        } 
        else { 
            p_sign[i] = -1; 
            dn[i] = -dn[i];   /* absolute value vector */ 
        } 
    } 
 
    /* Init pointers */ 
 
    rri0i0 = rr; 
    rri1i1 = rri0i0 + NB_POS; 
    rri2i2 = rri1i1 + NB_POS; 
    rri3i3 = rri2i2 + NB_POS; 
    rri4i4 = rri3i3 + NB_POS; 
 
    rri0i1 = rri4i4 + NB_POS; 
    rri0i2 = rri0i1 + MSIZE; 
    rri0i3 = rri0i2 + MSIZE; 
    rri0i4 = rri0i3 + MSIZE; 
    rri1i2 = rri0i4 + MSIZE; 
    rri1i3 = rri1i2 + MSIZE; 
    rri1i4 = rri1i3 + MSIZE; 
    rri2i3 = rri1i4 + MSIZE; 
    rri2i4 = rri2i3 + MSIZE; 
 
    /*-------------------------------------------------------------------* 
    * Modification of rrixiy to take into account signs.                * 
    *-------------------------------------------------------------------*/ 
    ptr_ri0i1 = rri0i1; 
    ptr_ri0i2 = rri0i2; 
    ptr_ri0i3 = rri0i3; 
    ptr_ri0i4 = rri0i4; 
     
    for(i0=0; i0 i1 m1 -> i0 (sub 0 vs sub 0) */ 
    m1 = 0; 
    ptr1 = rri0i0; 
    ptr3 = rri0i1; 
    for (pulse1=0; pulse1<24; pulse1+=3, m1+=STEP) { 
        m0 = 1; 
        ptr2 = rri1i1; 
        C0 = dn[m1]; 
        for (pulse0=0; pulse0<16; pulse0+=2, m0+=STEP) { 
            C = C0; 
            E = *ptr1; 
            C += dn[m0]; 
            Csq = C*C; 
            E += *ptr2++; 
            E += (F)2.0 * *ptr3++; 
            if ( (Csq*E_best) > (E*Csq_best) ) { 
                E_best = E; 
                Csq_best = Csq; 
                m0_bestIndex=pulse0; 
                m1_bestIndex=pulse1; 
            } 
        } 
        ptr1++; 
    } 
     
    /* m0 -> i1 m1 -> i2 (sub 0 vs sub 1) */ 
    m0 = 1; 
    ptr1 = rri1i1; 
    ptr3 = rri1i2; 
    for (pulse0=0; pulse0 (E*Csq_best) ) { 
                E_best = E; 
                Csq_best = Csq; 
                m0_bestIndex=pulse0; 
                m1_bestIndex=pulse1; 
            } 
        } 
        ptr1++; 
    } 
     
    /* m0 -> i1 m1 -> i4 (sub 0 vs sub 2) */ 
    m0 = 1; 
    ptr1 = rri1i1; 
    ptr3 = rri1i4; 
    for (pulse0=0; pulse0 (E*Csq_best) ) { 
                E_best = E; 
                Csq_best = Csq; 
                m0_bestIndex=pulse0; 
                m1_bestIndex=pulse1; 
            } 
        } 
        ptr1++; 
    } 
     
    /* m0 -> i1 m1 -> i1 (sub 0 vs sub 3) */ 
    m0 = 1; 
    ptr1 = rri1i1; 
    ptr3 = rri0i2; 
    for (pulse0=0; pulse0 (E*Csq_best) ) { 
                E_best = E; 
                Csq_best = Csq; 
                m0_bestIndex=pulse0; 
                m1_bestIndex=pulse1; 
            } 
        } 
        ptr1++; 
    } 
     
    /* m0 -> i3 m1 -> i0 (sub 1 vs sub 0) */ 
    m1 = 0; 
    ptr1 = rri0i0; 
    ptr3 = rri0i3; 
    for (pulse1=0; pulse1<24; pulse1+=3, m1+=STEP) { 
        m0 = 3; 
        ptr2 = rri3i3; 
        C0 = dn[m1]; 
        for (pulse0=1; pulse0<16; pulse0+=2, m0+=STEP) { 
            C = C0; 
            E = *ptr1; 
            C += dn[m0]; 
            Csq = C*C; 
            E += *ptr2++; 
            E += (F)2.0 * *ptr3++; 
            if ( (Csq*E_best) > (E*Csq_best) ) { 
                E_best = E; 
                Csq_best = Csq; 
                m0_bestIndex=pulse0; 
                m1_bestIndex=pulse1; 
            } 
        } 
        ptr1++; 
    } 
 
    /* m0 -> i3 m1 -> i2 (sub 1 vs sub 1) */ 
    m1 = 2; 
    ptr1 = rri2i2; 
    ptr3 = rri2i3; 
    for (pulse1=1; pulse1<24; pulse1+=3, m1+=STEP) { 
        m0 = 3; 
        ptr2 = rri3i3; 
        C0 = dn[m1]; 
        for (pulse0=1; pulse0<16; pulse0+=2, m0+=STEP) { 
            C = C0; 
            E = *ptr1; 
            C += dn[m0]; 
            Csq = C*C; 
            E += *ptr2++; 
            E += (F)2.0 * *ptr3++; 
            if ( (Csq*E_best) > (E*Csq_best) ) { 
                E_best = E; 
                Csq_best = Csq; 
                m0_bestIndex=pulse0; 
                m1_bestIndex=pulse1; 
            } 
        } 
        ptr1++; 
    } 
     
    /* m0 -> i3 m1 -> i4 (sub 1 vs sub 2) rri0i4 contains rri3i4 */ 
    m0 = 3; 
    ptr1 = rri3i3; 
    ptr3 = rri0i4; 
    for (pulse0=1; pulse0 (E*Csq_best) ) { 
                E_best = E; 
                Csq_best = Csq; 
                m0_bestIndex=pulse0; 
                m1_bestIndex=pulse1; 
            } 
        } 
        ptr1++; 
    } 
     
    /* m0 -> i3 m1 -> i1 (sub 1 vs sub 3) */ 
    m1 = 1; 
    ptr1 = rri1i1; 
    ptr3 = rri1i3; 
    for (pulse1=24; pulse1<32; pulse1++, m1+=STEP) { 
        m0 = 3; 
        ptr2 = rri3i3; 
        C0 = dn[m1]; 
        for (pulse0=1; pulse0<16; pulse0+=2, m0+=STEP) { 
            C = C0; 
            E = *ptr1; 
            C += dn[m0]; 
            Csq = C*C; 
            E += *ptr2++; 
            E += (F)2.0 * *ptr3++; 
            if ( (Csq*E_best) > (E*Csq_best) ) { 
                E_best = E; 
                Csq_best = Csq; 
                m0_bestIndex=pulse0; 
                m1_bestIndex=pulse1; 
            } 
        } 
        ptr1++; 
    } 
     
    m0_bestPos = trackTable0[m0_bestIndex]; 
    m1_bestPos = trackTable1[m1_bestIndex]; 
     
    posIndex[0] = grayEncode[m0_bestIndex]; 
    posIndex[1] = grayEncode[m1_bestIndex]; 
 
    signIndex[0] = ( p_sign[m0_bestPos] > 0); 
    signIndex[1] = ( p_sign[m1_bestPos] > 0); 
 
    /* build innovation vector */ 
    for (i = 0; i < L_SUBFR; i++) code[i] = (F)0.0; 
    code[m0_bestPos] = (FLOAT)p_sign[m0_bestPos]; 
    code[m1_bestPos] += (FLOAT)p_sign[m1_bestPos]; 
     
    *sign = signIndex[0] + 2*signIndex[1]; 
    index = posIndex[0] + 16*posIndex[1]; 
     
    /* compute filtered cbInnovation */ 
    for (i = 0; i < L_SUBFR; i++) y[i] = (F)0.0; 
     
    if(signIndex[0] == 1) { 
        for(i=m0_bestPos, j=0; i= (F)0.0) 
        { 
            p_sign[i] = (F)1.0; 
        } 
        else { 
            p_sign[i] = (F)-1.0; 
            dn[i] = -dn[i]; 
        } 
    } 
     
    /*-------------------------------------------------------------------* 
    * - Compute the search threshold after three pulses                 * 
    *-------------------------------------------------------------------*/ 
     
     
    average  = dn[0] + dn[1] + dn[2]; 
    max0 = dn[0]; 
    max1 = dn[1]; 
    max2 = dn[2]; 
    for (i = 5; i < L_SUBFR; i+=STEP) 
    { 
        average += dn[i] + dn[i+1]+ dn[i+2]; 
        if (dn[i]   > max0) max0 = dn[i]; 
        if (dn[i+1] > max1) max1 = dn[i+1]; 
        if (dn[i+2] > max2) max2 = dn[i+2]; 
    } 
    max0 += max1+max2; 
    average  *= (F)0.125;         /* 1/8 */ 
    thres = average + (max0-average)*THRESHFCB; 
     
    /*-------------------------------------------------------------------* 
    * Modification of rrixiy to take into account signs.                * 
    *-------------------------------------------------------------------*/ 
    ptr_ri0i1 = rri0i1; 
    ptr_ri0i2 = rri0i2; 
    ptr_ri0i3 = rri0i3; 
    ptr_ri0i4 = rri0i4; 
     
    for(i0=0; i0 thres) 
                { 
                    ptr_ri3i3 = rri3i3;    /* Init. pointers that depend on 4th loop */ 
                     
                    for (i3 = 3; i3 < L_SUBFR; i3 += STEP) 
                    { 
                        ps3 = ps2 + dn[i3]; 
                        alp3 = alp2 + *ptr_ri3i3++ + (F)2.0*(*ptr_ri1i3++ + *ptr_ri0i3++ + *ptr_ri2i3++); 
                         
                        ps3c = ps3*ps3; 
                        if( (ps3c*alpha) > (psc * alp3) ) 
                        { 
                            psc = ps3c; 
                            alpha = alp3; 
                            ip0 = i0; 
                            ip1 = i1; 
                            ip2 = i2; 
                            ip3 = i3; 
                        } 
                    }  /*  end of for i3 = */ 
                     
                    ptr_ri0i3 -= NB_POS; 
                    ptr_ri1i3 -= NB_POS; 
                     
                    ptr_ri4i4 = rri4i4;    /* Init. pointers that depend on 4th loop */ 
                     
                    for (i3 = 4; i3 < L_SUBFR; i3 += STEP) 
                    { 
                        ps3 = ps2 + dn[i3]; 
                        alp3 = alp2 + *ptr_ri4i4++ + (F)2.0*(*ptr_ri1i4++ + *ptr_ri0i4++ + *ptr_ri2i4++); 
                         
                        ps3c = ps3*ps3; 
                        if( (ps3c*alpha) > (psc * alp3) ) 
                        { 
                            psc = ps3c; 
                            alpha = alp3; 
                            ip0 = i0; 
                            ip1 = i1; 
                            ip2 = i2; 
                            ip3 = i3; 
                        } 
                    }       /*  end of for i3 = */ 
                    ptr_ri0i4 -= NB_POS; 
                    ptr_ri1i4 -= NB_POS; 
                     
                    time --; 
                    if(time <= 0 ) goto end_search;     /* Maximum time finish */ 
                     
                }  /* end of if >thres */ 
                else { 
                    ptr_ri2i3 += NB_POS; 
                    ptr_ri2i4 += NB_POS; 
                } 
                 
            } /* end of for i2 = */ 
             
            ptr_ri0i2 -= NB_POS; 
            ptr_ri1i3 += NB_POS; 
            ptr_ri1i4 += NB_POS; 
             
        } /* end of for i1 = */ 
         
        ptr_ri0i2 += NB_POS; 
        ptr_ri0i3 += NB_POS; 
        ptr_ri0i4 += NB_POS; 
         
    } /* end of for i0 = */ 
     
end_search: 
     
    extra = time; 
     
    /* Find the codeword corresponding to the selected positions */ 
     
    for(i=0; i (F)0.0) { 
        for(i=ip0, j=0; i (F)0.0) { 
        for(i=ip1, j=0; i (F)0.0) { 
        for(i=ip2, j=0; i (F)0.0) { 
        for(i=ip3, j=0; i (F)0.0) i+=1; 
    if(p_sign[ip1] > (F)0.0) i+=2; 
    if(p_sign[ip2] > (F)0.0) i+=4; 
    if(p_sign[ip3] > (F)0.0) i+=8; 
    *signs = i; 
     
    ip0 = ip0 / 5; 
    ip1 = ip1 / 5; 
    ip2 = ip2 / 5; 
    j   = (ip3 % 5) - 3; 
    ip3 = ( (ip3 / 5) << 1 ) + j; 
     
    i = (ip0) + (ip1<<3) + (ip2<<6) + (ip3<<9); 
     
    return i; 
} 
/*-------------------------------------------------------------------* 
* Function  ACELP_12i40_44bits()                                    * 
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                    * 
* Algebraic codebook; 44 bits: 12 pulses in a frame of 40 samples.  * 
*-------------------------------------------------------------------* 
* The code length is 40, containing 12 nonzero pulses: i0...i11.    * 
* 12 pulses can have two (2) possible amplitudes: +1 or -1.         * 
* 10 pulses can have eight (8) possible positions:                  * 
* i2,i7  :  0, 5, 10, 15, 20, 25, 30, 35.  --> t0                   * 
* i3,i8  :  1, 6, 11, 16, 21, 26, 31, 36.  --> t1                   * 
* i4,i9  :  2, 7, 12, 17, 22, 27, 32, 37.  --> t2                   * 
* i5,i10 :  3, 8, 13, 18, 23, 28, 33, 38.  --> t3                   * 
* i6,i11 :  4, 9, 14, 19, 24, 29, 34, 39.  --> t4                   * 
*                                                                   * 
* The 2 other pulses can be on the following track:                 * 
*   t0-t1,t1-t2,t2-t3,t3-t4,t4-t0.                                  * 
*-------------------------------------------------------------------*/ 
void ACELP_12i40_44bits( 
    FLOAT x[],    /* (i) : target vector                                 */ 
    FLOAT cn[],   /* (i) : residual after long term prediction           */ 
    FLOAT h1[],   /* (i) : impulse response of weighted synthesis filter */ 
    FLOAT code[], /* (o) : algebraic (fixed) codebook excitation         */ 
    FLOAT y[],    /* (o) : filtered fixed codebook excitation            */ 
    int indx[]    /* (o) : index 5 words: 13,10,7,7,7 = 44 bits          */ 
) 
{ 
 
    int i, j, k, ix, iy, itrk[3], track, pos, index; 
    int idx[NB_TRACK]; 
    FLOAT psk, ps, alpk, alp; 
    FLOAT s, corr[NB_TRACK]; 
    FLOAT *p0, *p1, *h_inv, *h; 
     
    FLOAT dn[L_SUBFR], sign[L_SUBFR], vec[L_SUBFR]; 
    int ip[12], codvec[12], pos_max[NB_TRACK]; 
    FLOAT cor_x[NB_POS], cor_y[NB_POS]; 
    FLOAT h_buf[4*L_SUBFR]; 
    FLOAT rrixix[NB_TRACK][NB_POS], rrixiy[NB_TRACK][MSIZE]; 
    FLOAT L_tmp; 
     
    h = h_buf; 
    h_inv = h_buf + (2*L_SUBFR); 
    for (i=0; i (FLOAT)0.) { 
                s = corr[i]; 
                track = i; 
            } 
        } 
        corr[track] = (FLOAT)-1.; 
        itrk[k] = track; 
    } 
     
    /*-------------------------------------------------------------------* 
    * Deep first search: 3 iterations of 320 tests = 960 tests.         * 
    *                                                                   * 
    * Stages of deep first search:                                      * 
    *   stage 1 : fix i0  and i1  --> 2 positions is fixed previously.  * 
    *   stage 2 : fix i2  and i3  --> try 8x8 = 64 positions.           * 
    *   stage 3 : fix i4  and i5  --> try 8x8 = 64 positions.           * 
    *   stage 4 : fix i6  and i7  --> try 8x8 = 64 positions.           * 
    *   stage 5 : fix i8  and i9  --> try 8x8 = 64 positions.           * 
    *   stage 6 : fix i10 and i11 --> try 8x8 = 64 positions.           * 
    *-------------------------------------------------------------------*/ 
     
    /* stage 0: fix pulse i0 and i1 according to max of correlation */ 
    psk = (FLOAT)-1.; 
    alpk = (FLOAT)1.; 
    for (pos=0; pos<3; pos++)  { 
        k = itrk[pos];       /* starting position index */ 
         
        /* stage 1: fix pulse i0 and i1 according to max of correlation */ 
        ix = pos_max[ipos[k]]; 
        iy = pos_max[ipos[k+1]]; 
        ps = dn[ix] + dn[iy]; 
        i = ix/5; 
        j = iy/5; 
        alp = rrixix[ipos[k]][i] + rrixix[ipos[k+1]][j]; 
        i = (i<<3) + j; 
        alp += rrixiy[ipos[k]][i]; 
        ip[0] = ix; 
        ip[1] = iy; 
         
        for (i=0; i (FLOAT)0.) { 
            psk = ps; 
            alpk = alp; 
            for (i=0; i<12; i++) codvec[i] = ip[i]; 
        } 
    } /* end of for (pos=0; pos<3; pos++) */ 
     
      /*-------------------------------------------------------------------* 
      * index of 12 pulses = 44 bits on 5 words                           * 
      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                           * 
      * indx[0] =13 bits --> 3(track) +                                   * 
      *                      3(pos#11) + 3(pos#6) + 1(sign#1) + 3(pos#1)  * 
      * indx[1] =10 bits --> 3(pos#12) + 3(pos#7) + 1(sign#2) + 3(pos#2)  * 
      * indx[2] = 7 bits -->             3(pos#8) + 1(sign#3) + 3(pos#3)  * 
      * indx[3] = 7 bits -->             3(pos#9) + 1(sign#4) + 3(pos#4)  * 
      * indx[4] = 7 bits -->             3(pos#10)+ 1(sign#5) + 3(pos#5)  * 
    *-------------------------------------------------------------------*/ 
    build_code(codvec+2, sign, 10, h, code, y, idx); 
    track = 0; /* to avoid visual warning */ 
    for (k=0; k<2; k++) { 
         
        pos = codvec[k]; 
        index = pos/5;    /* index = pos/5       */ 
        track = pos%5; 
        if (sign[pos] > (FLOAT)0.) { 
            code[pos] += (FLOAT)1.; 
            for (i=pos, j=0; i>4) & (int)15; 
        iy = idx[track] & (int)15; 
         
        index = pack3(ix, iy, index); 
        if (k == 0) index += track<<10; 
        indx[k] = index; 
         
    } 
     
    for (k=2; k= NB_TRACK) track = 0; 
        indx[k] = (idx[track] & (int)127); 
    } 
 
    return; 
} 
 
/*-------------------------------------------------------------------* 
* Function  ACELP_10i40_35bits()                                    * 
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                    * 
* Algebraic codebook; 35 bits: 10 pulses in a frame of 40 samples.  * 
*-------------------------------------------------------------------* 
* The code length is 40, containing 10 nonzero pulses: i0...i9.     * 
* All pulses can have two (2) possible amplitudes: +1 or -1.        * 
* Each pulse can have eight (8) possible positions:                 * 
*                                                                   * 
* i0,i5 :  0, 5, 10, 15, 20, 25, 30, 35.                            * 
* i1,i6 :  1, 6, 11, 16, 21, 26, 31, 36.                            * 
* i2,i7 :  2, 7, 12, 17, 22, 27, 32, 37.                            * 
* i3,i8 :  3, 8, 13, 18, 23, 28, 33, 38.                            * 
* i4,i9 :  4, 9, 14, 19, 24, 29, 34, 39.                            * 
*-------------------------------------------------------------------*/ 
void ACELP_10i40_35bits( 
    FLOAT x[],    /* (i) : target vector                                 */ 
    FLOAT cn[],   /* (i) : residual after long term prediction           */ 
    FLOAT h1[],   /* (i) : impulse response of weighted synthesis filter */ 
    FLOAT code[], /* (o) : algebraic (fixed) codebook excitation         */ 
    FLOAT y[],    /* (o) : filtered fixed codebook excitation            */ 
    int indx[]    /* (o) : index 5 words: 7,7,7,7,7 = 35 bits            */ 
) 
{ 
    int i, j, k, ix, iy, pos, track; 
    FLOAT psk, ps, alpk, alp; 
    int itrk[3]; 
    FLOAT s, corr[NB_TRACK], L_tmp; 
    FLOAT *p0, *p1, *h_inv, *h; 
     
    /* these vectors are not static */ 
    FLOAT dn[L_SUBFR], sign[L_SUBFR], vec[L_SUBFR]; 
    int ip[10], codvec[10], pos_max[NB_TRACK]; 
    FLOAT cor_x[NB_POS], cor_y[NB_POS]; 
    FLOAT h_buf[4*L_SUBFR]; 
    FLOAT rrixix[NB_TRACK][NB_POS], rrixiy[NB_TRACK][MSIZE]; 
     
    h = h_buf; 
    h_inv = h_buf + (2*L_SUBFR); 
    for (i=0; i (FLOAT)0.) { 
                s = corr[i]; 
                track = i; 
            } 
        } 
        corr[track] = (FLOAT)-1.; 
        itrk[k] = track; 
    } 
     
    /*-------------------------------------------------------------------* 
    * Deep first search: 4 iterations of 256 tests = 1024 tests.        * 
    *                                                                   * 
    * Stages of deep first search:                                      * 
    *     stage 1 : fix i0 and i1 --> 2 positions is fixed previously.  * 
    *     stage 2 : fix i2 and i3 --> try 8x8 = 64 positions.           * 
    *     stage 3 : fix i4 and i5 --> try 8x8 = 64 positions.           * 
    *     stage 4 : fix i6 and i7 --> try 8x8 = 64 positions.           * 
    *     stage 5 : fix i8 and i9 --> try 8x8 = 64 positions.           * 
    *-------------------------------------------------------------------*/ 
    psk = (FLOAT)-1.; 
    alpk = (FLOAT)1.; 
    for (pos=0; pos<3; pos++) { 
        k = itrk[pos];       /* starting position index */ 
         
        /* stage 1: fix pulse i0 and i1 according to max of correlation */ 
        ix = pos_max[ipos[k]]; 
        iy = pos_max[ipos[k+1]]; 
        ps = dn[ix] + dn[iy]; 
        i = ix/5; 
        j = iy/5; 
        alp = rrixix[ipos[k]][i] + rrixix[ipos[k+1]][j]; 
        i = (i<<3) +  j; 
        alp += rrixiy[ipos[k]][i]; 
        ip[0] = ix; 
        ip[1] = iy; 
         
        for (i=0; i (FLOAT)0.) { 
            psk = ps; 
            alpk = alp; 
            for (i=0; i<10; i++) codvec[i] = ip[i]; 
        } 
         
    } /* end of for (pos=0; pos<3; pos++) */ 
     
      /*-------------------------------------------------------------------* 
      * index of 10 pulses = 35 bits on 5 words                           * 
      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                           * 
      * indx[0] = 7 bits --> 3(pos#6) + 1(sign#1) + 3(pos#1)              * 
      * indx[1] = 7 bits --> 3(pos#7) + 1(sign#2) + 3(pos#2)              * 
      * indx[2] = 7 bits --> 3(pos#8) + 1(sign#3) + 3(pos#3)              * 
      * indx[3] = 7 bits --> 3(pos#9) + 1(sign#4) + 3(pos#4)              * 
      * indx[4] = 7 bits --> 3(pos#10)+ 1(sign#5) + 3(pos#5)              * 
    *-------------------------------------------------------------------*/ 
    build_code(codvec, sign, 10, h, code, y, indx); 
     
    for (i=0; i (FLOAT)0.) { 
                sqk = sq; 
                alpk = alp2; 
                pos = j; 
            } 
        } 
        p1 -= NB_POS; 
        if (pos >= 0) { 
            *ix = i; 
            *iy = pos; 
        } 
    } 
    *ps += dn[*ix] + dn[*iy]; 
    *alp = alpk; 
     
    return; 
} 
 
/*-------------------------------------------------------------------* 
* Function  set_sign()                                              * 
* ~~~~~~~~~~~~~~~~~~~~                                              * 
* Set the sign of each pulse position.                              * 
*-------------------------------------------------------------------*/ 
static void set_sign( 
    FLOAT cn[],       /* (i) : residual after long term prediction    */ 
    FLOAT dn[],       /* (i) : correlation between target and h[]     */ 
    FLOAT sign[],     /* (o) : sign vector (sign of each position)    */ 
    FLOAT inv_sign[], /* (o) : inverse of sign[]                      */ 
    int pos_max[],    /* (o) : pos of max of correlation              */ 
    FLOAT corr[]      /* (o) : correlation of each track              */ 
) 
{ 
    int i, k, pos; 
    FLOAT k_cn, k_dn, val; 
    FLOAT s, max; 
     
    /* calculate energy for normalization of cn[] and dn[] */ 
    s = (FLOAT)0.; 
    for (i=0; i= (FLOAT)0.) { 
                sign[i] = (FLOAT)1.; 
                inv_sign[i] = (FLOAT)-1.; 
            } 
            else { 
                sign[i] = (FLOAT)-1.; 
                inv_sign[i] = (FLOAT)1.; 
                val = -val; 
            } 
            dn[i] = val;      /* modify dn[] according to the fixed sign */ 
            s = (FLOAT)fabs(s); 
            if (s > max) { 
                max = s; 
                pos = i; 
            } 
        } 
        pos_max[k] = pos; 
        corr[k] = max; 
    } 
     
    return; 
} 
 
/*-------------------------------------------------------------------* 
* Function  cor_h_e()                                                 * 
* ~~~~~~~~~~~~~~~~~                                                 * 
* Compute correlations of h[] needed for the codebook search.       * 
*-------------------------------------------------------------------*/ 
static void cor_h_e( 
    FLOAT sign[],           /* (i) : sign vector                 */ 
    FLOAT inv_sign[],       /* (i) : inverse of sign[]           */ 
    FLOAT h[],              /* (o) : scaled h[]                 */ 
    FLOAT h_inv[],          /* (o) : inverse of scaled h[]      */ 
    FLOAT rrixix[][NB_POS], /* (o) energy of h[].                   */ 
    FLOAT rrixiy[][MSIZE]   /* (o) correlation between 2 pulses.    */ 
) 
{ 
    int i, j, k, pos; 
    FLOAT *ptr_h1, *ptr_h2, *ptr_hf, *psign; 
    FLOAT *p0, *p1, *p2, *p3, *p4; 
    FLOAT cor; 
     
    for(i=0; i i4i4, i3i3, i2i2, i1i1, i0i0 */ 
    /* Init pointers to last position of rrixix[] */ 
    p0 = &rrixix[0][NB_POS-1]; 
    p1 = &rrixix[1][NB_POS-1]; 
    p2 = &rrixix[2][NB_POS-1]; 
    p3 = &rrixix[3][NB_POS-1]; 
    p4 = &rrixix[4][NB_POS-1]; 
    ptr_h1 = h; 
    cor    = (FLOAT)0.; 
    for(i=0; i i3i4, i2i3, i1i2, i0i1, i4i0 */ 
    pos = MSIZE-1; 
    ptr_hf = h + 1; 
    for(k=0; k i4i0, i3i4, i2i3, i1i2, i0i1 */ 
    pos = MSIZE-1; 
    ptr_hf = h + 4; 
    for(k=0; k 0) { 
            code[i] += (FLOAT)1.; 
            for (i=codvec[k], j=0; i (index2 & 7)) { 
        tmp = index1; 
        index1 = index2; 
        index2 = tmp; 
    } 
    if ((index1 & 7) > (index3 & 7)) { 
        tmp = index1; 
        index1 = index3; 
        index3 = tmp; 
    } 
    if ((index2 & 7) > (index3 & 7)) { 
        tmp = index2; 
        index2 = index3; 
        index3 = tmp; 
    } 
     
    k = (int)(index1>> 1) & (int)4; 
    k += (int)(index2>> 2) & (int)2; 
    k +=  (int)(index3>>3) & (int)1; 
    index = 0; /* to avoid visual warning */ 
    switch (k) { 
    case 0: 
    case 7: 
        index = (int)(index1 & (int)7) << (int)7; 
        index += (int)(index2 & (int)7) << (int)4; 
        index += index3; 
        break; 
    case 1: 
    case 6: 
        index = (int)(index3 & (int)7) << (int)7; 
        index +=  (int)(index1 & (int)7) << (int)4; 
        index +=  index2; 
        break; 
    case 2: 
    case 5: 
        index = (int)(index2 & (int)7) << (int)7; 
        index += (int)(index1 & (int)7) << (int)4; 
        index +=  index3; 
        break; 
    case 3: 
    case 4: 
        index = (int)(index2 & (int)7) << (int)7; 
        index += (int)(index3 & (int)7)<< (int)4; 
        index += index1; 
        break; 
    } 
     
    return (index); 
}