![]() |
RTXI 1.3
|
00001 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00002 // 00003 // File = remezalg.cpp 00004 // 00005 // Remez algorithm for design of FIR filters 00006 // 00007 00008 #include <math.h> 00009 #include <stdlib.h> 00010 #include <ostream.h> 00011 #include "fs_dsgn.h" 00012 #include "fs_spec.h" 00013 #include "remezalg.h" 00014 #ifdef _DEBUG 00015 extern std::ofstream DebugFile; 00016 #endif 00017 00018 //====================================================== 00019 // constructor 00020 //------------------------------------------------------ 00021 00022 RemezAlgorithm::RemezAlgorithm( istream& uin, 00023 ostream& uout, 00024 int filter_length, 00025 double passband_edge_freq, 00026 double stopband_edge_freq, 00027 double ripple_ratio, 00028 FirFilterDesign **fir_filter) 00029 { 00030 int m, j; 00031 int grid_density; 00032 //-------------------------------- 00033 // get user-specified parameters 00034 00035 uout << "\nparameters for Remez algorithm\n" 00036 << "--------------------------------" << std::endl; 00037 uout << "number of grid points per extremal frequency?\n" 00038 << "( MUST be an integer)" << std::endl; 00039 uin >> grid_density; 00040 00041 //uout << "ripple ratio?" << std::endl; 00042 //uin >> ripple_ratio; 00043 00044 //-------------------------------- 00045 // set up frequency grid 00046 00047 Filter_Length = filter_length; 00048 PB_Edge_Freq = passband_edge_freq; 00049 SB_Edge_Freq = stopband_edge_freq; 00050 Num_Approx_Funcs = (filter_length + 1)/2; 00051 Grid_Density = grid_density; 00052 Ripple_Ratio = ripple_ratio; 00053 00054 double* extremal_freqs = new double[Num_Approx_Funcs+1]; 00055 double* filter_coeffs = new double[filter_length+1]; 00056 00057 SetupGrid(); 00058 00059 Ext_Freq = new int[Num_PB_Freqs+Num_SB_Freqs]; 00060 Old_Ext_Freq = new int[Num_PB_Freqs+Num_SB_Freqs]; 00061 00062 PB_Edge_Freq = PB_Edge_Freq + (PB_Edge_Freq/(2.0*Num_Grid_Pts_PB)); 00063 Max_Grid_Indx = 1 + Grid_Density*(Num_PB_Freqs+Num_SB_Freqs-1); 00064 Error = new double[Max_Grid_Indx+1]; 00065 00066 //---------------------------------------------- 00067 // make initial guess of extremal frequencies 00068 00069 for(j=0; j<Num_PB_Freqs; j++) Ext_Freq[j] = (j+1)* grid_density; 00070 00071 for(j=0; j<Num_SB_Freqs; j++) Ext_Freq[j+Num_PB_Freqs] = 00072 Num_Grid_Pts_PB + 1 + j * grid_density; 00073 00074 //---------------------------------------------------- 00075 // find optimal locations for extremal frequencies 00076 00077 for(m=1;m<=20;m++) 00078 { 00079 RemezError(); 00080 00081 RemezSearch(); 00082 00083 RemezStop2(); 00084 if(RemezStop()) break; 00085 #ifdef _DEBUG 00086 DebugFile << "done iteration " << m << std::endl; 00087 #endif 00088 } 00089 00090 for(j=0; j<=Num_Approx_Funcs; j++) 00091 { 00092 extremal_freqs[j] = GetFrequency(Ext_Freq[j]); 00093 #ifdef _DEBUG 00094 DebugFile << "extremal_freqs[ " << j << " ] = " 00095 << extremal_freqs[j] << std::endl; 00096 #endif 00097 } 00098 00099 RemezFinish( filter_coeffs); 00100 00101 *fir_filter = new FirFilterDesign( filter_length, 00102 FIR_SYM_EVEN_LEFT, 00103 filter_coeffs); 00104 return; 00105 }; 00106 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00107 00108 00109 void RemezAlgorithm::RemezFinish( double *filter_coeffs ) 00110 { 00111 int k; 00112 double freq, *aa; 00113 FreqSampFilterSpec *filter_spec; 00114 FreqSampFilterDesign *filter_design; 00115 00116 aa = new double[Num_Approx_Funcs]; 00117 00118 for( k=0; k<Num_Approx_Funcs; k++) 00119 { 00120 freq = (double) k/ (double) Filter_Length; 00121 aa[k] = ComputeRemezAmplitudeResponse (0, freq); 00122 } 00123 filter_spec = new FreqSampFilterSpec( 1, 1, Filter_Length, aa); 00124 filter_design = new FreqSampFilterDesign( *filter_spec); 00125 filter_design->ComputeCoefficients( filter_spec); 00126 filter_design->CopyCoefficients( filter_coeffs); 00127 00128 00129 for(k=0; k<Filter_Length; k++) 00130 { 00131 #ifdef _DEBUG 00132 DebugFile << "Coeff[ " << k << " ] = " 00133 << filter_coeffs[k] << std::endl; 00134 #endif 00135 } 00136 } 00137 00138 00139 00140 //====================================================== 00141 // 00142 //------------------------------------------------------ 00143 00144 void RemezAlgorithm::SetupGrid( void ) 00145 { 00146 double work; 00147 work = (0.5 + PB_Edge_Freq - SB_Edge_Freq)/Num_Approx_Funcs; 00148 00149 Num_PB_Freqs = (int)floor(0.5 + PB_Edge_Freq/work); 00150 00151 Num_Grid_Pts_PB = Num_PB_Freqs * Grid_Density; 00152 00153 Num_SB_Freqs = Num_Approx_Funcs + 1 - Num_PB_Freqs; 00154 00155 PB_Increment = PB_Edge_Freq / Num_Grid_Pts_PB; 00156 00157 SB_Increment = ( 0.5 - SB_Edge_Freq )/((Num_SB_Freqs-1) * Grid_Density); 00158 return; 00159 } 00160 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00161 00162 double RemezAlgorithm::GetFrequency( int grid_index) 00163 { 00164 if( grid_index <= Num_Grid_Pts_PB ) 00165 { 00166 // compute freq in passband 00167 00168 return( grid_index * PB_Increment ); 00169 } 00170 else 00171 { 00172 // compute freq in stopband 00173 00174 return( SB_Edge_Freq + 00175 ( grid_index - (Num_Grid_Pts_PB+1))*SB_Increment); 00176 } 00177 } 00178 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00179 00180 void RemezAlgorithm::RemezError( void) 00181 { 00182 int j; 00183 double freq; 00184 double ampl_resp; 00185 00186 ampl_resp = ComputeRemezAmplitudeResponse( 1, 0.0); 00187 00188 for( j=0; j<= Max_Grid_Indx; j++) 00189 { 00190 freq = GetFrequency(j); 00191 00192 ampl_resp = ComputeRemezAmplitudeResponse( 0, freq); 00193 00194 Error[j] = WeightFunction(freq) * (DesiredResponse(freq) - ampl_resp); 00195 } 00196 return; 00197 } 00198 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00199 00200 double RemezAlgorithm::ComputeRemezAmplitudeResponse( 00201 int init_flag, 00202 double contin_freq) 00203 { 00204 static int i, j, k, sign; 00205 static double freq, denom, numer, alpha, delta; 00206 static double absDelta, xCont, term; 00207 double aa; 00208 00209 if(init_flag) 00210 { 00211 X_ = new double[Num_Approx_Funcs+1]; 00212 Beta_ = new double[Num_Approx_Funcs+1]; 00213 Gamma_ = new double[Num_Approx_Funcs+1]; 00214 for(j=0; j<=Num_Approx_Funcs; j++) 00215 { 00216 freq = GetFrequency(Ext_Freq[j]); 00217 X_[j] = cos(TWO_PI * freq); 00218 } 00219 00220 // compute delta 00221 denom = 0.0; 00222 numer = 0.0; 00223 sign = -1; 00224 for( k=0; k<=Num_Approx_Funcs; k++) 00225 { 00226 sign = -sign; 00227 alpha = 1.0; 00228 for( i=0; i<=(Num_Approx_Funcs-1); i++) 00229 { 00230 if(i==k) continue; 00231 alpha = alpha / (X_[k] - X_[i]); 00232 } 00233 Beta_[k] = alpha; 00234 if( k != Num_Approx_Funcs ) 00235 alpha = alpha/(X_[k] - X_[Num_Approx_Funcs]); 00236 freq = GetFrequency(Ext_Freq[k]); 00237 numer = numer + alpha * DesiredResponse(freq); 00238 00239 denom = denom + sign*(alpha/WeightFunction(freq)); 00240 } // end of loop over k 00241 00242 delta = numer/denom; 00243 absDelta = fabs(delta); 00244 00245 sign = -1; 00246 for( k=0; k<=Num_Approx_Funcs-1; k++) 00247 { 00248 sign = -sign; 00249 freq = GetFrequency(Ext_Freq[k]); 00250 Gamma_[k] = DesiredResponse(freq) - sign * delta / 00251 WeightFunction(freq); 00252 } 00253 } // end of if(init_flag) 00254 else 00255 { 00256 xCont = cos(TWO_PI * contin_freq); 00257 numer = 0.0; 00258 denom = 0.0; 00259 for( k=0; k<Num_Approx_Funcs; k++) 00260 { 00261 term = xCont - X_[k]; 00262 if(fabs(term)<1.0e-7) 00263 { 00264 aa = Gamma_[k]; 00265 goto done; 00266 } 00267 else 00268 { 00269 term = Beta_[k]/(xCont - X_[k]); 00270 denom += term; 00271 numer += Gamma_[k]*term; 00272 } 00273 } 00274 aa = numer/denom; 00275 } 00276 done: 00277 return(aa); 00278 } 00279 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00280 00281 void RemezAlgorithm::RemezSearch(void) 00282 { 00283 int i,j,k,extras,indexOfSmallest; 00284 double minVal; 00285 00286 k=0; 00287 00288 /* test for extremum at f=0 */ 00289 if( ( (Error[0]>0.0) && 00290 (Error[0]>Error[1]) && 00291 (fabs(Error[0])>=Abs_Delta) ) || 00292 ( (Error[0]<0.0) && 00293 (Error[0]<Error[1]) && 00294 (fabs(Error[0])>=Abs_Delta) ) ) 00295 { 00296 Ext_Freq[k]=0; 00297 k++; 00298 } 00299 00300 /* search for extrema in passband */ 00301 for(j=1; j<Num_Grid_Pts_PB; j++) 00302 { 00303 if( ( (Error[j]>=Error[j-1]) && 00304 (Error[j]>Error[j+1]) && 00305 (Error[j]>0.0) ) || 00306 ( (Error[j]<=Error[j-1]) && 00307 (Error[j]<Error[j+1]) && (Error[j]<0.0) )) 00308 { 00309 Ext_Freq[k] = j; 00310 k++; 00311 } 00312 } 00313 00314 /* pick up an extremal frequency at passband edge */ 00315 Ext_Freq[k]=Num_Grid_Pts_PB; 00316 k++; 00317 00318 /* pick up an extremal frequency at stopband edge */ 00319 j=Num_Grid_Pts_PB+1; 00320 Ext_Freq[k]=j; 00321 k++; 00322 00323 /* search for extrema in stopband */ 00324 00325 for(j=Num_Grid_Pts_PB+2; j<Max_Grid_Indx; j++) 00326 { 00327 if( ( (Error[j]>=Error[j-1]) && 00328 (Error[j]>Error[j+1]) && 00329 (Error[j]>0.0) ) || 00330 ( (Error[j]<=Error[j-1]) && 00331 (Error[j]<Error[j+1]) && 00332 (Error[j]<0.0) )) 00333 { 00334 Ext_Freq[k] = j; 00335 k++; 00336 } 00337 } 00338 /* test for extremum at f=0.5 */ 00339 j = Max_Grid_Indx; 00340 if( ( (Error[j]>0.0) && 00341 (Error[j]>Error[j-1]) && 00342 (fabs(Error[j])>=Abs_Delta) ) || 00343 ( (Error[j]<0.0) && 00344 (Error[j]<Error[j-1]) && 00345 (fabs(Error[j])>=Abs_Delta) ) ) 00346 { 00347 Ext_Freq[k]=Max_Grid_Indx; 00348 k++; 00349 } 00350 /*----------------------------------------------------*/ 00351 /* find and remove superfluous extremal frequencies */ 00352 if( k>Num_Approx_Funcs+1) 00353 { 00354 extras = k - (Num_Approx_Funcs+1); 00355 for(i=1; i<=extras; i++) 00356 { 00357 minVal = fabs(Error[Ext_Freq[0]]); 00358 indexOfSmallest = 0; 00359 for(j=1; j< k; j++) 00360 { 00361 if(fabs(Error[Ext_Freq[j]]) >= minVal) continue; 00362 minVal = fabs(Error[Ext_Freq[j]]); 00363 indexOfSmallest = j; 00364 } 00365 k--; 00366 for(j=indexOfSmallest; j<k; j++) Ext_Freq[j] = Ext_Freq[j+1]; 00367 } 00368 } 00369 return; 00370 } 00371 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00372 00373 int RemezAlgorithm::RemezStop2() 00374 { 00375 double maxVal, minVal, qq; 00376 int j, result; 00377 00378 result = 0; 00379 maxVal = fabs(Error[Ext_Freq[0]]); 00380 minVal = fabs(Error[Ext_Freq[0]]); 00381 00382 for( j=1; j<= Num_Approx_Funcs; j++) 00383 { 00384 if(fabs(Error[Ext_Freq[j]]) < minVal) minVal = fabs(Error[Ext_Freq[j]]); 00385 if(fabs(Error[Ext_Freq[j]]) > maxVal) maxVal = fabs(Error[Ext_Freq[j]]); 00386 } 00387 qq = (maxVal - minVal)/maxVal; 00388 if(qq<0.01) result = 1; 00389 return(result); 00390 } 00391 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00392 00393 int RemezAlgorithm::RemezStop( void) 00394 { 00395 //static int Old_Ext_Freq[50]; 00396 int j, result; 00397 00398 result = 1; 00399 00400 for(j=0; j<=Num_Approx_Funcs; j++) 00401 { 00402 if(Ext_Freq[j] != Old_Ext_Freq[j]) result = 0; 00403 Old_Ext_Freq[j] = Ext_Freq[j]; 00404 } 00405 return(result); 00406 } 00407 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00408 00409 double RemezAlgorithm::WeightFunction(double freq) 00410 { 00411 double result; 00412 00413 result = 1.0; 00414 if(freq <= PB_Edge_Freq) result = 1.0/Ripple_Ratio; 00415 return(result); 00416 } 00417 00418 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00419 00420 double RemezAlgorithm::DesiredResponse(double freq) 00421 { 00422 double result; 00423 00424 result = 0.0; 00425 if(freq <= PB_Edge_Freq) result = 1.0; 00426 return(result); 00427 } 00428