∑ e

advertisement
EE 356
Notes on the Fast Fourier Transform
The discrete Fourier transform (DFT) and its inverse are given by:
N −1
F ( k ) = ∑ f ( n) ⋅ e
−j
2πkn
N
Discrete Fourier Transform
n =0
f ( n) =
2πkn
1 N −1
j
F (k ) e N
∑
N k =0
Inverse Discrete Fourier Transform
The variable n is the discrete counter in the time domain and the variable k is the discrete counter
in the frequency domain. In both cases there are N samples.
From the equations we see that to compute the DFT we need to do N complex multiplies for each
value of k and there are N such values. The DFT requires N2 complex multiplications. A
reasonable sized sound file could easily have 100,000 samples requiring 1010 complex
multiplications.
The fast Fourier transform is an algorithm for the efficient evaluation of the DFT. The number
of complex multiplications required for N samples using the FFT is proportional to N rather than
N2. The C# code below is an implementation of the FFT. It relies on the Complex number class
which follows.
The data file is in the d[] matrix which is complex. For sound files, all the values in the data file
will be real with zero imaginary parts. N is the number of samples and must be a power of 2.
N = 2p. The result is a complex number returned in the d[] matrix. You can plot the magnitude
and/or the phase angle of the complex result vs. frequency. The result will have N samples in
frequency space equally divided between 0 and fs/2 where fs is the sample frequency of the
sound file.
private void FFT(Complex[] d,int N,int p)
{int i, j = 1, k, L;
int ip;
int exp2L;
Complex u = new Complex(0, 0);
Complex W = new Complex(0, 0);
Complex t = new Complex(0, 0);
for(i=1;i<N;i++)
{if(i < j)
Swap(ref d[i-1], ref d[j-1]);
k = N/2;
while(k < j)
{j = j - k;
k = k/2;
}
j = j + k;
}
for(L=1;L<=p;L++)
{exp2L = (int)Math.Pow(2, L)/2;
u.Real = 1;u.Imag = 0;
W.Real = Math.Cos(Math.PI/exp2L);
W.Imag = -Math.Sin(Math.PI/exp2L);
for(j=1;j<=exp2L;j++)
{for(i=j;i<=N;i=i+2*exp2L)
{ip = i + exp2L;
t = d[ip-1]*u;
d[ip-1] = d[i-1] - t;
d[i-1] = d[i-1] + t;
}
u = u*W;
}
}
}
private void Swap(ref Complex x, ref Complex y)
{Complex tmp = new Complex(x.Real, x.Imag);
x.Real = y.Real;x.Imag = y.Imag;
y.Real = tmp.Real;y.Imag = tmp.Imag;
}
class Complex
{public Complex()
{real = 0;
imag = 0;
}
public Complex(double x, double y)
{real = x;
imag = y;
}
private double real;
private double imag;
//
public double Real
{get {return real;}
set {real = value;}
}
public double Imag
{get {return imag;}
set {imag = value;}
}
public double Magnitude()
{double tmp;
tmp = Math.Sqrt(Real*Real + Imag*Imag);
return tmp;
}
public static Complex
{Complex cTmp = new
cTmp.real = x.real
cTmp.imag = x.imag
return cTmp;
}
public static Complex
{Complex cTmp = new
cTmp.real = x.real
cTmp.imag = x.imag
return cTmp;
}
operator+(Complex x, Complex y)
Complex();
+ y.real;
+ y.imag;
operator-(Complex x, Complex y)
Complex();
- y.real;
- y.imag;
}
public static Complex operator*(Complex x, Complex y)
{Complex cTmp = new Complex();
cTmp.real = x.Real*y.Real - x.Imag*y.Imag;
cTmp.imag = x.Real*y.Imag + x.Imag*y.Real;
return cTmp;
}
Download