Microphone input for fix_fft processing

I'd like to venture into the FFT world with Arduino and am trying to figure out what's needed. It seems fix_fft is the best option to get what I need on the software side. On the hardware side though, do I need the raw audio input from an electret mic with an opamp, or can I use the breakout electret mic that SparkFun has (SparkFun Electret Microphone Breakout - BOB-12758 - SparkFun Electronics)?

Just use the board's audio output into an analog pin and have fix_fft process?

Yes , just connect mic breadboard to analog pin. With raw audio you will need to create DC offset. http://fftarduino.blogspot.com/2011/02/color-organ-spectrum-analyzer-on.html

DC offset? WHat I'd like to do is create a board that accepts two methods of input, either the on board electret mic, or have a 3.5mm jack. If the jack is used, the mic should be turned off (which I believe one can do when you plug something in the jack as it breaks the connection with one of its pins, I think.)

If I use the SparkFun breakout board, I don't need anything else right, just connect 5V+ and GND, and take the AUD pin to an analog input, yes? How do I augment that to add a 3.5mm jack to the circuit as well?

Also, with fix_fft, what is in the data array? Decimal values? Hex values?

Hi,

I'm reasonably new to all this so dont take my work as law but I looked into this recently.

In regards to DC offset: The Arduino ADC (Analog to Digital Convertor) can only read positive voltages i.e +0V. This is an issue when trying to read audio as a sound waves oscillate between positive and negative voltages. To overcome this you supply a DC offset to raise the signal between 0 and 5V so the Arduino can read it. Since the Arduino can read 0-5V range a +2.5V DC offset is a good idea however the circuit below uses a potentiometer to set the value.

http://interface.khm.de/wp-content/uploads/2008/11/arduinoaudiofig1.gif

The circuit around Analogue input 1 in that diagram will work fine for a 3.5mm input.

The sparkfun mic breakout board applies a DC offset for you so just plug it in and away you go.

As for fix_fft dont try to understand it...its mathematic magic. From memory you fill an array with samples and it returns an array of frequencies. I dont understand how it can tell when an Arduino samples so slow but apparently it works. Someone else will have to help you with this one.

fireman_sam6986:
http://interface.khm.de/wp-content/uploads/2008/11/arduinoaudiofig1.gif

The circuit around Analogue input 1 in that diagram will work fine for a 3.5mm input.

Cool, thanks.

fireman_sam6986:
As for fix_fft dont try to understand it...its mathematic magic. From memory you fill an array with samples and it returns an array of frequencies. I dont understand how it can tell when an Arduino samples so slow but apparently it works. Someone else will have to help you with this one.

Not so much trying to dissect it, but more what's in the arrays, or specifically, the data array. Is it decimal values between a specific range? Or is it all hex values? Somewhere, somehow one must be getting something to work with that people are using to control LEDs and what not.

Is it decimal values between a specific range? Or is it all hex values?

There is no difference between these two statements. All data is stored in binary bit patterns, how you represent the number in the code is up to you it all ends up as the same bit pattern.
For example defining something as 0x10 or as decimal 16 the same bit pattern is stored.

Yes, I realized that after I hit Post, and with the forums taking upwards of a minute or 2 to perform a task (that's when it doesn't simply timeout), I didn't bother to come back and fix my reply. Still doesn't answer my question of what is in the data array. What are those values? Frequency values? Values between 0 and 1023? I need to know what they are. The last time I tried that code and tried sending the data values to Serial.print(), all I got were odd characters such as '?', '.', '<' being displayed (and only the first 3 to 5 bins would output something.) But that may simply be because I don't know what they are to begin with. If they're stored as decimal values, then something's wrong. If they're stored as 0xFF then I need to print as HEX. Either way, I have no clue WHAT they are to begin with.

What are those values?

The data that is the result of the FFT.

The last time I tried that code and tried sending the data values to Serial.print(), all I got were odd characters such as '?', '.', '<' being displayed

They are numbers representing the energy in the different frequency bands, why would they correspond to anything other than odd characters?

Maybe because I was expecting to see an actual numerical value of sorts when I passed them to Serial.print(). If they are representing the energy, how are people translating that to something used to drive LEDs through PWM?

In replay #1 I post a link , there is an arduino sketch you can download. You may use it as starting point, sketch include a code to print data via serial link and controls a bunch of leds.
Data in the output array are magnitudes of specific sine frequencies in the input analog waveform

