www.pudn.com > G.723.1_c.rar > LPC.C


/* 
** 
** File:    lpc.c 
** 
** Description: Functions that implement linear predictive coding  
**      (LPC) operations.   
** 
** Functions: 
** 
**  Computing LPC coefficients: 
** 
**      Comp_Lpc() 
**      Durbin() 
** 
**  Perceptual noise weighting: 
** 
**      Wght_Lpc() 
**      Error_Wght() 
** 
**  Computing combined impulse response: 
** 
**      Comp_Ir() 
** 
**  Computing ringing response: 
** 
**      Sub_Ring() 
**      Upd_Ring() 
** 
**  Synthesizing speech: 
** 
**      Synt() 
**      Spf() 
*/ 
 
/* 
    ITU-T G.723 Speech Coder   ANSI-C Source Code     Version 5.00 
    copyright (c) 1995, AudioCodes, DSP Group, France Telecom, 
    Universite de Sherbrooke.  All rights reserved. 
*/ 
 
#include  
 
#include "typedef.h" 
#include "basop.h" 
#include "cst_lbc.h" 
#include "tab_lbc.h" 
#include "lbccodec.h" 
#include "coder.h" 
#include "decod.h" 
#include "util_lbc.h" 
#include "lpc.h" 
#include "cod_cng.h" 
 
#include "printdata.h" 
#include  
/* 
** 
** Function:        Comp_Lpc() 
** 
** Description:     Computes the tenth-order LPC filters for an 
**          entire frame.  For each subframe, a 
**          Hamming-windowed block of 180 samples, 
**          centered around the subframe, is used to 
**          compute eleven autocorrelation coefficients. 
**          The Levinson-Durbin algorithm then generates 
**          the LPC coefficients.  This function requires 
**          a look-ahead of one subframe, and hence 
**          introduces a 7.5 ms encoding delay. 
** 
** Links to text:   Section 2.4 
** 
** Arguments: 
** 
**  Word16 *UnqLpc      Empty Buffer 
**  Word16 PrevDat[]    Previous 2 subframes of samples (120 words) 
**  Word16 DataBuff[]   Current frame of samples (240 words) 
** 
** Outputs: 
 
** 
**  Word16 UnqLpc[]     LPC coefficients for entire frame (40 words) 
** 
** Return value:    None 
** 
*/ 
void  Comp_Lpc( Word16 *UnqLpc, Word16 *PrevDat, Word16 *DataBuff ) 
{ 
    int   i,j,k ; 
 
    Word16   Dpnt[Frame+LpcFrame-SubFrLen] ; 
    Word16   Vect[LpcFrame] ; 
    Word16   Acf_sf[LpcOrderP1*SubFrames]; 
    Word16   ShAcf_sf[SubFrames]; 
    Word16   Exp   ; 
    Word16   *curAcf; 
    Word16   Pk2; 
 
    Word32   Acc0,Acc1   ; 
 
 
    /* 
     * Generate a buffer of 360 samples.  This consists of 120 samples 
     * from the previous frame and 240 samples from the current frame. 
     */ 
    for ( i = 0 ; i < LpcFrame-SubFrLen ; i ++ ) 
        Dpnt[i] = PrevDat[i] ; 
    for ( i = 0 ; i < Frame ; i ++ ) 
        Dpnt[i+LpcFrame-SubFrLen] = DataBuff[i] ; 
 
 
    /* 
     * Repeat for all subframes 
     */ 
    curAcf = Acf_sf; 
    for ( k = 0 ; k < SubFrames ; k ++ ) { 
 
 
        /* 
        * Do windowing 
        */ 
 
        /* Get block of 180 samples centered around current subframe */ 
        for ( i = 0 ; i < LpcFrame ; i ++ ) 
            Vect[i] = Dpnt[k*SubFrLen+i] ; 
 
        /* Normalize */ 
        ShAcf_sf[k] = Vec_Norm( Vect, (Word16) LpcFrame ) ; 
		//printData(ShAcf_sf,SubFrames,1); 
        /* Apply the Hamming window */ 
        for ( i = 0 ; i < LpcFrame ; i ++ ) 
            Vect[i] = mult_r(Vect[i], HammingWindowTable[i]) ; 
 
		//printData(Vect,LpcFrame,1); 
        /* 
        * Compute the autocorrelation coefficients 
        */ 
 
        /* Compute the zeroth-order coefficient (energy) */ 
        Acc1 = (Word32) 0 ; 
        for ( i = 0 ; i < LpcFrame ; i ++ ) { 
            Acc0 = L_mult( Vect[i], Vect[i] ) ; 
            Acc0 = L_shr( Acc0, (Word16) 1 ) ; 
            Acc1 = L_add( Acc1, Acc0 ) ; 
        } 
 
        /* Apply a white noise correction factor of (1025/1024) */ 
        Acc0 = L_shr( Acc1, (Word16) RidgeFact ) ; 
        Acc1 = L_add( Acc1, Acc0 ) ; 
 
        /* Normalize the energy */ 
        Exp = norm_l( Acc1 ) ; 
        Acc1 = L_shl( Acc1, Exp ) ; 
 
        curAcf[0] = round( Acc1 ) ; 
        if(curAcf[0] == 0) { 
            for ( i = 1 ; i <= LpcOrder ; i ++ ) 
                curAcf[i] = 0; 
            ShAcf_sf[k] = 40; 
        } 
 
        else { 
            /* Compute the rest of the autocorrelation coefficients. 
               Multiply them by a binomial coefficients lag window. */ 
            for ( i = 1 ; i <= LpcOrder ; i ++ ) { 
                Acc1 = (Word32) 0 ; 
                for ( j = i ; j < LpcFrame ; j ++ ) { 
                    Acc0 = L_mult( Vect[j], Vect[j-i] ) ; 
                    Acc0 = L_shr( Acc0, (Word16) 1 ) ; 
                    Acc1 = L_add( Acc1, Acc0 ) ; 
                } 
                Acc0 = L_shl( Acc1, Exp ) ; 
                Acc0 = L_mls( Acc0, BinomialWindowTable[i-1] ) ; 
                curAcf[i] = round(Acc0) ; 
            } 
            /* Save Acf scaling factor */ 
            ShAcf_sf[k] = add(Exp, shl(ShAcf_sf[k], 1)); 
        } 
 
        /* 
         * Apply the Levinson-Durbin algorithm to generate the LPC 
         * coefficients 
        */ 
        Durbin( &UnqLpc[k*LpcOrder], &curAcf[1], curAcf[0], &Pk2 ); 
        CodStat.SinDet <<= 1; 
        if ( Pk2 > 0x799a ) { 
            CodStat.SinDet ++ ; 
        } 
        curAcf += LpcOrderP1; 
    } 
 
    /* Update sine detector */ 
    CodStat.SinDet &= 0x7fff ; 
 
    j = CodStat.SinDet ; 
    k = 0 ; 
    for ( i = 0 ; i < 15 ; i ++ ) { 
        k += j & 1 ; 
        j >>= 1 ; 
    } 
    if ( k >= 14 ) 
        CodStat.SinDet |= 0x8000 ; 
 
    /* Update CNG Acf memories */ 
    Update_Acf(Acf_sf, ShAcf_sf); 
 
 
} 
 
 
/* 
** 
** Function:        Durbin() 
** 
** Description:     Implements the Levinson-Durbin algorithm for a 
**          subframe.  The Levinson-Durbin algorithm 
**          recursively computes the minimum mean-squared 
**          error (MMSE) linear prediction filter based on the 
**          estimated autocorrelation coefficients. 
** 
** Links to text:   Section 2.4 
** 
** Arguments:        
** 
**  Word16 *Lpc Empty buffer 
**  Word16 Corr[]   First- through tenth-order autocorrelations (10 words) 
**  Word16 Err  Zeroth-order autocorrelation, or energy 
** 
** Outputs:      
** 
**  Word16 Lpc[]    LPC coefficients (10 words) 
** 
** Return value:    The error 
** 
*/ 
Word16  Durbin( Word16 *Lpc, Word16 *Corr, Word16 Err, Word16 *Pk2 ) 
{ 
    int   i,j   ; 
 
    Word16   Temp[LpcOrder] ; 
    Word16   Pk ; 
 
    Word32   Acc0,Acc1,Acc2 ; 
 
 /* 
  * Initialize the LPC vector 
  */ 
    for ( i = 0 ; i < LpcOrder ; i ++ ) 
        Lpc[i] = (Word16) 0 ; 
 
 /* 
  * Do the recursion.  At the ith step, the algorithm computes the 
  * (i+1)th - order MMSE linear prediction filter. 
  */ 
    for ( i = 0 ; i < LpcOrder ; i ++ ) { 
 
/* 
 * Compute the partial correlation (parcor) coefficient 
 */ 
 
        /* Start parcor computation */ 
        Acc0 = L_deposit_h( Corr[i] ) ; 
        Acc0 = L_shr( Acc0, (Word16) 2 ) ; 
        for ( j = 0 ; j < i ; j ++ ) 
            Acc0 = L_msu( Acc0, Lpc[j], Corr[i-j-1] ) ; 
        Acc0 = L_shl( Acc0, (Word16) 2 ) ; 
 
        /* Save sign */ 
        Acc1 = Acc0 ; 
        Acc0 = L_abs( Acc0 ) ; 
 
        /* Finish parcor computation */ 
        Acc2 = L_deposit_h( Err ) ; 
        if ( Acc0 >= Acc2 ) { 
            *Pk2 = 32767; 
            break ; 
        } 
 
        Pk = div_l( Acc0, Err ) ; 
 
        if ( Acc1 >= 0 ) 
            Pk = negate(Pk) ; 
 
 /* 
  * Sine detector 
  */ 
        if ( i == 1 ) *Pk2 = Pk; 
 
 /* 
  * Compute the ith LPC coefficient 
  */ 
        Acc0 = L_deposit_h( negate(Pk) ) ; 
        Acc0 = L_shr( Acc0, (Word16) 2 ) ; 
        Lpc[i] = round( Acc0 ) ; 
 
 /* 
  * Update the prediction error 
  */ 
        Acc1 = L_mls( Acc1, Pk ) ; 
        Acc1 = L_add( Acc1, Acc2 ) ; 
        Err = round( Acc1 ) ; 
 
 /* 
  * Compute the remaining LPC coefficients 
  */ 
        for ( j = 0 ; j < i ; j ++ ) 
            Temp[j] = Lpc[j] ; 
 
        for ( j = 0 ; j < i ; j ++ ) { 
            Acc0 = L_deposit_h( Lpc[j] ) ; 
            Acc0 = L_mac( Acc0, Pk, Temp[i-j-1] ) ; 
            Lpc[j] = round( Acc0 ) ; 
        } 
    } 
 
	 
    return Err ; 
} 
 
