www.pudn.com > g729.rar > postfilt.c


/* 
   ITU-T G.729A Speech Coder    ANSI-C Source Code 
   Version 1.1    Last modified: September 1996 
 
   Copyright (c) 1996, 
   AT&T, France Telecom, NTT, Universite de Sherbrooke 
   All rights reserved. 
*/ 
 
/*------------------------------------------------------------------------* 
 *                         POSTFILTER.C                                   * 
 *------------------------------------------------------------------------* 
 * Performs adaptive postfiltering on the synthesis speech                * 
 * This file contains all functions related to the post filter.           * 
 *------------------------------------------------------------------------*/ 
 
#include "typedef.h" 
#include "basic_op.h" 
#include "ld8a.h" 
#include "oper_32b.h" 
 
/*---------------------------------------------------------------* 
 *    Postfilter constant parameters (defined in "ld8a.h")       * 
 *---------------------------------------------------------------* 
 *   L_FRAME     : Frame size.                                   * 
 *   L_SUBFR     : Sub-frame size.                               * 
 *   M           : LPC order.                                    * 
 *   MP1         : LPC order+1                                   * 
 *   PIT_MAX     : Maximum pitch lag.                            * 
 *   GAMMA2_PST  : Formant postfiltering factor (numerator)      * 
 *   GAMMA1_PST  : Formant postfiltering factor (denominator)    * 
 *   GAMMAP      : Harmonic postfiltering factor                 * 
 *   MU          : Factor for tilt compensation filter           * 
 *   AGC_FAC     : Factor for automatic gain control             * 
 *---------------------------------------------------------------*/ 
 
 
/*------------------------------------------------------------* 
 *   static vectors                                           * 
 *------------------------------------------------------------*/ 
 
        /* inverse filtered synthesis (with A(z/GAMMA2_PST))   */ 
 
static Word16 res2_buf[PIT_MAX+L_SUBFR]; 
static Word16 *res2; 
static Word16 scal_res2_buf[PIT_MAX+L_SUBFR]; 
static Word16 *scal_res2; 
 
        /* memory of filter 1/A(z/GAMMA1_PST) */ 
 
static Word16 mem_syn_pst[M]; 
 
/*---------------------------------------------------------------* 
 * Procedure    Init_Post_Filter:                                * 
 *              ~~~~~~~~~~~~~~~~                                 * 
 *  Initializes the postfilter parameters:                       * 
 *---------------------------------------------------------------*/ 
 
void Init_Post_Filter(void) 
{ 
  res2  = res2_buf + PIT_MAX; 
  scal_res2  = scal_res2_buf + PIT_MAX; 
 
  Set_zero(mem_syn_pst, M); 
  Set_zero(res2_buf, PIT_MAX+L_SUBFR); 
  Set_zero(scal_res2_buf, PIT_MAX+L_SUBFR); 
 
  return; 
} 
 
 
 
 
/*------------------------------------------------------------------------* 
 *  Procedure     Post_Filter:                                            * 
 *                ~~~~~~~~~~~                                             * 
 *------------------------------------------------------------------------* 
 *  The postfiltering process is described as follows:                    * 
 *                                                                        * 
 *  - inverse filtering of syn[] through A(z/GAMMA2_PST) to get res2[]    * 
 *  - use res2[] to compute pitch parameters                              * 
 *  - perform pitch postfiltering                                         * 
 *  - tilt compensation filtering; 1 - MU*k*z^-1                          * 
 *  - synthesis filtering through 1/A(z/GAMMA1_PST)                       * 
 *  - adaptive gain control                                               * 
 *------------------------------------------------------------------------*/ 
 
 
 
