Fast Fourier Transform Reklamy Google
Opis klasy FFT Delphi - TFastFourier, wyniki szybkości obliczeń dla różnych wielkości danych oraz przykład zastosowania. Do pobrania gotowy komponent obliczający transformatę.
Krótka charakterystyka klasy TFastFourierKomponenet FastFourier zawiera w sobie Szybką Transformatę Fouriera. Pamiec jest przydzielana tutaj dynamicznie. Dwie zespolone tablice: wejsciowa i wyjsciowa sa typu zespolonego (InBuffer, OutBuffer). Okna czasowe jakie mozna stosowac okreslaja stałe w definicji modulu z przedrostkiem 'ok'. Najwazniejsze procedury to FFT oraz IFFT - obie bezparametrowe. Dla wypelnionej tablicy wejsciowej InBuffer procedura FFT wykonuje szybką transformate Fouriera a wynik zapisuje do tablicy OutBuffer. IFFT robi transformate odwrotna dla danych wejsciowych. Po dokonaniu transformaty mamy do dyspozycji funkcje: Normalize, Real, Imag, Absol, Power, Energy, Phase, LogEnergy - chyba nie trzeba tlumaczyc ich znaczenia. Ich argumentami sa indeksy tablicy OutBuffer.
Implementacja klasy TFastFourierPrzedstawiony komponent FastFourier dla Delphi zawiera stale dla okien czasowych, typ TComplex (liczba zespolona) oraz klasa calego mechanizmu.
Definicje te wygladaja nastepujaco:
type
TComplex = Record
Re : Extended;
Im : Extended;
end;
type
TFastFourier = class(TComponent)
public
InBuffer : array of TComplex;
OutBuffer : array of TComplex;
procedure FFT;
procedure IFFT;
function Real(idx : LongWord) : Extended;
function Imag(idx : LongWord) : Extended;
function Absol(idx : LongWord) : Extended;
function Power(idx, SamplFreq : LongWord) : Extended;
function Energy(idx : LongWord) : Extended;
function Phase(idx : LongWord) : Extended;
published
property NumSamples : LongWord read FNumSamples write SetNumSamples;
end;
Testy czasowe komponentu TFastFourier na AMD 333 MHz, 128 MB RAM:
dla N=8192 t=110 milisek
dla N=16384 t=220 milisek
dla N=32768 t~380 milisek
dla N=65536 t=880 milisek
dla N=131072 t=1.8 sek
dla N=262144 t=4.1 sek
dla N=524288 t=8,6 sek
dla N=1048576 t=17,6 sek
dla N=2097152 t=41,9 sek

