Comparing frequencies with FFT

Hi,

I want to use the FFT library on Arduino Uno to compare the incoming sound to an interval of [1000Hz..5000Hz] and I have no idea how to do so.
I used this code with a loop I found on the forum to make the reading of the FFT data easier (I had some troubles with the monitor showing me random characters) :

/*
fft_adc.pde
guest openmusiclabs.com 8.18.12
example sketch for testing the fft library.
it takes in data on ADC0 (Analog0) and processes them
with the fft. the data is sent out over the serial
port at 115.2kb.  there is a pure data patch for
visualizing the data.
*/

#define LOG_OUT 1 // use the log output function
#define FFT_N 256 // set to 256 point fft

#include <FFT.h> // include the library

void setup() {
  Serial.begin(115200); // use the serial port
  TIMSK0 = 0; // turn off timer0 for lower jitter
  ADCSRA = 0xe5; // set the adc to free running mode
  ADMUX = 0x40; // use adc0
  DIDR0 = 0x01; // turn off the digital input for adc0
}

void loop() {
  while(1) { // reduces jitter
    cli();  // UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i < 512 ; i += 2) { // save 256 samples
      while(!(ADCSRA & 0x10)); // wait for adc to be ready
      ADCSRA = 0xf5; // restart adc
      byte m = ADCL; // fetch adc data
      byte j = ADCH;
      int k = (j << 8) | m; // form into an int
      k -= 0x0200; // form into a signed int
      k <<= 6; // form into a 16b signed int
      fft_input[i] = k; // put real data into even bins
      fft_input[i+1] = 0; // set odd bins to 0
    }
    fft_window(); // window the data for better frequency response
    fft_reorder(); // reorder the data before doing the fft
    fft_run(); // process the data in the fft
    fft_mag_log(); // take the output of the fft
    sei();
	
      Serial.println("Start");
    for(int i = 0;i < 128;i++) {
    	Serial.println(fft_log_out[i]);
    }
    delay(10000);
	
  }
}

What should I do?

Pinguu:
What should I do?

Please be more specific.

  • What are you trying to accomplish?
  • You showed some code - did it work the way you expected?
  • Presuming it didn't work like you hoped- since you're posting here - what did it do?

And, you can do something about the Timer0 interrupt. Your code disables it early on, and then calls delay(), which relies on the Timer0 interrupt in order to function. Either refrain from disabling the interrupt, or don't call delay().

To be more specific, I need to detect a baby's cry out of the surrounding sounds.
I don't know how to use the FFT Lib, the only code I tried so far is the one I posted. It gave me the processed data by the FFT so I guess it worked just fine for now.
Is it a good start for the sketch? What should I do next to get the frequency I'm looking for?

Thanks for pointing out the Timer0 interrupt, I'll remove it from the code since I need the delay() for a better reading.

The FFT just tells you what audio frequencies are present in your sound sample, binned in groups (a spectrum). A large value in a particular output bin means a significant component in that range of frequencies. As time goes on and each sound sample is recorded and transformed, the spectrum of that sample will usually be different from the preceding ones.

For example, the FFT of a pure 1000 Hz tone will show a large value in frequency bin containing 1000 Hz, and zeros in all the others.

What you do with the spectra is up to you. It is not at all trivial to recognize a particular sound from its FFT spectrum. But it may be possible that particular frequencies will show up in a baby's cry and not in other sounds, so it will be a learning experience to do the experiment. In your posted example, you might consider the output to be a 128 element fingerprint of a sound sample and compare fingerprints. You will probaby see that most entries in the output are irrelevant and can be discarded, but then the problem becomes one of comparing the rest of the entries to match the fingerprints.

Pinguu:
I need to detect a baby's cry out of the surrounding sounds.

For what purpose? Do you envision a do-it-yourself device minding the baby while you barbecue steaks in the back yard, or nap in the solarium? I can't really think of another reason for this function. I'm not sure that I want to be part of it - I'd rather not have to answer in the next life for the sufferings of an infant in this one.

Maybe you just want to do this for the sheer intellectual joy of proving that it can be done. Maybe you're talking about some non-human baby crying. I'm OK with that. If that's so, then you'll want to explore the whole idea of the Fourier transform, and what it means. Then, look at the digital Fourier transform, and finally at its special case, the fast Fourier transform. I'd start with the Wikipedia, and google from there. Ultimately, you want to understand what the output of the FFT describes, and how it's related to the physical reality that gives rise to it.

You'll also want to read the datasheet for the processor you plan to use. You need to tell us which one. I assume that you're using an Uno. The section on the Analog-to-Digital Converter (ADC) will be especially helpful, since that's the engine that will acquire your data. The openmusiclabs code that you've incorporated runs the ADC at nearly 40 kHz - faster than the datasheet recommends, and maybe faster than you want, but not so fast that the data isn't usable. Or, so I read and hear.

You'll need to characterize the sound you want to identify. I don't really know how you're going to get sample data from a baby crying. Maybe just run a recorder until you get what you want, or maybe introduce a recorder during the inevitable moments when somebody else unsuccessfully tries to quiet the baby. For heaven's sake, don't make it cry just to get audio samples.

