www.pudn.com > 200411301125332697.rar > pst.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. 
*/ 
 
/************************************************************************/ 
/*      Post - filtering : short term + long term                       */ 
/************************************************************************/ 
#include  
#include  
 
/**** Prototypes                                                        */ 
#include "typedef.h" 
#include "ld8k.h" 
#include "basic_op.h" 
#include "oper_32b.h" 
 
 
/* Prototypes for local functions */ 
/**********************************/ 
 
static void pst_ltp(Word16 t0, Word16 *ptr_sig_in, 
    Word16 *ptr_sig_pst0, Word16 *vo); 
static void search_del(Word16 t0, Word16 *ptr_sig_in, Word16 *ltpdel, 
    Word16 *phase, Word16 *num_gltp, Word16 *den_gltp, Word16 *sh_num_gltp, 
    Word16 *sh_den_gltp, Word16 *y_up, Word16 *off_yup); 
static void filt_plt( Word16 *s_in, Word16 *s_ltp, 
    Word16 *s_out, Word16 gain_plt); 
static void compute_ltp_l(Word16 *s_in, Word16 ltpdel, Word16 phase, 
    Word16 *y_up, Word16 *num, Word16 *den, Word16 *sh_num, Word16 *sh_den); 
static Word16 select_ltp(Word16 num1, Word16 den1, Word16 sh_num1, 
    Word16 sh_den1, Word16 num2, Word16 den2, Word16 sh_num2, Word16 sh_den2); 
static void calc_st_filt(Word16 *apond2, Word16 *apond1, Word16 *parcor0, 
    Word16 *signal_ltp0_ptr); 
static void filt_mu(Word16 *sig_in, Word16 *sig_out, Word16 parcor0); 
static void calc_rc0_h(Word16 *h, Word16 *rc0); 
static void scale_st(Word16 *sig_in, Word16 *sig_out, Word16 *gain_prec); 
 
/* Static arrays and variables */ 
/*******************************/ 
 
/* Arrays */ 
static Word16 apond2[LONG_H_ST];    /* s.t. numerator coeff.        */ 
static Word16 mem_stp[M];           /* s.t. postfilter memory       */ 
static Word16 mem_zero[M];          /* null memory to compute h_st  */ 
static Word16 res2[SIZ_RES2];       /* A(gamma2) residual           */ 
 
/* pointers */ 
Word16 *res2_ptr; 
Word16 *ptr_mem_stp; 
 
/* Variables */ 
Word16 gain_prec; 
 
/************************************************************************/ 
/****   Short term postfilter :                                     *****/ 
/*      Hst(z) = Hst0(z) Hst1(z)                                        */ 
/*      Hst0(z) = 1/g0 A(gamma2)(z) / A(gamma1)(z)                      */ 
/*      if {hi} = i.r. filter A(gamma2)/A(gamma1) (truncated)           */ 
/*      g0 = SUM(|hi|) if > 1                                           */ 
/*      g0 = 1. else                                                    */ 
/*      Hst1(z) = 1/(1 - |mu|) (1 + mu z-1)                             */ 
/*      with mu = k1 * gamma3                                           */ 
/*      k1 = 1st parcor calculated on {hi}                              */ 
/*      gamma3 = gamma3_minus if k1<0, gamma3_plus if k1>0              */ 
/****   Long term postfilter :                                      *****/ 
/*      harmonic postfilter :   H0(z) = gl * (1 + b * z-p)              */ 
/*      b = gamma_g * gain_ltp                                          */ 
/*      gl = 1 / 1 + b                                                  */ 
/*      computation of delay p on A(gamma2)(z) s(z)                     */ 
/*      sub optimal search                                              */ 
/*      1. search around 1st subframe delay (3 integer values)          */ 
/*      2. search around best integer with fract. delays (1/8)          */ 
/************************************************************************/ 
 
/*---------------------------------------------------------------------------- 
 * Init_Post_Filter -  Initialize postfilter functions 
 *---------------------------------------------------------------------------- 
 */ 
