   
   /******************************************************************
   
       iLBC Speech Coder ANSI-C Source Code
   
       filter.c 
   
       Copyright (C) The Internet Society (2004). 
       All Rights Reserved.
   
   ******************************************************************/
   
   
   
   #include "iLBC_define.h"
   
   /*----------------------------------------------------------------*
    *  all-pole filter
    *---------------------------------------------------------------*/
   
   void AllPoleFilter(
       float *InOut,   /* (i/o) on entrance InOut[-orderCoef] to 
                              InOut[-1] contain the state of the 
                              filter (delayed samples). InOut[0] to 
                              InOut[lengthInOut-1] contain the filter
                              input, on en exit InOut[-orderCoef] to
                              InOut[-1] is unchanged and InOut[0] to
                              InOut[lengthInOut-1] contain filtered 
                              samples */
       float *Coef,/* (i) filter coefficients, Coef[0] is assumed 
                              to be 1.0 */
       int lengthInOut,/* (i) number of input/output samples */
       int orderCoef   /* (i) number of filter coefficients */
   ){  
       int n,k;
       
       for(n=0;n<lengthInOut;n++){
           for(k=1;k<=orderCoef;k++){
               *InOut -= Coef[k]*InOut[-k];
           }
           InOut++;
       }
   }
   
   /*----------------------------------------------------------------*
    *  all-zero filter                         
    *---------------------------------------------------------------*/
   
   void AllZeroFilter(
       float *In,      /* (i) In[0] to In[lengthInOut-1] contain 
                              filter input samples */
       float *Coef,/* (i) filter coefficients (Coef[0] is assumed 
                              to be 1.0) */
       int lengthInOut,/* (i) number of input/output samples */
       int orderCoef,  /* (i) number of filter coefficients */
       float *Out      /* (i/o) on entrance Out[-orderCoef] to Out[-1]
                              contain the filter state, on exit Out[0]
                              to Out[lengthInOut-1] contain filtered
                              samples */
   ){  
       int n,k;
       
       for(n=0;n<lengthInOut;n++){
           *Out = Coef[0]*In[0];
           for(k=1;k<=orderCoef;k++){
               *Out += Coef[k]*In[-k];
           }
   
   
           Out++;
           In++;
       }
   }
   
   /*----------------------------------------------------------------*
    *  pole-zero filter
    *---------------------------------------------------------------*/
   
   void ZeroPoleFilter(
       float *In,      /* (i) In[0] to In[lengthInOut-1] contain 
                              filter input samples In[-orderCoef] to 
                              In[-1] contain state of all-zero 
                              section */
       float *ZeroCoef,/* (i) filter coefficients for all-zero 
                              section (ZeroCoef[0] is assumed to 
                              be 1.0) */
       float *PoleCoef,/* (i) filter coefficients for all-pole section
                              (ZeroCoef[0] is assumed to be 1.0) */
       int lengthInOut,/* (i) number of input/output samples */
       int orderCoef,  /* (i) number of filter coefficients */
       float *Out      /* (i/o) on entrance Out[-orderCoef] to Out[-1]
                              contain state of all-pole section. On 
                              exit Out[0] to Out[lengthInOut-1] 
                              contain filtered samples */
   ){
       AllZeroFilter(In,ZeroCoef,lengthInOut,orderCoef,Out);
       AllPoleFilter(Out,PoleCoef,lengthInOut,orderCoef);
   }
   
   /*----------------------------------------------------------------*
    * downsample (LP filter and decimation)
    *---------------------------------------------------------------*/
   
   void DownSample (
       float  *In,     /* (i) input samples */
       float  *Coef,   /* (i) filter coefficients */
       int lengthIn,   /* (i) number of input samples */ 
       float  *state,  /* (i) filter state */
       float  *Out     /* (o) downsampled output */
   ){
       float   o;
       float *Out_ptr = Out;
       float *Coef_ptr, *In_ptr;
       float *state_ptr;
       int i, j, stop;
   
       /* LP filter and decimate at the same time */
   
       for (i = DELAY_DS; i < lengthIn; i+=FACTOR_DS)
       {
           Coef_ptr = &Coef[0];
           In_ptr = &In[i];
           state_ptr = &state[FILTERORDER_DS-2];
   
   
   
           o = (float)0.0;
           
           stop = (i < FILTERORDER_DS) ? i + 1 : FILTERORDER_DS;
   
           for (j = 0; j < stop; j++) 
           {
               o += *Coef_ptr++ * (*In_ptr--);
           }
           for (j = i + 1; j < FILTERORDER_DS; j++) 
           {
               o += *Coef_ptr++ * (*state_ptr--);
           }
   
           *Out_ptr++ = o;
       }
   
       /* Get the last part (use zeros as input for the future) */
   
       for (i=(lengthIn+FACTOR_DS); i<(lengthIn+DELAY_DS); 
               i+=FACTOR_DS) {
   
           o=(float)0.0;
           
           if (i<lengthIn) {
               Coef_ptr = &Coef[0];
               In_ptr = &In[i];
               for (j=0; j<FILTERORDER_DS; j++) {
                       o += *Coef_ptr++ * (*Out_ptr--);
               }
           } else {
               Coef_ptr = &Coef[i-lengthIn];
               In_ptr = &In[lengthIn-1];
               for (j=0; j<FILTERORDER_DS-(i-lengthIn); j++) {
                       o += *Coef_ptr++ * (*In_ptr--);
               }
           }
           *Out_ptr++ = o;
       }
   }
   
   
