www.pudn.com > source.rar > LPCA.C


/* ITU-T G.729 Software Package Release 2 (November 2006) */ 
/* 
   ITU-T G.729 Annex C - Reference C code for floating point 
                         implementation of G.729 Annex A 
                         Version 1.01 of 15.September.98 
*/ 
 
/* 
---------------------------------------------------------------------- 
                    COPYRIGHT NOTICE 
---------------------------------------------------------------------- 
   ITU-T G.729 Annex C ANSI C source code 
   Copyright (C) 1998, AT&T, France Telecom, NTT, University of 
   Sherbrooke.  All rights reserved. 
---------------------------------------------------------------------- 
*/ 
 
/* 
 File : LPCA.C 
 Used for the floating point version of G.729A only 
 (not for G.729 main body) 
*/ 
 
/*****************************************************************************/ 
/* lpc analysis routines                                                     */ 
/*****************************************************************************/ 
 
#include "typedef.h" 
#include "ld8a.h" 
#include "tab_ld8a.h" 
 
/* NOTE: these routines are assuming that the order is defined as M */ 
/*       and that NC is defined as M/2. M has to be even           */ 
 
/*---------------------------------------------------------------------------- 
 * autocorr - compute the auto-correlations of windowed speech signal 
 *---------------------------------------------------------------------------- 
 */ 
void autocorr( 
     FLOAT *x,              /* input : input signal x[0:L_WINDOW] */ 
     int m,                 /* input : LPC order                  */ 
     FLOAT *r               /* output: auto-correlation vector r[0:M]*/ 
) 
{ 
   static FLOAT y[L_WINDOW];  /* dynamic memory allocation is used in real time*/ 
   FLOAT sum; 
   int i, j; 
 
 
   for (i = 0; i < L_WINDOW; i++) 
        y[i] = x[i]*hamwindow[i]; 
 
   for (i = 0; i <= m; i++) 
   { 
     sum = (F)0.0; 
     for (j = 0; j < L_WINDOW-i; j++) 
          sum += y[j]*y[j+i]; 
     r[i] = sum; 
   } 
   if (r[0]<(F)1.0) r[0]=(F)1.0; 
 
   return; 
} 
 
/*-------------------------------------------------------------* 
 * procedure lag_window:                                       * 
 *           ~~~~~~~~~                                         * 
 * lag windowing of the autocorrelations                       * 
 *-------------------------------------------------------------*/ 
 
void lag_window( 
     int m,                 /* input : LPC order                  */ 
     FLOAT   r[]            /* in/out: correlation */ 
) 
{ 
   int i; 
 
   for (i=0; i<= m; i++) 
     r[i] *= lwindow[i]; 
 
   return; 
} 
 
 
/*---------------------------------------------------------------------------- 
 * levinson - levinson-durbin recursion to compute LPC parameters 
 *---------------------------------------------------------------------------- 
 */ 
FLOAT levinson(         /* output: prediction error (energy) */ 
 FLOAT *r,              /* input : auto correlation coefficients r[0:M] */ 
 FLOAT *a,              /* output: lpc coefficients a[0] = 1 */ 
 FLOAT *rc              /* output: reflection coefficients rc[0:M-1]    */ 
) 
{ 
   FLOAT s, at, err; 
   int i, j, l; 
 
   rc[0] = (-r[1])/r[0]; 
   a[0] = (F)1.0; 
   a[1] = rc[0]; 
   err = r[0] + r[1]*rc[0]; 
   for (i = 2; i <= M; i++) 
   { 
     s = (F)0.0; 
     for (j = 0; j < i; j++) 
       s += r[i-j]*a[j]; 
     rc[i-1]= (-s)/(err); 
     for (j = 1; j <= (i/2); j++) 
     { 
       l = i-j; 
       at = a[j] + rc[i-1]*a[l]; 
       a[l] += rc[i-1]*a[j]; 
       a[j] = at; 
     } 
     a[i] = rc[i-1]; 
     err += rc[i-1]*s; 
     if (err <= (F)0.0) 
        err = (F)0.001; 
   } 
   return (err); 
} 
 
