Skip to content
Snippets Groups Projects
helpfun.c 9.04 KiB
Newer Older
  • Learn to ignore specific revisions
  • 
       /******************************************************************
    
           iLBC Speech Coder ANSI-C Source Code
    
           helpfun.c
    
           Copyright (C) The Internet Society (2004).
           All Rights Reserved.
    
       ******************************************************************/
    
       #include <math.h>
    
       #include "iLBC_define.h"
       #include "constants.h"
    
       /*----------------------------------------------------------------*
        *  calculation of auto correlation
        *---------------------------------------------------------------*/
    
       void autocorr(
           float *r,       /* (o) autocorrelation vector */
           const float *x, /* (i) data vector */
           int N,          /* (i) length of data vector */
           int order       /* largest lag for calculated
                              autocorrelations */
       ){
           int     lag, n;
           float   sum;
    
           for (lag = 0; lag <= order; lag++) {
               sum = 0;
               for (n = 0; n < N - lag; n++) {
                   sum += x[n] * x[n+lag];
               }
               r[lag] = sum;
           }
    
    
    
    
    
       }
    
       /*----------------------------------------------------------------*
        *  window multiplication
        *---------------------------------------------------------------*/
    
       void window(
           float *z,       /* (o) the windowed data */
           const float *x, /* (i) the original data vector */
           const float *y, /* (i) the window */
           int N           /* (i) length of all vectors */
       ){
           int     i;
    
           for (i = 0; i < N; i++) {
               z[i] = x[i] * y[i];
           }
       }
    
       /*----------------------------------------------------------------*
        *  levinson-durbin solution for lpc coefficients
        *---------------------------------------------------------------*/
    
       void levdurb(
           float *a,       /* (o) lpc coefficient vector starting
                                  with 1.0 */
           float *k,       /* (o) reflection coefficients */
           float *r,       /* (i) autocorrelation vector */
           int order       /* (i) order of lpc filter */
       ){
           float  sum, alpha;
           int     m, m_h, i;
    
           a[0] = 1.0;
    
           if (r[0] < EPS) { /* if r[0] <= 0, set LPC coeff. to zero */
               for (i = 0; i < order; i++) {
                   k[i] = 0;
                   a[i+1] = 0;
               }
           } else {
               a[1] = k[0] = -r[1]/r[0];
               alpha = r[0] + r[1] * k[0];
               for (m = 1; m < order; m++){
                   sum = r[m + 1];
                   for (i = 0; i < m; i++){
                       sum += a[i+1] * r[m - i];
                   }
    
    
    
    
    
                   k[m] = -sum / alpha;
                   alpha += k[m] * sum;
                   m_h = (m + 1) >> 1;
                   for (i = 0; i < m_h; i++){
                       sum = a[i+1] + k[m] * a[m - i];
                       a[m - i] += k[m] * a[i+1];
                       a[i+1] = sum;
                   }
                   a[m+1] = k[m];
               }
           }
       }
    
       /*----------------------------------------------------------------*
        *  interpolation between vectors
        *---------------------------------------------------------------*/
    
       void interpolate(
           float *out,      /* (o) the interpolated vector */
           float *in1,     /* (i) the first vector for the
                                  interpolation */
           float *in2,     /* (i) the second vector for the
                                  interpolation */
           float coef,      /* (i) interpolation weights */
           int length      /* (i) length of all vectors */
       ){
           int i;
           float invcoef;
    
           invcoef = (float)1.0 - coef;
           for (i = 0; i < length; i++) {
               out[i] = coef * in1[i] + invcoef * in2[i];
           }
       }
    
       /*----------------------------------------------------------------*
        *  lpc bandwidth expansion
        *---------------------------------------------------------------*/
    
       void bwexpand(
           float *out,      /* (o) the bandwidth expanded lpc
                                  coefficients */
           float *in,      /* (i) the lpc coefficients before bandwidth
                                  expansion */
           float coef,     /* (i) the bandwidth expansion factor */
           int length      /* (i) the length of lpc coefficient vectors */
       ){
           int i;
    
    
    
    
    
           float  chirp;
    
           chirp = coef;
    
           out[0] = in[0];
           for (i = 1; i < length; i++) {
               out[i] = chirp * in[i];
               chirp *= coef;
           }
       }
    
       /*----------------------------------------------------------------*
        *  vector quantization
        *---------------------------------------------------------------*/
    
       void vq(
           float *Xq,      /* (o) the quantized vector */
           int *index,     /* (o) the quantization index */
           const float *CB,/* (i) the vector quantization codebook */
           float *X,       /* (i) the vector to quantize */
           int n_cb,       /* (i) the number of vectors in the codebook */
           int dim         /* (i) the dimension of all vectors */
       ){
           int     i, j;
           int     pos, minindex;
           float   dist, tmp, mindist;
    
           pos = 0;
           mindist = FLOAT_MAX;
           minindex = 0;
           for (j = 0; j < n_cb; j++) {
               dist = X[0] - CB[pos];
               dist *= dist;
               for (i = 1; i < dim; i++) {
                   tmp = X[i] - CB[pos + i];
                   dist += tmp*tmp;
               }
    
               if (dist < mindist) {
                   mindist = dist;
                   minindex = j;
               }
               pos += dim;
           }
           for (i = 0; i < dim; i++) {
               Xq[i] = CB[minindex*dim + i];
           }
           *index = minindex;
    
    
    
    
    
       }
    
       /*----------------------------------------------------------------*
        *  split vector quantization
        *---------------------------------------------------------------*/
    
       void SplitVQ(
           float *qX,      /* (o) the quantized vector */
           int *index,     /* (o) a vector of indexes for all vector
                                  codebooks in the split */
           float *X,       /* (i) the vector to quantize */
           const float *CB,/* (i) the quantizer codebook */
           int nsplit,     /* the number of vector splits */
           const int *dim, /* the dimension of X and qX */
           const int *cbsize /* the number of vectors in the codebook */
       ){
           int    cb_pos, X_pos, i;
    
           cb_pos = 0;
           X_pos= 0;
           for (i = 0; i < nsplit; i++) {
               vq(qX + X_pos, index + i, CB + cb_pos, X + X_pos,
                   cbsize[i], dim[i]);
               X_pos += dim[i];
               cb_pos += dim[i] * cbsize[i];
           }
       }
    
       /*----------------------------------------------------------------*
        *  scalar quantization
        *---------------------------------------------------------------*/
    
       void sort_sq(
           float *xq,      /* (o) the quantized value */
           int *index,     /* (o) the quantization index */
           float x,    /* (i) the value to quantize */
           const float *cb,/* (i) the quantization codebook */
           int cb_size      /* (i) the size of the quantization codebook */
       ){
           int i;
    
           if (x <= cb[0]) {
               *index = 0;
               *xq = cb[0];
           } else {
               i = 0;
               while ((x > cb[i]) && i < cb_size - 1) {
                   i++;
    
    
    
    
    
               }
    
               if (x > ((cb[i] + cb[i - 1])/2)) {
                   *index = i;
                   *xq = cb[i];
               } else {
                   *index = i - 1;
                   *xq = cb[i - 1];
               }
           }
       }
    
       /*----------------------------------------------------------------*
        *  check for stability of lsf coefficients
        *---------------------------------------------------------------*/
    
       int LSF_check(    /* (o) 1 for stable lsf vectors and 0 for
                                  nonstable ones */
           float *lsf,     /* (i) a table of lsf vectors */
           int dim,    /* (i) the dimension of each lsf vector */
           int NoAn    /* (i) the number of lsf vectors in the
                                  table */
       ){
           int k,n,m, Nit=2, change=0,pos;
           static float eps=(float)0.039; /* 50 Hz */
           static float eps2=(float)0.0195;
           static float maxlsf=(float)3.14; /* 4000 Hz */
           static float minlsf=(float)0.01; /* 0 Hz */
    
           /* LSF separation check*/
    
           for (n=0; n<Nit; n++) { /* Run through a couple of times */
               for (m=0; m<NoAn; m++) { /* Number of analyses per frame */
                   for (k=0; k<(dim-1); k++) {
                       pos=m*dim+k;
    
                       if ((lsf[pos+1]-lsf[pos])<eps) {
    
                           if (lsf[pos+1]<lsf[pos]) {
                               lsf[pos+1]= lsf[pos]+eps2;
                               lsf[pos]= lsf[pos+1]-eps2;
                           } else {
                               lsf[pos]-=eps2;
                               lsf[pos+1]+=eps2;
                           }
                           change=1;
    
    
    
    
    
                       }
    
                       if (lsf[pos]<minlsf) {
                           lsf[pos]=minlsf;
                           change=1;
                       }
    
                       if (lsf[pos]>maxlsf) {
                           lsf[pos]=maxlsf;
                           change=1;
                       }
                   }
               }
           }
    
           return change;
       }