Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

VrComplexFIRfilter.h

Go to the documentation of this file.
00001 /* -*- Mode: c++ -*- 
00002  *
00003  *  Copyright 1997 Massachusetts Institute of Technology
00004  * 
00005  *  Permission to use, copy, modify, distribute, and sell this software and its
00006  *  documentation for any purpose is hereby granted without fee, provided that
00007  *  the above copyright notice appear in all copies and that both that
00008  *  copyright notice and this permission notice appear in supporting
00009  *  documentation, and that the name of M.I.T. not be used in advertising or
00010  *  publicity pertaining to distribution of the software without specific,
00011  *  written prior permission.  M.I.T. makes no representations about the
00012  *  suitability of this software for any purpose.  It is provided "as is"
00013  *  without express or implied warranty.
00014  * 
00015  */
00016 
00017 
00018 #ifndef _VrCOMPLExFIRFILTER_H_
00019 #define _VrCOMPLExFIRFILTER_H_
00020 
00021 #include <VrDecimatingSigProc.h>
00022 
00023 #if defined (ENABLE_MMX)
00024 #include <VrMMX.h>
00025 #endif
00026 
00027 /*  FIR filter definition:
00028 
00029     VrComplexFIRfilter(N, Num of taps[], decimation factor, center frequency[], gain[])
00030 
00031     N = number of filters
00032     decimation factor => set to one unless some integer >1 specified
00033     cutoff (Hz) = 0.0  => LPF using Hamming window, o/w LPF transformed to have higher cutoff freq
00034     center_freq (Hz) => used to specify a composite frequency-shifting filter (i.e. channel filter)
00035     gain = the gain
00036 */
00037 
00038 template<class iType> 
00039 class VrComplexFIRfilter : public VrDecimatingSigProc<iType,VrComplex> {
00040 protected:
00041   int *numTaps, num_ch;
00042   VrComplex** taps;
00043   VrComplex *phase_corr_incr, *phase_offset;
00044   long time;
00045   float *center_freq, *gain;
00046   void buildFilter_complex(int);
00047 #if defined (ENABLE_MMX)
00048   mmxTaps** processedTaps; //Precomputed constants, shifted four times
00049 #endif
00050 public: 
00051   virtual const char *name() { return "VrComplexFIRfilter"; }
00052   virtual int work(VrSampleRange output, void *o[],
00053                    VrSampleRange inputs[], void *i[]);
00054 
00055   virtual void initialize();
00056   int setCenter_Freq(int, float);
00057   int setPhase_Offset(VrComplex);
00058   int setCenter_Freq(float);
00059   int setNumber_Taps(int,int);
00060   int setNumber_Taps(int);
00061   VrComplexFIRfilter(int n, int d, const int t[], const float f[], 
00062                      const float g[]);
00063   VrComplexFIRfilter(int d, int t,float f, float g);
00064   ~VrComplexFIRfilter();
00065 };
00066 
00067 template<class iType> int
00068 VrComplexFIRfilter<iType>::work(VrSampleRange output, void *ao[],
00069                                 VrSampleRange inputs[], void *ai[])
00070 {
00071   iType **i = (iType **)ai;
00072   VrComplex **o = (VrComplex **)ao;
00073   VrComplex result = 0;
00074   int ch_num = 0;
00075   unsigned int size = output.size;
00076 
00077   VrComplex phase_correction[num_ch];
00078   for(ch_num=0;ch_num<num_ch; ch_num++) {
00079     phase_correction[ch_num]=pow(phase_corr_incr[ch_num],(int) output.index) * phase_offset[ch_num];
00080   }
00081 
00082   for (;size>0;size--,i[0]+=decimation) {
00083     result = 0;
00084 
00085     for (ch_num =0; ch_num<num_ch; ch_num++){
00086       //make input pointer local (is this the fastest way?)
00087       iType *inputArray = i[0]+history-numTaps[ch_num];
00088 
00089 #if defined (ENABLE_MMX)
00090       if(processedTaps[ch_num]->mmxReady())
00091         result = processedTaps[ch_num]->mmxCVDProduct(inputArray);
00092       else
00093 #endif
00094      { 
00095         VrComplex *taps_tmp = taps[ch_num];
00096         int j = 0;
00097 #if 0
00098         int n = numTaps[ch_num] & ~0x3;
00099         for (j = 0; j < n; j += 4){             // give compiler a chance
00100           result += taps_tmp[j + 0] * inputArray[j + 0];
00101           result += taps_tmp[j + 1] * inputArray[j + 1];
00102           result += taps_tmp[j + 2] * inputArray[j + 2];
00103           result += taps_tmp[j + 3] * inputArray[j + 3];
00104         }
00105 #endif
00106         for (; j < numTaps[ch_num]; j++)        // handle stragglers
00107           result += taps_tmp[j] * inputArray[j];
00108           
00109       }
00110 
00111       // Perform phase correction (non-trivial only for freq-xlating filter)
00112       if (center_freq[ch_num] != 0.0) {
00113         phase_correction[ch_num] *= phase_corr_incr[ch_num];
00114         result *= phase_correction[ch_num];
00115       }
00116       *o[ch_num]++=result;
00117     }
00118   }
00119   return output.size;
00120 }
00121 
00122 template<class iType> void
00123 VrComplexFIRfilter<iType>::buildFilter_complex(int ch){
00124   // Build Complex Filter => 
00125   //       produces a low-pass filter using a real Hamming window
00126   double inSampFreq;
00127   int index;
00128   float N = numTaps[ch];
00129   float M = N-1; /* filter Order */
00130 
00131   inSampFreq = getInputSamplingFrequencyN(0); 
00132   time = 0;
00133   
00134   if (center_freq[ch] == 0.0) {
00135       for ( index=0 ; index < numTaps[ch] ; index++) {
00136        taps[ch][index] = gain[ch]*VrComplex((0.54-0.46*cos(2*M_PI*index/(M))));
00137     }
00138   } else {                      // add freq-shifting part
00139     float arg = 2*M_PI*center_freq[ch] / inSampFreq;
00140     for ( index=0 ; index < numTaps[ch] ; index++) {
00141       taps[ch][index] = VrComplex(gain[ch]*cos(arg*index)*(0.54-0.46*cos(2*M_PI*index/(M))),
00142          gain[ch]*(-1)*sin(arg*index)*(0.54-0.46*cos(2*M_PI*index/(M))));
00143     }
00144     phase_corr_incr[ch] = VrComplex(cos(arg*(float)decimation),
00145                                 (-1)*sin(arg*(float)decimation));
00146   }
00147 #if defined (ENABLE_MMX)
00148   if(processedTaps[ch]!=NULL)
00149     delete processedTaps[ch];
00150   processedTaps[ch]=new mmxTaps(taps[ch],numTaps[ch]);
00151 #endif
00152 }
00153 
00154 template<class iType> 
00155 VrComplexFIRfilter<iType>::VrComplexFIRfilter(int n, int dec, const int t[], 
00156       const float freq[], const float g[])
00157   :VrDecimatingSigProc<iType,VrComplex>(n,dec), num_ch(n)
00158 {
00159   numTaps=new int[num_ch];
00160   phase_corr_incr = new VrComplex[num_ch];
00161   phase_offset = new VrComplex[num_ch];
00162   center_freq = new float[num_ch];
00163   gain = new float[num_ch];
00164   taps = new (VrComplex *[num_ch]);
00165 
00166 #if defined (ENABLE_MMX)
00167   processedTaps = new (mmxTaps *[num_ch]);
00168 #endif
00169   
00170   for (int i=0; i<num_ch; i++){
00171     numTaps[i] = t[i];
00172     phase_corr_incr[i] = VrComplex(1,0);
00173     phase_offset[i] = VrComplex(1,0);
00174     center_freq[i] = freq[i];
00175     gain[i] = g[i];
00176 #if defined (ENABLE_MMX)
00177   processedTaps[i]=NULL;
00178 #endif
00179   }
00180 }
00181 
00182 template<class iType> 
00183 VrComplexFIRfilter<iType>::VrComplexFIRfilter(int dec,int t,float freq, float g)
00184   :VrDecimatingSigProc<iType,VrComplex>(1,dec), num_ch(1)
00185 {
00186   numTaps=new int[num_ch];
00187   phase_corr_incr = new VrComplex[num_ch];
00188   phase_offset = new VrComplex[num_ch];
00189   center_freq = new float[num_ch];
00190   gain = new float[num_ch];
00191   taps = new (VrComplex *[num_ch]);
00192 
00193 #if defined (ENABLE_MMX)
00194   processedTaps = new (mmxTaps *[num_ch]);
00195 #endif
00196   
00197   numTaps[0] = t;
00198   phase_corr_incr[0] = VrComplex(1,0);
00199   phase_offset[0] = VrComplex(1,0);
00200   center_freq[0] = freq;
00201   gain[0] = g;
00202 #if defined (ENABLE_MMX)
00203   processedTaps[0]=NULL;
00204 #endif
00205 }
00206 
00207 template<class iType> 
00208 void VrComplexFIRfilter<iType>::initialize()
00209 {
00210   for (int i=0; i<num_ch; i++){ 
00211     taps[i]=new VrComplex[numTaps[i]];
00212     buildFilter_complex(i);
00213   }
00214 
00215   int max_numTaps = 0;
00216   for (int i=0; i<num_ch; i++){
00217     if (numTaps[i] > max_numTaps) max_numTaps = numTaps[i];
00218   }
00219   history=max_numTaps;
00220 }
00221 
00222 template<class iType> 
00223 int VrComplexFIRfilter<iType>::setCenter_Freq(int ch, float cf)
00224 {
00225   center_freq[ch] = cf;
00226   buildFilter_complex(ch);
00227   return 1;
00228 }
00229 
00230 template<class iType> 
00231 int VrComplexFIRfilter<iType>::setCenter_Freq(float cf)
00232 {
00233   return setCenter_Freq(0,cf);
00234 }
00235 
00236 template<class iType> 
00237 int VrComplexFIRfilter<iType>::setPhase_Offset(VrComplex f)
00238 {
00239  phase_offset[0]=f;
00240 }
00241 
00242 template<class iType> 
00243 int VrComplexFIRfilter<iType>::setNumber_Taps(int ch, int numT)
00244 {
00245   numTaps[ch] = numT;
00246   delete taps[ch];
00247   taps[ch]=new VrComplex[numTaps[ch]];
00248 
00249   int max_numTaps = 0;
00250   for (int i=0; i<num_ch; i++){
00251     if (numTaps[i] > max_numTaps) max_numTaps = numTaps[i];
00252   }
00253   if(history<(unsigned int) max_numTaps) {
00254     history=(unsigned int) max_numTaps;
00255     setup_upstream();
00256   }
00257 
00258   buildFilter_complex(ch);
00259   return 1;
00260 }
00261 
00262 template<class iType> 
00263 int VrComplexFIRfilter<iType>::setNumber_Taps(int numT)
00264 {
00265   return setNumber_Taps(0, numT);
00266 }
00267 
00268 template<class iType> 
00269 VrComplexFIRfilter<iType>::~VrComplexFIRfilter()
00270 {
00271   for (int i=0; i<num_ch; i++){ 
00272     delete taps[i];
00273 #if defined (ENABLE_MMX)
00274     if(processedTaps[i]!=NULL)
00275       delete processedTaps[i];
00276 #endif
00277   }
00278   delete numTaps;
00279   delete [] phase_corr_incr;
00280   delete center_freq;
00281   delete gain;
00282   delete taps;
00283 }
00284 #endif

Generated on Tue Mar 15 23:55:33 2005 for GNU Radio by  doxygen 1.4.0