I wrote this FFT that you can put in a module file and use anywhere in your program.
You just call SetupFFT before using it, to set the size of the FFT (must be a power-of-2), and then you perform an FFT or IFFT on your data by calling the FFT sub. You also need to call SetupFFT again, any time you want to change the size of your FFT. I moved as much stuff out of the FFT sub to the SetupFFT sub, so that this setup stuff doesn't get run with every single you run the FFT sub (which would slow it down). To do an FFT, call it with the Sign parameter set to -1. To do an IFFT, call the FFT sub with the Sign parameter set to 1. The FFT parameters Data1 and Data2 are arrays of type Complex (a user-defined type). Data1 is the input, and Data2 is the output. Data1 is time domain, and Data2 is frequency domain, when performing an FFT. Data1 is frequency domain, and Data2 is time domain, when performing an IFFT.
Code:
Public Const Pi As Double = 3.14159265358979
Public Type Complex
Re As Double
Im As Double
End Type
Dim FFTSize As Long
Dim FFTSize_Log2 As Long
Dim BOR_LUT() As Long
Dim Pow2_LUT() As Long
Public Sub SetupFFT(ByVal Size As Long)
Dim n As Long
Dim n1 As Long
Dim n2 As Long
Dim i As Long
FFTSize = Size
FFTSize_Log2 = Log(FFTSize) / Log(2)
ReDim BOR_LUT(FFTSize - 1)
For n = 0 To FFTSize - 1
n1 = n
n2 = 0
For i = 0 To FFTSize_Log2 - 1
n2 = (n2 * 2) Or (n1 And 1)
n1 = n1 \ 2
Next i
BOR_LUT(n) = n2
Next n
ReDim Pow2_LUT(FFTSize_Log2 - 1)
For n = 0 To FFTSize_Log2 - 1
Pow2_LUT(n) = 2 ^ n
Next n
End Sub
Public Sub FFT(ByRef Data1() As Complex, ByRef Data2() As Complex, ByVal Sign As Long)
Dim Layer As Long
Dim BlockCount As Long
Dim BlockSize As Long
Dim HalfBlockSize As Long
Dim BlockNumber As Long
Dim ButterflyNumber As Long
Dim n0 As Long
Dim n1 As Long
Dim n2 As Long
Dim DataTemp() As Complex
Dim Twiddles() As Complex
Dim n As Long
ReDim Twiddles(FFTSize - 1)
For n = 0 To FFTSize - 1
Twiddles(n) = GetTwiddle(n, Sign)
Next n
DataTemp() = Data1()
For Layer = 0 To FFTSize_Log2 - 1
BlockCount = Pow2_LUT(Layer)
BlockSize = FFTSize \ BlockCount
HalfBlockSize = BlockSize \ 2
For BlockNumber = 0 To BlockCount - 1
n0 = BlockNumber * BlockSize
For ButterflyNumber = 0 To HalfBlockSize - 1
n1 = n0 + ButterflyNumber
n2 = n1 + HalfBlockSize
'do butterfly calculation
Data2(n1) = ComplexAdd(DataTemp(n1), DataTemp(n2))
Data2(n2) = ComplexMult(ComplexSub(DataTemp(n1), DataTemp(n2)), Twiddles(ButterflyNumber * BlockCount))
Next ButterflyNumber
Next BlockNumber
DataTemp() = Data2()
Next Layer
For n = 0 To FFTSize - 1
Data2(n) = DataTemp(BOR_LUT(n))
Next n
End Sub
Private Function ComplexAdd(ByRef Value1 As Complex, ByRef Value2 As Complex) As Complex
ComplexAdd.Re = Value1.Re + Value2.Re
ComplexAdd.Im = Value1.Im + Value2.Im
End Function
Private Function ComplexSub(ByRef Value1 As Complex, ByRef Value2 As Complex) As Complex
ComplexSub.Re = Value1.Re - Value2.Re
ComplexSub.Im = Value1.Im - Value2.Im
End Function
Private Function ComplexMult(ByRef Value1 As Complex, ByRef Value2 As Complex) As Complex
ComplexMult.Re = Value1.Re * Value2.Re - Value1.Im * Value2.Im
ComplexMult.Im = Value1.Re * Value2.Im + Value1.Im * Value2.Re
End Function
Private Function GetTwiddle(ByVal k As Long, ByVal Sign As Long) As Complex
With GetTwiddle
.Re = Cos(2 * Pi * k / FFTSize)
.Im = Sin(2 * Pi * k / FFTSize) * Sign
End With
End Function
You just call SetupFFT before using it, to set the size of the FFT (must be a power-of-2), and then you perform an FFT or IFFT on your data by calling the FFT sub. You also need to call SetupFFT again, any time you want to change the size of your FFT. I moved as much stuff out of the FFT sub to the SetupFFT sub, so that this setup stuff doesn't get run with every single you run the FFT sub (which would slow it down). To do an FFT, call it with the Sign parameter set to -1. To do an IFFT, call the FFT sub with the Sign parameter set to 1. The FFT parameters Data1 and Data2 are arrays of type Complex (a user-defined type). Data1 is the input, and Data2 is the output. Data1 is time domain, and Data2 is frequency domain, when performing an FFT. Data1 is frequency domain, and Data2 is time domain, when performing an IFFT.