Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
FFT and IFFT
#1
Hi. I wish everyone all the best in the new year and lots of success not only in programming but also in personal life.

Today I dealt with the fast Fourier transform and signal decomposition. Since this is a topic highly beyond my knowledge, I used all the options available to me and finally created this. The question is: Can anyone speed it up? It would be necessary to set the Blok, RealPart and ImagPart field sizes to at least 1023 and N to 1024, so that the frequency detection would be smoother. Unfortunately, in this implementation with my computer, I had to set the fields as they are to get at least some good results.
On line 2, set your own MP3 audio file. After starting (it is assumed that the MP3 is stereo), only the left track is read. It is run through the FFT, which decomposes it into real and imaginary components, then in the condition on line 34, an adjustment is made so that everything with a frequency higher than 400 Hz is discarded and finally the sound is reconstructed back with this adjustment through the IFFP. However, the sound is significantly distorted precisely because of the low accuracy - due to the low size of the fields. I was wondering if someone might have a better solution, or if they would see a problem that I am overlooking.

Code: (Select All)

Zdroj = _SndOpen("s.mp3") 'USE MP3 here (MEM read singles from _Memsound block)
Dim Zvuk As _MEM
Dim A As Long
Dim Blok(31) As Single '                            Block for FFT samples. Here is 32 values (0 to 31), is very small so detection is not too accuracy
Dim RealPart(31) As Single, ImagPart(31) As Single ' Real and imaginary signal values for FFT
Dim Shared N As Long
Dim VzorkovaciFrekvence As Single '                  SoundRate
N = 32 '                                            FFT Block size

Zvuk = _MemSound(Zdroj, 0)
VzorkovaciFrekvence = _SndRate

Do Until A& = Zvuk.SIZE
    ' Načtení bloku vzorků
    For i = 0 To N - 1
        If A& >= Zvuk.SIZE Then Exit For
        LevaStopa = _MemGet(Zvuk, Zvuk.OFFSET + A&, Single)
        Blok(i) = LevaStopa '                      This demo save left track only. Blok must contins sound data to work
        RealPart(i) = LevaStopa '                  RealPart must contains sound data
        ImagPart(i) = 0
        A& = A& + 8 '                              go to next sample (8 bytes = 2 * 4 (left, right))
    Next i

    ' Apply FFT to block
    Call FFT(RealPart(), ImagPart(), N)



    'spectrum filtration - in this case output signal contains just frequency 350 Hz and slower
    For k = 0 To N - 1
        Frekvence = k * VzorkovaciFrekvence / N 'Frequency calculation (k * _SndRate / N)

        If Frekvence > 400 Then 'how killing signal:
            RealPart(k) = 0
            ImagPart(k) = 0
        End If
    Next k

    'create new audio signal using IFFT  (from this block)
    Call IFFT(RealPart(), ImagPart(), N)


    'Play created signal
    For i = 0 To N - 1
        _SndRaw RealPart(i), 0
    Next i

    'wait until is possible playing next block
    Do Until _SndRawLen < .1
    Loop
Loop
_MemFree Zvuk


Sub FFT (RealPart() As Single, ImagPart() As Single, N As Long)
    Dim i As Long, j As Long, k As Long, m As Long, stp As Long
    Dim angle As Double
    Dim tReal As Double, tImag As Double, uReal As Double, uImag As Double

    ' Bit-reverse permutation (That sounds really good, doesn't it?)            Don't ask me what that means, okay?  Smile))
    j = 0
    For i = 0 To N - 1
        If i < j Then
            Swap RealPart(i), RealPart(j)
            Swap ImagPart(i), ImagPart(j)
        End If
        k = N \ 2
        Do While (k >= 1 And j >= k)
            j = j - k
            k = k \ 2
        Loop
        j = j + k
    Next i

    ' FFT: my loop over the size of the level (N)
    m = 1
    Do While m < N
        stp = m * 2
        angle = -3.14159265359 / m
        For k = 0 To m - 1
            uReal = Cos(k * angle)
            uImag = Sin(k * angle)
            For i = k To N - 1 Step stp
                j = i + m
                tReal = uReal * RealPart(j) - uImag * ImagPart(j)
                tImag = uReal * ImagPart(j) + uImag * RealPart(j)
                RealPart(j) = RealPart(i) - tReal
                ImagPart(j) = ImagPart(i) - tImag
                RealPart(i) = RealPart(i) + tReal
                ImagPart(i) = ImagPart(i) + tImag
            Next i
        Next k
        m = stp
    Loop
End Sub

' Inverse FFT (IFFT) for signal reconstruction
Sub IFFT (RealPart() As Single, ImagPart() As Single, N As Long)
    Dim i As Long, j As Long, k As Long, m As Long, stp As Long
    Dim angle As Double
    Dim tReal As Double, tImag As Double, uReal As Double, uImag As Double

    'The inverse FFT is the same as the FFT, but with the opposite sign in the exponent
    m = 1
    Do While m < N
        stp = m * 2
        angle = 3.14159265359 / m ' opposite sign
        For k = 0 To m - 1
            uReal = Cos(k * angle)
            uImag = Sin(k * angle)
            For i = k To N - 1 Step stp
                j = i + m
                tReal = uReal * RealPart(j) - uImag * ImagPart(j)
                tImag = uReal * ImagPart(j) + uImag * RealPart(j)
                RealPart(j) = RealPart(i) - tReal
                ImagPart(j) = ImagPart(i) - tImag
                RealPart(i) = RealPart(i) + tReal
                ImagPart(i) = ImagPart(i) + tImag
            Next i
        Next k
        m = stp
    Loop

    ' Normalization  for inverse FFT
    For i = 0 To N - 1
        RealPart(i) = RealPart(i) / N
        ImagPart(i) = ImagPart(i) / N
    Next i