You'll also need to characterize the ambient sound in the environment where you'll use it. Obviously, if you're trying to pick out your baby's cry in a nursery full of other children, it'll be a lot harder than picking it out against the background noise of, say, the air conditioner fan blowing in the background.

When you can describe the FFT's of those two sounds - baby crying and not baby crying - then you'll have to devise a way of telling the difference in the sketch. That might be easy, or it might be hard.

It sounds like you're relatively new to audio analysis, to programming, and to this hardware. You've selected a very challenging early project. If you have a high tolerance for frustration and disappointment, then by all means, proceed. If not, you might be better advised to start with easier projects with hope of quicker success, and less rigorous theoretical demands.

jremington:
It is not at all trivial to recognize a particular sound from its FFT spectrum. But it may be possible that particular frequencies will show up in a baby's cry and not in other sounds.

A baby's cry has a frequency of 3500kHz on average. Is it possible to get the spectrum of that frequency and compare it to the samples?

tmd3:
For what purpose?

I'm working on a surveillance system for baby. It includes a PIR sensor, a sound sensor and a GSM module. The purpose is to detect if the baby stopped breathing or started crying and send an alert SMS to the parents.
I'm only having a problem with the sound sensor part.

tmd3:
It sounds like you're relatively new to audio analysis, to programming, and to this hardware. You've selected a very challenging early project. If you have a high tolerance for frustration and disappointment, then by all means, proceed. If not, you might be better advised to start with easier projects with hope of quicker success, and less rigorous theoretical demands.

Yes I am new to audio analysis and Arduino, I can manage myself in programming.
It's a school project and I need to make it work for the sake of my grades xD
I have a teacher supervising me but he's an expert on STM boards he only can help me with the algorithm and a bit in the coding but I have to figure it out on my own first.
Isn't there an alternative way to get what I want then?

tmd3:
I assume that you're using an Uno.

Yes I am, I already mentioned it in my first post.

tmd3:
You'll need to characterize the sound you want to identify. I don't really know how you're going to get sample data from a baby crying. Maybe just run a recorder until you get what you want, or maybe introduce a recorder during the inevitable moments when somebody else unsuccessfully tries to quiet the baby. For heaven's sake, don't make it cry just to get audio samples.

I assure you no babies will be harmed during the process xD
Do I have to get a sample data from a baby crying? Wouldn't it be a "particular baby" cry?

tmd3:
You'll also need to characterize the ambient sound in the environment where you'll use it.

We'll just consider that the baby is in a silent room sleeping peacefully until he wakes up and starts crying.


Thanks for your help.

OK, it sounds like the audio part of this problem is to discern the difference between these two conditions:

  • A quiet room, and
  • An otherwise quiet room with a baby crying in it.

The fact that it's very easy for a human to make that distinction is promising. Here are some differences that we'd expect to find between when the baby cries:

  • The total audio signal will be louder overall - maybe a lot louder
  • The signal will have significant content at baby-crying frequencies

A start might be to find some audio files of babies crying, play them to your Arduino in a quiet room, and observe the output of the FFT with and without crying. It will be easier to see the differences graphically. I usually print the output to the serial monitor, copy it to a spreadsheet, and graph it. There may be better or more convenient ways to do it. A quick google finds a number of mp3's of babies crying.

A more fundamental approach would be to use test tones with known spectral content, to verify that the assembled project accurately reflects the audio signal. I'd recommend this if it's important that you're able to accurately characterize how your system works, or how you derived your solution. mp3 files of test tones are easy to google.

I have no expertise on the spectral content of babies crying. I think that this:

A baby's cry has a frequency of 3500kHz on average.

is probably a typographical error, and that you meant to say 3500 Hz, or maybe 350 Hz. 3500 Hz is the third-highest white key on a concert piano - it's a really high note. The first estimate of the pitch of a baby's cry that I found was 515 Hz.

Note that the output that you can expect from your code is a logarithmic representation of the Fourier transform. That representation compresses the magnitude of the spectrum: it de-emphasizes large spectral components, and emphasizes small ones. You might want to experiment with a linear representation. You can find information about how to get that in the fft_read_me.txt file in the openmusiclabs FFT library.

What's your current understanding of the meaning of the FFT output?

Audio spectrograms (FFT amplitudes versus frequency and time) are 3-D representations of audio samples and have been used extensively to characterize bird songs, animal vocalizations, etc. See Spectrogram - Wikipedia

I used to use a program called Spectrogram (for the PC) in teaching this material and found it to be extremely helpful. A quick search did not turn up that particular program, but many others like it are available and are free or inexpensive. If you are interested, I recommend that you spend some time learning about spectral analysis using a well documented, correctly functioning program on a PC or Mac before you tackle the subject with an Arduino. Raven Lite from Cornell is a free demo of a professional program that runs on all PC-type platforms and may be a good place to start. http://www.birds.cornell.edu/brp/Raven/RavenOverview.html

if it is a quiet room, just detect any noise.

Hi Guys !
Just windering if someone can tell us what happened :slight_smile:
Iam trying to get my Arduino to detect breaking GLAS in a car that is parked in a quiet spot.
Is there anyone that can help me ?

Thank you all !
:slight_smile: