Go Down

Topic: FHT/FFT how to use (Read 841 times) previous topic - next topic


Hi, I'm working on an Arduino audio spectrum analyzer. I've already solved everything from audio input to outputing signals to ws2812 LEDs but my problem in processing the audio with the FHT library. I don't understand how many samples I need to input into the algorithm or how to do it at all, nor do I understand what frequencies it outputs and what range the values are.

All I need is around 10 different frequency ranges for the LEDs or just 3 (bass middle treble).

My Questions:
Do I need to just make like 256 samples at the same intervals as fast as possible for the input into the algorithm?
How many frequency ranges do I get?
What is the range of the values that come out?

I can't build the entire board because of cost/time restraints, so I can't just upload und Play around till I understand the library. That's why I'm asking.


Full range audio needs sampling at something like 44.1 or 48kSPS, due to the Nyquist limit,
so that frequency components upto 20kHz can be determined.

Its essential the sampling is at regular intervals or the spectrum will come out badly distorted.

Its important that you identify which exact library you are talking about, so please include a
link for it - these days there are many many libraries out there, many have multiple versions too.
Have you looked at the libraries source code? There are often function-by-function comments in
there explaining everything.

Also which Arduino board are we talking about?
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]


Jun 12, 2018, 03:28 pm Last Edit: Jun 12, 2018, 03:29 pm by Yo90bosses
Im using this library:

And I'm using an Arduino Nano.


Try the examples that come with the library.


I wrote an audio library and a tutorial for it which explains many of the finer points of actually using FFT output.  The library runs on Teensy, so probably won't help you directly if you have a differeny boards, but maybe some of the tutorial material will help at least explain the concepts.  The good news is we made a video, so if you've got about 10 minutes you can just watch the FFT part.


If you prefer reading, the tutorial PDF file can be found here:


Now, let's see if I can answer some of your specific questions...

My Questions:
Do I need to just make like 256 samples at the same intervals as fast as possible for the input into the algorithm?
If your FFT is a 256 point one, then yes you need to collect up 256 samples.  What matters most is that you collected the samples at a consistent known speed, rather than merely as fast as possible.  You need how quickly you measured the samples, because that info is how to interpret the FFT output.

If the FFT code you're using takes complex numbers, you'd put your samples into the real part of each input number and put a zero in the imaginary part.  Some FFT code is designed to only take the real samples, and internally it converts then to complex numbers for the computation.

Before you give the 256 samples to the FFT algorithm, you would usually want to scale them by a "window", which is just a list of 256 numbers.  There are lots of these window scalings available (they all involve trade-offs), but the general idea is to reduce the amplitude of the numbers near the ends, to avoid a well known FFT problem called "spectral leakage".  I talked about this in the video with pictures of what really happens in the waveform, so best to just watch the tutorial if this seems like a strange concept.

With using window scaling your FFT becomes mostly sensitive to the 128 samples in the center of your group of 256 (or however many you use... in the tutorial a 1024 point FFT is used).  The usual way to work around this is to compute twice as many FFTs, where you hold half the samples for next time.  With a 50% overlap, you get FFT outputs twice as often.  While they technically have 50% overlap in time, due to the necessity of window scaling, each one mostly measures just in the center of its samples.

How many frequency ranges do I get?
Generally a FFT using only real number (zeros in the imaginary parts of the inputs) gives N/2+1 unique output "bins".  Often the +1 bin is disregarded.  So if you give a FFT 256 samples, you'd get 129 outputs, but if you only wish to do visualizations, you'd do fine to just use the first 128 and ignore that 129th.

Technically, the FFT algorithm gives N outputs for N inputs, but if you gave it only real samples (no imaginary numbers as inputs), the 2nd half is always a redundant duplicate of the first half.  Well, technically it's a mirror image, but redundant duplicate data that does you no good.

If you're using a FFT algorithm that's been written for low memory, it might take only the real numbers in and give you half that many outputs.  Or it might give you half the number of outputs as complex numbers, or 2 numbers per "bin".  If you're working with that sort of code, and if you only care about the amplitude and wish to discard the relative phase info the FFT gives, you'd combine each real & imaginary pair with sqrt(real*real + imag*imag).  It all depends on the specific FFT code you're using.  The FFT algorithm itself takes complex numbers in and gives complex numbers out, but many libraries intended for visualization automatically discard the phase info.  The one I wrote does that, and internally if does that magnitude calc using square root.

What is the range of the values that come out?
This question could be about the frequencies or the numerical range.

The frequency question is simple.  The output numbers are frequency "bins" linearly scaled from 0 Hz (DC) to half of whatever sample rate you used to collect the input data.  That's why it's so important to collect the input at a known consistent speed.

The output numerical range depends quite a lot on the specific code.  Ideally using high precision floating point, you'd expect numbers from 0 to 1.0.  But a FFT written for a small microcontroller may give you integers, which are meant to represent 0 to 1.0.  It really depends on the specific code you're using.

Go Up