/* 
** 
** Function:        Wght_Lpc() 
** 
** Description:     Computes the formant perceptual weighting 
**          filter coefficients for a frame.  These 
**          coefficients are geometrically scaled versions 
**          of the unquantized LPC coefficients. 
** 
** Links to text:   Section 2.8   
** 
** Arguments:        
** 
**  Word16 *PerLpc      Empty Buffer 
**  Word16 UnqLpc[]     Unquantized LPC coefficients (40 words) 
** 
** Outputs:      
 
** 
**  Word16 PerLpc[]     Perceptual weighting filter coefficients 
**              (80 words) 
** 
** Return value:    None 
** 
*/ 
void  Wght_Lpc( Word16 *PerLpc, Word16 *UnqLpc ) 
{ 
    int   i,j   ; 
 
 
 /* 
  * Do for all subframes 
  */ 
    for ( i = 0 ; i < SubFrames ; i ++ ) { 
 
 
 /* 
  * Compute the jth FIR coefficient by multiplying the jth LPC 
  * coefficient by (0.9)^j. 
  */ 
        for ( j = 0 ; j < LpcOrder ; j ++ ) 
            PerLpc[j] = mult_r( UnqLpc[j], PerFiltZeroTable[j] ) ; 
        PerLpc += LpcOrder ; 
 
 
/* 
 * Compute the jth IIR coefficient by multiplying the jth LPC 
 * coefficient by (0.5)^j. 
 */ 
        for ( j = 0 ; j < LpcOrder ; j ++ ) 
            PerLpc[j] = mult_r( UnqLpc[j], PerFiltPoleTable[j] ) ; 
        PerLpc += LpcOrder ; 
        UnqLpc += LpcOrder ; 
    } 
 
} 
 
/* 
** 
** Function:        Error_Wght() 
** 
** Description:     Implements the formant perceptual weighting 
**          filter for a frame. This filter effectively 
**          deemphasizes the formant frequencies in the 
**          error signal. 
** 
** Links to text:   Section 2.8 
** 
** Arguments: 
** 
**  Word16 Dpnt[]       Highpass filtered speech x[n] (240 words) 
**  Word16 PerLpc[]     Filter coefficients (80 words) 
** 
** Inputs: 
** 
**  CodStat.WghtFirDl[] FIR filter memory from previous frame (10 words) 
**  CodStat.WghtIirDl[] IIR filter memory from previous frame (10 words) 
 
** 
** Outputs: 
** 
**  Word16 Dpnt[]       Weighted speech f[n] (240 words) 
** 
** Return value:    None 
** 
*/ 
void  Error_Wght( Word16 *Dpnt, Word16 *PerLpc ) 
{ 
    int   i,j,k ; 
	int	  temp  ;//仅为提高代码效率,无实际意义. 
    Word32   Acc0  ; 
 
 
/* 
 * Do for all subframes 
 */ 
    for ( k = 0 ; k < SubFrames ; k ++ ) { 
 
        for ( i = 0 ; i < SubFrLen ; i ++ ) { 
			 
			temp=SubFrLen-i; 
 
/* 
 * Do the FIR part 
 */ 
            /* Filter */ 
            Acc0 = L_mult( *Dpnt, (Word16) 0x2000 ) ; 
            for ( j = 0 ; j < LpcOrder ; j ++ ) 
                //Acc0 = L_msu( Acc0, PerLpc[j], CodStat.WghtFirDl[j] ) ; 
				Acc0 = L_msu( Acc0, PerLpc[j], CodStat.WghtFirDl[temp+j] ) ; 
 
            /* Update memory */ 
			/* 
            for ( j = LpcOrder-1 ; j > 0 ; j -- ) 
                CodStat.WghtFirDl[j] = CodStat.WghtFirDl[j-1] ; 
			*/ 
            //CodStat.WghtFirDl[0] = *Dpnt ; 
			CodStat.WghtFirDl[temp-1] = *Dpnt ; 
 
 /* 
  * Do the IIR part 
  */ 
 
            /* Filter */ 
            for ( j = 0 ; j < LpcOrder ; j ++ ) 
                //Acc0 = L_mac( Acc0, PerLpc[LpcOrder+j], 
                //                                    CodStat.WghtIirDl[j] ) ; 
                Acc0 = L_mac( Acc0, PerLpc[LpcOrder+j], 
                                                    CodStat.WghtIirDl[temp+j] ) ; 
			/* Update memory */ 
			/* 
            for ( j = LpcOrder-1 ; j > 0 ; j -- ) 
                CodStat.WghtIirDl[j] = CodStat.WghtIirDl[j-1] ; 
			*/ 
            Acc0 = L_shl( Acc0, (Word16) 2 ) ; 
 
            /* Update memory */ 
            //CodStat.WghtIirDl[0] = round( Acc0 ) ; 
            //*Dpnt ++ = CodStat.WghtIirDl[0] ; 
			CodStat.WghtIirDl[temp-1] = round( Acc0 ) ; 
            *Dpnt ++ = CodStat.WghtIirDl[temp-1] ; 
        } 
        PerLpc += 2*LpcOrder ; 
    } 
} 
 
/* 
** 
** Function:        Comp_Ir() 
** 
** Description:     Computes the combined impulse response of the 
**          formant perceptual weighting filter, harmonic 
**          noise shaping filter, and synthesis filter for 
**          a subframe. 
** 
** Links to text:   Section 2.12 
** 
** Arguments: 
** 
**  Word16 *ImpResp     Empty Buffer 
**  Word16 QntLpc[]     Quantized LPC coefficients (10 words) 
**  Word16 PerLpc[]     Perceptual filter coefficients (20 words) 
**  PWDEF Pw        Harmonic noise shaping filter parameters 
** 
** Outputs: 
** 
**  Word16 ImpResp[]    Combined impulse response (60 words) 
** 
** Return value:    None 
** 
*/ 
void  Comp_Ir( Word16 *ImpResp, Word16 *QntLpc, Word16 *PerLpc, PWDEF Pw ) 
{ 
    int   i,j   ; 
 
    Word16   FirDl[LpcOrder] ; 
    Word16   IirDl[LpcOrder] ; 
    Word16   Temp[PitchMax+SubFrLen] ; 
 
    Word32   Acc0,Acc1 ; 
 
 
 /* 
  * Clear all memory.  Impulse response calculation requires 
  * an all-zero initial state. 
  */ 
 
    /* Perceptual weighting filter */ 
    for ( i = 0 ; i < LpcOrder ; i ++ ) 
        FirDl[i] = IirDl[i] = (Word16) 0 ; 
 
    /* Harmonic noise shaping filter */ 
    for ( i = 0 ; i < PitchMax+SubFrLen ; i ++ ) 
        Temp[i] = (Word16) 0 ; 
 
 
 /* 
  * Input a single impulse 
  */ 
    Acc0 = (Word32) 0x04000000L ; 
 
 /* 
  * Do for all elements in a subframe 
  */ 
    for ( i = 0 ; i < SubFrLen ; i ++ ) { 
 
 /* 
  * Synthesis filter 
  */ 
        for ( j = 0 ; j < LpcOrder ; j ++ ) 
            Acc0 = L_mac( Acc0, QntLpc[j], FirDl[j] ) ; 
        Acc1 = L_shl( Acc0, (Word16) 2 ) ; 
 
 /* 
  * Perceptual weighting filter 
  */ 
 
        /* FIR part */ 
        for ( j = 0 ; j < LpcOrder ; j ++ ) 
            Acc0 = L_msu( Acc0, PerLpc[j], FirDl[j] ) ; 
                                Acc0 = L_shl( Acc0, (Word16) 1 ) ; 
        for ( j = LpcOrder-1 ; j > 0 ; j -- ) 
            FirDl[j] = FirDl[j-1] ; 
        FirDl[0] = round( Acc1 ) ; 
 
        /* Iir part */ 
        for ( j = 0 ; j < LpcOrder ; j ++ ) 
            Acc0 = L_mac( Acc0, PerLpc[LpcOrder+j], IirDl[j] ) ; 
        for ( j = LpcOrder-1 ; j > 0 ; j -- ) 
            IirDl[j] = IirDl[j-1] ; 
        Acc0 = L_shl( Acc0, (Word16) 2 ) ; 
        IirDl[0] = round( Acc0 ) ; 
        Temp[PitchMax+i] = IirDl[0] ; 
 
 /* 
  * Harmonic noise shaping filter 
  */ 
 
        Acc0 = L_deposit_h( IirDl[0] ) ; 
        Acc0 = L_msu( Acc0, Pw.Gain, Temp[PitchMax-Pw.Indx+i] ) ; 
        ImpResp[i] = round( Acc0 ) ; 
 
        Acc0 = (Word32) 0 ; 
    } 
} 
 
