summaryrefslogtreecommitdiff
path: root/codecs/ilbc/iCBSearch.c
diff options
context:
space:
mode:
authorMatthew Jordan <mjordan@digium.com>2012-01-18 21:06:29 +0000
committerMatthew Jordan <mjordan@digium.com>2012-01-18 21:06:29 +0000
commit16adf6de8c4e3bf7dbfb1960b7ba2e4e5400d1b2 (patch)
tree51ddec1e752656271970856e230a8312d9394446 /codecs/ilbc/iCBSearch.c
parentf69fd136f4b43944e95769bf5774dd9d77246405 (diff)
Include iLBC source code for distribution with Asterisk
This patch includes the iLBC source code for distribution with Asterisk. Clarification regarding the iLBC source code was provided by Google, and the appropriate licenses have been included in the codecs/ilbc folder. Review: https://reviewboard.asterisk.org/r/1675 Review: https://reviewboard.asterisk.org/r/1649 (closes issue: ASTERISK-18943) Reporter: Leif Madsen Tested by: Matt Jordan ........ Merged revisions 351450 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 351451 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@351452 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'codecs/ilbc/iCBSearch.c')
-rw-r--r--codecs/ilbc/iCBSearch.c512
1 files changed, 512 insertions, 0 deletions
diff --git a/codecs/ilbc/iCBSearch.c b/codecs/ilbc/iCBSearch.c
new file mode 100644
index 000000000..78d67df17
--- /dev/null
+++ b/codecs/ilbc/iCBSearch.c
@@ -0,0 +1,512 @@
+
+ /******************************************************************
+
+ 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++, pp++) {
+ *ppe+=(*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;
+ }
+
+
+
+
+
+
+ /* 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;
+ }
+ }
+ }
+
+ /* 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++, pp++) {
+ *ppe+=(*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;
+ }
+
+
+
+
+
+
+
+
+