All right, I'm using your code Magician and dumping all 64 bins to Serial. So I see a bunch of numbers .. great, it works. Using a tone generator I can see which bins get affected and all of that. Great. Technically, if I have 64 LEDs, corresponding to each bin, I should be able to control that LED with PWM, yes? What's the min and max value that could be in the bin (so I can map it properly to 0-1024 for PWM)?

And I'm starting to realize this won't work for what I'd like to do in the future, so I'll be looking for something else. But in the mean time ... it's still fun to play with.

You should get 32 bins on serial monitor. PWM is 256. Value in the bin 0 - 8192 for single tone with amplitude 2.5V (RMS = 2.5 / sqrt (2)).

32? That's odd. After the "Calculation of the magnitude" (this is in your code), I dump bins 0 to 63, and they all show data in them. I do see that further down you're only using bins 1 to 32 for the LEDs (1-11, 11-21, and 21-32). So where is the data I'm seeing coming from?

When I tap the mic, I see some negative values and some rather high positives as well:

fx[0]	fx[1]	fx[2]	fx[3]	fx[4]	fx[5]	.....	fx[60]	fx[61]	fx[62]	fx[63]
847	783	284	289	185	231	.....	166	231	262	738
-23699	4513	4491	4435	4344	4218	.....	4125	4266	4377	4457
14417	22868	7199	4946	4583	2909	.....	4419	4969	6971	22584
-27143	4818	1835	1598	985	547	.....	973	1516	1823	4751
10454	613	482	116	122	247	.....	77	126	423	616
4574	721	414	307	245	117	.....	224	252	411	673
1316	727	369	262	184	363	.....	178	207	346	706

All I did was stick a print inside of the loop and removed the other stuff (the monitor, and calculations to light up the LEDs):

 void loop()
 {
 //Filling up input raw data array x[];
 // 14.6 msec for ADC and 12.4 msec everything else, TOTAL = 27 msec if FFT size = 64 (N=128).
 // 28.8 msec for ADC and 27.1 msec everything else, TOTAL = 55.9 msec if FFT size = 128 (N).

   ADCSRA = 0x87;
   // turn on adc, freq = 1/128 , 125 kHz.  
   ADMUX = 0x60;
   //Bit 5 – ADLAR: ADC Left Adjust Result
   ADCSRA |= (1<<ADSC);
   //    while((ADCSRA&(1<<ADIF)) == 0); //Discard first conversion result.
   while(!(ADCSRA & 0x10));

   for(i=0; i<N; i++ ) {
     ADCSRA |= (1<<ADSC);
     //    while((ADCSRA&(1<<ADIF)) == 0);
     while(!(ADCSRA & 0x10));

     x[i] = ADCL;
     x[i] += (ADCH << 8);  
   }  

   ADCSRA = 0x00;

   for (i=0; i<N; i++) {
     x[i] -=  sdvig;
     if (i & 0x01)
       fx[(N+i)>>1] = x[i] ;
     else
       fx[i>>1] = x[i] ;
   }  

 //Performing FFT, getting fx[] array, where each element represents
 //frequency bin with width 65 Hz.

   fix_fftr( fx, log2N );

 // Calculation of the magnitude:
   for (i=0; i<N/2; i++) {
     fx[i] = sqrt((long)fx[i] * (long)fx[i] + (long)fx[i+N/2] * (long)fx[i+N/2]);
   }

   // show 64 bins
   for (int d = 0; d < 64; d++) {
     Serial.print(fx[d], DEC);
     Serial.print(", ");
   }
   Serial.println();
 }

This is using SFE's electret breakout by the way.

32? That's odd

No 32 is even :slight_smile:
An FFT produces two copies of the data so you only need half of them.

Hrm, two copies? As in bins 0-31 are the same as 32-63? The values aren't ... Could you enlighten me please?

They represent positave and negitave frequencies and as negitave frequencies don't exist it is safe to ignore them.

Ok, so I ignore anything past bin 31 ... Fair 'nuf. Now, go back to my output posted earlier. How come I see some rather high values, as well as negative ones? All I did was gently tap the mic.

I am not sure about the negative values in general they represent a magnitude so they should all be positive, so maybe there is some overflow going on in the arithmetic. As it is not my code I can't say, and I don't have the next two days free to try and work it out.

How come I see some rather high values

You will do because you:-

All I did was gently tap the mic

This is an impulse and that Fourier series goes up to infinity. So you should see the higher frequency bins high.

Just a random question are you plugging the mic/stereo line directly into the arduino? I wanted to try doing this is a future project and was wondering if the fft will work by using a mic breakout straight into an Arduino analog pin or do you need to use an external fast ADC.

Cheers.