End Sub


Reply
#2
There is a bad implementation of the IFFT code in the previous code. Guys, I didn't give up. The sound equalization function has been fulfilled at this point. Here with only one frequency, but in a perfect way.    Functional FFT and IFFT opens up gigantic additional possibilities with audio.

This works as expected!
Place your MP3 stereo file in first row.

Code: (Select All)

Zdroj = _SndOpen("s.mp3") 'USE MP3 here (MEM read singles from _Memsound block)
Dim Zvuk As _MEM
Dim A As Long
UU = 8191 '                                        We detecting frequency from 8192 samples (0 to 8191)
Dim Blok(UU) As Single '                            Block for FFT samples - Left channel
Dim BlokR(UU) As Single '                                                  Right
Dim RealPart(UU) As Single, ImagPart(UU) As Single ' Real and imaginary signal values for FFT - Left
Dim RealPartR(UU) As Single, ImagPartR(UU) As Single '                                        - Right
Dim Shared N As Long
Dim VzorkovaciFrekvence As Single '                  SoundRate
N = UU + 1 '                                        FFT Block size

Zvuk = _MemSound(Zdroj, 0)
VzorkovaciFrekvence = _SndRate

Do Until A& = Zvuk.SIZE
    ' Načtení bloku vzorků
    For i = 0 To N - 1
        If A& >= Zvuk.SIZE Then Exit For
        LevaStopa = _MemGet(Zvuk, Zvuk.OFFSET + A&, Single)
        PravaStopa = _MemGet(Zvuk, Zvuk.OFFSET + A& + 4, Single)
        Blok(i) = LevaStopa '                      This demo save both tracks. Blok must contains sound data to work
        BlokR(i) = PravaStopa
        RealPart(i) = LevaStopa '                  RealPart must contains sound data
        RealPartR(i) = PravaStopa
        ImagPart(i) = 0
        ImagPartR(i) = 0
        A& = A& + 8 '                              go to next sample (8 bytes = 2 * 4 (left, right))
    Next i

    ' Apply FFT to block

    Call FFT(RealPart(), ImagPart(), N)
    Call FFT(RealPartR(), ImagPartR(), N)


    'spectrum filtration - in this case output signal contains just frequency 350 Hz and slower

    For k = 0 To N - 1
        Frekvence = k * VzorkovaciFrekvence / N 'Frequency calculation (k * _SndRate / N)

        If Frekvence > 350 Then 'how killing signal:
            RealPart(k) = 0
            ImagPart(k) = 0

            RealPartR(k) = 0
            ImagPartR(k) = 0

        End If
    Next k

    'create new audio signal using IFFT  (from this block)
    Call IFFT(RealPart(), ImagPart(), N)
    Call IFFT(RealPartR(), ImagPartR(), N)

    'Play created signal
    For i = 0 To N - 1
        _SndRaw RealPart(i), RealPartR(i)
    Next i

    'wait until is possible playing next block
Loop

Do Until _SndRawLen < .1
Loop

_MemFree Zvuk


Sub FFT (RealPart() As Single, ImagPart() As Single, N As Long)
    Dim i As Long, j As Long, k As Long, m As Long, stp As Long
    Dim angle As Double
    Dim tReal As Double, tImag As Double, uReal As Double, uImag As Double

    ' Bit-reverse permutation (That sounds really good, doesn't it?)            Don't ask me what that means, okay?  ))
    j = 0
    For i = 0 To N - 1
        If i < j Then
            Swap RealPart(i), RealPart(j)
            Swap ImagPart(i), ImagPart(j)
        End If
        k = N \ 2
        Do While (k >= 1 And j >= k)
            j = j - k
            k = k \ 2
        Loop
        j = j + k
    Next i

    ' FFT: my loop over the size of the level (N)
    m = 1
    Do While m < N
        stp = m * 2
        angle = -3.14159265359 / m
        For k = 0 To m - 1
            uReal = Cos(k * angle)
            uImag = Sin(k * angle)
            For i = k To N - 1 Step stp
                j = i + m
                tReal = uReal * RealPart(j) - uImag * ImagPart(j)
                tImag = uReal * ImagPart(j) + uImag * RealPart(j)
                RealPart(j) = RealPart(i) - tReal
                ImagPart(j) = ImagPart(i) - tImag
                RealPart(i) = RealPart(i) + tReal
                ImagPart(i) = ImagPart(i) + tImag
            Next i
        Next k
        m = stp
    Loop
End Sub






Sub IFFT (RealPart() As Single, ImagPart() As Single, N As Long)
    Dim i As Long

    ' Otočení znamének imaginárních složek
    For i = 0 To N - 1
        ImagPart(i) = -ImagPart(i)
    Next i

    ' Provedení FFT
    Call FFT(RealPart(), ImagPart(), N)

    ' Normalizace a znovu otočení znamének imaginárních složek
    For i = 0 To N - 1
        RealPart(i) = RealPart(i) / N
        ImagPart(i) = -ImagPart(i) / N
    Next i
End Sub


Reply




Users browsing this thread: MasterGy, 2 Guest(s)