/* 
** 
** Function:        Sub_Ring() 
** 
** Description:     Computes the zero-input response of the 
**          combined formant perceptual weighting filter, 
**          harmonic noise shaping filter, and synthesis 
**          filter for a subframe.  Subtracts the 
**          zero-input response from the harmonic noise 
**          weighted speech vector to produce the target  
**          speech vector. 
** 
** Links to text:   Section 2.13 
** 
** Arguments:        
** 
**  Word16 Dpnt[]       Harmonic noise weighted vector w[n] (60 words) 
**  Word16 QntLpc[]     Quantized LPC coefficients (10 words) 
**  Word16 PerLpc[]     Perceptual filter coefficients (20 words) 
**  Word16 PrevErr[]    Harmonic noise shaping filter memory (145 words) 
**  PWDEF Pw        Harmonic noise shaping filter parameters 
**   
** Inputs: 
** 
**  CodStat.RingFirDl[] Perceptual weighting filter FIR memory from  
**               previous subframe (10 words) 
**  CodStat.RingIirDl[] Perceptual weighting filter IIR memory from  
**               previous subframe (10 words) 
** 
** Outputs:      
** 
**  Word16 Dpnt[]       Target vector t[n] (60 words) 
** 
** Return value:    None 
** 
*/ 
void  Sub_Ring( Word16 *Dpnt, Word16 *QntLpc, Word16 *PerLpc, Word16 
*PrevErr, PWDEF Pw ) 
{ 
    int   i,j   ; 
    Word32   Acc0,Acc1 ; 
 
    Word16   FirDl[LpcOrder] ; 
    Word16   IirDl[LpcOrder] ; 
    Word16   Temp[PitchMax+SubFrLen] ; 
 
 
 /* 
  * Initialize the memory 
  */ 
    for ( i = 0 ; i < PitchMax ; i ++ ) 
        Temp[i] = PrevErr[i] ; 
 
    for ( i = 0 ; i < LpcOrder ; i ++ ) { 
        FirDl[i] = CodStat.RingFirDl[i] ; 
        IirDl[i] = CodStat.RingIirDl[i] ; 
    } 
 
 /* 
  * Do for all elements in a subframe 
  */ 
    for ( i = 0 ; i < SubFrLen ; i ++ ) { 
 
 /* 
  * Input zero 
  */ 
        Acc0 = (Word32) 0 ; 
 
 /* 
  * Synthesis filter 
  */ 
        for ( j = 0 ; j < LpcOrder ; j ++ ) 
            Acc0 = L_mac( Acc0, QntLpc[j], FirDl[j] ) ; 
        Acc1 = L_shl( Acc0, (Word16) 2 ) ; 
 
 /* 
  * Perceptual weighting filter 
  */ 
 
        /* Fir part */ 
        for ( j = 0 ; j < LpcOrder ; j ++ ) 
            Acc0 = L_msu( Acc0, PerLpc[j], FirDl[j] ) ; 
        for ( j = LpcOrder-1 ; j > 0 ; j -- ) 
            FirDl[j] = FirDl[j-1] ; 
        FirDl[0] = round( Acc1 ) ; 
 
        /* Iir part */ 
        for ( j = 0 ; j < LpcOrder ; j ++ ) 
            Acc0 = L_mac( Acc0, PerLpc[LpcOrder+j], IirDl[j] ) ; 
        Acc0 = L_shl( Acc0, (Word16) 2 ) ; 
        for ( j = LpcOrder-1 ; j > 0 ; j -- ) 
            IirDl[j] = IirDl[j-1] ; 
        IirDl[0] = round( Acc0 ) ; 
        Temp[PitchMax+i] = IirDl[0] ; 
 
 /* 
  * Do the harmonic noise shaping filter and subtract the result 
  * from the harmonic noise weighted vector. 
  */ 
        Acc0 = L_deposit_h( sub( Dpnt[i], IirDl[0] ) ) ; 
        Acc0 = L_mac( Acc0, Pw.Gain, Temp[PitchMax-(int)Pw.Indx+i] ) ; 
        Dpnt[i] = round ( Acc0 ) ; 
    } 
} 
 
