Estimate the length of a windowed FIR filter.
Returns the length of the FIR filter, windowed with the Kaiser window, where the maximum allowed ripple of the pass band is Ripple and sampling frequency is FS. The W array holds two parameters: the start and the stop of the narrowest transition band, relative to the specified sampling frequency. The equation can be found in [1] p. 453, eq. 7.93. The length of the filter designed with kaiser window is about 10% bigger then the length of the filter with the same specifications designed with the remez algorithm. The ripple of the passband and the stopband attenuation of a FIR filter designed with a Kaiser window are related with the equations:
Example 1
Design a highpass filter with at least 80 dB attenuation in the stopband and not more then 0.0001 ripple in the passband. Transition band is between 0.5 and 0.6 Hz. Sampling frequency is 2 Hz.
uses MtxExpr, Math387, MtxVec, SignalUtils, MtxVecTee, MtxVecEdit;
procedure TForm1.Button1Click(Sender: TObject);
var h,response: Vector;
n: integer;
FS,Ripple: TSample;
begin
Ripple := 0.0001;
FS := 2;
n := KaiserFirLength([0.5,0.6], Ripple, FS);
n := EnsureRange(4, n, MaxFirLength);
if not Odd(n) then Inc(n); //must be odd, if passband at FS/2
FIRImpulse(H.Size(n), [0.5,0.6], ftHighpass,FS); //get impulse response
Kaiser(H,KaiserBetaFir(Ripple)); //apply Kaiser window
FrequencyResponse(H,nil,Response,8); //zero padd by 8x
DrawIt(20*Log10(Abs(Response)));
end;
#include "MtxVecCPP.h" //MtxVecCPP.cpp must be included in the project
#include "MtxVecEdit.hpp"
#include "MtxVecTee.hpp"
#include "SignalUtils.hpp"
void __fastcall TForm41::BitBtn1Click(TObject *Sender)
{
Vector h,Response;
int n;
double FS = 2;
double Ripple = 0.0001;
n = KaiserFirLength(OPENARRAY(double,(0.5,0.6)), Ripple, FS);
n = EnsureRange(4, n, MaxFirLength);
if ((n%2) == 0) n++; //must be odd, if passband at FS/2
FirImpulse(h->Size(n), OPENARRAY(double,(0.5,0.6)), ftHighPass,FS); //get impulse response
Kaiser(h,KaiserBetaFir(Ripple)); //apply Kaiser window
FrequencyResponse(h,NULL,Response,8); //zero padd by 8x
DrawIt(20*Log10(Abs(Response)));
}
using Dew.Math;
using Dew.Math.Editors;
using Dew.Math.Units;
using Dew.Signal;
using Dew.Signal.Units;
using Dew.Math.Tee;
using Dew.Signal.Tee;
private void button1_Click(object sender, EventArgs e)
{
Vector h = new Vector(0);
Vector response = new Vector(0);
double FS = 2;
double Ripple = 0.0001;
int n = SignalUtils.KaiserFirLength(new double[2] {0.5,0.6}, Ripple, FS);
n = Math387.EnsureRange(4, n, SignalUtils.MaxFirLength);
if (n % 2 == 0)
{
n++; //must be odd, if passband at FS/2
}
SignalUtils.FirImpulse(h.Size(n), new double[2] { 0.5, 0.6 }, TFilterType.ftHighPass, FS); //get impulse response
SignalUtils.Kaiser(h,SignalUtils.KaiserBetaFir(Ripple)); //apply Kaiser window
SignalUtils.FrequencyResponse(h,null,response,8,false,TSignalWindowType.wtRectangular,0); //zero padd by 8x
TeeChart.DrawIt(20*MtxExpr.Log10(MtxExpr.Abs(response)),"Highpass FIR filter",false);
}