Contributor: JACK BAKKER
{> I'm Looking for a source for a FFT of the Soundblaster> Input. Could somebody help me?
Do you know the basics of Fourier Transformation?
Not that you need to, for this routine, but it might be handy to know.
Anyhow, here's something I still didn't test:
}
Program FOURIER;
{ Real FFT with single sine look-up per pass }
Const
 Asize = 4096; { Size of array goes here }
 PI2 = 1.570796327; { PI/2 }
 F = 16; { Format constants }
 D = 6; { " " }
Type
 Xform = (Fwd,Inverse); { Transform types }
 Xary = Array[1..Asize] of Real;
Var
 I,j,N,modulo : Integer;
 F1 : Text; { File of Real;}
 X : Xary; { Array to transform }
 Inv : Xform; { Transform type - Forward or Inverse }
 w : Real; { Frequency of wave }
{*****************************************************************************}
Procedure Debug; { Used to print intermediate results }
Var I3 : Integer;
Begin
 For I3 := 1 to N Do
 Writeln((I3-1):3,X[I3]:F:D);
End; { Debug }
{*****************************************************************************}
Function Ibitr(j,nu : Integer) : Integer;
 { Function to bit invert the number j by nu bits }
Var
 i,j2,ib : Integer;
Begin
 ib := 0; { Default return integer }
 For i := 1 to nu do
 Begin
 j2 := j Div 2; { Divide by 2 and compare lowest bits }
 { ib is doubled and bit 0 set to 1 if j is odd }
 ib := ib*2 + (j - 2*j2);
 j := j2; { For next pass }
 End; {For}
 ibitr := ib; { Return bit inverted value }
End; { Ibitr }
{*****************************************************************************}
Procedure Expand;
Var
 i,nn2,nx2 : Integer;
Begin
 nn2 := n div 2;
 nx2 := n + n;
 For i := 1 to nn2 do x[i+n] := x[i+nn2]; { Copy IM to 1st half IM position }
 For i := 2 to nn2 do
 Begin
 x[nx2-i+2] := -x[i+n]; { Replicate 2nd half Imag as negative }
 x[n-i+2] := x[i]; { Replicate 2nd half Real as mirror image }
 End;
 n := nx2; { We have doubled number of points }
End;
{*****************************************************************************}
Procedure Post(inv : Xform);
 { Post processing for forward real transforms and pre-processing for inverse
 real transforms, depending on state of the variable inv. }
Var
 nn2,nn4,l,i,m,ipn2,mpn2 : Integer;
 arg,rmsin,rmcos,ipcos,ipsin,ic,is1,rp,rm,ip,im : Real;
Begin
 nn2 := n div 2; { n is global }
 nn4 := n div 4;
 { imax represents PI/2 }
 For l := 1 to nn4 Do
 { Start at ends of array and work towards middle }
 Begin
 i := l+1; { Point near beginning }
 m := nn2-i+2; { Point near end }
 ipn2 := i+nn2; { Avoids recalculation each time }
 mpn2 := m+nn2; { Calcs ptrs to imaginary part }
 rp := x[i]+x[m];
 rm := x[i]-x[m];
 ip := x[ipn2]+x[mpn2];
 im := x[ipn2]-x[mpn2];
 { Take cosine of PI/2 }
 arg := (Pi2/nn4)*(i-1);
 ic := Cos(arg);
 { Cosine term is minus if inverse }
 If inv = Inverse Then ic := -ic;
 Is1 := Sin(arg);
 ipcos := ip*ic; { Avoid remultiplication below }
 ipsin := ip*is1;
 rmsin := rm*is1;
 rmcos := rm*ic;
 x[i] := (rp + ipcos - rmsin)/2.0; {* Combine for real-1st pt }
 x[ipn2] := (im - ipsin - rmcos)/2.0; {* Imag-1st point }
 x[m] := (rp - ipcos + rmsin)/2.0; {* Real - last pt }
 x[mpn2] := -(im +ipsin +rmcos)/2.0; {* Imag, last pt }
 End; { For }
 x[1] := x[1]+x[nn2+1]; {** For first complex pair}
 x[nn2+1] := 0.0; {**}
End; { Post }
{*****************************************************************************}
Procedure Shuffl(inv : Xform);
 { This procedure shuffels points from alternate real-imaginary to
 1st-half real, 2nd-half imaginary order if inv=Fwd, and reverses the
 process if inv=Inverse. Algorithm is much like Cooley-Tukey:
 Starts with large cells and works to smaller ones for Fwd
 Starts with small cells and increases if inverse }
Var
 i,j,k,ipcm1,celdis,celnum,parnum : Integer;
 xtemp : Real;
