   
   
   
   /******************************************************************
   
       iLBC Speech Coder ANSI-C Source Code
   
       createCB.c
   
       Copyright (C) The Internet Society (2004). 
       All Rights Reserved.
   
   ******************************************************************/
   
   #include "iLBC_define.h"
   #include "constants.h"
   #include <string.h>
   #include <math.h>
   
   /*----------------------------------------------------------------*
    *  Construct an additional codebook vector by filtering the
    *  initial codebook buffer. This vector is then used to expand
    *  the codebook with an additional section.
    *---------------------------------------------------------------*/
   
   void filteredCBvecs(
       float *cbvectors,   /* (o) Codebook vectors for the 
                                  higher section */
       float *mem,         /* (i) Buffer to create codebook 
                                  vector from */
       int lMem        /* (i) Length of buffer */
   ){
       int j, k;
       float *pp, *pp1;
       float tempbuff2[CB_MEML+CB_FILTERLEN];
       float *pos;
   
       memset(tempbuff2, 0, (CB_HALFFILTERLEN-1)*sizeof(float));
       memcpy(&tempbuff2[CB_HALFFILTERLEN-1], mem, lMem*sizeof(float));
       memset(&tempbuff2[lMem+CB_HALFFILTERLEN-1], 0, 
           (CB_HALFFILTERLEN+1)*sizeof(float));
   
       /* Create codebook vector for higher section by filtering */
   
       /* do filtering */
       pos=cbvectors;
       memset(pos, 0, lMem*sizeof(float));
       for (k=0; k<lMem; k++) {
           pp=&tempbuff2[k];
           pp1=&cbfiltersTbl[CB_FILTERLEN-1];
           for (j=0;j<CB_FILTERLEN;j++) {
               (*pos)+=(*pp++)*(*pp1--);
           }
           pos++;
       }
   }
   
   
   
   /*----------------------------------------------------------------*
    *  Search the augmented part of the codebook to find the best
    *  measure.
    *----------------------------------------------------------------*/
   
   void searchAugmentedCB(
       int low,        /* (i) Start index for the search */
       int high,           /* (i) End index for the search */
       int stage,          /* (i) Current stage */
       int startIndex,     /* (i) Codebook index for the first 
                                  aug vector */
       float *target,      /* (i) Target vector for encoding */
       float *buffer,      /* (i) Pointer to the end of the buffer for
                                  augmented codebook construction */
       float *max_measure, /* (i/o) Currently maximum measure */
       int *best_index,/* (o) Currently the best index */
       float *gain,    /* (o) Currently the best gain */
       float *energy,      /* (o) Energy of augmented codebook 
                                  vectors */
       float *invenergy/* (o) Inv energy of augmented codebook 
                                  vectors */
   ) {
       int icount, ilow, j, tmpIndex;
       float *pp, *ppo, *ppi, *ppe, crossDot, alfa; 
       float weighted, measure, nrjRecursive;
       float ftmp;
   
       /* Compute the energy for the first (low-5) 
          noninterpolated samples */
       nrjRecursive = (float) 0.0;
       pp = buffer - low + 1;
       for (j=0; j<(low-5); j++) {
           nrjRecursive += ( (*pp)*(*pp) );
           pp++;
       }
       ppe = buffer - low;
   
   
       for (icount=low; icount<=high; icount++) {
   
           /* Index of the codebook vector used for retrieving 
              energy values */
           tmpIndex = startIndex+icount-20;
   
           ilow = icount-4;
               
           /* Update the energy recursively to save complexity */
           nrjRecursive = nrjRecursive + (*ppe)*(*ppe);
           ppe--;
           energy[tmpIndex] = nrjRecursive;
   
           /* Compute cross dot product for the first (low-5) 
              samples */
           crossDot = (float) 0.0;
   
   
           pp = buffer-icount;
           for (j=0; j<ilow; j++) {
               crossDot += target[j]*(*pp++);
           }
   
           /* interpolation */
           alfa = (float) 0.2;
           ppo = buffer-4;
           ppi = buffer-icount-4;
           for (j=ilow; j<icount; j++) {
               weighted = ((float)1.0-alfa)*(*ppo)+alfa*(*ppi);
               ppo++;
               ppi++;
               energy[tmpIndex] += weighted*weighted;
               crossDot += target[j]*weighted;
               alfa += (float)0.2;
           }
   
           /* Compute energy and cross dot product for the 
              remaining samples */
           pp = buffer - icount;
           for (j=icount; j<SUBL; j++) {
               energy[tmpIndex] += (*pp)*(*pp);
               crossDot += target[j]*(*pp++);
           }
           
           if (energy[tmpIndex]>0.0) {
               invenergy[tmpIndex]=(float)1.0/(energy[tmpIndex]+EPS);
           } else {
               invenergy[tmpIndex] = (float) 0.0;
           }
           
           if (stage==0) {
               measure = (float)-10000000.0;
               
               if (crossDot > 0.0) {
                   measure = crossDot*crossDot*invenergy[tmpIndex];
               }
           }
           else {
               measure = crossDot*crossDot*invenergy[tmpIndex];
           }
       
           /* check if measure is better */
           ftmp = crossDot*invenergy[tmpIndex];
           
           if ((measure>*max_measure) && (fabs(ftmp)<CB_MAXGAIN)) {
               *best_index = tmpIndex;
               *max_measure = measure;
               *gain = ftmp;
           }
       }
   }
   
   
   
   
   /*----------------------------------------------------------------*
    *  Recreate a specific codebook vector from the augmented part.
    *
    *----------------------------------------------------------------*/
   
   void createAugmentedVec(
       int index,      /* (i) Index for the augmented vector 
                              to be created */
       float *buffer,  /* (i) Pointer to the end of the buffer for
                              augmented codebook construction */
       float *cbVec/* (o) The construced codebook vector */
   ) {
       int ilow, j;
       float *pp, *ppo, *ppi, alfa, alfa1, weighted;
   
       ilow = index-5;
               
       /* copy the first noninterpolated part */
   
       pp = buffer-index;
       memcpy(cbVec,pp,sizeof(float)*index);
   
       /* interpolation */
   
       alfa1 = (float)0.2;
       alfa = 0.0;
       ppo = buffer-5;
       ppi = buffer-index-5;
       for (j=ilow; j<index; j++) {
           weighted = ((float)1.0-alfa)*(*ppo)+alfa*(*ppi);
           ppo++;
           ppi++;
           cbVec[j] = weighted;
           alfa += alfa1;
       }
   
       /* copy the second noninterpolated part */
   
       pp = buffer - index;
       memcpy(cbVec+index,pp,sizeof(float)*(SUBL-index));
   }
   
   
