Forum > Packages and Libraries
[SOLVED] Is there FFT and hanning window code for Lazarus?
(1/1)
mas steindorff:
I'm looking for an FFT and "Hanning windowing" signal processing code to add to one of my projects.
I remember (and found) my old Numerical Recipes for pascal tool box I got back in the D4 days but the code needs work to run with the today's FPC. [and I would need to find an old floppy disk drive to access the code :( ]
It seems to me this code has been around long enough to be built in to some math library some where but I can't find it.
I searched and found out there uses to be an FFT example included with Lazarus back with fpc 2.2.2 but it was a dll interface. That example is not included with 2.4.2 and the website it calls out longer supports free pascal .
I though I'd ask here before I reinvent the wheel.
MAS
Laksen:
I made some functions for it once making use of high level functionality. Surprisingly it was still really fast
There's a lot of extra functionality, but if you want you can just pry out the stuff you need
http://j-software.dk/dsp.zip
mas steindorff:
Thanks Laksen, it looks like the code also has some other vector functions I was figuring I would have to write myself like mean() and median() as well ::).
depending on how fast my end code is, this may be the 2nd to final nail for some python code >:D I' hoping to do away with. Now all I need is a HDF5 file writer as the final nail!
Ocye:
"Numerical recipes" published the whole code not only in C/C++ but as well in standard Pascal. Have a look for the keywords with your preferred search engine.
BTW: I know Hann and Hamming window functions (and some other) but not Hanning. Some old stuff that needs to be checked carefully, perhaps it helps a little bit:
--- Code: ---
procedure Windowing(var data:array of double;Taps:integer;WF:TWindowFunktion);
var i:integer;
begin
for i:=0 to high(data) do
case WF of
wf_None : ;
wf_Hamming : data[i]:=data[i]*(0.54-0.46*cos((i*2*PI)/Taps));
wf_Blackman : data[i]:=data[i]*(0.42-0.5*cos((i*2*PI)/Taps)+0.08*cos((i*4*PI)/Taps));
wf_KaiserBessel : data[i]:=data[i]*(0.4021-0.4986*cos((i*2*PI)/Taps)+0.0981*cos((i*4*PI)/Taps)-0.0012*cos((i*6*PI)/Taps));
wf_FlatTop : data[i]:=data[i]*(0.2155-0.4159*cos((i*2*PI)/Taps)+0.2780*cos((i*4*PI)/Taps)-0.0836*cos((i*6*PI)/Taps)+0.0070*cos((i*8*PI)/Taps));
end;//case
end;
procedure DFT(data: array of RealType;isign:integer);
var i,i1,i2,i3,i4,np3, Count : integer;
c1,c2,h1r,h2r,h1i,h2i : RealType;
wr,wi,wpr,wpi,wtemp,theta : RealType;
begin
Count:=length(data);
if (Count mod 4<>0) then raise EMathError.Create('Fehler in DFT (N kein Vielfaches von 4)');
c1:=0.5;
theta:=PI/(Count/2);
if (isign=1) then
begin
c2:=-0.5;
four(data,1);
end else
begin
c2:=0.5;
theta:=-theta;
end;
wtemp:=sin(0.5*theta);
wpr:=-2.0*wtemp*wtemp;
wpi:=sin(theta);
wr:=1.0+wpr;
wi:=wpi;
np3:=Count+3;
for i:=2 to Count div 4 do
begin
// i4:=1+(i3=np3-(i2=1+(i1=i+i-1)));
h1r:=c1*(data[i1]+data[i3]);
h1i:=c1*(data[i2]-data[i4]);
h2r:=-c2*(data[i2]+data[i4]);
h2i:=c2*(data[i1]-data[i3]);
data[i1]:=h1r+wr*h2r-wi*h2i;
data[i2]:= h1i+wr*h2i+wi*h2r;
data[i3]:= h1r-wr*h2r+wi*h2i;
data[i4]:=-h1i+wr*h2i+wi*h2r;
// wr:=(wtemp=wr)*wpr-wi*wpi+wr;
wi:=wi*wpr+wtemp*wpi+wi;
end;
if (isign=1) then
begin
// data[1]:=(h1r=data[1])+data[2];
data[2]:=h1r-data[2];
end else
begin
// data[1]:=c1*((h1r=data[1])+data[2]);
data[2]:=c1*(h1r-data[2]);
four(data,-1);
end;
end;
procedure SWAP(var a, b:double);
var temp:double;
begin
temp:=(a);
a:=b;
b:=temp;
end;
procedure FFT(var data: array of double; nn:integer; invers: boolean);
(* Programs using routine FOUR1 must define type
TYPE
gldarray = ARRAY [1..nn2] OF real;
in the calling routine, where nn2=nn+nn. *)
var ii,jj,n,mmax,m,j,istep,i: integer;
wtemp,wr,wpr,wpi,wi,theta: double;
tempr,tempi: real;
begin
n := 2*nn;
j := 1;
for ii := 1 to nn do
begin
i := 2*ii-1;
if (j > i) then
begin
tempr := data[j];
tempi := data[j+1];
data[j] := data[i];
data[j+1] := data[i+1];
data[i] := tempr;
data[i+1] := tempi
end;
m := n div 2;
while ((m >= 2) and (j > m)) do
begin
j := j-m;
m := m div 2
end;
j := j+m
end;
mmax := 2;
while (n > mmax) do
begin
istep := 2*mmax;
if invers then
theta := 6.28318530717959/mmax else
theta := 6.28318530717959/-mmax;
wpr := -2.0*sqr(sin(0.5*theta));
wpi := sin(theta);
wr := 1.0;
wi := 0.0;
for ii := 1 to (mmax div 2) do
begin
m := 2*ii-1;
for jj := 0 to ((n-m) div istep) do
begin
i := m + jj*istep;
j := i+mmax;
tempr := real(wr)*data[j]-real(wi)*data[j+1];
tempi := real(wr)*data[j+1]+real(wi)*data[j];
data[j] := data[i]-tempr;
data[j+1] := data[i+1]-tempi;
data[i] := data[i]+tempr;
data[i+1] := data[i+1]+tempi
end;
wtemp := wr;
wr := wr*wpr-wi*wpi+wr;
wi := wi*wpr+wtemp*wpi+wi
end;
mmax := istep
end;
end;
procedure four(data : array of RealType; isign: integer);
var tmpdata : array of RealType;
alpha, beta, theta,
temp,sw,cw : double;
i,j,Count : integer;
begin
Count:=length(data);
setlength(tmpdata,2*Count);
ZeroMemory(tmpdata,sizeof(tmpdata));
for i:=0 to Count-1 do
begin
theta:=isign*2.0*PI*(i/Count);
temp:=sin(0.5*theta);
alpha:=2.0*sqr(temp);
beta:=sin(theta);
cw:=1.0;
sw:=0.0;
for j:=0 to Count-1 do
begin
tmpdata[2*i]:=tmpdata[2*i]+(cw*data[2*j]-sw*data[2*j+1]);
tmpdata[2*i+1]:=tmpdata[2*i+1]+(cw*data[2*j+1]+sw*data[2*j]);
// cw:=(temp=cw)-(alpha*cw+beta*sw);
sw:=sw-(alpha*sw-beta*temp);
end;
end;
if (isign=-1) then for i:=0 to 2*Count-1 do tmpdata[i]:=tmpdata[i]/Count;
for i:=0 to 2*Count-1 do data[i]:=tmpdata[i];
setlength(tmpdata,0);
end;
--- End code ---
Blaazen:
Of some reason, "Hanning" is name of function in Matlab. His name was Julius von Hann.
Thanks for code Ocye, it is useful.
I used windowing for design of FIR filters (linear frequency filters). If I will have time I will make the unit usable (user freindly) and I will publish it too.
Navigation
[0] Message Index