void Init_Post_Filter( 
    void 
) 
{ 
    int i; 
 
    /* Initialize arrays and pointers */ 
 
    /* res2 =  A(gamma2) residual */ 
    for(i=0; iLONG_H_ST-1] with zeroes */ 
    for(i=MP1; i 0 delay */ 
 Word16 Vad             /* input : frame type */ 
) 
{ 
 
    /* Local variables and arrays */ 
    Word16 apond1[MP1];             /* s.t. denominator coeff.      */ 
    Word16 sig_ltp[L_SUBFRP1];      /* H0 output signal             */ 
    Word16 *sig_ltp_ptr; 
    Word16 parcor0; 
 
    /* Compute weighted LPC coefficients */ 
    Weight_Az(coeff, GAMMA1_PST, M, apond1); 
    Weight_Az(coeff, GAMMA2_PST, M, apond2); 
 
    /* Compute A(gamma2) residual */ 
    Residu(apond2, signal_ptr, res2_ptr, L_SUBFR); 
 
    /* Harmonic filtering */ 
    sig_ltp_ptr = sig_ltp + 1; 
    if (sub(Vad, 1) == 0) 
      pst_ltp(t0, res2_ptr, sig_ltp_ptr, vo); 
    else{ 
      *vo = 0; 
      Copy(res2_ptr, sig_ltp_ptr, L_SUBFR); 
    } 
 
    /* Save last output of 1/A(gamma1)  */ 
    /* (from preceding subframe)        */ 
    sig_ltp[0] = *ptr_mem_stp; 
 
    /* Controls short term pst filter gain and compute parcor0   */ 
    calc_st_filt(apond2, apond1, &parcor0, sig_ltp_ptr); 
 
    /* 1/A(gamma1) filtering, mem_stp is updated */ 
    Syn_filt(apond1, sig_ltp_ptr, sig_ltp_ptr, L_SUBFR, mem_stp, 1); 
 
    /* Tilt filtering */ 
    filt_mu(sig_ltp, sig_out, parcor0); 
 
    /* Gain control */ 
    scale_st(signal_ptr, sig_out, &gain_prec); 
 
    /**** Update for next subframe */ 
    Copy(&res2[L_SUBFR], &res2[0], MEM_RES2); 
 
    return; 
} 
 
/*---------------------------------------------------------------------------- 
 *  pst_ltp - harmonic postfilter 
 *---------------------------------------------------------------------------- 
 */ 
static void pst_ltp( 
 Word16 t0,             /* input : pitch delay given by coder */ 
 Word16 *ptr_sig_in,    /* input : postfilter input filter (residu2) */ 
 Word16 *ptr_sig_pst0,  /* output: harmonic postfilter output */ 
 Word16 *vo             /* output: voicing decision 0 = uv,  > 0 delay */ 
) 
{ 
 
/**** Declare variables                                 */ 
    int i; 
    Word16 temp; 
    Word16 ltpdel, phase; 
    Word16 num_gltp, den_gltp; 
    Word16 num2_gltp, den2_gltp; 
    Word16 sh_num, sh_den; 
    Word16 sh_num2, sh_den2; 
    Word16 gain_plt; 
    Word16 y_up[SIZ_Y_UP]; 
    Word16 *ptr_y_up; 
    Word16 off_yup; 
    Word16 *ptr_sig; 
    Word16 sig_cadr[SIZ_RES2], *ptr_sig_cadr; 
    Word16 nb_sh_sig; 
    Word32 L_temp; 
 
    /* input signal justified on 13 bits */ 
    ptr_sig = ptr_sig_in - MEM_RES2; 
 
    temp = 0; 
    for(i=0; i0, <0 or =0 */ 
        sig_cadr[i] = shr( ptr_sig[i], nb_sh_sig); 
    } 
 
    ptr_sig_cadr = sig_cadr + MEM_RES2; 
 
    /* Sub optimal delay search */ 
    search_del(t0, ptr_sig_cadr, <pdel, &phase, &num_gltp, &den_gltp, 
                            &sh_num, &sh_den, y_up, &off_yup); 
    *vo = ltpdel; 
 
    if(num_gltp == 0)   { 
        Copy(ptr_sig_in, ptr_sig_pst0, L_SUBFR); 
    } 
 
    else { 
        if(phase == 0) { 
            ptr_y_up = ptr_sig_in - ltpdel; 
        } 
 
        else { 
 
            /* Filtering with long filter */ 
            compute_ltp_l(ptr_sig_cadr, ltpdel, phase, ptr_sig_pst0, 
                &num2_gltp, &den2_gltp, &sh_num2, &sh_den2); 
 
            if(select_ltp(num_gltp, den_gltp, sh_num, sh_den, 
                num2_gltp, den2_gltp, sh_num2, sh_den2) == 1) { 
 
                /* select short filter */ 
                temp   = sub(phase, 1); 
                L_temp = L_mult(temp, L_SUBFRP1); 
                L_temp = L_shr(L_temp, 1); 
                temp   = extract_l(L_temp); 
                temp   = add(temp, off_yup); 
                /* ptr_y_up = y_up + (phase-1) * L_SUBFRP1 + off_yup */ 
                ptr_y_up = y_up + temp; 
            } 
            else { 
                /* select long filter */ 
                num_gltp = num2_gltp; 
                den_gltp = den2_gltp; 
                sh_num   = sh_num2; 
                sh_den   = sh_den2; 
                ptr_y_up = ptr_sig_pst0; 
            } 
 
            /* rescale y_up */ 
            for(i=0; i0, <0 or =0 */ 
                ptr_y_up[i] = shl(ptr_y_up[i], nb_sh_sig); 
            } 
        } 
 
        temp = sub(sh_num,sh_den); 
        if(temp >= 0) den_gltp = shr(den_gltp, temp); 
        else { 
            num_gltp = shl(num_gltp, temp); /*  >> (-temp) */ 
        } 
 
        if(sub(num_gltp ,den_gltp)>=0) { 
            /* beta bounded to 1 */ 
            gain_plt = MIN_GPLT; 
        } 
        else { 
 
            /* GAMMA_G = 0.5                                            */ 
            /* gain_plt = den_gltp x 2**15 / (den_gltp + 0.5 num_gltp)  */ 
            /* shift 1 bit to avoid overflows in add                    */ 
            num_gltp = shr(num_gltp, 2); 
            den_gltp = shr(den_gltp, 1); 
            temp     = add(den_gltp, num_gltp); 
            gain_plt = div_s(den_gltp, temp);   /* Q15 */ 
        } 
 
        /** filtering by H0(z) = harmonic filter **/ 
        filt_plt(ptr_sig_in, ptr_y_up, ptr_sig_pst0, gain_plt); 
 
    } 
 
    return; 
} 
 
/*---------------------------------------------------------------------------- 
 *  search_del: computes best (shortest) integer LTP delay + fine search 
 *---------------------------------------------------------------------------- 
 */ 
static void search_del( 
 Word16 t0,                /* input : pitch delay given by coder */ 
 Word16 *ptr_sig_in,       /* input : input signal (with delay line) */ 
 Word16 *ltpdel,           /* output: delay = *ltpdel - *phase / f_up */ 
 Word16 *phase,            /* output: phase */ 
 Word16 *num_gltp,         /* output: 16 bits numerator of LTP gain */ 
 Word16 *den_gltp,         /* output: 16 bits denominator of LTP gain */ 
 Word16 *sh_num_gltp,      /* output: justification for num_gltp */ 
 Word16 *sh_den_gltp,      /* output: justification for den_gltp */ 
 Word16 *y_up,             /* output: LT delayed signal if fract. delay */ 
 Word16 *off_yup           /* output: offset in y_up */ 
) 
{ 
 
    /* Tables of constants */ 
    extern Word16 tab_hup_s[SIZ_TAB_HUP_S]; 
 
    Word32 L_den0[F_UP_PST-1]; 
    Word32 L_den1[F_UP_PST-1]; 
    Word32 *ptr_L_den0, *ptr_L_den1; 
 
    int i, n; 
    Word16 *ptr_h; 
    Word16 *ptr_sig_past, *ptr_sig_past0; 
    Word16 *ptr1, *ptr_y_up; 
    Word16 num, den0, den1; 
    Word16 den_max, num_max; 
    Word32 L_num_int, L_den_int, L_den_max; 
    Word16 hi_numsq, hi_numsq_max; 
    Word16 lo_numsq, lo_numsq_max; 
    Word16 ener; 
    Word16 sh_num, sh_den, sh_ener; 
    Word16 i_max, lambda, phi, phi_max, ioff; 
    Word16 temp; 
    Word32 L_temp0, L_temp1; 
    Word32 L_acc; 
    Word32 L_temp; 
 
 
    /* Computes energy of current signal */ 
    /*************************************/ 
 
    L_acc = 0L; 
    for(i=0; i 0) { 
        ener = extract_l(L_shr(L_acc, sh_ener)); 
    } 
    else { 
        sh_ener = 0; 
        ener = extract_l(L_acc); 
    } 
 
    /*************************************/ 
    /* Selects best of 3 integer delays  */ 
    /* Maximum of 3 numerators around t0 */ 
    /*************************************/ 
    lambda = sub(t0,1); 
    ptr_sig_past = ptr_sig_in - lambda; 
 
    L_num_int = -1L; 
 
   /* initialization used only to suppress Microsoft Visual C++ warnings */ 
    i_max = (Word16)0; 
 
    for(i=0; i<3; i++) { 
        L_acc = 0L; 
        for(n=0; n 0L) { 
            L_num_int = L_acc; 
            i_max = (Word16)i; 
        } 
        ptr_sig_past--; 
    } 
 
    if(L_num_int == 0) { 
        *num_gltp = 0; 
        *den_gltp = 1; 
        *ltpdel = 0; 
        *phase = 0; 
        return; 
    } 
 
    /* Compute den for i_max */ 
    lambda = add(lambda, (Word16)i_max); 
    ptr_sig_past = ptr_sig_in - lambda; 
    L_acc = 0L; 
    for(i=0; i0) { 
            L_temp =L_sub(*ptr_L_den0 ,L_den_max ); 
            if(L_temp> 0L) { 
                L_den_max = *ptr_L_den0; 
            } 
        } 
        else { 
            L_temp =L_sub(*ptr_L_den1 ,L_den_max ); 
            if(L_temp> 0L) { 
                L_den_max = *ptr_L_den1; 
            } 
        } 
        ptr_L_den0++; 
        ptr_L_den1++; 
        ptr_y_up += L_SUBFRP1; 
        ptr_h += LH2_S; 
    } 
 
    if(L_den_max == 0) { 
        *num_gltp = 0; 
        *den_gltp = 1; 
        *ltpdel = 0; 
        *phase = 0; 
        return; 
    } 
 
    sh_den = sub(16, norm_l(L_den_max)); 
    /* if sh_den <= 0 :  dynamic between current frame */ 
    /* and delay line too high                         */ 
    if(sh_den <= 0) { 
        *num_gltp = 0; 
        *den_gltp = 1; 
        *ltpdel = 0; 
        *phase = 0; 
        return; 
    } 
 
    /* search sh_num to justify correlations   */ 
    /* sh_num = Max(sh_den, sh_ener)           */ 
    sh_num = (sub( sh_den , sh_ener)>=0) ? sh_den : sh_ener; 
 
    /* Computation of the numerators                */ 
    /* and selection of best num*num/den            */ 
    /* for non null phases                          */ 
 
    /* Initialize with null phase */ 
    L_acc        = L_shr(L_den_int, sh_den);   /* sh_den > 0 */ 
    den_max      = extract_l(L_acc); 
    L_acc        = L_shr(L_num_int, sh_num);   /* sh_num > 0 */ 
    num_max      = extract_l(L_acc); 
    L_acc        = L_mult(num_max, num_max); 
    L_Extract(L_acc, &hi_numsq_max, &lo_numsq_max); 
    phi_max      = 0; 
    ioff         = 1; 
 
    ptr_L_den0   = L_den0; 
    ptr_L_den1   = L_den1; 
    ptr_y_up     = y_up; 
 
    /* if den_max = 0 : will be selected and declared unvoiced */ 
    /* if num!=0 & den=0 : will be selected and declared unvoiced */ 
    /* degenerated seldom cases, switch off LT is OK */ 
 
    /* Loop on phase */ 
    for(phi=1; phi 0 */ 
        if(L_acc < 0L) { 
            num = 0; 
        } 
        else { 
            num  = extract_l(L_acc); 
        } 
 
        /* selection if num**2/den0 max */ 
        L_acc    = L_mult(num, num); 
        L_Extract(L_acc, &hi_numsq, &lo_numsq); 
        L_temp0  = Mpy_32_16(hi_numsq, lo_numsq, den_max); 
        L_acc    = *ptr_L_den0++; 
        L_acc    = L_shr(L_acc, sh_den);        /* sh_den > 0 */ 
        den0     = extract_l(L_acc); 
        L_temp1  = Mpy_32_16(hi_numsq_max, lo_numsq_max, den0); 
        L_temp = L_sub(L_temp0, L_temp1); 
        if(L_temp>0L) { 
            num_max      = num; 
            hi_numsq_max = hi_numsq; 
            lo_numsq_max = lo_numsq; 
            den_max      = den0; 
            ioff         = 0; 
            phi_max      = phi; 
        } 
 
        /* compute num for lambda - phi/F_UP_PST */ 
        ptr_y_up++; 
        L_acc = 0L; 
        for(n = 0; n 0 */ 
        if(L_acc < 0L) { 
            num = 0; 
        } 
        else { 
            num  = extract_l(L_acc); 
        } 
 
        /* selection if num**2/den1 max */ 
        L_acc    = L_mult(num, num); 
        L_Extract(L_acc, &hi_numsq, &lo_numsq); 
        L_temp0  = Mpy_32_16(hi_numsq, lo_numsq, den_max); 
        L_acc    = *ptr_L_den1++; 
        L_acc    = L_shr(L_acc, sh_den);        /* sh_den > 0 */ 
        den1     = extract_l(L_acc); 
        L_temp1  = Mpy_32_16(hi_numsq_max, lo_numsq_max, den1); 
        L_temp = L_sub(L_temp0,L_temp1); 
        if(L_temp> 0L) { 
            num_max      = num; 
            hi_numsq_max = hi_numsq; 
            lo_numsq_max = lo_numsq; 
            den_max     = den1; 
            ioff        = 1; 
            phi_max     = phi; 
        } 
 
        ptr_y_up += L_SUBFR; 
    } 
 
    /***************************************************/ 
    /*** test if normalized crit0[iopt] > THRESHCRIT ***/ 
    /***************************************************/ 
    if((num_max == 0) || (sub(den_max,1) <= 0)) { 
        *num_gltp = 0; 
        *den_gltp = 1; 
        *ltpdel = 0; 
        *phase = 0; 
        return; 
    } 
 
    /* compare num**2               */ 
    /* to ener * den * 0.5          */ 
    /* (THRESHCRIT = 0.5)           */ 
    L_temp1 = L_mult(den_max, ener); 
    L_temp0 = L_Comp(hi_numsq_max, lo_numsq_max); 
 
    /* temp = 2 * sh_num - sh_den - sh_ener + 1 */ 
    /* 16 bits with no overflows  */ 
    temp = shl(sh_num,1); 
    temp = sub(temp, sh_den); 
    temp = sub(temp, sh_ener); 
    temp = add(temp, 1); 
    if(temp < 0) { 
        temp    = negate(temp);             /* no overflow */ 
        L_temp0 = L_shr(L_temp0, temp); 
    } 
    else { 
        if(temp > 0) L_temp1 = L_shr(L_temp1, temp); 
    } 
    L_temp = L_sub(L_temp0 ,L_temp1); 
    if(L_temp >= 0L) { 
        temp         = add(lambda, 1); 
        *ltpdel      = sub(temp, ioff); 
        *off_yup     = ioff; 
        *phase       = phi_max; 
        *num_gltp    = num_max; 
        *den_gltp    = den_max; 
        *sh_den_gltp = sh_den; 
        *sh_num_gltp = sh_num; 
    } 
    else { 
        *num_gltp = 0; 
        *den_gltp = 1; 
        *ltpdel = 0; 
        *phase = 0; 
    } 
    return; 
 
} 
 
/*---------------------------------------------------------------------------- 
 *  filt_plt -  ltp  postfilter 
 *---------------------------------------------------------------------------- 
 */ 
static void filt_plt( 
 Word16 *s_in,       /* input : input signal with past*/ 
 Word16 *s_ltp,      /* input : filtered signal with gain 1 */ 
 Word16 *s_out,      /* output: output signal */ 
 Word16 gain_plt     /* input : filter gain  */ 
) 
{ 
 
    /* Local variables */ 
    int n; 
    Word32 L_acc; 
    Word16 gain_plt_1; 
 
    gain_plt_1 = sub(32767, gain_plt); 
    gain_plt_1 = add(gain_plt_1, 1);        /* 2**15 (1 - g) */ 
 
    for(n=0;  n= 0 */ 
        *num = extract_l(L_acc); 
        *sh_num = temp; 
    } 
 
    /* Compute den */ 
    L_acc = 0L; 
    for(n=0; n= 0 */ 
    *den = extract_l(L_acc); 
    *sh_den = temp; 
 
    return; 
} 
 
/*---------------------------------------------------------------------------- 
 *  select_ltp : selects best of (gain1, gain2) 
 *  with gain1 = num1 * 2** sh_num1 / den1 * 2** sh_den1 
 *  and  gain2 = num2 * 2** sh_num2 / den2 * 2** sh_den2 
 *---------------------------------------------------------------------------- 
 */ 
static Word16 select_ltp(  /* output : 1 = 1st gain, 2 = 2nd gain */ 
 Word16 num1,       /* input : numerator of gain1 */ 
 Word16 den1,       /* input : denominator of gain1 */ 
 Word16 sh_num1,    /* input : just. factor for num1 */ 
 Word16 sh_den1,    /* input : just. factor for den1 */ 
 Word16 num2,       /* input : numerator of gain2 */ 
 Word16 den2,       /* input : denominator of gain2 */ 
 Word16 sh_num2,    /* input : just. factor for num2 */ 
 Word16 sh_den2)    /* input : just. factor for den2 */ 
{ 
    Word32 L_temp1, L_temp2; 
    Word16 temp1, temp2; 
    Word16 hi, lo; 
    Word32 L_temp; 
 
    if(den2 == 0) { 
 
        return(1); 
    } 
 
    /* compares criteria = num**2/den */ 
    L_temp1 = L_mult(num1, num1); 
    L_Extract(L_temp1, &hi, &lo); 
    L_temp1 = Mpy_32_16(hi, lo, den2); 
 
    L_temp2 = L_mult(num2, num2); 
    L_Extract(L_temp2, &hi, &lo); 
    L_temp2 = Mpy_32_16(hi, lo, den1); 
 
    /* temp1 = sh_den2 + 2 * sh_num1 */ 
    temp1 = shl(sh_num1, 1); 
    temp1 = add(temp1, sh_den2); 
    /* temp2 = sh_den1 + 2 * sh_num2; */ 
    temp2 = shl(sh_num2, 1); 
    temp2 = add(temp2, sh_den1); 
 
    if(sub(temp2 ,temp1)>0) { 
        temp2 = sub(temp2, temp1); 
        L_temp1 = L_shr(L_temp1, temp2);    /* temp2 > 0 */ 
    } 
    else { 
        if(sub(temp1 ,temp2) >0){ 
            temp1 = sub(temp1, temp2); 
            L_temp2 = L_shr(L_temp2, temp1);    /* temp1 > 0 */ 
        } 
    } 
 
    L_temp = L_sub(L_temp2,L_temp1); 
    if(L_temp>0L) { 
 
        return(2); 
    } 
    else { 
 
        return(1); 
    } 
} 
 
/*---------------------------------------------------------------------------- 
 *   calc_st_filt -  computes impulse response of A(gamma2) / A(gamma1) 
 *   controls gain : computation of energy impulse response as 
 *                    SUMn  (abs (h[n])) and computes parcor0 
 *---------------------------------------------------------------------------- 
 */ 
static void calc_st_filt( 
 Word16 *apond2,     /* input : coefficients of numerator */ 
 Word16 *apond1,     /* input : coefficients of denominator */ 
 Word16 *parcor0,    /* output: 1st parcor calcul. on composed filter */ 
 Word16 *sig_ltp_ptr    /* in/out: input of 1/A(gamma1) : scaled by 1/g0 */ 
) 
{ 
    Word16 h[LONG_H_ST]; 
    Word32 L_temp, L_g0; 
    Word16 g0, temp; 
    int i; 
 
    /* compute i.r. of composed filter apond2 / apond1 */ 
    Syn_filt(apond1, apond2, h, LONG_H_ST, mem_zero, 0); 
 
    /* compute 1st parcor */ 
    calc_rc0_h(h, parcor0); 
 
    /* compute g0 */ 
    L_g0 = 0L; 
    for(i=0; i0) { 
        temp = div_s(1024, g0);     /* temp = 2**15 / gain0 */ 
        for(i=0; i 0) { 
        *rc0 = negate(*rc0); 
    } 
 
    return; 
} 
 
 
/*---------------------------------------------------------------------------- 
 * filt_mu - tilt filtering with : (1 + mu z-1) * (1/1-|mu|) 
 *   computes y[n] = (1/1-|mu|) (x[n]+mu*x[n-1]) 
 *---------------------------------------------------------------------------- 
 */ 
static void filt_mu( 
 Word16 *sig_in,     /* input : input signal (beginning at sample -1) */ 
 Word16 *sig_out,    /* output: output signal */ 
 Word16 parcor0      /* input : parcor0 (mu = parcor0 * gamma3) */ 
) 
{ 
    int n; 
    Word16 mu, mu2, ga, temp; 
    Word32 L_acc, L_temp, L_fact; 
    Word16 fact, sh_fact1; 
    Word16 *ptrs; 
 
    if(parcor0 > 0) { 
        mu      = mult_r(parcor0, GAMMA3_PLUS); 
        /* GAMMA3_PLUS < 0.5 */ 
        sh_fact1 = 15;                   /* sh_fact + 1 */ 
        fact     = (Word16)0x4000;       /* 2**sh_fact */ 
        L_fact   = (Word32)0x00004000L; 
    } 
    else { 
        mu       = mult_r(parcor0, GAMMA3_MINUS); 
        /* GAMMA3_MINUS < 0.9375 */ 
        sh_fact1 = 12;                   /* sh_fact + 1 */ 
        fact     = (Word16)0x0800;       /* 2**sh_fact */ 
        L_fact   = (Word32)0x00000800L; 
    } 
 
    temp = sub(1, abs_s(mu)); 
    mu2  = add(32767, temp);    /* 2**15 (1 - |mu|) */ 
    ga   = div_s(fact, mu2);    /* 2**sh_fact / (1 - |mu|) */ 
 
    ptrs = sig_in;     /* points on sig_in(-1) */ 
    mu   = shr(mu, 1);          /* to avoid overflows   */ 
 
    for(n=0; n 2 * L_gain_out  */ 
        g0 = shr(g0, sh_g0);        /* sh_g0 may be >0, <0, or =0 */ 
        g0 = mult_r(g0, AGC_FAC1);  /* L_gain_in/L_gain_out * AGC_FAC1      */ 
 
    } 
 
    /* gain(n) = AGC_FAC gain(n-1) + AGC_FAC1 gain_in/gain_out          */ 
    /* sig_out(n) = gain(n) sig_out(n)                                  */ 
    gain = *gain_prec; 
    for(i=0; i