/* 
** 
** Function:        Upd_Ring() 
** 
** Description:     Updates the memory of the combined formant 
**          perceptual weighting filter, harmonic noise 
**          shaping filter, and synthesis filter for a 
**          subframe.  The update is done by passing the 
**          current subframe's excitation through the 
**          combined filter. 
** 
** Links to text:   Section 2.19 
** 
** Arguments:        
** 
**  Word16 Dpnt[]       Decoded excitation for the current subframe e[n]  
**               (60 words) 
**  Word16 QntLpc[]     Quantized LPC coefficients (10 words) 
**  Word16 PerLpc[]     Perceptual filter coefficients (20 words) 
**  Word16 PrevErr[]    Harmonic noise shaping filter memory (145 words) 
**   
** Inputs: 
** 
**  CodStat.RingFirDl[] Perceptual weighting filter FIR memory from  
 
**               previous subframe (10 words) 
**  CodStat.RingIirDl[] Perceptual weighting filter IIR memory from  
**               previous subframe (10 words) 
** 
** Outputs:      
** 
**  Word16 PrevErr[]    Updated harmonic noise shaping filter memory  
**  CodStat.RingFirDl[] Updated perceptual weighting filter FIR memory  
**  CodStat.RingIirDl[] Updated perceptual weighting filter IIR memory  
** 
** Return value:    None 
** 
*/ 
void  Upd_Ring( Word16 *Dpnt, Word16 *QntLpc, Word16 *PerLpc, Word16 
*PrevErr ) 
{ 
    int   i,j   ; 
 
    Word32   Acc0,Acc1   ; 
 
 
 /* 
  * Shift the harmonic noise shaping filter memory 
  */ 
    for ( i = SubFrLen ; i < PitchMax ; i ++ ) 
        PrevErr[i-SubFrLen] = PrevErr[i] ; 
 
 
 /* 
  * Do for all elements in the subframe 
  */ 
    for ( i = 0 ; i < SubFrLen ; i ++ ) { 
 
 /* 
  * Input the current subframe's excitation 
  */ 
        Acc0 = L_deposit_h( Dpnt[i] ) ; 
        Acc0 = L_shr( Acc0, (Word16) 3 ) ; 
 
 /* 
  * Synthesis filter 
  */ 
        for ( j = 0 ; j < LpcOrder ; j ++ ) 
            Acc0 = L_mac( Acc0, QntLpc[j], CodStat.RingFirDl[j] ) ; 
        Acc1 = L_shl( Acc0, (Word16) 2 ) ; 
 
        Dpnt[i] = shl( round( Acc1 ), (Word16) 1 ) ; 
 
 /* 
  * Perceptual weighting filter 
  */ 
 
        /* FIR part */ 
        for ( j = 0 ; j < LpcOrder ; j ++ ) 
            Acc0 = L_msu( Acc0, PerLpc[j], CodStat.RingFirDl[j] ) ; 
 
        /* Update FIR memory */ 
        for ( j = LpcOrder-1 ; j > 0 ; j -- ) 
            CodStat.RingFirDl[j] = CodStat.RingFirDl[j-1] ; 
        CodStat.RingFirDl[0] = round( Acc1 ) ; 
 
        /* IIR part */ 
        for ( j = 0 ; j < LpcOrder ; j ++ ) 
            Acc0 = L_mac( Acc0, PerLpc[LpcOrder+j], CodStat.RingIirDl[j] ) ; 
        Acc0 = L_shl( Acc0, (Word16) 2 ) ; 
 
        /* Update IIR memory */ 
        for ( j = LpcOrder-1 ; j > 0 ; j -- ) 
            CodStat.RingIirDl[j] = CodStat.RingIirDl[j-1] ; 
        CodStat.RingIirDl[0] = round( Acc0 ) ; 
 
        /* Update harmonic noise shaping memory */ 
        PrevErr[PitchMax-SubFrLen+i] = CodStat.RingIirDl[0] ; 
    } 
} 
 