Program prezentacyjny komponentu TFastFourier. W pasku statusu pokazywane są czasy obliczeń.
Pliki do pobrania:
Przykład użycia TFastFourier
uses TFastFourier;
var FFT : TFastFourier;
FFT.NumSamples:=128;
For i:=0 to NumSamples-1 do
FFT.InBuffer[i].re:=sin(0.5*i);
FFT.FFT;
For i:=0 to NumSamples-1 do
Wykres.Data[i]:=Energy(i);
Wykres.Rysuj;
Algorytm transformaty Fouriera w wersji Fast - algorytm o podstawie 2 Tutaj postaram się przedstawię algorytm szybkiej transformaty Fouriera. Warunkiem do algorytmu
FFT jest aby liczba próbek do przetworzenia byla całkowitą potegą liczby 2 - czyli liczba próbek
poddawana transformacie moęe być równa 2, 4, 8 ... 128, 256, 512, 1024 ... itd.
Nie bedę tutaj przytaczała calego wyprowadzenia. Powiem tylko, ęe algorytm wymaga nastepujących
procedur i funkcji, których definicje zamieszczam w dalszej części:
IsPowerOfTwo(x : LongWord) : Boolean
- Funkcja zwraca wartosc logiczna True, jesli jej argument x jest potega liczby 2.
NumberOfBitsNeeded(Ile : LongWord) : LongWord
- Funkcja zwraca liczbe bitow potrzebnych do zakodowania liczby argumentu Ile. Ile musi byc potega liczby 2.
ReverseBits(index, NumBits : LongWord) : LongWord
- Funkcja robi "odwrocenie bitowe" dla 'index' przy znajomosci liczby potrzebnych bitow NumBits.
FourierTransform ( Angle: Extended)
- Procedura szybkiej transformaty. To jest wlasnie najwazniejsza funkcja. W zaleznosci od kata Angle
procedura robi FFT lub IFFT.
FFT
- Procedura FFT jest wywolaniem procedury FourierTransform z argumentem 2*PI
IFFT
- Procedura IFFT jest wywolaniem procedury FourierTransform z argumentem -2*PI. Dodatkowo przetransformowane
probki nalezy podzielic przez ich ilosc (wynika to z definicji Transformaty Fouriera).
Unit FastFourier;
{*********************************************************}
{*** FAST FOURIER TRANSFORM Component ***}
{*** Autor : Natalia Walkowicz, grudzien 2003 ***}
{*** Maxymalna liczba probek: N = 2 147 483 648 ***}
{*********************************************************}
interface
uses
Windows, Messages, SysUtils, Classes, Math, Complex;
type
TFastFourier = class(TComponent)
private
FNumSamples : LongWord;
function IsPowerOfTwo(x : LongWord) : Boolean;
function PowerOf2(Liczba : LongWord) : LongWord;
function NumberOfBitsNeeded(Ile : LongWord) : LongWord;
function ReverseBits(index, NumBits : LongWord) : LongWord;
procedure FourierTransform(Angle : Extended);
procedure SetNumSamples(Value : LongWord);
public
InBuffer : array of TComplex;
OutBuffer : array of TComplex;
procedure FFT;
procedure IFFT;
function NumberOfSamples(Count : LongWord) : LongWord;
function Real(idx : LongWord) : Extended;
function Imag(idx : LongWord) : Extended;
function Absol(idx : LongWord) : Extended;
function Energy(idx, SamplFreq : LongWord) : Extended;
function Power(idx : LongWord) : Extended;
function Phase(idx : LongWord) : Extended;
function Frequency(idx, SamplFreq : LongWord) : Extended;
procedure Free;
constructor Create(AOwner : TComponent); override;
destructor Destroy; override;
published
property NumSamples : LongWord read FNumSamples write SetNumSamples;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Engineering', [TFastFourier]);
end;
constructor TFastFourier.Create(AOwner : TComponent);
begin
inherited Create(AOwner);
NumSamples:=0;
end;
destructor TFastFourier.Destroy;
begin
SetLength(InBuffer,0);
SetLength(OutBuffer,0);
inherited;
end;
procedure TFastFourier.SetNumSamples(Value : LongWord);
begin
FNumSamples:=Value;
SetLength(InBuffer,Value);
SetLength(OutBuffer,Value);
end;
function TFastFourier.NumberOfSamples(Count: LongWord): LongWord;
var i, wynik, potega : LongWord;
begin
if IsPowerOfTwo(Count) then
wynik:=Count;
if not IsPowerOfTwo(Count) then
begin
potega := 1;
i:=0;
while ((i<=31) and (potega
begin
potega := potega SHL 1;
i:=i+1;
end;
end;
Result:=potega;
end;
function TFastFourier.PowerOf2(Liczba : LongWord) : LongWord;
var i, potega : LongWord;
begin
potega:=1;
for i :=1 to Liczba do
potega:=potega*2;
Result:=potega;
end;
function TFastFourier.IsPowerOfTwo(x : LongWord) : Boolean;
var i, y : LongWord;
begin
y:=2;
for i:=1 to 31 do
begin
if x = y then
begin
Result := True;
exit;
end;
y:=y SHL 1;
end;
Result := False;
end;
function TFastFourier.NumberOfBitsNeeded(Ile : LongWord) : LongWord;
var i : LongWord;
begin
for i:=0 to 31 do
begin
if (Ile AND (1 SHL i)) <> 0 then
begin
Result:=i;
Exit;
end;
end;
end;
function TFastFourier.ReverseBits(index, NumBits : LongWord) : LongWord;
var i, rev : LongWord;
begin
rev:=0;
for i:=0 to NumBits-1 do
begin
rev:=(rev SHL 1) OR (index AND 1);
index:=index SHR 1;
end;
Result:=rev;
end;
procedure TFastFourier.FourierTransform(Angle : Extended);
var NumBits, i, j, k, n, BlockSize, BlockEnd : LongWord;
delta_angle, delta_ar : Extended;
alpha, beta : Extended;
tr, ti, ar, ai : Extended;
begin
NumBits:=NumberOfBitsNeeded(FNumSamples);
for i:=0 to FNumSamples-1 do
begin
j:=ReverseBits(i, NumBits);
OutBuffer[j]:=InBuffer[i];
end;
BlockEnd:=1;
BlockSize:=2;
while BlockSize<=FNumSamples do
begin
delta_angle:=Angle/BlockSize;
alpha:=sin(0.5* delta_angle);
alpha:=2.0*alpha*alpha;
beta:=sin(delta_angle);
i:=0;
while i
begin
ar:=1.0; // cos(0)
ai:=0.0; // sin(0)
j:=i;
for n:=0 to BlockEnd-1 do
begin
k:=j+BlockEnd;
tr:=ar*OutBuffer[k].Re-ai*OutBuffer[k].Im;
ti:=ar*OutBuffer[k].Im+ai*OutBuffer[k].Re;
OutBuffer[k].Re:=OutBuffer[j].Re-tr;
OutBuffer[k].Im:=OutBuffer[j].Im-ti;
OutBuffer[j].Re:=OutBuffer[j].Re+tr;
OutBuffer[j].Im:=OutBuffer[j].Im+ti;
delta_ar:=alpha*ar+beta*ai;
ai:=ai-(alpha*ai-beta*ar);
ar:=ar-delta_ar;
INC(j);
end;
i:=i+BlockSize;
end;
BlockEnd:=BlockSize;
BlockSize:=BlockSize SHL 1;
end;
end;
procedure TFastFourier.FFT;
begin
FourierTransform(2*PI);
end;
procedure TFastFourier.IFFT;
var i: LongWord;
begin
FourierTransform(-2*PI);
for i:=0 to FNumSamples-1 do
begin
OutBuffer[i].Re:=OutBuffer[i].Re/FNumSamples;
OutBuffer[i].Im:=OutBuffer[i].Im/FNumSamples;
end;
end;
function TFastFourier.Imag(idx: LongWord): Extended;
var z : TComplex;
begin
z:=OutBuffer[idx];
Result:=z.Im;
end;
function TFastFourier.Real(idx: LongWord): Extended;
var z : TComplex;
begin
z:=OutBuffer[idx];
Result:=z.Re;
end;
function TFastFourier.Absol(idx : LongWord) : Extended;
var z : TComplex;
begin
z:=OutBuffer[idx];
if idx=0 then
Result:=sqrt(z.Re*z.Re+z.Im*z.Im)/FNumSamples;
if idx>0 then
Result:=sqrt(z.Re*z.Re+z.Im*z.Im)/FNumSamples*2;
end;
function TFastFourier.Power(idx: LongWord): Extended;
var z : TComplex;
begin
z:=OutBuffer[idx];
if idx=0 then
Result:=(z.Re*z.Re+z.Im*z.Im)/FNumSamples;
if idx>0 then
Result:=(z.Re*z.Re+z.Im*z.Im)/FNumSamples*2;
end;
function TFastFourier.Energy(idx, SamplFreq : LongWord): Extended;
var x : Extended;
begin
x:=Power(idx);
Result:=x*x/FNumSamples*SamplFreq;
end;
function TFastFourier.Phase(idx: LongWord): Extended;
var re, im : Extended;
begin
re:=Real(idx);
im:=Imag(idx);
if abs(re)>1e-5 then
Result:=ArcTan(im/re)
else
Result:=0;
end;
function TFastFourier.Frequency(idx, SamplFreq: LongWord): Extended;
begin
if (idx>=0) or (idx
Result:=SamplFreq/FNumSamples*idx
else
Result:=0;
end;
procedure TFastFourier.Free;
begin
SetLength(InBuffer,0);
SetLength(OutBuffer,0);
end;
end.
Pliki do pobrania:
Visitors
Reklamy Google
Komentarze (1)
Zapraszam do pisania komentarzy w tym temacie.
Napisz komentarz
Pamiętaj, aby wypełnić wszystkie pola.
|