B4A Class [B4x] xFFT Class and b4xlib

klaus

Expert
Licensed User
This class performs Fast Fourier Transformations forward and inverse.

The class has been updated to a B4XLibrary.
The name hase changed from FFT to xFFT, you need to change it in the declaration if you update from the previous code module to the b4xlib.
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.

Attached files:
xFFTDemo.zip contains three demo programs, one for each platform, these programs use the xFFT.b4xlib
xFFT.b4xlib the B4X Library file
xFFT.bas the Class file
FFT_Record.zip a concrete B4A project explained below.
xFFT.xml the xml help file, it is only needed for the B4X Help Viewer if you use it.
Don't copy this file to the AdditionalLibraries\B4X folder.
Copy it in the AdditionalLibraries\B4XlibXMLFiles folder, again, only if you use the B4X Help Viewer.


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 use the xFFT.b4xlib.

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.
 

Attachments

Last edited:

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
 

klaus

Expert
Licensed User
@freedom2000
... is there any improvment (performance or something else) ?
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.
 

Beja

Expert
Licensed User
Thank you Klaus..
Great work that will help a lot in some of my projects.
 

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
B4X:
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
B4X:
If DateTime.Now > StartTime + "500" Then Exit
What does that mean?
The FFT is calculate over 300ms or 500ms chunk?
 

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
 

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:

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:

B4X:
'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.
 

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.
 

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.
 

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).
 

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...
 

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.
 

Attachments

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.
 

FrankBerra

Active Member
Licensed User

Attachments

klaus

Expert
Licensed User
The FFT Class has been updated to xFFT Class and b4xlib version 1.2.
Be aware of the name change from FFT to xFFT.
Nothing has changed in the calculations.
 
Top