/* 
** 
** Function:        Synt() 
** 
** Description:     Implements the decoder synthesis filter for a 
**          subframe.  This is a tenth-order IIR filter. 
** 
** Links to text:   Section 3.7 
** 
** Arguments:        
** 
**  Word16 Dpnt[]       Pitch-postfiltered excitation for the current 
**               subframe ppf[n] (60 words) 
**  Word16 Lpc[]        Quantized LPC coefficients (10 words) 
**   
** Inputs: 
** 
**  DecStat.SyntIirDl[] Synthesis filter memory from previous 
subframe (10 words) 
** 
** Outputs:      
** 
**  Word16 Dpnt[]       Synthesized speech vector sy[n] 
**  DecStat.SyntIirDl[] Updated synthesis filter memory  
** 
** Return value:    None 
** 
*/ 
void     Synt( Word16 *Dpnt, Word16 *Lpc ) 
{ 
    int   i,j   ; 
	int	  temp  ;//仅为提高代码效率,无实际意义. 
    Word32   Acc0  ; 
	 
	 
 /* 
  * Do for all elements in the subframe 
  */ 
    for ( i = 0 ; i < SubFrLen ; i ++ ) { 
		temp=SubFrLen-i; 
 /* 
  * Input the current subframe's excitation 
  */ 
		Acc0 = L_deposit_h( Dpnt[i] ) ; 
		Acc0 = L_shr( Acc0, (Word16) 3 ) ; 
 /* 
  * Synthesis 
  */ 
 
        /* Filter */ 
 
        for ( j = 0 ; j < LpcOrder ; j ++ ){ 
            Acc0 = L_mac( Acc0, Lpc[j], DecStat.SyntIirDl[temp+j] ) ;	 
		} 
 
        /* Update memory */ 
		/* 
        for ( j = LpcOrder-1 ; j > 0 ; j -- ) 
            DecStat.SyntIirDl[j] = DecStat.SyntIirDl[j-1] ; 
		*/ 
        Acc0 = L_shl( Acc0, (Word16) 2 ) ; 
		 
        //DecStat.SyntIirDl[0] = round( Acc0 ) ;		 
		DecStat.SyntIirDl[temp-1] = round( Acc0 ) ;	 
 
 /* 
  * Scale output if postfilter is off.  (Otherwise output is 
  * scaled by the gain scaling unit.) 
  */ 
		/* 
        if ( UsePf ) 
            Dpnt[i] = DecStat.SyntIirDl[0] ; 
        else 
            Dpnt[i] = shl( DecStat.SyntIirDl[0], (Word16) 1 ) ; 
		*/ 
		if ( UsePf ) 
            Dpnt[i] = DecStat.SyntIirDl[temp-1] ; 
        else 
            Dpnt[i] = shl( DecStat.SyntIirDl[temp-1], (Word16) 1 ) ; 
    }	 
	 
	/* Update memory , 这样由原来的每个样值需要更新1次,变为60个样值才更新一次.*/ 
	 
    //for ( j = LpcOrder-1 ; j > 0 ; j -- ) 
    //   DecStat.SyntIirDl[j] = DecStat.SyntIirDl[j-1] ; 
	memcpy(&DecStat.SyntIirDl[SubFrLen],&DecStat.SyntIirDl[0],LpcOrder*2); 
	//for ( j = 0 ; j < LpcOrder ; j ++ ) 
    //   DecStat.SyntIirDl[j+SubFrLen] = DecStat.SyntIirDl[j] ; 
 
} 
 