Begin
 { Choose whether to start with large cells and go down or start with small
 cells and increase }
 Case inv Of
 Fwd: Begin
 celdis := n div 2; { Distance between cells }
 celnum := 1; { One cell in first pass }
 parnum := n div 4; { n/4 pairs per cell in 1st pass }
 End; { Fwd case }
 Inverse: Begin
 celdis := 2; { Cells are adjacent }
 celnum := n div 4; { n/4 cells in first pass }
 parnum := 1;
 End; { Inverse case }
 End; { Case }
 Repeat { Until cells large if Fwd or small if Inverse }
 i := 2;
 For j:= 1 to celnum do
 Begin
 For k := 1 to parnum do { Do all pairs in each cell }
 Begin
 Xtemp := x[i];
 ipcm1 := i+celdis-1; { Index of other pts }
 x[i] := x[ipcm1];
 x[ipcm1] := xtemp;
 i := i+2;
 End; { For k }
 { End of cell, advance to next one }
 i := i+celdis;
 End; { For j }
 { Change values for next pass }
 Case inv Of
 Fwd: Begin
 celdis := celdis div 2; { Decrease cell distance }
 celnum := celnum * 2; { More cells }
 parnum := parnum div 2; { Less pairs per cell }
 End; { Case Fwd }
 Inverse: Begin
 celdis := celdis * 2; { More distance between cells }
 celnum := celnum div 2; { Less cells }
 parnum := parnum * 2; { More pairs per cell }
 End; { Case Inverse }
 End; { Case }
 Until (((inv = Fwd) And (Celdis < 2)) Or ((inv=Inverse) And (celnum = 0))); End; { Shuffl } {*****************************************************************************} Procedure FFT(inv : Xform); { Fast Fourier transform procedure operating on data in 1st half real, 2nd half imaginary order and produces a complex result } Var n1,n2,nu,celnum,celdis,parnum,ipn2,kpn2,jpn2, i,j,k,l,i2,imax,index : Integer; arg,cosy,siny,r2cosy,r2siny,i2cosy,i2siny,picons, y,deltay,k1,k2,tr,ti,xtemp : Real; Begin { Calculate nu = log2(n) } nu := 0; n1 := n div 2; n2 := n1; While n1>= 2 Do
 Begin
 nu := nu + 1; { Increment power-of-2 counter }
 n1 := n1 div 2; { divide by 2 until zero }
 End;
 { Shuffel the data into bit-inverted order }
 For i := 1 to n2 Do
 Begin
 k := ibitr(i-1,nu)+1; { Calc bit-inverted position in array }
 If i>k Then { Prevent swapping twice }
 Begin
 ipn2 := i+n2;
 kpn2 := k+n2;
 tr := x[k]; { Temp storage of real }
 ti := x[kpn2]; { Temp imag }
 x[k] := x[i];
 x[kpn2] := x[ipn2];
 x[i] := tr;
 x[ipn2] := ti;
 End; { If }
 End; { For }
 { Do first pass specially, since it has no multiplications }
 i := 1;
 While i <= n2 Do Begin k := i+1; kpn2 := k+n2; ipn2 := i+n2; k1 := x[i]+x[k]; { Save this sum } x[k] := x[i]-x[k]; { Diff to k's } x[i] := k1; { Sum to I's } k1 := x[ipn2]+x[kpn2]; { Sum of imag } x[kpn2] := x[ipn2]-x[kpn2]; x[ipn2] := k1; i := i+2; End; { While } { Set up deltay for 2nd pass, deltay=PI/2 } deltay := PI2; { PI/2 } celnum := n2 div 4; parnum := 2; { Number of pairs between cell } celdis := 2; { Distance between cells } { Each pass after 1st starts here } Repeat { Until number of cells becomes zero } { Writeln(Lst,'After Nth Pass:'); ### } { Debug; } { Each new cell starts here } index := 1; y := 0; { Exponent of w } { Do the number of pairs in each cell } For i2 := 1 To parnum Do Begin If y  0 Then
 Begin { Use sines and cosines if y is not zero }
 cosy := cos(y); { Calc sine and cosine }
 siny := sin(y);
 { Negate sine terms if transform is inverse }
 If inv = Inverse then siny := -siny;
 End; { If }
 { These are the fundamental equations of the FFT }
 For l := 0 to celnum-1 Do
 Begin
 i := (celdis*2)*l + index;
 j := i+celdis;
 ipn2 := i + n2;
 jpn2 := j + n2;
 If y = 0 Then { Special case for y=0 -- No sine or cosine terms }
 Begin
 k1 := x[i]+x[j];
 k2 := x[ipn2]+x[jpn2];
 x[j] := x[i]-x[j];
 x[jpn2] := x[ipn2]-x[jpn2];
 End { If-Then }
 Else
 Begin
 r2cosy := x[j]*cosy; { Calc intermediate constants }
 r2siny := x[j]*siny;
 i2cosy := x[jpn2]*cosy;
 i2siny := x[jpn2]*siny;
 { Butterfly }
 k1 := x[i] + r2cosy + i2siny;
 k2 := x[ipn2] - r2siny + i2cosy;
 x[j] := x[i] - r2cosy - i2siny;
 x[jpn2] := x[ipn2] + r2siny - i2cosy;
 End; { Else }
 { Replace the i terms }
 x[i] := k1;
 x[ipn2] := k2;
 { Advance angle for next pair }
 End; { For l }
 Y := y + deltay;
 index := index + 1;
 End; { For i2 }
 { Pass done - change cell distance and number of cells }
 celnum := celnum div 2;
 parnum := parnum * 2;
 celdis := celdis * 2;
 deltay := deltay/2;
 Until celnum = 0;
End; { FFT }
{*****************************************************************************}
Begin { * Main program * }
 For i := 0 To Asize-1 Do
 Begin
 x[i] := 0.0;
 End;
{ Write('Enter number of points: ');
 Readln(n);}
 n := 32;
 If (n> Asize) Then
 Begin
 Writeln('Too large, will use maximum');
 n := Round(asize/2.0);
 End;
 For i := 2 to n Do x[i] := Exp((1-i)*0.25); { Create Real array }
 x[1] := 0.5;
 Writeln('Input Array:');
 Debug;
 Shuffl(Fwd);
 FFT(Fwd);
 Post(Fwd);
 For i:= 1 to n Do x[i] := x[i]*8/n;
 Writeln('Forward FFT with real array first:');
 Debug;
End.


AltStyle によって変換されたページ (->オリジナル) /