void Post_Filter( 
  Word16 *syn,       /* in/out: synthesis speech (postfiltered is output)    */ 
  Word16 *Az_4,      /* input : interpolated LPC parameters in all subframes */ 
  Word16 *T          /* input : decoded pitch lags in all subframes          */ 
) 
{ 
 /*-------------------------------------------------------------------* 
  *           Declaration of parameters                               * 
  *-------------------------------------------------------------------*/ 
 
 Word16 res2_pst[L_SUBFR];  /* res2[] after pitch postfiltering */ 
 Word16 syn_pst[L_FRAME];   /* post filtered synthesis speech   */ 
 
 Word16 Ap3[MP1], Ap4[MP1];  /* bandwidth expanded LP parameters */ 
 
 Word16 *Az;                 /* pointer to Az_4:                 */ 
                             /*  LPC parameters in each subframe */ 
 Word16   t0_max, t0_min;    /* closed-loop pitch search range   */ 
 Word16   i_subfr;           /* index for beginning of subframe  */ 
 
 Word16 h[L_H]; 
 
 Word16  i, j; 
 Word16  temp1, temp2; 
 Word32  L_tmp; 
 
   /*-----------------------------------------------------* 
    * Post filtering                                      * 
    *-----------------------------------------------------*/ 
 
    Az = Az_4; 
 
    for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) 
    { 
      /* Find pitch range t0_min - t0_max */ 
 
      t0_min = sub(*T++, 3); 
      t0_max = add(t0_min, 6); 
      if (sub(t0_max, PIT_MAX) > 0) { 
        t0_max = PIT_MAX; 
        t0_min = sub(t0_max, 6); 
      } 
 
      /* Find weighted filter coefficients Ap3[] and ap[4] */ 
 
      Weight_Az(Az, GAMMA2_PST, M, Ap3); 
      Weight_Az(Az, GAMMA1_PST, M, Ap4); 
 
      /* filtering of synthesis speech by A(z/GAMMA2_PST) to find res2[] */ 
 
      Residu(Ap3, &syn[i_subfr], res2, L_SUBFR); 
 
      /* scaling of "res2[]" to avoid energy overflow */ 
 
      for (j=0; j (Word32)0) 
    { 
      cor_max = corr; 
      t0 = i; 
    } 
    deb_sig--; 
  } 
 
  /* Compute the energy of the signal delayed by t0 */ 
 
  ener = 1; 
  p = scal_sig - t0; 
  for ( i=0; i temp) 
  { 
    temp = ener; 
  } 
  if (ener0 > temp) 
  { 
    temp = ener0; 
  } 
  j = norm_l(temp); 
  cmax = round(L_shl(cor_max, j)); 
  en = round(L_shl(ener, j)); 
  en0 = round(L_shl(ener0, j)); 
 
  /* prediction gain (dB)= -10 log(1-cor_max*cor_max/(ener*ener0)) */ 
 
  /* temp = (cor_max * cor_max) - (0.5 * ener * ener0)  */ 
  temp = L_mult(cmax, cmax); 
  temp = L_sub(temp, L_shr(L_mult(en, en0), 1)); 
 
  if (temp < (Word32)0)           /* if prediction gain < 3 dB   */ 
  {                               /* switch off pitch postfilter */ 
    for (i = 0; i < L_subfr; i++) 
      signal_pst[i] = signal[i]; 
    return; 
  } 
 
  if (sub(cmax, en) > 0)      /* if pitch gain > 1 */ 
  { 
    g0 = INV_GAMMAP; 
    gain = GAMMAP_2; 
  } 
  else { 
    cmax = shr(mult(cmax, GAMMAP), 1);  /* cmax(Q14) = cmax(Q15) * GAMMAP */ 
    en = shr(en, 1);          /* Q14 */ 
    i = add(cmax, en); 
    if(i > 0) 
    { 
      gain = div_s(cmax, i);    /* gain(Q15) = cor_max/(cor_max+ener)  */ 
      g0 = sub(32767, gain);    /* g0(Q15) = 1 - gain */ 
    } 
    else 
    { 
      g0 =  32767; 
      gain = 0; 
    } 
  } 
 
 
  for (i = 0; i < L_subfr; i++) 
  { 
    /* signal_pst[i] = g0*signal[i] + gain*signal[i-t0]; */ 
 
    signal_pst[i] = add(mult(g0, signal[i]), mult(gain, signal[i-t0])); 
 
  } 
 
  return; 
} 
 
 
/*---------------------------------------------------------------------* 
 * routine preemphasis()                                               * 
 * ~~~~~~~~~~~~~~~~~~~~~                                               * 
 * Preemphasis: filtering through 1 - g z^-1                           * 
 *---------------------------------------------------------------------*/ 
 
void preemphasis( 
  Word16 *signal,  /* (i/o)   : input signal overwritten by the output */ 
  Word16 g,        /* (i) Q15 : preemphasis coefficient                */ 
  Word16 L         /* (i)     : size of filtering                      */ 
) 
{ 
  static Word16 mem_pre = 0; 
  Word16 *p1, *p2, temp, i; 
 
  p1 = signal + L - 1; 
  p2 = p1 - 1; 
  temp = *p1; 
 
  for (i = 0; i <= L-2; i++) 
  { 
    *p1-- = sub(*p1, mult(g, *p2--)); 
  } 
 
  *p1 = sub(*p1, mult(g, mem_pre)); 
 
  mem_pre = temp; 
 
  return; 
} 
 
 
 
/*----------------------------------------------------------------------* 
 *   routine agc()                                                      * 
 *   ~~~~~~~~~~~~~                                                      * 
 * Scale the postfilter output on a subframe basis by automatic control * 
 * of the subframe gain.                                                * 
 *  gain[n] = AGC_FAC * gain[n-1] + (1 - AGC_FAC) g_in/g_out            * 
 *----------------------------------------------------------------------*/ 
 
void agc( 
  Word16 *sig_in,   /* (i)     : postfilter input signal  */ 
  Word16 *sig_out,  /* (i/o)   : postfilter output signal */ 
  Word16 l_trm      /* (i)     : subframe size            */ 
) 
{ 
  static Word16 past_gain=4096;         /* past_gain = 1.0 (Q12) */ 
  Word16 i, exp; 
  Word16 gain_in, gain_out, g0, gain;                     /* Q12 */ 
  Word32 s; 
 
  Word16 signal[L_SUBFR]; 
 
  /* calculate gain_out with exponent */ 
 
  for(i=0; i