/* 
** 
** Function:        Spf() 
** 
** Description:     Implements the formant postfilter for a 
**          subframe.  The formant postfilter is a 
**          10-pole, 10-zero ARMA filter followed by a 
**          single-tap tilt compensation filter. 
** 
** Links to text:   Section 3.8 
** 
** Arguments: 
** 
**  Word16 Tv[]     Synthesized speech vector sy[n] (60 words) 
**  Word16 Lpc[]        Quantized LPC coefficients (10 words) 
** 
** Inputs: 
** 
**  DecStat.PostIirDl[] Postfilter IIR memory from previous 
subframe (10 words) 
**  DecStat.PostFirDl[] Postfilter FIR memory from previous 
subframe (10 words) 
**  DecStat.Park        Previous value of compensation filter parameter 
** 
** Outputs: 
** 
**  Word16 Tv[]     Postfiltered speech vector pf[n] (60 words) 
**  DecStat.PostIirDl[] Updated postfilter IIR memory 
**  DecStat.PostFirDl[] Updated postfilter FIR memory 
**  DecStat.Park        Updated compensation filter parameter 
** 
** Return value: Input vector energy 
** 
*/ 
Word32  Spf( Word16 *Tv, Word16 *Lpc ) 
{ 
    int   i,j   ; 
	int	  temp  ;//仅为提高代码效率,无实际意义. 
 
    Word32   Acc0,Acc1   ; 
    Word32   Sen ; 
    Word16   Tmp ; 
    Word16   Exp ; 
 
    Word16   FirCoef[LpcOrder] ; 
    Word16   IirCoef[LpcOrder] ; 
 
    Word16   TmpVect[SubFrLen] ; 
 
 /* 
  * Compute ARMA coefficients.  Compute the jth FIR coefficient by 
  * multiplying the jth quantized LPC coefficient by (0.65)^j. 
  * Compute the jth IIR coefficient by multiplying the jth quantized 
  * LPC coefficient by (0.75)^j.  This emphasizes the formants in 
  * the frequency response. 
  */ 
    for ( i = 0 ; i < LpcOrder ; i ++ ) { 
        FirCoef[i] = mult_r( Lpc[i], PostFiltZeroTable[i] ) ; 
        IirCoef[i] = mult_r( Lpc[i], PostFiltPoleTable[i] ) ; 
    } 
 
 /* 
  * Normalize the speech vector. 
  */ 
    for ( i = 0 ; i < SubFrLen ; i ++ ) 
        TmpVect[i] = Tv[i] ; 
    Exp = Vec_Norm( TmpVect, (Word16) SubFrLen ) ; 
 
 /* 
  * Compute the first two autocorrelation coefficients R[0] and R[1] 
  */ 
    Acc0 = (Word32) 0 ; 
    Acc1 = L_mult( TmpVect[0], TmpVect[0] ) ; 
    for ( i = 1 ; i < SubFrLen ; i ++ ) { 
        Acc0 = L_mac( Acc0, TmpVect[i], TmpVect[i-1] ) ; 
        Acc1 = L_mac( Acc1, TmpVect[i], TmpVect[i] ) ; 
    } 
 
 /* 
  * Scale the energy for the later use. 
  */ 
    Sen = L_shr( Acc1, (Word16)(2*Exp + 4) ) ; 
 
 /* 
  * Compute the first-order partial correlation coefficient of the 
  * input speech vector. 
  */ 
    Tmp = extract_h( Acc1 ) ; 
    if ( Tmp != (Word16) 0 ) { 
 
        /* Compute first parkor */ 
        Acc0 = L_shr( Acc0, (Word16) 1 ) ; 
        Acc1 = Acc0 ; 
        Acc0 = L_abs( Acc0 ) ; 
 
        Tmp = div_l( Acc0, Tmp ) ; 
 
        if ( Acc1 < (Word32) 0 ) 
            Tmp = negate( Tmp ) ; 
    } 
    else 
        Tmp = (Word16) 0 ; 
 
 /* 
  * Compute the compensation filter parameter and update the memory 
  */ 
    Acc0 = L_deposit_h( DecStat.Park ) ; 
    Acc0 = L_msu( Acc0, DecStat.Park, (Word16) 0x2000 ) ; 
    Acc0 = L_mac( Acc0, Tmp, (Word16) 0x2000 ) ; 
    DecStat.Park = round( Acc0 ) ;/*(1-1/4)k1old+(1/4)k,qfg add*/ 
 
    Tmp  = mult( DecStat.Park, PreCoef ) ; 
    Tmp &= (Word16) 0xfffc ; 
 
 
 /* 
  *  Do for all elements in the subframe 
  */ 
    for ( i = 0 ; i < SubFrLen ; i ++ ) { 
		temp=SubFrLen-i; 
 /* 
  * Input the speech vector 
  */ 
        Acc0 = L_deposit_h( Tv[i] ) ; 
        Acc0 = L_shr( Acc0, (Word16) 2 ) ; 
 
 /* 
  * Formant postfilter 
  */ 
 
        /* FIR part */ 
        for ( j = 0 ; j < LpcOrder ; j ++ ) 
            //Acc0 = L_msu( Acc0, FirCoef[j], DecStat.PostFirDl[j] ) ; 
			Acc0 = L_msu( Acc0, FirCoef[j], DecStat.PostFirDl[temp+j] ) ;			 
 
        /* Update FIR memory */ 
		/* 
        for ( j = LpcOrder-1 ; j > 0 ; j -- ) 
            DecStat.PostFirDl[j] = DecStat.PostFirDl[j-1] ; 
		*/ 
 
        //DecStat.PostFirDl[0] = Tv[i] ; 
		DecStat.PostFirDl[temp-1] = Tv[i] ; 
 
        /* IIR part */ 
        for ( j = 0 ; j < LpcOrder ; j ++ ) 
            //Acc0 = L_mac( Acc0, IirCoef[j], DecStat.PostIirDl[j] ) ; 
			Acc0 = L_mac( Acc0, IirCoef[j], DecStat.PostIirDl[temp+j] ) ; 
 
        /* Update IIR memory */ 
		/* 
        for ( j = LpcOrder-1 ; j > 0 ; j -- ) 
            DecStat.PostIirDl[j] = DecStat.PostIirDl[j-1] ; 
		*/ 
 
        Acc0 = L_shl( Acc0, (Word16) 2 ) ; 
        Acc1 = Acc0 ; 
 
        //DecStat.PostIirDl[0] = round( Acc0 ) ; 
		DecStat.PostIirDl[temp-1] = round( Acc0 ) ; 
 
 /* 
  * Compensation filter 
  */ 
        //Acc1 = L_mac( Acc1, DecStat.PostIirDl[1], Tmp ) ;	/*z^(-1)*/ 
		Acc1 = L_mac( Acc1, DecStat.PostIirDl[temp], Tmp ) ; /*z^(-1)*/ 
 
        Tv[i] = round( Acc1 ) ; 
    } 
    return Sen ; 
}