123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515 |
- /******************************************************************
- 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 "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' samples. */
- 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
- //if (CB_RESRANGE == -1) {
- sInd=0;
- eInd=range-1;
- sIndAug=20;
- eIndAug=39;
- //}
- # else
- /* restricted 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;
- }
- }
- //}
- # endif /* CB_RESRANGE == -1 */
- /* 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;
- }
|