FFT on Arduino, the audio spectrum is cluttered?

Hello guys!

I have been tackling this problem for a long time now and didn't want to be a burdon to anyone, hence I never really
posted any question about this in the forum earlier.

So basically, I downloaded both the FFT and FHT libraries from Open Music Lab's website.

I hooked my Arduino Uno to the computer, hooked an audio input (my computer's audio out) to the arduino,
and did a Sine wave sweep test.

I was expecting some results like the gentleman in the video below achieved, but I can't get the same results.

I have tried both the FFT and FHT library original examples (no modifications), both give me the same results on Arduino Uno, Mega 2560, Mini 05 and Sparkfun pro Micro 16MHz.

Can anybody help me with this?

Mr Chris Roberts demonstrates his results in his video:

My results look like this:

And I would like to have results looking like this:

Basically what I want is a clean spectrum.

EDIT: I have searched the web, searched the forum, tried to modify the code. Nothing changes anything. Still get the same results.

2 of 3 videos blocked....

robtillaart:
2 of 3 videos blocked....

Oops! Not anymore!

your FFT shows all harmonics I think!

FFT is beyond my mathematical & programming abilities...

I've never seen a perfect FFT spectrum. It's my understanding that it theoretically takes an infinite number of samples and in infinitely-long unchanging signal to get a perfect result. In the real world, a [u]window[/u] of a certain number of samples it taken (representing a small amount of time). There's a discontinuity where the window starts & stops, so there are various window shaping and window overlapping algorithms to compensate. These all have various compromises.

The bit depth and sample rate may also affect FFT accuracy (or sample rate may just be a different way of thinking about window size).

Haven't try Open Music software, but looking at video #2, I'm sure you have a problem in this part:

I hooked my Arduino Uno to the computer, hooked an audio input (my computer's audio out) to the arduino,
and did a Sine wave sweep test.

How exactly you connect audio input? Video shows great amount of DC and all harmonics above 2-nd, which is remarkable indicator that sampling heavy distorted. Show your connection diagram.

robtillaart:
your FFT shows all harmonics I think!

Yes I think so too!

DVDdoug:
FFT is beyond my mathematical & programming abilities...

I've never seen a perfect FFT spectrum. It's my understanding that it theoretically takes an infinite number of samples and in infinitely-long unchanging signal to get a perfect result. In the real world, a [u]window[/u] of a certain number of samples it taken (representing a small amount of time). There's a discontinuity where the window starts & stops, so there are various window shaping and window overlapping algorithms to compensate. These all have various compromises.

The bit depth and sample rate may also affect FFT accuracy (or sample rate may just be a different way of thinking about window size).

I see!
As long as I can differentiate frequencies from each other, that's all I need.

Magician:
Haven't try Open Music software, but looking at video #2, I'm sure you have a problem in this part:

I hooked my Arduino Uno to the computer, hooked an audio input (my computer's audio out) to the arduino,
and did a Sine wave sweep test.

How exactly you connect audio input? Video shows great amount of DC and all harmonics above 2-nd, which is remarkable indicator that sampling heavy distorted. Show your connection diagram.

Basically:
Arduino > USB
Computer Audio Out Ground > Arduino Ground
Computer Audio Out Left > Arduino Analog 0

In order to get a "perfect" FFT spectrum:

  1. you must use an anti-aliasing filter at the ADC input
  2. you have to use a "FFT window" function applied over your input data, there are at least of dozen of various ones (see wiki)
  3. you have to average many FFT spectra, the accuracy with S spectra is sqrt(S) with FFT
  4. you have to cut off the spectral lines from N/2..N (N - number of input samples)
  5. you have to use floating point math with FFT
    Happy ffting :slight_smile:

Keep in mind that with 10-bit sampling, the highest frequency that can be "minimally" sampled by the Arduino (according to the Nyquist Theorem) is about 4.8 kHz. If any frequencies higher than 4.8 kHz are present in the input to the FFT, the result will show strong aliasing, which show up as signals of frequency (4.8 - f kHz). So, as f increases above 4.8 kHz, the aliased peak in the spectrum moves down. This aliasing effect is very clearly shown in the first video that you posted. Much of the distortion or clipping in the signal shows up as aliasing.

DC signals, necessarily present initially because the ADC samples only from 0 to 5 V (or 3.3V), show up as strong peaks in the lowest bins, unless you subtract off the DC average before transforming.

Also, you don't say what representation of the spectrum you are displaying. If it is a log scale power spectrum, the large peaks in the spectrum are compressed downwards and there will always be a noise level visible.

pito:
In order to get a "perfect" FFT spectrum:

  1. you must use an anti-aliasing filter at the ADC input
  2. you have to use a "FFT window" function applied over your input data, there are at least of dozen of various ones (see wiki)
  3. you have to average many FFT spectra, the accuracy with S spectra is sqrt(S) with FFT
  4. you have to cut off the spectral lines from N/2..N (N - number of input samples)
  5. you have to use floating point math with FFT
    Happy ffting :slight_smile:

Haha, yeah "happy"...

jremington:
Keep in mind that with 10-bit sampling, the highest frequency that can be "minimally" sampled by the Arduino (according to the Nyquist Theorem) is about 4.5 kHz. If any frequencies higher than 4.5 kHz are present in the input to the FFT, the result will show strong aliasing, which show up as signals of frequency (f - 4.5 kHz). This aliasing effect is very clearly shown in the first video that you posted. Much of the distortion or clipping in the signal shows up as aliasing.

DC signals, necessarily present initially because the ADC samples only from 0 to 5 V (or 3.3V), show up as strong peaks in the lowest bins, unless you subtract off the DC average before transforming.

Also, you don't say what representation of the spectrum you are displaying. If it is a log scale power spectrum, the large peaks in the spectrum are compressed downwards and there will always be a noise level visible.

Hmmmmm...

But how come my aliasing is so strong?

I'm not so worried about noise, it can always be filtered out somehow.

So... do you guys have any suggestion on how fix this issue?

Other people get clear results except me =(

4.5 Khz is more than enough for my applicaton.

I know spoon-feeding with code isn't anything anybody wants to do,
but could anyone at least try the Open Music Lab libraries and see what results you get?

As I said before, I have tried to modify the code, but the results are pretty much the same,
so using the original examples should be fine, so that we can get a good reference.

Computer Audio Out Ground > Arduino Ground
Computer Audio Out Left > Arduino Analog 0

Don't. You are not only getting wrong results, but potentially could destroy your arduino. Here is right way to feed AC to analog input:
http://interface.khm.de/index.php/lab/experiments/arduino-realtime-audio-processing/

The number of bits in a sample does not determine the minimum or maximum sampling frequency. It determines the quantisation signal-to-noise ratio which for a sample of B bits is approximately 6*B dB.
The reason that, on a Uno or similar processor, the audio is limited to about 4.5kHz is because about the fastest you can sample the ADC is 9kHz.

Pete

@Pete: On the Atmega-based Arduino, the number of bits per sample does determine the upper sampling frequency. If you choose 8 bit sampling, then you can sample at about 40 kHz, with a 20 kHz upper frequency (Nyquist limit).

@OP: If you want to see what the FFT is capable of, you have to make certain of your input signal. A mathematically pure, single tone (unachievable in practice) will give a single sharp peak. You can approximate this by feeding the FFT input with a precalculated sine wave, pretending that it came from the ADC and see what happens. As it is, your actual audio signal probably is quite noisy and distorted.

jremington:
@Pete: On the Atmega-based Arduino, the number of bits per sample does determine the upper sampling frequency. If you choose 8 bit sampling, then you can sample at about 40 kHz, with a 20 kHz upper frequency (Nyquist limit).

@OP: If you want to see what the FFT is capable of, you have to make certain of your input signal. A mathematically pure, single tone (unachievable in practice) will give a single sharp peak. You can approximate this by feeding the FFT input with a precalculated sine wave, pretending that it came from the ADC and see what happens. As it is, your actual audio signal probably is quite noisy and distorted.

I tried something like that and the FFT worked fine!

Magician:

Computer Audio Out Ground > Arduino Ground
Computer Audio Out Left > Arduino Analog 0

Don't. You are not only getting wrong results, but potentially could destroy your arduino. Here is right way to feed AC to analog input:
http://interface.khm.de/index.php/lab/experiments/arduino-realtime-audio-processing/

Great success!

I followed the diagram as showed in the link and it all works fine now, just as expected!

Allthough I replaced the 100k resistors with 120k, the 10k resistor with 8.2k and the 4.7nF capacitor with 1uF.

Thanks you so so much!!!!

Here's the results in the following video:

BTW: as you can see in the video, the frequency response if VERY good. it recognizes frequencies up to 20 KHz :astonished:
I know it is good but why? You guys told me only 4.7 KHz would b recognizable???

Thanks a LOT to EVERYONE!

I'll be coming back for more questions so that I can fine tune this project and eventually upload my project so that more people can have good use of it XD

Ok, so now I have modified the FHT code a little bit.

I hooked the audio signal to A1, and it turns out that most of the unwanted signal is being leaked to A0.
So I thought why not take the leaked signal in A0 and remove it from A1 as noise cancellation.

After testing out all of the Analog inputs I noticed that the Unwanted signal is being leaked throughout all of the
analog inputs, but the music itself is less noticable the further away you go from the noise reference input.
So I connected the Audio signal to A5 instead, and use A0 as noise reference.

Works pretty good :smiley:

Ok, now I will create a new thread regarding other things about FFT.

Once again guys, thank you a lot!

The cluttering is fixed Magician :smiley:

I attached my sketch so you can try it out for yourself :slight_smile:

FHT.zip (1.96 KB)

@jremington:
I see what you mean now - sorry, my bad.

Pete

BTW: as you can see in the video, the frequency response if VERY good. it recognizes frequencies up to 20 KHz

No, it doesn't. What you are seeing is aliasing and this is very well understood. Any frequencies higher than 4.8 kHz present in the input get "folded" down into the range of 0-4.8 kHz.

So I connected the Audio signal to A5 instead, and use A0 as noise reference.

Frankly, I can imagine that working when A0 and A5 are sampled simultaneously, but that is not the case with arduino...
PS: As I wrote above, you need an anti-aliasing filter at the ADC input (low-pass), ie when using 20kHz sampling frequency the filter shall cut off everything above 10kHz.

jremington:

BTW: as you can see in the video, the frequency response if VERY good. it recognizes frequencies up to 20 KHz

No, it doesn't. What you are seeing is aliasing and this is very well understood. Any frequencies higher than 4.8 kHz present in the input get "folded" down into the range of 0-4.8 kHz.

But how come that when I sweep the tone generator to 20khz it shows up on the arduino's far right side?
And anything beyond 20 khz starts to move to the left again?

pito:

So I connected the Audio signal to A5 instead, and use A0 as noise reference.

Frankly, I can imagine that working when A0 and A5 are sampled simultaneously, but that is not the case with arduino...

But I AM using an Arduino. An Arduino Uno to be exact, and it Does work, so I don't quite understand what it is that you are saying?

But I AM using an Arduino. An Arduino Uno to be exact, and it Does work, so I don’t quite understand what it is that you are saying?

I did not check the noise cancellation code, but in case there is a delay between A0 and A5 sampling, noise cancellation may not work properly.

it Does work

That could be an illusion, unless you are an experienced dsp guy :slight_smile:

PS: As I wrote above, you need an anti-aliasing filter at the ADC input (low-pass), ie when using 20kHz sampling frequency the filter shall cut off everything above 10kHz.