/* $Log: FFT4.java,v $ * Revision 1.2 1999/08/31 03:58:46 stuart * check size argument * * Revision 1.1 1999/08/31 03:48:12 stuart * Initial revision * */ import java.io.*; /** Radix 4 Fast Fourier Transform. @author Stuart D. Gathman, adapted from a posting by Jo Desmet Jo Desmet wrote:

I have attached a uuencoded file containing plain C code to make a radix 4 FFT (it could also be a radix 8, i am not sure anymore because its a while ago that i have coded it). It is translated from machine code for the ADSP2101, and i have optimized it for the use in C. It is possible to build a C++ wrapper around it, but the main code must stay plain C (speed). I will not explain the functions, I will only say that there is also a Reverse FFT.

Remember: radix 4 is not the fastest!! If you are only interested in real numbers, there exist faster routines for it!! And I am sure that even my routine can be more optimized, there are some places in my code that i coppy an array: try to eliminate this.

I use this code tho prove that it is possible to use 1D algoritms on 2D Images to do image recognision.

happy programming,
Jo Desmet Jo's Web Page */ public class FFT4 { private final double[] ReplaceXData; private final double[] ReplaceYData; private final double[] Sin; private final int[] UnscrambledIndex; private final int N,N_DIV_4,LOG2Ndiv2; /** Create an FFT engine. @param n the data size this engine will handle - must be a power of 4 */ public FFT4(int n) { int i,j; for (i = 4; i != n; i <<= 2) if (i == 0) throw new IllegalArgumentException("N="+n); N=n; N_DIV_4=N/4; LOG2Ndiv2=((int)(Math.log(N)/Math.log(2))+1)>>1; //Juist afronden en snel System.err.println("LOG2Ndiv2="+ LOG2Ndiv2); ReplaceXData=new double[N]; ReplaceYData=new double[N]; Sin=new double[N+N/4]; UnscrambledIndex=new int[N]; for (i=0;i>((LOG2Ndiv2-1-j)<<1))&0x3)<<(j<<1); } } public void FFT(double[] Input,double[] OutputRe,double[] OutputIm) { int i; System.arraycopy(Input,0,ReplaceXData,0,N); for (i=0;i 0;Stage--) { int XA=0; int XB=XA+BFlys; int XC=XB+BFlys; int XD=XC+BFlys; int YA=0; int YB=YA+BFlys; int YC=YB+BFlys; int YD=YC+BFlys; for (int Group=Groups;Group > 0;Group--) { int Cb, Cc, Cd; int Sb, Sc, Sd; Cb=Cc=Cd=N_DIV_4; Sb=Sc=Sd=0; for (int BFly=BFlys;BFly > 0;BFly--) { double xa=ReplaceXData[XA]; double xb=ReplaceXData[XB]; double xc=ReplaceXData[XC]; double xd=ReplaceXData[XD]; double ya=ReplaceYData[YA]; double yb=ReplaceYData[YB]; double yc=ReplaceYData[YC]; double yd=ReplaceYData[YD]; ReplaceXData[XA++]=xa+xb+xc+xd; ReplaceYData[YA++]=ya+yb+yc+yd; ReplaceXData[XB++]=(xa+yb-xc-yd)*Sin[Cb]+(ya-xb-yc+xd)*Sin[Sb]; ReplaceYData[YB++]=(ya-xb-yc+xd)*Sin[Cb]-(xa+yb-xc-yd)*Sin[Sb]; ReplaceXData[XC++]=(xa-xb+xc-xd)*Sin[Cc]+(ya-yb+yc-yd)*Sin[Sc]; ReplaceYData[YC++]=(ya-yb+yc-yd)*Sin[Cc]-(xa-xb+xc-xd)*Sin[Sc]; ReplaceXData[XD++]=(xa-yb-xc+yd)*Sin[Cd]+(ya+xb-yc-xd)*Sin[Sd]; ReplaceYData[YD++]=(ya+xb-yc-xd)*Sin[Cd]-(xa-yb-xc+yd)*Sin[Sd]; Cb+=Groups; Cc+=GroupsBy2; Cd+=GroupsBy3; Sb+=Groups; Sc+=GroupsBy2; Sd+=GroupsBy3; } /* ButterFly */ XA+=BFlysBy3; XB+=BFlysBy3; XC+=BFlysBy3; XD+=BFlysBy3; YA+=BFlysBy3; YB+=BFlysBy3; YC+=BFlysBy3; YD+=BFlysBy3; } /* Group */ Groups<<=2; GroupsBy2<<=2; GroupsBy3<<=2; BFlys>>=2; BFlysBy3>>=2; } /* Stage */ } public static void main(String[] argv) throws IOException { StreamTokenizer data = new StreamTokenizer(new FileReader(argv[0])); data.resetSyntax(); data.parseNumbers(); data.whitespaceChars(0,' '); data.whitespaceChars(',',','); double[] v = new double[256]; double[] ore = new double[256]; double[] oim = new double[256]; int vi = 0; for (;;) { int tok = data.nextToken(); if (tok == data.TT_EOF) break; if (tok == data.TT_NUMBER) v[vi++] = data.nval; } FFT4 fft = new FFT4(vi); fft.FFT(v,ore,oim); for (int i = 0; i < vi; ++i) System.out.println("(" + ore[i] + ',' + oim[i] + ')'); fft.IFFT(ore,oim,v); for (int i = 0; i < vi; ++i) System.out.println(v[i]); } }