Filter data with an exponential average filter.
Design an exponential filter with Decay parameter and place the transfer function in Num (numerator) and Den (denominator). Transfer function can be used to initialize an IIR filter by passing num and den to the IirInit routine.
Example 1
Exponential average filter.
uses MtxExpr, Math387, MtxVec, SignalUtils, MtxVecTee, MtxVecEdit,OptimalFir;
procedure TForm1.Button1Click(Sender: TObject);
var b,c,num,den: Vector;
n,i: integer;
IirState: TIirState;
State: TSample;
begin
//Alternative 1: Tone with 5 periods
// b := Sin(Ramp(300,0,2*Pi*5/300));
//Alternative 2: Gaussian noise
b := RandGauss(300);
c.Copy(b);
n := 10;
State := 0;
for i := 0 to (b.Length div n) - 1 do //streaming test 1
begin
b.SetSubRange(i*n,n);
ExpAverageFilter(b,State,10); //set to 10%
end;
b.SetFullRange;
DrawIt([c,b],['Unfiltered','Filtered']);
b.Copy(c);
ExpAverageFilter(10,num,den); //set to 10x, (1/10 = 0.1, => 10%)
FillChar(IirState,SizeOf(IirState),0);
IirInit(Num,Den,IirState);
for i := 0 to (b.Length div n) - 1 do //streaming test 2
begin
b.SetSubRange(i*n,n);
c.SetSubRange(i*n,n);
IirFilter(b,c,IirState);
end;
IirFree(IirState);
b.SetFullRange;
c.SetFullRange;
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 "OptimalFir.hpp"
#include <string.h>
void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
Vector num,den,b,c;
int n,i;
TIirState IirState;
double State = 0;
//Alternative 1: Tone with 5 periods
// b = Sin(Ramp(300,0,2*Pi*5/300));
//Alternative 2: Gaussian noise
b->Size(300);
b->RandGauss();
c = b; //delayed deep copy
n = 10;
for (i = 0; i < (b->Length/n); i++) //streaming test 1
ExpAverageFilter(b(i*n,i*n+n-1),State,10); //set to 10%
DrawIt(OPENARRAY(TVec*,(c,b)),OPENARRAY(AnsiString,("Unfiltered","Filtered")));
b = c;
ExpAverageFilter(10,num,den); //set to 10x, (1/10 = 0.1, => 10%)
memset(&IirState,0,sizeof(IirState));
IirInit(num,den,IirState);
for (i = 0; i < (b->Length/n); i++) //streaming test 2
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")));
}
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;
Vector c = new Vector(0);
Vector num = new Vector(0);
Vector den = new Vector(0);
int n;
int i;
TIirState IirState = new TIirState();
double state;
//Alternative 1: Tone with 5 periods
// b := Sin(Ramp(300,0,2*Pi*5/300));
//Alternative 2: Gaussian noise
b = MtxExpr.RandGauss(300,false);
c.Copy(b);
n = 10;
state = 0;
int bLength = b.Length;
for (i = 0; i < (bLength / n); i ++) //streaming test 1
{
b.SetSubRange(i*n,n);
SignalUtils.ExpAverageFilter(b,ref state, 10); //set to 10%
}
b.SetFullRange();
TeeChart.DrawIt(new TVec[2] {c,b}, new string[2] {"Unfiltered","Filtered"},"Exponential averaging",false);
b.Copy(c);
SignalUtils.ExpAverageFilter(10,num,den); //set to 10x, (1/10 = 0.1, => 10%)
SignalUtils.IirInit(num,den,ref IirState,false);
bLength = b.Length;
for (i = 0; i < (bLength / n); i ++) //streaming test 2
{
b.SetSubRange(i*n,n);
c.SetSubRange(i*n,n);
SignalUtils.IirFilter(b,c,ref IirState);
}
SignalUtils.IirFree(ref IirState);
b.SetFullRange();
c.SetFullRange();
TeeChart.DrawIt(new TVec[2] { b, c }, new string[2] { "Unfiltered", "Filtered" }, "Exponential averaging with IirFilter", false);
}
Declaration
Procedure ExpAverageFilter(Data: TVec; var State: TCplx; Decay: TSample = 50);
Description
Exponential average filter without the TIirState structure for complex data.
Declaration
Procedure ExpAverageFilter(Data: TVec; var State: TSample; Decay: TSample = 50);
Description
Exponential average filter without the TIirState structure. The function can be called to filter sample by sample. Initialize the State to 0 on the first call. Decay defines the decay from sample to sample and is initialized to 50% by default. With each new sample, the filter will take average from the 50% of the new sample and 50% of the previous average. The exponential average filter implements the following difference equation:
y[i] = 1/d * x[i] + (d-1)/d * y[i-1]
x.. input signal
y.. output signal
d.. Decay factor
In terms of percentage:
y[i] = a * x[i] + b * y[i-1] , a + b = 1
a*100 ... percent of the new data used.
b*100 ... percent of the old average used to compute the new average.