B4J=true Group=Default Group ModulesStructureVersion=1 Type=Class Version=5.45 @EndOfDesignText@ 'FFT Class module Fast Fourier Transform ' 'Version 1.2 2020.02.27 'renamed it to xFFT and made a B4X Library ' 'Version 1.1 'added precalculated Sin and Cos functions ' 'Version 1.0 ' Sub Class_Globals Private N, N2, N_2, N_21, NU As Int Private xReal(), xImag(), tReal, tImag, fReal(), fImag(), fAmpl(), fPhase(), mSin(), mCos() As Double Private mModeDegrees = True As Boolean Private mWindow = "NONE" As String End Sub 'Initializes the object. You can add parameters to this method if needed. Public Sub Initialize End Sub 'Calculates the forward FFT (Fast Fourier Transformation) 'Real() = the real part of the time signal, the imaginary part is supposed to be 0 managed internally 'The length of Real must be a power of 2? 'Returns the amplitude of the frequencies 'Example code 'FFTMagnitude = FFT1.Forward(Real) ' Public Sub Forward(Real() As Double) As Double() Private i As Int Private ld As Double N = Real.Length ld = Logarithm(N, 2) If ld - Floor(ld) > 0 Then Log("N must be a power of 2") Return fReal End If NU = ld N2 = N / 2 N_2 = N2 N_21 = N2 + 1 Private xReal(N), xImag(N), fReal(N_21), fImag(N_21), fAmpl(N_21), fPhase(N_21), mSin(N_21), mCos(N_21) As Double 'precalculates the sin and cos values Private arg As Double For i = 0 To N2 arg = -2 * cPI * i / N mCos(i) = Cos(arg) mSin(i) = Sin(arg) Next ' xReal = Real Select mWindow Case "NONE" For i = 0 To N - 1 xReal(i) = Real(i) xImag(i) = 0 Next Case "Hann" Private w As Double w = 360 / N For i = 0 To N - 1 xReal(i) = Real(i) * (1 - CosD(w * i)) xImag(i) = 0 Next End Select 'First phase - calculation Private k, l, p, nu1 As Int Private c, s As Double nu1 = NU - 1 k = 0 For l = 1 To NU Do While k < N For i = 1 To N2 p = BitReverse(Bit.ShiftRight(k, nu1)) c = mCos(p) s = mSin(p) tReal = xReal(k + N2) * c + xImag(k + N2) * s tImag = xImag(k + N2) * c - xReal(k + N2) * s xReal(k + N2) = xReal(k) - tReal xImag(k + N2) = xImag(k) - tImag xReal(k) = xReal(k) + tReal xImag(k) = xImag(k) + tImag k = k + 1 Next k = k + N2 Loop k = 0 nu1 = nu1 - 1 N2 = N2 / 2 Next 'Second phase - recombination Private r As Int k = 0 Do While k < N r = BitReverse(k) If r > k Then tReal = xReal(k) tImag = xImag(k) xReal(k) = xReal(r) xImag(k) = xImag(r) xReal(r) = tReal xImag(r) = tImag End If k = k + 1 Loop If mModeDegrees = True Then For i = 0 To N_2 fReal(i) = xReal(i) / N_2 fImag(i) = xImag(i) / N_2 fAmpl(i) = Sqrt(fReal(i) * fReal(i) + fImag(i) * fImag(i)) fPhase(i) = ATan2D(xImag(i), xReal(i)) Next Else For i = 0 To N_2 fReal(i) = xReal(i) / N_2 fImag(i) = xImag(i) / N_2 fAmpl(i) = Sqrt(fReal(i) * fReal(i) + fImag(i) * fImag(i)) fPhase(i) = ATan2(xImag(i), xReal(i)) Next End If Return fAmpl End Sub 'Calculates the inverse FFT (Fast Fourier Transformation) 'Real() = the real part of the frequency 'Imag() = the imaginary part of the frequency 'The length of Real and Imag must be a power of 2 + 1 'Returns the real values of the time signal 'Example code 'TimeRealINV = FFT1.Inverse(Real, Imag) ' Public Sub Inverse(Real() As Double, Imag() As Double) As Double() Private i, j As Int Private ld As Double N = (Real.Length - 1) * 2 ld = Logarithm(N, 2) If ld - Floor(ld) > 0 Then Log("N must be a power of 2") Return fReal End If NU = ld N2 = N / 2 N_2 = N2 N_21 = N2 + 1 Private xReal(N), xImag(N), invReal(N), mSin(N_21), mCos(N_21) As Double xReal(0) = Real(0) xImag(0) = Imag(0) For i = 1 To N2 - 1 xReal(i) = Real(i) xImag(i) = Imag(i) j = n - i xReal(j) = Real(i) xImag(j) = -Imag(i) Next xReal(N2) = Real(N2) xImag(N2) = Imag(N2) Private ang As Double For i = 0 To N2 ang = 2 * cPI * i / N mCos(i) = Cos(ang) mSin(i) = Sin(ang) Next 'First phase - calculation Private k, l, p, nu1 As Int Private c, s As Double nu1 = NU - 1 k = 0 For l = 1 To NU Do While k < N For i = 1 To N2 p = BitReverse(Bit.ShiftRight(k, nu1)) c = mCos(p) s = mSin(p) tReal = xReal(k + N2) * c + xImag(k + N2) * s tImag = xImag(k + N2) * c - xReal(k + N2) * s xReal(k + N2) = xReal(k) - tReal xImag(k + N2) = xImag(k) - tImag xReal(k) = xReal(k) + tReal xImag(k) = xImag(k) + tImag k = k + 1 Next k = k + N2 Loop k = 0 nu1 = nu1 - 1 N2 = N2 / 2 Next 'Second phase - recombination Private r As Int k = 0 Do While k < N r = BitReverse(k) If r > k Then tReal = xReal(k) tImag = xImag(k) xReal(k) = xReal(r) xImag(k) = xImag(r) xReal(r) = tReal xImag(r) = tImag End If k = k + 1 Loop For i = 0 To N - 1 invReal(i) = xReal(i) / 2 Next Return invReal End Sub Private Sub BitReverse(j As Int) As Int Private j1, j2, k As Int j1 = j k = 0 For i = 1 To NU j2 = j1 / 2 k = 2 * k + j1 - 2 * j2 j1 = j2 Next Return k End Sub 'gets the FFT Real array Public Sub getReal As Double() Return fReal End Sub 'gets the FFT Imaginary array Public Sub getImag As Double() Return fImag End Sub 'gets the FFT Magnitude array Public Sub getMagnitude As Double() Return fAmpl End Sub 'gets the FFT Phase array in radian or degrees depending on ModeDegrees Public Sub getPhase As Double() Return fPhase End Sub 'gets or sets the Degree mode 'ModeDegrees = True reutuens the FFT Phase in degrees instead of radians Public Sub getModeDegrees As Boolean Return mModeDegrees End Sub Public Sub setModeDegrees(ModeDegrees As Boolean) mModeDegrees = ModeDegrees End Sub 'gets or sets the FFT window 'possible values "NONE", "Hann" Public Sub getWindow As String Return mWindow End Sub Public Sub setWindow(Window As String) If Window = "NONE" Or Window = "Hann" Then mWindow = Window Else Log("Wrong window") End If End Sub