www.pudn.com > 200411301125332697.rar > lpc.c


/* 
   ITU-T G.729 Speech Coder with Annex B    ANSI-C Source Code 
   Version 1.3    Last modified: August 1997 
 
   Copyright (c) 1996, 
   AT&T, France Telecom, NTT, Universite de Sherbrooke, Lucent Technologies, 
   Rockwell International 
   All rights reserved. 
*/ 
 
/*-----------------------------------------------------* 
 * Function Autocorr()                                 * 
 *                                                     * 
 *   Compute autocorrelations of signal with windowing * 
 *                                                     * 
 *-----------------------------------------------------*/ 
 
#include "typedef.h" 
#include "basic_op.h" 
#include "oper_32b.h" 
 
#include "ld8k.h" 
#include "tab_ld8k.h" 
 
void Autocorr( 
  Word16 x[],      /* (i)    : Input signal                      */ 
  Word16 m,        /* (i)    : LPC order                         */ 
  Word16 r_h[],    /* (o)    : Autocorrelations  (msb)           */ 
  Word16 r_l[],    /* (o)    : Autocorrelations  (lsb)           */ 
  Word16 *exp_R0 
) 
{ 
  Word16 i, j, norm; 
  Word16 y[L_WINDOW]; 
  Word32 sum; 
 
  extern Flag Overflow; 
 
  /* Windowing of signal */ 
 
  for(i=0; i mantissa in Q31 plus exponent         | 
 |               A[i]    Q27   +- 15.999..                                   | 
 |                                                                           | 
 |       The additions are performed in 32 bit.  For the summation used      | 
 |       to calculate the K[i], we multiply numbers in Q31 by numbers        | 
 |       in Q27, with the result of the multiplications in Q27,              | 
 |       resulting in a dynamic of +- 16.  This is sufficient to avoid       | 
 |       overflow, since the final result of the summation is                | 
 |       necessarily < 1.0 as both the K[i] and Alpha are                    | 
 |       theoretically < 1.0.                                                | 
 |___________________________________________________________________________| 
*/ 
 
 
/* Last A(z) for case of unstable filter */ 
 
static Word16 old_A[M+1]={4096,0,0,0,0,0,0,0,0,0,0}; 
static Word16 old_rc[2]={0,0}; 
 
void Levinson( 
  Word16 Rh[],      /* (i)     : Rh[M+1] Vector of autocorrelations (msb) */ 
  Word16 Rl[],      /* (i)     : Rl[M+1] Vector of autocorrelations (lsb) */ 
  Word16 A[],       /* (o) Q12 : A[M]    LPC coefficients  (m = 10)       */ 
  Word16 rc[],      /* (o) Q15 : rc[M]   Reflection coefficients.         */ 
  Word16 *Err       /* (o)     : Residual energy                          */ 
) 
{ 
 Word16 i, j; 
 Word16 hi, lo; 
 Word16 Kh, Kl;                /* reflection coefficient; hi and lo           */ 
 Word16 alp_h, alp_l, alp_exp; /* Prediction gain; hi lo and exponent         */ 
 Word16 Ah[M+1], Al[M+1];      /* LPC coef. in double prec.                   */ 
 Word16 Anh[M+1], Anl[M+1];    /* LPC coef.for next iteration in double prec. */ 
 Word32 t0, t1, t2;            /* temporary variable                          */ 
 
 
/* K = A[1] = -R[1] / R[0] */ 
 
  t1  = L_Comp(Rh[1], Rl[1]);           /* R[1] in Q31      */ 
  t2  = L_abs(t1);                      /* abs R[1]         */ 
  t0  = Div_32(t2, Rh[0], Rl[0]);       /* R[1]/R[0] in Q31 */ 
  if(t1 > 0) t0= L_negate(t0);          /* -R[1]/R[0]       */ 
  L_Extract(t0, &Kh, &Kl);              /* K in DPF         */ 
  rc[0] = Kh; 
  t0 = L_shr(t0,4);                     /* A[1] in Q27      */ 
  L_Extract(t0, &Ah[1], &Al[1]);        /* A[1] in DPF      */ 
 
/*  Alpha = R[0] * (1-K**2) */ 
 
  t0 = Mpy_32(Kh ,Kl, Kh, Kl);          /* K*K      in Q31 */ 
  t0 = L_abs(t0);                       /* Some case <0 !! */ 
  t0 = L_sub( (Word32)0x7fffffffL, t0 ); /* 1 - K*K  in Q31 */ 
  L_Extract(t0, &hi, &lo);              /* DPF format      */ 
  t0 = Mpy_32(Rh[0] ,Rl[0], hi, lo);    /* Alpha in Q31    */ 
 
/* Normalize Alpha */ 
 
  alp_exp = norm_l(t0); 
  t0 = L_shl(t0, alp_exp); 
  L_Extract(t0, &alp_h, &alp_l);         /* DPF format    */ 
 
/*--------------------------------------* 
 * ITERATIONS  I=2 to M                 * 
 *--------------------------------------*/ 
 
  for(i= 2; i<=M; i++) 
  { 
 
    /* t0 = SUM ( R[j]*A[i-j] ,j=1,i-1 ) +  R[i] */ 
 
    t0 = 0; 
    for(j=1; j convert to Q31 */ 
                                       /* No overflow possible            */ 
    t1 = L_Comp(Rh[i],Rl[i]); 
    t0 = L_add(t0, t1);                /* add R[i] in Q31                 */ 
 
    /* K = -t0 / Alpha */ 
 
    t1 = L_abs(t0); 
    t2 = Div_32(t1, alp_h, alp_l);     /* abs(t0)/Alpha                   */ 
    if(t0 > 0) t2= L_negate(t2);       /* K =-t0/Alpha                    */ 
    t2 = L_shl(t2, alp_exp);           /* denormalize; compare to Alpha   */ 
    L_Extract(t2, &Kh, &Kl);           /* K in DPF                        */ 
    rc[i-1] = Kh; 
 
    /* Test for unstable filter. If unstable keep old A(z) */ 
 
    if (sub(abs_s(Kh), 32750) > 0) 
    { 
      for(j=0; j<=M; j++) 
      { 
        A[j] = old_A[j]; 
      } 
      rc[0] = old_rc[0];        /* only two rc coefficients are needed */ 
      rc[1] = old_rc[1]; 
      return; 
    } 
 
    /*------------------------------------------* 
     *  Compute new LPC coeff. -> An[i]         * 
     *  An[j]= A[j] + K*A[i-j]     , j=1 to i-1 * 
     *  An[i]= K                                * 
     *------------------------------------------*/ 
 
 
    for(j=1; jconvert to Q27  */ 
    L_Extract(t2, &Anh[i], &Anl[i]);    /* An[i] in Q27                    */ 
 
    /*  Alpha = Alpha * (1-K**2) */ 
 
    t0 = Mpy_32(Kh ,Kl, Kh, Kl);          /* K*K      in Q31 */ 
    t0 = L_abs(t0);                       /* Some case <0 !! */ 
    t0 = L_sub( (Word32)0x7fffffffL, t0 ); /* 1 - K*K  in Q31 */ 
    L_Extract(t0, &hi, &lo);              /* DPF format      */ 
    t0 = Mpy_32(alp_h , alp_l, hi, lo);   /* Alpha in Q31    */ 
 
    /* Normalize Alpha */ 
 
    j = norm_l(t0); 
    t0 = L_shl(t0, j); 
    L_Extract(t0, &alp_h, &alp_l);         /* DPF format    */ 
    alp_exp = add(alp_exp, j);             /* Add normalization to alp_exp */ 
 
    /* A[j] = An[j] */ 
 
    for(j=1; j<=i; j++) 
    { 
      Ah[j] =Anh[j]; 
      Al[j] =Anl[j]; 
    } 
  } 
 
  *Err = shr(alp_h, alp_exp); 
 
  /* Truncate A[i] in Q27 to Q12 with rounding */ 
 
  A[0] = 4096; 
  for(i=1; i<=M; i++) 
  { 
    t0   = L_Comp(Ah[i], Al[i]); 
    old_A[i] = A[i] = round(L_shl(t0, 1)); 
  } 
  old_rc[0] = rc[0]; 
  old_rc[1] = rc[1]; 
 
  return; 
} 
 
 
 
 
/*-------------------------------------------------------------* 
 *  procedure Az_lsp:                                          * 
 *            ~~~~~~                                           * 
 *   Compute the LSPs from  the LPC coefficients  (order=10)   * 
 *-------------------------------------------------------------*/ 
 
/* local function */ 
 
static Word16 Chebps_11(Word16 x, Word16 f[], Word16 n); 
static Word16 Chebps_10(Word16 x, Word16 f[], Word16 n); 
 
void Az_lsp( 
  Word16 a[],        /* (i) Q12 : predictor coefficients              */ 
  Word16 lsp[],      /* (o) Q15 : line spectral pairs                 */ 
  Word16 old_lsp[]   /* (i)     : old lsp[] (in case not found 10 roots) */ 
) 
{ 
 Word16 i, j, nf, ip; 
 Word16 xlow, ylow, xhigh, yhigh, xmid, ymid, xint; 
 Word16 x, y, sign, exp; 
 Word16 *coef; 
 Word16 f1[M/2+1], f2[M/2+1]; 
 Word32 t0, L_temp; 
 Flag   ovf_coef; 
 Word16 (*pChebps)(Word16 x, Word16 f[], Word16 n); 
 
/*-------------------------------------------------------------* 
 *  find the sum and diff. pol. F1(z) and F2(z)                * 
 *    F1(z) <--- F1(z)/(1+z**-1) & F2(z) <--- F2(z)/(1-z**-1)  * 
 *                                                             * 
 * f1[0] = 1.0;                                                * 
 * f2[0] = 1.0;                                                * 
 *                                                             * 
 * for (i = 0; i< NC; i++)                                     * 
 * {                                                           * 
 *   f1[i+1] = a[i+1] + a[M-i] - f1[i] ;                       * 
 *   f2[i+1] = a[i+1] - a[M-i] + f2[i] ;                       * 
 * }                                                           * 
 *-------------------------------------------------------------*/ 
 
 ovf_coef = 0; 
 pChebps = Chebps_11; 
 
 f1[0] = 2048;          /* f1[0] = 1.0 is in Q11 */ 
 f2[0] = 2048;          /* f2[0] = 1.0 is in Q11 */ 
 
 for (i = 0; i< NC; i++) 
 { 
   Overflow = 0; 
   t0 = L_mult(a[i+1], 16384);          /* x = (a[i+1] + a[M-i]) >> 1        */ 
   t0 = L_mac(t0, a[M-i], 16384);       /*    -> From Q12 to Q11             */ 
   x  = extract_h(t0); 
   if ( Overflow ) { 
     ovf_coef = 1;      } 
 
   Overflow = 0; 
   f1[i+1] = sub(x, f1[i]);    /* f1[i+1] = a[i+1] + a[M-i] - f1[i] */ 
   if ( Overflow ) { 
     ovf_coef = 1;      } 
 
   Overflow = 0; 
   t0 = L_mult(a[i+1], 16384);          /* x = (a[i+1] - a[M-i]) >> 1        */ 
   t0 = L_msu(t0, a[M-i], 16384);       /*    -> From Q12 to Q11             */ 
   x  = extract_h(t0); 
   if ( Overflow ) { 
     ovf_coef = 1;      } 
 
   Overflow = 0; 
   f2[i+1] = add(x, f2[i]);    /* f2[i+1] = a[i+1] - a[M-i] + f2[i] */ 
   if ( Overflow ) { 
     ovf_coef = 1;      } 
 } 
 
 if ( ovf_coef ) { 
   /*printf("===== OVF ovf_coef =====\n");*/ 
 
   pChebps = Chebps_10; 
 
   f1[0] = 1024;          /* f1[0] = 1.0 is in Q10 */ 
   f2[0] = 1024;          /* f2[0] = 1.0 is in Q10 */ 
 
   for (i = 0; i< NC; i++) 
   { 
     t0 = L_mult(a[i+1], 8192);          /* x = (a[i+1] + a[M-i]) >> 1        */ 
     t0 = L_mac(t0, a[M-i], 8192);       /*    -> From Q11 to Q10             */ 
     x  = extract_h(t0); 
     f1[i+1] = sub(x, f1[i]);    /* f1[i+1] = a[i+1] + a[M-i] - f1[i] */ 
 
     t0 = L_mult(a[i+1], 8192);          /* x = (a[i+1] - a[M-i]) >> 1        */ 
     t0 = L_msu(t0, a[M-i], 8192);       /*    -> From Q11 to Q10             */ 
     x  = extract_h(t0); 
     f2[i+1] = add(x, f2[i]);    /* f2[i+1] = a[i+1] - a[M-i] + f2[i] */ 
   } 
 } 
 
/*-------------------------------------------------------------* 
 * find the LSPs using the Chebichev pol. evaluation           * 
 *-------------------------------------------------------------*/ 
 
 nf=0;          /* number of found frequencies */ 
 ip=0;          /* indicator for f1 or f2      */ 
 
 coef = f1; 
 
 xlow = grid[0]; 
 ylow = (*pChebps)(xlow, coef, NC); 
 
 j = 0; 
 while ( (nf < M) && (j < GRID_POINTS) ) 
 { 
   j =add(j,1); 
   xhigh = xlow; 
   yhigh = ylow; 
   xlow  = grid[j]; 
   ylow  = (*pChebps)(xlow,coef,NC); 
 
   L_temp = L_mult(ylow ,yhigh); 
   if ( L_temp <= (Word32)0) 
   { 
 
     /* divide 4 times the interval */ 
 
     for (i = 0; i < 4; i++) 
     { 
       xmid = add( shr(xlow, 1) , shr(xhigh, 1)); /* xmid = (xlow + xhigh)/2 */ 
 
       ymid = (*pChebps)(xmid,coef,NC); 
 
       L_temp = L_mult(ylow,ymid); 
       if ( L_temp <= (Word32)0) 
       { 
         yhigh = ymid; 
         xhigh = xmid; 
       } 
       else 
       { 
         ylow = ymid; 
         xlow = xmid; 
       } 
     } 
 
    /*-------------------------------------------------------------* 
     * Linear interpolation                                        * 
     *    xint = xlow - ylow*(xhigh-xlow)/(yhigh-ylow);            * 
     *-------------------------------------------------------------*/ 
 
     x   = sub(xhigh, xlow); 
     y   = sub(yhigh, ylow); 
 
     if(y == 0) 
     { 
       xint = xlow; 
     } 
     else 
     { 
       sign= y; 
       y   = abs_s(y); 
       exp = norm_s(y); 
       y   = shl(y, exp); 
       y   = div_s( (Word16)16383, y); 
       t0  = L_mult(x, y); 
       t0  = L_shr(t0, sub(20, exp) ); 
       y   = extract_l(t0);            /* y= (xhigh-xlow)/(yhigh-ylow) in Q11 */ 
 
       if(sign < 0) y = negate(y); 
 
       t0   = L_mult(ylow, y);                  /* result in Q26 */ 
       t0   = L_shr(t0, 11);                    /* result in Q15 */ 
       xint = sub(xlow, extract_l(t0));         /* xint = xlow - ylow*y */ 
     } 
 
     lsp[nf] = xint; 
     xlow    = xint; 
     nf =add(nf,1); 
 
     if(ip == 0) 
     { 
       ip = 1; 
       coef = f2; 
     } 
     else 
     { 
       ip = 0; 
       coef = f1; 
     } 
     ylow = (*pChebps)(xlow,coef,NC); 
 
   } 
 } 
 
 /* Check if M roots found */ 
 
 if( sub(nf, M) < 0) 
 { 
    for(i=0; i