/*------------------------------------------------------------------* 
 *  procedure az_lsp:                                               * 
 *            ~~~~~~                                                * 
 *   Compute the LSPs from  the LP coefficients a[] using Chebyshev * 
 * polynomials. The found LSPs are in the cosine domain with values * 
 * in the range from 1 down to -1.                                  * 
 * The table grid[] contains the points (in the cosine domain) at   * 
 * which the polynomials are evaluated. The table corresponds to    * 
 * NO_POINTS frequencies uniformly spaced between 0 and pi.         * 
 *------------------------------------------------------------------*/ 
/* prototypes of local functions */ 
 
static FLOAT chebyshev(FLOAT x, FLOAT *f, int n); 
 
void az_lsp( 
  FLOAT *a,         /* input : LP filter coefficients                     */ 
  FLOAT *lsp,       /* output: Line spectral pairs (in the cosine domain) */ 
  FLOAT *old_lsp    /* input : LSP vector from past frame                 */ 
) 
{ 
 int i, j, nf, ip; 
 FLOAT xlow,ylow,xhigh,yhigh,xmid,ymid,xint; 
 FLOAT *pf1; 
 
 FLOAT f1[NC+1], f2[NC+1]; 
 
 /*-------------------------------------------------------------* 
  * find the sum and diff polynomials F1(z) and F2(z)           * 
  *      F1(z) = [A(z) + z^11 A(z^-1)]/(1+z^-1)                 * 
  *      F2(z) = [A(z) - z^11 A(z^-1)]/(1-z^-1)                 * 
  *-------------------------------------------------------------*/ 
 
 f1[0] = (F)1.0; 
 f2[0] = (F)1.0; 
 for (i=1, j=M; i<=NC; i++, j--){ 
    f1[i] = a[i]+a[j]-f1[i-1]; 
    f2[i] = a[i]-a[j]+f2[i-1]; 
 } 
 
 /*---------------------------------------------------------------------* 
  * Find the LSPs (roots of F1(z) and F2(z) ) using the                 * 
  * Chebyshev polynomial evaluation.                                    * 
  * The roots of F1(z) and F2(z) are alternatively searched.            * 
  * We start by finding the first root of F1(z) then we switch          * 
  * to F2(z) then back to F1(z) and so on until all roots are found.    * 
  *                                                                     * 
  *  - Evaluate Chebyshev pol. at grid points and check for sign change.* 
  *  - If sign change track the root by subdividing the interval        * 
  *    NO_ITER times and ckecking sign change.                          * 
  *---------------------------------------------------------------------*/ 
 
 nf=0;      /* number of found frequencies */ 
 ip=0;      /* flag to first polynomial   */ 
 
 pf1 = f1;  /* start with F1(z) */ 
 
 xlow=grid[0]; 
 ylow = chebyshev(xlow,pf1,NC); 
 
 j = 0; 
 while ( (nf < M) && (j < GRID_POINTS) ) 
 { 
   j++; 
   xhigh = xlow; 
   yhigh = ylow; 
   xlow = grid[j]; 
   ylow = chebyshev(xlow,pf1,NC); 
 
   if (ylow*yhigh <= 0.0)  /* if sign change new root exists */ 
   { 
     j--; 
 
     /* divide the interval of sign change by 2 */ 
 
     for (i = 0; i < 2; i++) 
     { 
       xmid = (F)0.5*(xlow + xhigh); 
       ymid = chebyshev(xmid,pf1,NC); 
       if (ylow*ymid <= (F)0.0) 
       { 
         yhigh = ymid; 
         xhigh = xmid; 
       } 
       else 
       { 
         ylow = ymid; 
         xlow = xmid; 
       } 
     } 
 
     /* linear interpolation for evaluating the root */ 
 
     xint = xlow - ylow*(xhigh-xlow)/(yhigh-ylow); 
 
     lsp[nf] = xint;    /* new root */ 
     nf++; 
 
     ip = 1 - ip;         /* flag to other polynomial    */ 
     pf1 = ip ? f2 : f1;  /* pointer to other polynomial */ 
 
     xlow = xint; 
     ylow = chebyshev(xlow,pf1,NC); 
   } 
 } 
 
 /* Check if M roots found */ 
 /* if not use the LSPs from previous frame */ 
 
 if ( nf < M) 
    for(i=0; i