Arduino Forum

Using Arduino => Audio => Topic started by: Shadorc on Feb 10, 2015, 03:25 pm

Title: FFT Library
Post by: Shadorc on Feb 10, 2015, 03:25 pm
Hello!

For a school project, we are looking for an Arduino FFT library able to give the fundamental frequency of a single music notes (no chord).

I tried with this fix_fft  (http://forum.arduino.cc/index.php?topic=38153.0). The problem is that it doesn't give a constant specific result, for example a constant frequency of 82.41 Hz (which corresponds to a E1, the low string of a guitar) the library returned a fundamental which varies between the 1, 2 and 3 place in the array (data[]).

I also found a library (http://wiki.openmusiclabs.com/wiki/ArduinoFHT), which seems more official. The problem is that I didn't understand how it's work.

If you have a library or a means, using the two mentioned ones above, to obtain a single output value, it would help us a lot.

Thank you for your help and sorry for the bad english.
Title: Re: FFT Library
Post by: Ps991 on Feb 10, 2015, 10:13 pm
Unfortunately there is no "single output value". There is simply how accurate your microphone is picking up the frequency and how fast your arduino is sampling it.

I used that 2nd library you found (except I used the FFT version, which is pretty much the same)
The way it works is this. If you sample at 10,000 hz, then you can map frequencies 0-5,000 hz. Depending on your FFT_N size, you can get more and more accurate readings. Example: If you sample at 10Khz, you can map 0-5Khz, if your FFT_N size is 256, then the first 128 (maybe 127) bins contain useful information. This means that you have 128 bins to represent 5000hz. Thus you can calculte that each bin represents (5000 / 128) = 39hz.

So the problem with your 82.41hz is that it is so low that it is hard to pin down which bin it belongs to.

If you really needed to detect 1 specific frequency, then you may consider using an online calculator to calculate capacitor values for a low-pass and a high-pass filter. These filters will block out higher/lower frequencies.

Please read this thread for more information, I have some good code in 2 posts, so read all of it
http://forum.arduino.cc/index.php?topic=292834.msg2046136#msg2046136
Title: Re: FFT Library
Post by: tmd3 on Feb 11, 2015, 02:37 am
Does your assignment require you to use the Fourier transform to determine the frequency, or can you use other techniques?

What's the sound source?  Is it a sine input, or the signal from a musical instrument?

Title: Re: FFT Library
Post by: Ps991 on Feb 11, 2015, 07:25 am
The method I proposed was using the FFT, however there are other techniques to detecting frequencies, each with their own pros and cons. My program used a standard electret microphone and an op-amp and performed the FFT on each 128 samples, but yes, it was basically a sine wave, it was sound.
Title: Re: FFT Library
Post by: tmd3 on Feb 12, 2015, 02:51 pm
Asking the original poster:

Do you have to use the Fourier transform to estimate frequency, or do you have some latitude in selecting your method?  I'm concerned about Fourier, because I've never seen a post where anyone claimed that it worked well as a method frequency estimation.  I've seen a lot that echoed your concerns - it gave inconsistent results.  Another method - maybe autocorrelation - might be better in your application.

You mention getting inconsistent results for an input frequency of 82.4 Hz, and you mention a guitar string.  That makes me wonder what the input source will be.  Is it a pure sine input, like from a signal generator, or is the source a musical instrument, or a recording of one?  A sine signal will be easier to analyze.  A musical instrument will normally have considerable harmonic content, and low-order harmonics will often have a higher magnitude than the fundamental - sometimes a lot higher.  If you use the Fourier transform, you may have to look for the lowest-frequency peak with significant content, rather than the highest peak.  And, you'll likely have to empirically determine what "significant" means.  I think that it may vary for different instruments.  This notion is strictly conceptual, and speculative at that; I've never tried it.

Title: Re: FFT Library
Post by: jremington on Feb 12, 2015, 06:08 pm
Autocorrelation analysis can work better than Fourier methods to determine the fundamental frequency of a musical note, and was discussed in this thread. http://forum.arduino.cc/index.php?topic=195085.0
Title: Re: FFT Library
Post by: tmd3 on Feb 13, 2015, 04:36 am
Autocorrelation analysis can work better than Fourier methods ...
Indeed.  I'd recommend reviewing the sketch at the referenced link carefully.  It looks to me that it returns a value that's one larger than the advertised value.  And, I'm dubious about the value of examining lag values larger than half the number of samples.
Title: Re: FFT Library
Post by: jremington on Feb 13, 2015, 04:57 am
Quote
And, I'm dubious about the value of examining lag values larger than half the number of samples.
Agreed. In addition to abusing the procedure, the original sketch was not normalized correctly for the lag.
Title: Re: FFT Library
Post by: Shadorc on Feb 17, 2015, 01:27 pm
Does your assignment require you to use the Fourier transform to determine the frequency, or can you use other techniques?

What's the sound source?  Is it a sine input, or the signal from a musical instrument?
No, we don't need to use FFT to determine the frequency, but it's the only one we have heard of, we can use other technique.
The sound source is a musical instrument, a guitar but for the moment we only simulate it with ISIS with a sine input.

Is there any other way to detect a note of music based on a sound?

Thanks for your suggestions, we're gonna study it !

Title: Re: FFT Library
Post by: tmd3 on Feb 17, 2015, 05:59 pm
Some other techniques are:

The Wikipedia article on pitch detection algorithms lists several ways to estimate pitch.

Is my memory accurate?  Have we ever seen an Arduino implementation of the Fourier transform give usable results in estimating pitch?
Title: Re: FFT Library
Post by: KeithRB on Feb 17, 2015, 06:13 pm
I am currently using an FFT and while I know what frequencies I am using, they always show up in the same bins. Of course, I am using 4,000,000 points. 8^)
Title: Re: FFT Library
Post by: Shadorc on Mar 08, 2015, 10:49 am
KeithRB: Do you use the fix_fft library ? And if so, how do you do to increase the number of points ?

And for the fix_fft library, what is the utility of the second array (for imaginary numbers) ?
Title: Re: FFT Library
Post by: KeithRB on Mar 09, 2015, 03:56 pm
No, I am using a PC and MatLab.

The arduino's memory won't allow for 4,000,000 points! Note the smiley in my post.
Title: Re: FFT Library
Post by: Shadorc on Mar 10, 2015, 02:11 pm
So it is not possible to increase the number of points with fix_fft library ? Can't it be possible to be more specific than that ?
And I wanted to know, I understood how the library worked but the second argument, the array of imaginary numbers, what it is ?

Thanks
Title: Re: FFT Library
Post by: KeithRB on Mar 10, 2015, 02:33 pm
You can have as many points as your RAM allows, which aren't many.

The imaginary array contains the imaginary part of your signal, which in your case is 0. In my case I was using a 1 bit ADC with quadrature output so I used the quadrature data from the ADC for the imaginary data.

Title: Re: FFT Library
Post by: Ps991 on Mar 11, 2015, 04:11 am
The input imaginary array should be 0, while the output is important. To calculate the real bin value you must take sqrt(re*re + im*im). The imaginary represents the phase shift of the signal.
Title: Re: FFT Library
Post by: Shadorc on Mar 14, 2015, 09:44 am
Okay, thank you all for your responses.
We found a guitar has its lowest note to 82.4Hz and most acute in 1318.52Hz.

Is it possible to adjust the Fourier analysis for more accurate values between 0Hz and 2000Hz ?
I understood what is the imaginary array. But, what is the third argument, "7"? I know this is 2**7=128 but I do not know what it is.

Thank you !
Title: Re: FFT Library
Post by: Ps991 on Mar 14, 2015, 10:18 pm
The 7 is to limit your results to that of a "char" which is only 8 bits, otherwise you would have an overflow and your results would be useless.

To accurately sample between 0-2000, your best bet is to sample at 4000 times a second and set your FFT_N to 256 (or the max), this would mean your accuracy would be (4000 / 2) / (256 / 2) = 15 hz per bin

To really accurately sample between 0-2000hz you will need a new chip altogether or get creative. As a new chip, you would be better off using an Arduino Due or if you want something cheaper an ATmega1284P because they have much more memory to work with. If this is not an option, then maybe try using some of the flash memory as your memory to get larger FFT_N sizes

The only library I used that actually worked was OpenMusicLabs FFT (http://wiki.openmusiclabs.com/wiki/ArduinoFFT)
Title: Re: FFT Library
Post by: Shadorc on Mar 31, 2015, 03:13 pm
PS991 thank you very much, it's perfect!

We changed our Arduino Uno to an Arduino MEGA2560 and adjusted the FFT_N to 256 bits.
This is much more accurate!

A new question:
for lines
Code: [Select]

val = analogRead(A0);
data[i] = val / 4 - 128;


What is the point of dividing val by 4 and subtract it 128 ?

Thank you all for your help
Title: Re: FFT Library
Post by: Ps991 on Apr 03, 2015, 09:21 pm
Please be sure to use code tags when posting code, because this
Code: [Select]
array[i] = 0; //this text is not italic
now becomes
array = 0; //this text IS italic, also notice the [ i ] is now missing

back on track

Code: [Select]

if (millis() > tt){
     if (i < 128){
       val = analogRead(pin_adc);
       data[i] = val / 4 - 128;
       im[i] = 0;
       i++;   
       
     }

the reason it is divided by 4 and subtracted by 128 is because the "data" is of type "char" which is an 8 bit variable (-128 to 127). So because analogRead returns 0-1023, dividing it by 4 gives you 0-255, subtracting it by 128 gives you -128-127.

You will notice that a (sine wave)/(audio wave) has positive and negative values, so this is why you see it centered around 0.
Title: Re: FFT Library
Post by: Shadorc on Apr 04, 2015, 09:07 pm
Thank you! I added code tags.

All right, our project seems to work as intended, thanks to you !
Thank you for all, you have been of great help!
Title: Re: FFT Library
Post by: tmd3 on Apr 05, 2015, 12:14 am
All right, our project seems to work as intended ...
That's good news.  Can you post your code, and a description or schematic of the circuit?  Some sample output would be interesting, as well.
Title: Re: FFT Library
Post by: Shadorc on Apr 05, 2015, 01:05 am
We wanted to post a video of the project with the code, cabling, once finished.
But we're working on it once a week, there is still a lot to do but we will post it once finished !
Title: Re: FFT Library
Post by: tmd3 on Apr 05, 2015, 04:40 am
Before you go, let me ask:  does this -
... our project seems to work as intended ...
- mean that you accomplished your original goal, which was to accurately and reliably get the frequency of a guitar string using the FFT?  If you did, I hope you'll tell us which of the several suggested techniques you used, and give us an idea of how well it works.
Title: Re: FFT Library
Post by: Shadorc on Apr 05, 2015, 11:28 am
For now we just tried with a simulation on ISIS.
We still have to connect the microphone to the Arduino by amplifying the sound and adding a DC component.

Finaly, we used the library fix_fft : http://forum.arduino.cc/index.php?topic=38153.0 and set FFT_N to 256 by using an Arduino Mega 2560.

I prefer wait Tuesday before to explain, I would have the code available to me and it will be simpler to explain
Title: Re: FFT Library
Post by: Shadorc on Apr 14, 2015, 02:28 pm
Hello !

I'm here because I have some others questions...

To set FFT_N to 256, we need to change it in the library or in my program ? (like change all the 128 to 256 : im[256], data[256], if(i < 256), etc...)

And, there's something I don't understand, if we use
Code: [Select]
for (i=0; i<64;i++){
, i will be set to 65 when for loop finished so, in the next loop(),
Code: [Select]
if (i < 128){
 will only fill data with 63 values ! (128-65) Why ?

And my last question,
is
Code: [Select]
if (millis() > tt){
 necessary ? I know why there is this line but, it is really necessary ?

Thanks you !
Title: Re: FFT Library
Post by: Ps991 on Apr 16, 2015, 05:23 am
Code: [Select]

char im[256];
char data[256];

void loop(){
 int static i = 0;
 static long tt;
 int val;
 
  if (millis() >= tt){
     if (i < 256){
       val = analogRead(pin_adc);
       data[i] = val / 4 - 128;
       im[i] = 0;
       i++;   
       
     }
     else{
       //this could be done with the fix_fftr function without the im array.
       fix_fft(data,im,8,0);
       // I am only interessted in the absolute value of the transformation
       for (i=0; i< 128;i++){
          data[i] = sqrt(data[i] * data[i] + im[i] * im[i]);
       }
       
       //do something with the data values 1..128 and ignore im
       show_big_bars(data,0);
     }
   
   tt = millis();
  }
}


As far as
Code: [Select]
if (millis() > tt) part, this is your sample rate. This is very poor programming. Ideally you would use interrupts for precise timing. Ideally you would also eliminate analogRead() and replace it with much faster code.
But if you want a better, just slightly improved version, do something like this...
Code: [Select]

long frequency = 500; //hz
...
if(micros() >= tt){
  tt = micros() + (int)(1000000L / frequency);
  ...
}
Title: Re: FFT Library
Post by: Shadorc on May 12, 2015, 04:52 pm
Hello !

First of all, thank to PS991 for the explications !

I'm here again for new questions ! :D (Sorry but you are the only ones who can help me, my professor doesn't understand this library...)

So, the data[] returns by the fix_fft() function,
If I understand correctly, this array contains amplitudes in ascending order of frequency ? Is that exact ?

And if it's true, why the maximum value contained in the data[] array will increase with the frequency and, arrived at 127, decrease to 0, and increase to 127, and decrease to 0... ?

Thank you !
Title: Re: FFT Library
Post by: KeithRB on May 12, 2015, 07:59 pm
What is the data being passed to fix_fft()?

The data can look like anything depending on the spectrum of the time domain signal you are inputting. You might also have aliasing problems.
Title: Re: FFT Library
Post by: Ps991 on May 20, 2015, 10:27 am
Sorry for the huge delay...I have not been on much...

Quote
If I understand correctly, this array contains amplitudes in ascending order of frequency ? Is that exact ?
I'm no expert, but this seems exactly correct.

Quote
And if it's true, why the maximum value contained in the data[] array will increase with the frequency and, arrived at 127, decrease to 0, and increase to 127, and decrease to 0... ?
You will be need to be more specific, I do not understand the question. What is oscillating between 127 and 0, under what conditions? Maybe post some data?
Title: Re: FFT Library
Post by: pjrc on May 21, 2015, 11:40 am
To accurately sample between 0-2000, your best bet is to sample at 4000 times a second and ....
The trouble with this is what happens if your signal has any signal content between 2000 to 20000 Hz, like the many harmonics of the notes between 82.4 to 1318.52 Hz.  Those harmonics at higher frequencies, and other frequency content associates with the way the note changes over time, are why it sounds like a musical instrument and not a sterile-sounding pure sine wave.

Anything above 2000 Hz doesn't magically go away.  It corrupts your measurements in the 0 to 2000 Hz range.  This is call "aliasing", and it's a well known and often ignored (by hobbyists) problem.

To make this really work, you'd need an extreme analog filter circuit to remove everything above 2000 Hz (or attenuate it to low levels that limit the damage it does to your signal).  Even very intense filters have a substantial transition region, which usually means you need to sample somewhat faster that you'd otherwise want to, simply to prevent the higher frequency content you couldn't filter away from aliasing onto your signal you wanted to sample.
Title: Re: FFT Library
Post by: sossio89 on Jan 23, 2016, 10:50 am
I'm  looking for an Arduino FFT library able to give the presence in frequenquency domain of a characteristic frequency of a bearing failure.

There are some characteristic frequency in a frequenquency domain when  I analyze  the vibrational signal of a   failed bearing.

I use an accelerometer with arduino.


Can I found this frequency?
Title: Re: FFT Library
Post by: jremington on Jan 24, 2016, 08:59 pm
What would that "characteristic frequency" be?
Title: Re: FFT Library
Post by: pjrc on Jan 24, 2016, 11:48 pm
If you have a signal where you wish the measure the frequency, FFT is a poor choice.  You'll be frustrated by the coarse resolution of the frequency bins, and the additional frequency smearing that results from window algorithms.

The first and most important question is whether your signal is simple enough to be reliably turned into a digital waveform of the correct frequency?  For complex signals like musical notes from guitars or vocals, you (usually) can't.  There's far too much harmonic content, where digital circuit would sometimes/often give a frequency twice, three times or more the intended frequency.

If your vibration signal is simple enough, perhaps you can build a circuit to reliably turn it into a digital signal without extra rising/falling edges.  Usually such a circuit involves a low pass filter and a voltage comparator with a small amount of hysteresis feedback.  If you can get a reliable digital signal, then you can use the FreqCount or FreqMeasure libraries.

If you can't get a good digital signal, then you'll need to use analog sampling and a sophisticated algorithm to find the frequency while ignoring other stuff like harmonics and noise.  A very good one is the YIN algorithm.  A good implementation of this was recently contributed to the Teensy Audio Library.  But that does require using a Teensy board (full disclosure: I'm the guy who makes Teensy...), because the YIN algorithm is too much computation for normal Arduino.

https://github.com/PaulStoffregen/Audio/blob/master/examples/Analysis/NoteFrequency/NoteFrequency.ino
http://www.pjrc.com/teensy/gui/?info=AudioAnalyzeNoteFrequency

Another lower quality algorithm that can run on normal Arduino is here:

http://www.instructables.com/id/Arduino-Frequency-Detection/
Title: Re: FFT Library
Post by: sossio89 on Jan 25, 2016, 11:28 am
I know characteristic frequency from some math formulas.

In this first part of my experimentation I don't know if my vibration signal is simple enough to be reliably turned into a digital waveform of the correct frequency.


The signals are generated from rotation of rolling bearings in a elettric motor.


This is the frequency domain of an other experiment:

(http://s26.postimg.org/6inawru05/Cattura.jpg) (http://postimg.org/image/6inawru05/)

They wanted to find a specific frequency: 130 Hz.




Can you hel me to built the hardware part and software part If my vibration signal is simple enough?

Title: Re: FFT Library
Post by: sossio89 on Jan 26, 2016, 09:04 am
Can you help me for this work?
Title: Re: FFT Library
Post by: KeithRB on Jan 26, 2016, 03:56 pm
First do some some simulations to decide how many points you need for your FFT. Then we can help you with your hardware. You should also start your own darn topic!
Title: Re: FFT Library
Post by: sossio89 on Jan 26, 2016, 05:09 pm
I write this in another topic?
Title: Re: FFT Library
Post by: sossio89 on Jan 27, 2016, 12:35 pm
http://forum.arduino.cc/index.php?topic=374902.0