Design an optimal equiripple FIR filter with Parks-McClellan algorithm.
function remez(const h: TVec; const bands: array of Double; const gains: array of Double; const weights: array of Double; FilterType: TRemezType; out err: Double; FS: Double = 2; ConstantRipple: boolean = false): integer;
|
Parameters |
Description |
|
h |
An array of length h.Length on entry and contains the filter impulse response on exit. |
|
bands |
Defines the frequency bands. |
|
gains |
Defines, if the band is a stopband or a passband. |
|
weights |
Array contains the ratios between required ripples for different bands. |
|
FilterType |
Choose between bandpass, hilbert, differentator and integrator. |
|
err |
Contains the maximum ripple error upon return. |
|
FS |
Specifies the sampling frequency. |
|
ConstantRipple |
If True, the ripple will be constant and not weighted to give constant percentage error in case of the following filter types: rmtDifferentiator, rmtIntegrator, rmtDoubleDifferentiator, rmtDoubleIntegrator |
Designs an equiripple (optimal) FIR filter. The routine will not always converge. Parameters have to be specified, for which the filter exists. Most common causes for trouble are:
The length of the filter can be estimated with the RemezLength routine. RemezLength routine will also properly adjust the error weights. An extensive explanation of the algorithm can be found in [1] Ch. 7.6, p. 462.
A few need to know things about FIR filters:
The Fortran source code can be found in [2] p. 198.
References:
A sample lowpass filter design with sampling frequency 8000Hz, transition band between at 1500Hz and 2000Hz with 60 dB attenuation (20 * Log10(0.001)) and 0.001 ripple in the passband. To try out other setups comment out the lowpass and comment in the desired filter.
uses MtxExpr, Math387, MtxVec, SignalUtils, MtxVecTee, MtxVecEdit, OptimalFIR; procedure TForm1.Button1Click(Sender: TObject); var z,Response,Weights: Vector; n: integer; err: Double; begin n := RemezLength([0, 1500, 2000, 4000], [1, 0], [0.001, 0.001],Weights, 8000); z.Size(n); Remez(z,[0, 1500, 2000, 4000], [1, 0], TDoubleArray(Weights), rmtBandpass,err,8000); //Design a highpass // n := RemezLength([0, 1500, 2000, 4000], [0, 1], [0.001, 0.001],Weights, 8000); // z.Size(n); // Remez(z,[0, 1500, 2000, 4000], [0, 1], TDoubleArray(Weights), rmtBandpass,err,8000); //Design a bandpass (Sampling frequency = 2) // n := RemezLength([0, 0.15, 0.25, 0.45, 0.55, 1], [0, 1, 0], [0.001, 0.001, 0.001],Weights); // z.Size(n); // Remez(z,[0, 0.15, 0.25, 0.45, 0.55, 1], [0, 1, 0], TDoubleArray(Weights), rmtBandpass, err); //Design a bandstop (Sampling frequency = 2) // n := RemezLength([0, 0.15, 0.25, 0.45, 0.55, 1], [1, 0, 1], [0.001, 0.001, 0.001],Weights); // z.Size(n); // Remez(z,[0, 0.15, 0.25, 0.45, 0.55, 1], [1, 0, 1], TDoubleArray(Weights), rmtBandpass, err); //Design a multiband (Sampling frequency = 2) // n := RemezLength([0.00, 0.10, 0.20, 0.30, 0.40, // 0.45, 0.55, 0.60, 0.70, 1.00], [1, 0, 1, 0, 1], [0.001, 0.001, 0.001, 0.001, 0.001],Weights); // z.Size(n); // Remez(z,[0.00, 0.10, 0.20, 0.30, 0.40, // 0.45, 0.55, 0.60, 0.70, 1.00], [1, 0, 1, 0, 1], TDoubleArray(Weights), rmtBandpass, err); //Design a hilbert (type III) transformer (Sampling frequency = 2) // n := RemezLength([0, 0, 0.1, 0.9, 1, 1], [0,1,0], [0.01,0.01,0.01],Weights); // if not Odd(n) then Inc(n); //odd length type III filter // z.Size(n); // Remez(z,[0.1, 0.9], [1], [1], rmtHilbert,err); //Design a hilbert (type IV) transformer (Sampling frequency = 2) // n := RemezLength([0, 0, 0.1, 0.9, 1, 1], [0,1,0], [0.01,0.01,0.01],Weights); // if Odd(n) then Inc(n); //even length type IV filter // z.Size(n); // Remez(z,[0.1, 1], [1], [1], rmtHilbert,err); //Design a differentiator (type III) (Sampling frequency = 2) // n := RemezLength([0, 0, 0.1, 0.9, 1, 1], [0,1,0], [0.01,0.01,0.01],Weights); // if not Odd(n) then Inc(n); //odd length type III filter // z.Size(n); // Remez(z,[0.1, 0.9], [1], [1], rmtDifferentiator,err); h//Design a differentiator (type IV) (Sampling frequency = 2) // n := RemezLength([0, 0, 0.1, 0.9, 1, 1], [0,1,0], [0.01,0.01,0.01],Weights); // if Odd(n) then Inc(n); //even length type IV filter // z.Size(n); // Remez(z,[0.1, 1], [1], [1], rmtDifferentiator,err); //Design a double differentiator (Sampling frequency = 2) // n := RemezLength([0, 0, 0.05, 0.95, 1, 1], [0,1,0], [0.01,0.01,0.01],Weights); // if Odd(n) then Inc(n); //even length type IV filter // z.Size(n); // Remez(z,[0.05, 1], [1], [1], rmtDoubleDifferentiator,err); //Design an integrator (Sampling frequency = 2) // n := RemezLength([0, 0, 0.05, 0.95, 1, 1], [0,1,0], [0.01,0.01,0.01],Weights); // if Odd(n) then Inc(n); //even length type IV filter // z.Size(n); // Remez(z,[0.05, 1], [1], [1], rmtIntegrator,err); //Design a double integrator (Sampling frequency = 2) // n := RemezLength([0, 0, 0.05, 0.95, 1, 1], [0,1,0], [0.01,0.01,0.01],Weights); // if Odd(n) then Inc(n); //even length type IV filter // z.Size(n); // Remez(z,[0.05, 1], [1], [1], rmtDoubleIntegrator,err); FrequencyResponse(z,nil,Response,8); DrawIt(Response); end;
#include "MtxExpr.hpp" #include "MtxVecEdit.hpp" #include "MtxVecTee.hpp" #include "SignalUtils.hpp" #include "OptimalFIR.hpp" void __fastcall TForm1::BitBtn1Click(TObject *Sender) { sVector z, Response, Weights; int n; double err; n = RemezLength(OPENARRAY(double,(0, 1500, 2000, 4000)), OPENARRAY(double,(1, 0)), OPENARRAY(double,(0.001, 0.001)),Weights, 8000); z.Size(n); remez(z,OPENARRAY(double,(0, 1500, 2000, 4000)), OPENARRAY(double,(1, 0)), Weights.PValues1D(0), Weights.Length-1, rmtBandPass,err,8000); //Design a highpass // n = RemezLength(OPENARRAY(double,(0, 1500, 2000, 4000)), OPENARRAY(double,(0, 1)), OPENARRAY(double,(0.001, 0.001)),Weights, 8000); // z.Size(n); // remez(z,OPENARRAY(double,(0, 1500, 2000, 4000)), OPENARRAY(double,(0, 1)), Weights.PValues1D(0), Weights.Length-1, rmtBandPass,err,8000); //Design a bandpass (Sampling frequency = 2) // n = RemezLength(OPENARRAY(double,(0, 0.15, 0.25, 0.45, 0.55, 1)), OPENARRAY(double,(0, 1, 0)), OPENARRAY(double,(0.001, 0.001, 0.001)),Weights); // z.Size(n); // remez(z,OPENARRAY(double,(0, 0.15, 0.25, 0.45, 0.55, 1)), OPENARRAY(double,(0, 1, 0)), Weights.PValues1D(0), Weights.Length-1, rmtBandPass, err); //Design a bandstop (Sampling frequency = 2) // n = RemezLength(OPENARRAY(double,(0, 0.15, 0.25, 0.45, 0.55, 1)), OPENARRAY(double,(1, 0, 1)), OPENARRAY(double,(0.001, 0.001, 0.001)),Weights); // z.Size(n); // remez(z,OPENARRAY(double,(0, 0.15, 0.25, 0.45, 0.55, 1)), OPENARRAY(double,(1, 0, 1)), Weights.PValues1D(0), Weights.Length-1, rmtBandPass, err); //Design a multiband (Sampling frequency = 2) // n = RemezLength(OPENARRAY(double,(0.00, 0.10, 0.20, 0.30, 0.40, 0.45, 0.55, 0.60, 0.70, 1.00)), // OPENARRAY(double,(1, 0, 1, 0, 1)), OPENARRAY(double,(0.001, 0.001, 0.001, 0.001, 0.001)),Weights); // z.Size(n); // remez(z,OPENARRAY(double,(0.00, 0.10, 0.20, 0.30, 0.40, 0.45, 0.55, 0.60, 0.70, 1.00)), // OPENARRAY(double,(1, 0, 1, 0, 1)), Weights.PValues1D(0), Weights.Length-1, rmtBandPass, err); //Design a hilbert (type III) transformer (Sampling frequency = 2) // n = RemezLength(OPENARRAY(double,(0, 0, 0.1, 0.9, 1, 1)), OPENARRAY(double,(0,1,0)), OPENARRAY(double,(0.01,0.01,0.01)),Weights); // if ((n%2) == 0) n++; //odd length type III filter // z.Size(n); // remez(z,OPENARRAY(double,(0.1, 0.9)), OPENARRAY(double,(1)), OPENARRAY(double,(1)), rmtHilbert,err); //Design a hilbert (type IV) transformer (Sampling frequency = 2) // n = RemezLength(OPENARRAY(double,(0, 0, 0.1, 0.9, 1, 1)), OPENARRAY(double,(0,1,0)), OPENARRAY(double,(0.01,0.01,0.01)),Weights); // if (!((n%2) == 0)) n++; //odd length type IV filter // z.Size(n); // remez(z,OPENARRAY(double,(0.1, 1)), OPENARRAY(double,(1)), OPENARRAY(double,(1)), rmtHilbert,err); //Design a differentiator (type III) (Sampling frequency = 2) // n = RemezLength(OPENARRAY(double,(0, 0, 0.1, 0.9, 1, 1)), OPENARRAY(double,(0,1,0)), OPENARRAY(double,(0.01,0.01,0.01)),Weights); // if ((n%2) == 0) n++; //odd length type III filter // z.Size(n); // remez(z,OPENARRAY(double,(0.1, 0.9)), OPENARRAY(double,(1)), OPENARRAY(double,(1)), rmtDifferentiator,err); //Design a differentiator (type IV) (Sampling frequency = 2) // n = RemezLength(OPENARRAY(double,(0, 0, 0.1, 0.9, 1, 1)), OPENARRAY(double,(0,1,0)), OPENARRAY(double,(0.01,0.01,0.01)),Weights); // if (!((n%2) == 0)) n++; //even length type IV filter // z.Size(n); // remez(z,OPENARRAY(double,(0.1, 1)), OPENARRAY(double,(1)), OPENARRAY(double,(1)), rmtDifferentiator,err); //Design a double differentiator (Sampling frequency = 2) // n = RemezLength(OPENARRAY(double,(0, 0, 0.05, 0.95, 1, 1)), OPENARRAY(double,(0,1,0)), OPENARRAY(double,(0.01,0.01,0.01)),Weights); // if (!((n%2) == 0)) n++; //even length type IV filter // z.Size(n); // remez(z,OPENARRAY(double,(0.05, 1)), OPENARRAY(double,(1)), OPENARRAY(double,(1)), rmtDoubleDifferentiator,err); // Design an integrator (Sampling frequency = 2) // n = RemezLength(OPENARRAY(double,(0, 0, 0.05, 0.95, 1, 1)), OPENARRAY(double,(0,1,0)), OPENARRAY(double,(0.01,0.01,0.01)),Weights); // if (!((n%2) == 0)) n++; //even length type IV filter // z.Size(n); // remez(z,OPENARRAY(double,(0.05, 1)), OPENARRAY(double,(1)), OPENARRAY(double,(1)), rmtIntegrator,err); //Design a double integrator (Sampling frequency = 2) // n = RemezLength(OPENARRAY(double,(0, 0, 0.05, 0.95, 1, 1)), OPENARRAY(double,(0,1,0)), OPENARRAY(double,(0.01,0.01,0.01)),Weights); // if (!((n%2) == 0)) n++; //even length type IV filter // z.Size(n); // remez(z,OPENARRAY(double,(0.05, 1)), OPENARRAY(double,(1)), OPENARRAY(double,(1)), rmtDoubleIntegrator,err); FrequencyResponse(z,NULL,Response,8); DrawIt(Response); }
|
Copyright (c) 1999-2025 by Dew Research. All rights reserved.
|
|
What do you think about this topic? Send feedback!
|