aboutsummaryrefslogtreecommitdiffstats
path: root/trunk/codecs/ilbc/iCBSearch.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/codecs/ilbc/iCBSearch.c')
-rw-r--r--trunk/codecs/ilbc/iCBSearch.c480
1 files changed, 480 insertions, 0 deletions
diff --git a/trunk/codecs/ilbc/iCBSearch.c b/trunk/codecs/ilbc/iCBSearch.c
new file mode 100644
index 000000000..c047297e3
--- /dev/null
+++ b/trunk/codecs/ilbc/iCBSearch.c
@@ -0,0 +1,480 @@
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ iCBSearch.c
+
+ Copyright (C) The Internet Society (2004).
+ All Rights Reserved.
+
+******************************************************************/
+
+#include <math.h>
+#include <string.h>
+
+#include "iLBC_define.h"
+#include "iCBSearch.h"
+#include "gainquant.h"
+#include "createCB.h"
+#include "filter.h"
+#include "constants.h"
+
+/*----------------------------------------------------------------*
+ * Search routine for codebook encoding and gain quantization.
+ *---------------------------------------------------------------*/
+
+void iCBSearch(
+ iLBC_Enc_Inst_t *iLBCenc_inst,
+ /* (i) the encoder state structure */
+ int *index, /* (o) Codebook indices */
+ int *gain_index,/* (o) Gain quantization indices */
+ float *intarget,/* (i) Target vector for encoding */
+ float *mem, /* (i) Buffer for codebook construction */
+ int lMem, /* (i) Length of buffer */
+ int lTarget, /* (i) Length of vector */
+ int nStages, /* (i) Number of codebook stages */
+ float *weightDenum, /* (i) weighting filter coefficients */
+ float *weightState, /* (i) weighting filter state */
+ int block /* (i) the sub-block number */
+){
+ int i, j, icount, stage, best_index, range, counter;
+ float max_measure, gain, measure, crossDot, ftmp;
+ float gains[CB_NSTAGES];
+ float target[SUBL];
+ int base_index, sInd, eInd, base_size;
+ int sIndAug=0, eIndAug=0;
+ float buf[CB_MEML+SUBL+2*LPC_FILTERORDER];
+
+
+ float invenergy[CB_EXPAND*128], energy[CB_EXPAND*128];
+ float *pp, *ppi=0, *ppo=0, *ppe=0;
+ float cbvectors[CB_MEML];
+ float tene, cene, cvec[SUBL];
+ float aug_vec[SUBL];
+
+ memset(cvec,0,SUBL*sizeof(float));
+
+ /* Determine size of codebook sections */
+
+ base_size=lMem-lTarget+1;
+
+ if (lTarget==SUBL) {
+ base_size=lMem-lTarget+1+lTarget/2;
+ }
+
+ /* setup buffer for weighting */
+
+ memcpy(buf,weightState,sizeof(float)*LPC_FILTERORDER);
+ memcpy(buf+LPC_FILTERORDER,mem,lMem*sizeof(float));
+ memcpy(buf+LPC_FILTERORDER+lMem,intarget,lTarget*sizeof(float));
+
+ /* weighting */
+
+ AllPoleFilter(buf+LPC_FILTERORDER, weightDenum,
+ lMem+lTarget, LPC_FILTERORDER);
+
+ /* Construct the codebook and target needed */
+
+ memcpy(target, buf+LPC_FILTERORDER+lMem, lTarget*sizeof(float));
+
+ tene=0.0;
+ for (i=0; i<lTarget; i++) {
+ tene+=target[i]*target[i];
+ }
+
+ /* Prepare search over one more codebook section. This section
+ is created by filtering the original buffer with a filter. */
+
+ filteredCBvecs(cbvectors, buf+LPC_FILTERORDER, lMem);
+
+ /* The Main Loop over stages */
+
+ for (stage=0; stage<nStages; stage++) {
+
+ range = search_rangeTbl[block][stage];
+
+ /* initialize search measure */
+
+ max_measure = (float)-10000000.0;
+ gain = (float)0.0;
+ best_index = 0;
+
+ /* Compute cross dot product between the target
+
+
+ and the CB memory */
+
+ crossDot=0.0;
+ pp=buf+LPC_FILTERORDER+lMem-lTarget;
+ for (j=0; j<lTarget; j++) {
+ crossDot += target[j]*(*pp++);
+ }
+
+ if (stage==0) {
+
+ /* Calculate energy in the first block of
+ 'lTarget' sampels. */
+ ppe = energy;
+ ppi = buf+LPC_FILTERORDER+lMem-lTarget-1;
+ ppo = buf+LPC_FILTERORDER+lMem-1;
+
+ *ppe=0.0;
+ pp=buf+LPC_FILTERORDER+lMem-lTarget;
+ for (j=0; j<lTarget; j++) {
+ *ppe+=(*pp)*(*pp);
+ pp++;
+ }
+
+ if (*ppe>0.0) {
+ invenergy[0] = (float) 1.0 / (*ppe + EPS);
+ } else {
+ invenergy[0] = (float) 0.0;
+ }
+ ppe++;
+
+ measure=(float)-10000000.0;
+
+ if (crossDot > 0.0) {
+ measure = crossDot*crossDot*invenergy[0];
+ }
+ }
+ else {
+ measure = crossDot*crossDot*invenergy[0];
+ }
+
+ /* check if measure is better */
+ ftmp = crossDot*invenergy[0];
+
+ if ((measure>max_measure) && (fabs(ftmp)<CB_MAXGAIN)) {
+ best_index = 0;
+ max_measure = measure;
+ gain = ftmp;
+ }
+
+ /* loop over the main first codebook section,
+ full search */
+
+ for (icount=1; icount<range; icount++) {
+
+ /* calculate measure */
+
+
+
+ crossDot=0.0;
+ pp = buf+LPC_FILTERORDER+lMem-lTarget-icount;
+
+ for (j=0; j<lTarget; j++) {
+ crossDot += target[j]*(*pp++);
+ }
+
+ if (stage==0) {
+ *ppe++ = energy[icount-1] + (*ppi)*(*ppi) -
+ (*ppo)*(*ppo);
+ ppo--;
+ ppi--;
+
+ if (energy[icount]>0.0) {
+ invenergy[icount] =
+ (float)1.0/(energy[icount]+EPS);
+ } else {
+ invenergy[icount] = (float) 0.0;
+ }
+
+ measure=(float)-10000000.0;
+
+ if (crossDot > 0.0) {
+ measure = crossDot*crossDot*invenergy[icount];
+ }
+ }
+ else {
+ measure = crossDot*crossDot*invenergy[icount];
+ }
+
+ /* check if measure is better */
+ ftmp = crossDot*invenergy[icount];
+
+ if ((measure>max_measure) && (fabs(ftmp)<CB_MAXGAIN)) {
+ best_index = icount;
+ max_measure = measure;
+ gain = ftmp;
+ }
+ }
+
+ /* Loop over augmented part in the first codebook
+ * section, full search.
+ * The vectors are interpolated.
+ */
+
+ if (lTarget==SUBL) {
+
+ /* Search for best possible cb vector and
+ compute the CB-vectors' energy. */
+ searchAugmentedCB(20, 39, stage, base_size-lTarget/2,
+ target, buf+LPC_FILTERORDER+lMem,
+ &max_measure, &best_index, &gain, energy,
+ invenergy);
+
+
+ }
+
+ /* set search range for following codebook sections */
+
+ base_index=best_index;
+
+ /* unrestricted search */
+
+ if (CB_RESRANGE == -1) {
+ sInd=0;
+ eInd=range-1;
+ sIndAug=20;
+ eIndAug=39;
+ }
+
+ /* restriced search around best index from first
+ codebook section */
+
+ else {
+ /* Initialize search indices */
+ sIndAug=0;
+ eIndAug=0;
+ sInd=base_index-CB_RESRANGE/2;
+ eInd=sInd+CB_RESRANGE;
+
+ if (lTarget==SUBL) {
+
+ if (sInd<0) {
+
+ sIndAug = 40 + sInd;
+ eIndAug = 39;
+ sInd=0;
+
+ } else if ( base_index < (base_size-20) ) {
+
+ if (eInd > range) {
+ sInd -= (eInd-range);
+ eInd = range;
+ }
+ } else { /* base_index >= (base_size-20) */
+
+ if (sInd < (base_size-20)) {
+ sIndAug = 20;
+ sInd = 0;
+ eInd = 0;
+ eIndAug = 19 + CB_RESRANGE;
+
+ if(eIndAug > 39) {
+ eInd = eIndAug-39;
+ eIndAug = 39;
+ }
+ } else {
+ sIndAug = 20 + sInd - (base_size-20);
+ eIndAug = 39;
+
+
+ sInd = 0;
+ eInd = CB_RESRANGE - (eIndAug-sIndAug+1);
+ }
+ }
+
+ } else { /* lTarget = 22 or 23 */
+
+ if (sInd < 0) {
+ eInd -= sInd;
+ sInd = 0;
+ }
+
+ if(eInd > range) {
+ sInd -= (eInd - range);
+ eInd = range;
+ }
+ }
+ }
+
+ /* search of higher codebook section */
+
+ /* index search range */
+ counter = sInd;
+ sInd += base_size;
+ eInd += base_size;
+
+
+ if (stage==0) {
+ ppe = energy+base_size;
+ *ppe=0.0;
+
+ pp=cbvectors+lMem-lTarget;
+ for (j=0; j<lTarget; j++) {
+ *ppe+=(*pp)*(*pp);
+ pp++;
+ }
+
+ ppi = cbvectors + lMem - 1 - lTarget;
+ ppo = cbvectors + lMem - 1;
+
+ for (j=0; j<(range-1); j++) {
+ *(ppe+1) = *ppe + (*ppi)*(*ppi) - (*ppo)*(*ppo);
+ ppo--;
+ ppi--;
+ ppe++;
+ }
+ }
+
+ /* loop over search range */
+
+ for (icount=sInd; icount<eInd; icount++) {
+
+ /* calculate measure */
+
+ crossDot=0.0;
+
+
+ pp=cbvectors + lMem - (counter++) - lTarget;
+
+ for (j=0;j<lTarget;j++) {
+ crossDot += target[j]*(*pp++);
+ }
+
+ if (energy[icount]>0.0) {
+ invenergy[icount] =(float)1.0/(energy[icount]+EPS);
+ } else {
+ invenergy[icount] =(float)0.0;
+ }
+
+ if (stage==0) {
+
+ measure=(float)-10000000.0;
+
+ if (crossDot > 0.0) {
+ measure = crossDot*crossDot*
+ invenergy[icount];
+ }
+ }
+ else {
+ measure = crossDot*crossDot*invenergy[icount];
+ }
+
+ /* check if measure is better */
+ ftmp = crossDot*invenergy[icount];
+
+ if ((measure>max_measure) && (fabs(ftmp)<CB_MAXGAIN)) {
+ best_index = icount;
+ max_measure = measure;
+ gain = ftmp;
+ }
+ }
+
+ /* Search the augmented CB inside the limited range. */
+
+ if ((lTarget==SUBL)&&(sIndAug!=0)) {
+ searchAugmentedCB(sIndAug, eIndAug, stage,
+ 2*base_size-20, target, cbvectors+lMem,
+ &max_measure, &best_index, &gain, energy,
+ invenergy);
+ }
+
+ /* record best index */
+
+ index[stage] = best_index;
+
+ /* gain quantization */
+
+ if (stage==0){
+
+ if (gain<0.0){
+ gain = 0.0;
+
+
+ }
+
+ if (gain>CB_MAXGAIN) {
+ gain = (float)CB_MAXGAIN;
+ }
+ gain = gainquant(gain, 1.0, 32, &gain_index[stage]);
+ }
+ else {
+ if (stage==1) {
+ gain = gainquant(gain, (float)fabs(gains[stage-1]),
+ 16, &gain_index[stage]);
+ } else {
+ gain = gainquant(gain, (float)fabs(gains[stage-1]),
+ 8, &gain_index[stage]);
+ }
+ }
+
+ /* Extract the best (according to measure)
+ codebook vector */
+
+ if (lTarget==(STATE_LEN-iLBCenc_inst->state_short_len)) {
+
+ if (index[stage]<base_size) {
+ pp=buf+LPC_FILTERORDER+lMem-lTarget-index[stage];
+ } else {
+ pp=cbvectors+lMem-lTarget-
+ index[stage]+base_size;
+ }
+ } else {
+
+ if (index[stage]<base_size) {
+ if (index[stage]<(base_size-20)) {
+ pp=buf+LPC_FILTERORDER+lMem-
+ lTarget-index[stage];
+ } else {
+ createAugmentedVec(index[stage]-base_size+40,
+ buf+LPC_FILTERORDER+lMem,aug_vec);
+ pp=aug_vec;
+ }
+ } else {
+ int filterno, position;
+
+ filterno=index[stage]/base_size;
+ position=index[stage]-filterno*base_size;
+
+
+ if (position<(base_size-20)) {
+ pp=cbvectors+filterno*lMem-lTarget-
+ index[stage]+filterno*base_size;
+ } else {
+ createAugmentedVec(
+ index[stage]-(filterno+1)*base_size+40,
+ cbvectors+filterno*lMem,aug_vec);
+ pp=aug_vec;
+
+
+ }
+ }
+ }
+
+ /* Subtract the best codebook vector, according
+ to measure, from the target vector */
+
+ for (j=0;j<lTarget;j++) {
+ cvec[j] += gain*(*pp);
+ target[j] -= gain*(*pp++);
+ }
+
+ /* record quantized gain */
+
+ gains[stage]=gain;
+
+ }/* end of Main Loop. for (stage=0;... */
+
+ /* Gain adjustment for energy matching */
+ cene=0.0;
+ for (i=0; i<lTarget; i++) {
+ cene+=cvec[i]*cvec[i];
+ }
+ j=gain_index[0];
+
+ for (i=gain_index[0]; i<32; i++) {
+ ftmp=cene*gain_sq5Tbl[i]*gain_sq5Tbl[i];
+
+ if ((ftmp<(tene*gains[0]*gains[0])) &&
+ (gain_sq5Tbl[j]<(2.0*gains[0]))) {
+ j=i;
+ }
+ }
+ gain_index[0]=j;
+}
+
+