Design a DC filter.
Design a DC filter with TransitionBandwidth and place the transfer function in Num (numerator) and Den (denominator). You can then use this transfer function to initialize an IIR filter with a call to IirInit. A DC filtered signal will be centered around zero. This DC filter is a simple differentiator/integrator pair. Transition bandwidth is the width of the frequency band where the amplitude is not yet completely attenuated. With DC filters, the transition band starts at 0 Hz. Narrow transition band (TransitionBandwidth/FS ratio is small) will result in filters with longer delays. FS is the sampling frequency. The filter implements the following difference equation:
Design a DC filter with alpha parameter and place the transfer function in Num (numerator) and Den (denominator). This transfer function can be used to initialize an IIR filter with a call to IirInit. A DC filtered signal will be centered around zero. The DC filter is a simple differentiator/integrator pair. alpha is typically between 0.99 and 0.9999 and must be < 1. A bigger alpha will cause longer filter delay.
State parameter holds the filter state. NewValue is the next sample and alpha is typically between 0.99 and 0.9999 and must be < 1. Big alpha will cause longer filter delay and more ringing. State should be initialized to zero before the routine is called for the first time.
Example 1
DC filtering.
uses MtxExpr, Math387, MtxVec, SignalUtils, MtxVecTee, MtxVecEdit;
procedure TForm1.Button1Click(Sender: TObject);
var b,c,Response,num,den,X: Vector;
n,i: integer;
IirState: TIirState;
DCState: TCplx;
begin
Tone(b,300,5/300,0,1); //generate sine with 5 periods in 300 samples
// Alternative:
// b.RandGauss;
b := b + 2;
c.Copy(b);
n := 10;
DCFilter(0.95,num,den);
IirInit(num,den,IirState);
for i := 0 to b.Length div n-1 do //only to test the streaming
begin
b.SetSubRange(i*n,n);
c.SetSubRange(i*n,n);
IirFilter(b,c,IirState);
end;
b.SetFullRange;
c.SetFullRange;
DrawIt([b,c],['Unfiltered','Filtered'],'DC filter');
FrequencyResponse(num,den,Response,64);
DrawIt(Response,'Frequency response');
DcFilter(0.05,2,num,den);
IirInit(num,den,IirState);
for i := 0 to b.Length div n-1 do // the loop is only to test the streaming
begin
b.SetSubRange(i*n,n);
c.SetSubRange(i*n,n);
IirFilter(b,c,IirState);
end;
b.SetFullRange;
c.SetFullRange;
DrawIt([b,c],['Unfiltered','Filtered']);
FrequencyResponse(num,den,Response,64);
DrawIt(Response,'Frequency response');
DCState := C_ZERO;
for i := 0 to b.Length -1 do
c.Values[i] := DcFilter(b.Values[i],DcState,0.95);
DrawIt([b,c],['Unfiltered','Filtered']);
end;
#include "MtxVecCPP.h" //MtxVecCPP.cpp must be included in the project
#include "MtxVecEdit.hpp"
#include "MtxVecTee.hpp"
#include "SignalUtils.hpp"
#include <string.h>
void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
Vector num,den,b,c,Response;
int n,i;
TIirState IirState;
double State = 0;
TCplx DCState;
Tone(b,300,5.0/300,0,1); //generate sine with 5 periods in 300 samples
// Alternative:
// b->RandGauss();
b += 2; //add 2 to vector
c = b; //delayed deep copy
n = 10;
DcFilter(0.95,num,den); //specify alfa
memset(&IirState,0,sizeof(IirState));
IirInit(num,den,IirState);
for (i = 0; i < (b->Length/n); i++) //streaming test 1
IirFilter(b(i*n,i*n+n-1),c(i*n,i*n+n-1),IirState);
DrawIt(OPENARRAY(TVec*,(b,c)),OPENARRAY(AnsiString,("Unfiltered","Filtered")));
FrequencyResponse(num,den,Response,64);
DrawIt(Response,"Frequency response");
DcFilter(0.05,2,num,den); //specify transition bandwidth and FS
IirInit(num,den,IirState);
for (i = 0; i < (b->Length/n); i++) //streaming test 1
IirFilter(b(i*n,i*n+n-1),c(i*n,i*n+n-1),IirState);
DrawIt(OPENARRAY(TVec*,(b,c)),OPENARRAY(AnsiString,("Unfiltered","Filtered")));
FrequencyResponse(num,den,Response,64);
DrawIt(Response,"Frequency response");
DCState = C_ZERO;
for (i = 0; i < b->Length; i++) //streaming test 1
c.Values(i) = DcFilter(b.Values(i),DCState,0.95);
DrawIt(OPENARRAY(TVec*,(b,c)),OPENARRAY(AnsiString,("Unfiltered","Filtered")));
}
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 b = new Vector(0);
Vector c = new Vector(0);
Vector num = new Vector(0);
Vector x = new Vector(0);
Vector den = new Vector(0);
Vector Response = new Vector(0);
int n;
int i;
TIirState IirState = new TIirState();
TCplx DCState;
SignalUtils.Tone(b,300,5.0/300,0,1,false); //generate sine with 5 periods in 300 samples
// Alternative:
// b.RandGauss;
b = b + 2;
c.Copy(b);
n = 10;
SignalUtils.DcFilter(0.95,num,den);
SignalUtils.IirInit(num,den,ref IirState,false);
int bLength = b.Length;
for (i = 0; i < (bLength/n); i++) //only to test the streaming
{
b.SetSubRange(i*n,n);
c.SetSubRange(i*n,n);
SignalUtils.IirFilter(b,c,ref IirState);
}
b.SetFullRange();
c.SetFullRange();
TeeChart.DrawIt(new TVec[2] { b, c }, new string[2] { "Unfiltered", "Filtered" }, "DC IirFilter", false);
SignalUtils.FrequencyResponse(num,den,Response,64,false,TSignalWindowType.wtRectangular,0);
TeeChart.DrawIt(Response,"Frequency response",false);
SignalUtils.DcFilter(0.05,2,num,den);
SignalUtils.IirInit(num,den,ref IirState,false);
bLength = b.Length;
for (i = 0; i < (bLength/n); i++) //only to test the streaming
{
b.SetSubRange(i*n,n);
c.SetSubRange(i*n,n);
SignalUtils.IirFilter(b,c,ref IirState);
}
b.SetFullRange();
c.SetFullRange();
TeeChart.DrawIt(new TVec[2] { b, c }, new string[2] { "Unfiltered", "Filtered" }, "DC IirFilter", false);
SignalUtils.FrequencyResponse(num,den,Response,64,false,TSignalWindowType.wtRectangular,0);
TeeChart.DrawIt(Response,"Frequency response",false);
DCState = Math387.C_ZERO;
for (i = 0; i < (b.Length); i++) //only to test the streaming
{
c.Values[i] = SignalUtils.DcFilter(b.Values[i],ref DCState,0.95);
}
TeeChart.DrawIt(new TVec[2] { b, c }, new string[2] { "Unfiltered", "Filtered" }, "DC IirFilter", false);
}