B4A Class [B4x] FFT class

Discussion in 'Additional libraries, classes and official updates' started by klaus, Apr 25, 2017.

  1. klaus

    klaus Expert Licensed User

    This class performs Fast Fourier Transformations forward and inverse.
    The class is exactly the same for B4A, B4i and B4J.

    A FFT library already exists, but only for B4A.

    A Fast Fourier Transformation transforms a signal from its original domain (mostly the time domain) into its representation in the frequency domain.

    The number N of samples in the original domain must be a power of 2?
    Examples: 256, 1024, 2048, 4096 etc.

    In theory, the source signal must have a real and an imaginary part.
    In time signals the imaginary samples are all 0, this is treated internally in the class, no need to transmit them.
    The result of an FFT is two signals real and imaginary.
    Which can also be represented by magnitude and phase.

    In concrete applications, the magnitude of the frequency signal is mostly used, therefore the Forward method returns the Magnitude.
    The phase, real and imaginary signals can be accessed as properties.

    Methods:

    Forward(Real() As Double) As Double() performs a FFT calculation
    Real = an array of N Doubles representing the Real time signal.
    Returns the Magnitude of the frequency domain N/2 + 1 samples.

    Inverse(Real() As Double, Imag() As Double) As Double() performs an inverse FFT calculation
    Real = an array of N/2 + 1 Doubles representing the real part of the frequency signal.
    Imag = an array of N/2 + 1 Doubles representing the imaginary part of the frequency signal.
    Returns the inverse frequency real signal, N samples.

    Properties:

    Magnitude = magnitude of the frequency signal N/2 + 1 samples, read only.

    Phase = phase of the frequency signal N/2 + 1 samples, read only.

    Real = real part of the frequency signal N/2 + 1 samples, read only.

    Imag = imaginary part of the frequency signal N/2 + 1 samples, read only.

    ModeDegrees = True (default), the phase signal is in degrees otherwise in radians.

    Window = NONE or Hann, applies no window or a Hann window.


    Demo programs:

    Attached a demo project for each product B4A, B4i and B4J, they all include the FFT class which is the same for all three.

    The program can:

    Calculate different input signals.

    Calculate forward and inverse FFTs.

    Display the different signals.

    Apply a Window.

    upload_2017-4-25_11-46-19.png

    upload_2017-4-25_11-46-45.png


    For Android phones and iPhones tap on the chart to show the menu.

    On Android and iOS tablets and in the B4J project the menu is always visible.


    upload_2017-4-25_11-47-11.png


    Concrete B4A application: FFT_Record

    The program reads the microphone signal.


    upload_2017-4-25_11-49-24.png

    upload_2017-4-25_11-49-43.png


    upload_2017-4-25_11-50-12.png Start stop the reading

    upload_2017-4-25_11-50-27.png Switch between Time and FFT

    upload_2017-4-25_11-50-44.png Generate a sound composed of three frequencies: 500, 1000 and 2000

    upload_2017-4-25_11-51-5.png Change the scale up and down

    upload_2017-4-25_11-51-19.png Display the signal values when moving the finger over the diagram.
     

    Attached Files:

  2. freedom2000

    freedom2000 Well-Known Member Licensed User

    Hi @klaus

    Great job as usual !

    Compared to the library (which is only for B4A) is there any improvment (performance or something else) ?
    JP
     
  3. Erel

    Erel Administrator Staff Member Licensed User

    Great work Klaus!
     
  4. klaus

    klaus Expert Licensed User

    @freedom2000
    I haven't made speed comparisons between the two.
    The main goal was to have FFT for the three products.
    You could make libraries with the class, I don't know if there would be speed improvements.
     
    freedom2000 likes this.
  5. Beja

    Beja Expert Licensed User

    Thank you Klaus..
    Great work that will help a lot in some of my projects.
     
  6. FrankBerra

    FrankBerra Active Member Licensed User

    I am trying to understand how FFT_Record works and modifying it for saving (not displaying) FFT data to a file.

    I see that you are calling the sub Record with a timer every 300ms
    Code:
    Timer1.Initialize("Timer1"300)
    ...
    Private Sub Timer1_Tick
        Record
    End Sub
    But in the Record Sub you exit from the While loop only after 500ms
    Code:
    If DateTime.Now > StartTime + "500" Then Exit
    What does that mean?
    The FFT is calculate over 300ms or 500ms chunk?
     
  7. klaus

    klaus Expert Licensed User

    It is a TimeOut limit.
     
  8. FrankBerra

    FrankBerra Active Member Licensed User

    When i click on the "Go" button it sets StartTime so on the first execution of the Do While it exits after 500ms, but in the following Do While it exits immediately because StartTime is never set anymore.
    I feel confused, why Does that Timeout limit is needed?

    Thank you
     
  9. klaus

    klaus Expert Licensed User

    I tested it again and the timeout is only necessary for the first time.
    Without this line the program hangs in the While/Do loop.
    Don't ask me why, I found this as a workaround and it works.
     
    Last edited: Feb 3, 2019
  10. FrankBerra

    FrankBerra Active Member Licensed User

    Yes you are right, the loop must have a condition for exiting from the loop. But if you remove the loop the program still works correctly:

    Code:
    'Do While True
            sound = AR.ReadShort(0, BufferSize)
            DataSize = DataSize + sound.Length
                   
            
    'If DateTime.Now > StartTime + "500" Then Exit
     'Loop
    I think the loop it is only needed in the original code of Audiorecord example bacause it records for 10 seconds and it need to check during the loop execution if the program already recorded for 10 seconds or not.
    But in this case you call the sub Record every 300ms so you don't need any other loop for getting data from the audio source.
     
    klaus likes this.
  11. skrjabin

    skrjabin Active Member Licensed User

    Thank you, Klaus, for sharing this great library.
    Is it possible to calculate one main frequence of a pitch, from the array? It could be very usful for a music intrument tuner.
     
  12. klaus

    klaus Expert Licensed User

    What exactly do you mean?
    Detect frequency peaks?
    Is THIS what you are looking for, it's a B4A project?
    I haven't updated this project with this class.
     
  13. skrjabin

    skrjabin Active Member Licensed User

    I think the frequency peak is not enough to calculate the accurate basic frequence (in your sound file of the FFT-Record sample it is 500 Hz). I need an output that gives me only the basic pitch, but with even 1 Hz difference (499 Hz, 500 Hz, 501 Hz) accuracity. Do you think it is possible with FFT? Yes, it's a B4A project.
     
  14. klaus

    klaus Expert Licensed User

    Sorry, but I still don't understand what exactly you want to do.
    What exactly do you mean with only the basic pitch?
    If you want a frequeny increment (accuracy) of 1Hz, the duration of the time signal must be 1 second.
    Which means 44100 time samples.
    But the number of samples for FFT must be a power of 2.
    So at least 32768 samples which represents 0.743 second therefore a 1.346 frequency increment (accuracy).
     
  15. skrjabin

    skrjabin Active Member Licensed User

    What I want to do is a kind of guitar tuner. You play the pitch "a", this is 440 Hz. If you play 441 Hz the tuner will tell you, to tune the guitar a bit lower. Thats why I only need the fundamental frequency (in that case 440 Hz) and not the overtone (which would be in that case 880 Hz, ...). I could calculate the peak of the FFT array, but I think it is not good enough, to detect small differences between 440 Hz and 441 Hz. I now allready wrote an algorythm, which seems to work. I can public it, if someone is interested...
     
  16. klaus

    klaus Expert Licensed User

    I would be interest in.
     
  17. skrjabin

    skrjabin Active Member Licensed User

    Here is my small first tuner project. It analyzes the fundamental frequency of a soundwave in two steps:
    1. findig the first periode in the wave and creating an array with periode positions
    2. comparing the first periode with later periodes and calculating the accurate wavelenght
    I tested with piano, clarinet and singing. Piano and clarinet worked fine, singing sometimes, but this is more my voice than the algorythm.
    Anyhow I would be glad, if somebody has a better solution. As a musician I would have some ideas, how to make better tuners, more practical in orchester. But at first I need a good and stabil calculation of the fundamental frequency.
     

    Attached Files:

  18. moster67

    moster67 Expert Licensed User

    Nice piece of work!
    I tested it quickly with my guitar and it seems to work fine although I need some more time to check if tuning up or tuning down is suggested correctly but it seems to do that fine. I used to tune my guitar by ear once but I have lost that "ability" for now, probably because I have not been playing for years.
    Just for fun, I tried it also with electric piano (always tuned) and it detected tones correctly.
    Keep up the good work and if you decide to publish it on Google Play, please let us know!

    What regards the coding, this stuff is a bit over my head and I am sure there are other users who can suggest improvements if needed. In my opinion, it worked already very fast.
     
  19. FrankBerra

    FrankBerra Active Member Licensed User

    Attached Files:

    skrjabin, Erel and klaus like this.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice