

   /******************************************************************

       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));





}
