Programa Càlcul FFT Fressa


Codi en pascal del càlcul de l'FFT a partir dels estudis fets. Està en procés de revissió i comprovació. De fet, aquest codi, no és el que surt de La màgia de l'FFT. Surt d'una idea prèvia inspirada per intuició. Aquest codi no reflecteix exactament el codi del butterfly diagram ja que fa servir que els coeficient de la meitat inferior, els que multipliquen en les línies horitzontals, són els mateixos que que els que multipliquen les línies de la meitat superior, les oblíqües, canviades de signe. D'aquí ve aquesta matriu, un que adafa valors `1` i `-1`.

Aquest codi es presenta sense cap garantia. Tothom que el faci servir és sota la seva propia responsabilitat. En cap moment es garanteix que funcioni correctament.

    var f: array[0..NMax-1] of real; //valors de la funció Procedure FFT; Const NMax = 8; //Nombre màxim de dades MaxStages = 4; //Això ha de ser més gran que el lg2(NMax); var N:integer; //Nombre de dades, nombre dels coeficients de Fourier N més petit que NMAX i cal que sigui una potència de 2, 2, 4, 8, 16, 32, 64, 128, ... nStages:integer; cFr,cFi: array[0..NMAx-1,0..MaxStages-1] of real; //Coeficients Fourier, part real i part imaginària //això serveix per calcular l'ordre en què s'ha de posar les dades de la funció ncoe:integer; coe,coev: array[1..NMax] of integer; //coeficients dels valors de la x on cal buscar l'f(x) s,s1,s2:string; //Per mostrar informació debug x,y:integer; //posició dins la matriu de coeficients i,l,lp:integer; //Comptadors a:real; //això ho fem servir per calcular amb menys decimals, caldria treure-ho. Es per mostrar valors de debug mentre desenvolupem que no sigui massa llargs b:integer; Wr,Wi: array [0..NMax-1,1..MaxStages-1] of real; un: array [0..NMax-1,1..MaxStages-1] of integer; begin n:=NMax; //Primera col·lecció de dades per comprovar resultats f(0)=0, f(1)=1, ... https://youtu.be/FaWSGmkboOs for y:=0 to N-1 do f[y]:=y; //Segona col·lecció de dades per comprovar resultats https://youtu.be/RioJKiSBlyg { f[0]:=1; f[1]:=2; f[2]:=3; f[3]:=4; f[4]:=4; f[5]:=3; f[6]:=2; f[7]:=1; } //Posem tots els valors 0 for y:=0 to N-1 do for x:=0 to MaxStages-1 do cFr[y,x]:=0; for y:=0 to N-1 do for x:=0 to MaxStages-1 do cFi[y,x]:=0; //log2(dades) Això es pot fer d'una altra manera, però ens assegurem que el nombre de dades és una potència de 2. Màxim 4096 dades. Això es pot canviar per si cal que la finestra de dades, nombre de dades sigui més gran. if N=1 then begin nStages:=1; ncoe:=1; end else if N=2 then begin nStages:=2; ncoe:=2; end else if N=4 then begin nStages:=3; end else if N=8 then begin nStages:=4; end else if N=16 then begin nStages:=5; end else if N=32 then begin nStages:=6; end else if N=64 then begin nStages:=7; end else if N=128 then begin nStages:=8; end else if N=256 then begin nStages:=9; end else if N=512 then begin nStages:=10; end else if N=1024 then begin nStages:=11; end else if N=2048 then begin nStages:=12; end else if N=4096 then begin nStages:=13; end else begin ShowMessage('El nombre de dades no és una potència de 2 <= que 4096'); exit; end; //Càlcul de l'ordre en que s'han d'avaluar les f. Això es fa posant el nombres en binari, inveertint i reordenant, però ho faig així perquè és entendor coe[1]:=0; coe[2]:=1; coev[1]:=0; coev[2]:=1; if nStages>2 then begin ncoe:=2; for i:=3 to nStages do begin for l:=1 to ncoe do begin coe[l]:=2*coev[l]; coe[ncoe+l]:=2*coev[l]+1; end; for l:=1 to ncoe do begin coev[l]:=coe[l]; coev[ncoe+l]:=coe[ncoe+l]; end; ncoe:=2*ncoe; end; end; if N<>ncoe then begin ShowMessage('No coincideix el nombre de coeficients amb el nombre de dades, error no cotrolat'); exit; end; //Això és informació per debug s:=IntToStr(N)+' - '+IntToStr(ncoe)+' - '; for i:=1 to N do s:=s+IntToStr(coe[i])+', '; ShowMessage(s); //ordre dels valors de les n que es posen a la fórmula. Per exemple si n=8, 0, 4, 2, 6, 1, 5, 3, 7, és l'ordre que cal posar a la fórmula //Posem els valors del coeficients del primer stage amb els valors f ordenats for i:=1 to N do cFr[i-1,0]:=f[coe[i]]; //Això és informació per debug s:=''; for i:=0 to N-1 do s:=s+RealToString(cFr[i,0])+', '; ShowMessage(s); //valors de les f. Per exemple si n=8, f(0), f(4), f(2), f(6), f(1), f(5), f(3), f(7). //calcula coeficients que multipliquen l:=2; //Stage lp:=1; //Stage petit, meitat de l'anterior, pas for x:=1 to nStages-1 do begin for y:=0 to N-1 do begin if y mod l >= lp then b:=-1 else b:=1; un[y,x]:=b; if b=1 then begin Wr[y,x]:=1; Wi[y,x]:=0; end else begin a:=cos(2*pi*(y mod lp)/l); if abs(a)<0.00001 then a:=0; Wr[y,x]:=a; a:=sin(2*pi*(y mod lp)/l); if abs(a)<0.00001 then a:=0; Wi[y,x]:=a; end; end; lp:=l; l:=l*2; end; //Per mostrar resultats. FormPrincipal.MemoResultats.Text:=''; //FFT l:=2; //Stage lp:=1; //Stage petit, meitat de l'anterior, pas x:=0; while x0 then s2:='+'+s2+'i' else s2:=s2+'i'; s:=s+s1+' '+s2+#9; FormPrincipal.MemoResultats.Lines.Append(s); end; end;