Go Down

Topic: Limiting fix_fft to a Band (Read 6570 times) previous topic - next topic

rickso234

Want to do some drum beat analysis with Arduino.
How do configure fix_fft to only work on the band of 0Hz to 256Hz and only 32 bins?
Will 32 bins run faster than 64? Only interested in frequencies below 256Hz (doesn't have to be exactly 256, it's just the nearest power of 2) so figure if I constrain the FFT to that range, it'll execute faster.
I assume the data array contains the returned frequency bins' values?

Magician

Quote
How do configure fix_fft to only work on the band of 0Hz to 256Hz and only 32 bins?

Freq. 256 Hz is defined by sampling rate, 512 samples/second in this case by Nyquist. Quantity of bins  defines spectral resolution, 256 / 32 = 8 Hz/bin, and sampling period:  1/8 = 0.125 second.
Quote
Will 32 bins run faster than 64?

Yes, less bins better speed. The same time spectral resolution higher with 64 bins: 4 Hz.
Quote
I assume the data array contains the returned frequency bins' values?

Not clear, if you reference 8-bit fix_fft  (link?), I'd advise not use it. 8-bit fft has very low dynamic range, and would make sense only if you really need very fast math (256 bin or more). Which isn't your case,  so look in 16-bit.
http://fftarduino.blogspot.com/2011/02/color-organ-spectrum-analyzer-on.html


rickso234

Okay, thanks. I was thinking the 8-bit FFT so perhaps I'll try the 16-bit. Can't tell from the link if the "music_color" sketch includes all the code (the 8-bit code had .h, and .cpp files). Still not clear how I set the sampling rate, spectral resolution, and sampling period in the FFT code.

Magician

Quote
Can't tell from the link if the "music_color" sketch includes all the code (the 8-bit code had .h, and .cpp files)
Misic color includes all code to run 16-bit FFT  in one scketch. But sampling is running in free mode, with default ~9 kHz sampling freq. Plus  sampling is stopped during calculation, no real time, which isn't necessary for LED lights illumination.
You project is more complex:
1 You have to define sampling freq. by Timer 0/1/2, as ADC can't go below 9 kHz.-
2. Arrange two buffers in "ping-pong" for real - time processing
There is couple links I have in my collection to start :
http://www.adrianlombard.com/physical-computing/avr-fft-code/
http://www.waitingforfriday.com/index.php/Real-Time_Audio_Spectrum_Analyser#ADC_Sampling

rickso234

Thanks! I'll check the 16-bit code out tonight. Tried the 8-bit code expecting to get an array of zeros (no input signal) but get... absolutely nothing... an array of nulls. Assuming the 8-bit (256 counts) will give me 5V/256 = 19mV resolution, 16-bit is 5/65536 or about 76uV, which seems way smaller than I need. Actually, a 9kHz sample rate may be fine. That gives me bins to around 4kHz (9k/2), right? Could be a "nice to have"  for future exploration.

Magician

Quote
Assuming the 8-bit (256 counts) will give me 5V/256 = 19mV resolution,

Not quite, 128 counts only, as signal AC you have to offset it , to pass both negative and positive half-wave.  Problem better to consider as dynamic range limits in dB, not millivolts.   Fix_fft outputs 64 counts max value, it's how algorithm works to prevent overflow, limiting dynamics to 36 dB , which is a too low for musical performance.
Quote
Actually, a 9kHz sample rate may be fine. That gives me bins to around 4kHz (9k/2), right?

No. I'll try explain better this time:
1 . Sampling rate define upper freq. range by Nyquist theorem: Fmax = Fsamp / 2.
     Sampling with 9 kHz you can get 4.5 kHz as upper Fmax.
2.  Bins width or spectral resolution depends on how long you do a sampling. Fmin = 1 / Tsampl.
     If you taking samples 1 second, you getting 1 Hz resolution and each bin width.
     But there is a problem,  reading with 9 kHz gives 9 kB array of data. There is no    memory and no CPU to calculate big volume of data. So in your  situation, you should decrease sampling rate in order to limit size of data to less than 512 bytes on Uno(2K). 

rickso234

Have the 16-bit code running, but confused... the text for the "color organ" project says fx is 32 bins but the code is outputting 64 bins.

Also, how do I set sample rate and spectral resolution? Is it in here somewhere?
#define N_WAVE          1024    /* full length of Sinewave[] */
#define LOG2_N_WAVE     10   /* log2(N_WAVE) */

#define FFT_SIZE    64
#define log2FFT      6
#define N             (2 * FFT_SIZE)
#define log2N        (log2FFT + 1)

And... what does the value in each bin represent? I know it's amplitude but what is it relative to?

I hate to keep asking questions... is this stuff documented anywhere?

Magician

Quote
32 bins but the code is outputting 64 bins.
It's how algorithm FFT works, it produced twice data size, with second half is exact "mirror" copy first half. Bin 33 is reflection 31, 34 - 30, and so on up to 63 - 1. Sampling rate is not define at all, as I say in reply #3 , ADC running on defaults settings, 9 kHz. To set this rate for lower value, I'd suggest you look into MsTimer2 library. It's common practice, to do some repetitive functions on regular basis to use a timer.
Value each bin represent magnitude corresponding freq. in the input waveform. For example, if you apply single sine freq, with max non-distorted voltage 0-5V ( 2.5 V AC), ADC converts this to binary 0 - 1023 ( or 0 - 32767 if result "left-shifted" ), than bin value would be 1/4 = 8192.
1/4 because AC only 2.5V , and scaling operation fix_fft taking off 1/2
Quote
I hate to keep asking questions... is this stuff documented anywhere?

What else forum for? Take a "crash" course DSP:
http://101science.com/dsp.htm



rickso234

I thought about the "mirror image" but when I insert a wire into A0 input I get 60/120Hz pickup that gives larger numbers in bins 1 and 2, and 3 which doesn't appear mirrored anywhere. "Bin 33 is reflection 31, 34 - 30, and so on up to 63 - 1". Don't understand...  which is a reflection of which? So 9kHz is default ADC on the Arduino Uno?

As for level, 8192 corresponds to 2.5V or 5V? I have a function generator that I should use to inject sine tones at known freq/ampl to see what the output does. Considering trying DFT instead of FFT so I can select frequencies of interest to transform and will run quicker. Maybe?

BTW, is it chilly there in Montreal this morning? Manchester, NH is 23deg. F!

Magician

Code: [Select]
     if (incomingByte == 'f') {
       for (i=1; i<N/4; i++){

Try N/2.   8192 corresponds to 2.5 V AC. As you can't connect AC generator to input directly (AtMega doesn't accept negative voltage), you have to create DC offset 2.5V , then AC will go up and down from 0 (negative max) to 5 (positive max). There is good topic:
http://interface.khm.de/index.php/lab/experiments/arduino-realtime-audio-processing/
It's +1 (C), I'm missing for snow, there is some delay in delivery....

oilburner

Some food for thought:

Undersampling will produce results even for frequencies over the Nyquist frequency. With a bandpass filter I could isolate frequency bands and work on 2.5kHz - 5kHz with a sampling frequency of 2.5kHz.

The speed is influenced by sampling rate and number of FFT points. My algorithm produces a result every second, since I use a 256Hz sampling frequency and 256 FFT points because I need 1 Hz precision.

rickso234

Connected a function generator and, with a 2Vpp sinewave offset by 1V (0V to 2V), bins 1 to 63 are each 69.2Hz wide up to 4.3kHz. This makes sense given a 9kHz default sample rate. Level of the 2V sine (which was measured approximately on a scope before connection) in the expected bin is just over 10,000, so for a 5V sine would be likely 32,768 That makes sense also.

I'd like to cut the overall band to 1/2 or even 1/4, a 2.2kHz or 1.1kHz overall range with 35Hz and 18Hz wide bands respectively, so I need to decrease the sampling rate by 1/2 or 1/4, correct? How would I accomplish this with the Uno and what other changes to the code would be required?

Magician

Quote
bins 1 to 63 are each 69.2Hz wide up to 4.3kHz

What is the code you are running? With color_music I'd expect 2.2 kHz / 32 bins.
Quote
How would I accomplish this with the Uno and what other changes to the code would be required?

I already told you, look for MsTimer2 or similar library, that would help you to take a sample reading with any desired freq. Second modification, you need to decide if  input data processed w/o interruption. In color_music, data is not sampled when calculation works. There is a "gap" 12-14 mS, so it's not real-time application.

rickso234

> What is the code you are running?
Thought it was the code from color_music, the site you'd referenced. I'll double-check.

> With color_music I'd expect 2.2 kHz / 32 bins.
Yes, that's what I expected but getting double that. I provided tones up to 4kHz and the expected bins (69Hz/bin) showed the signal.

> I already told you, look for MsTimer2 or similar library...
Sorry, now I remember but couldn't find the reference earlier to the library name in this posting thread.

> ...you need to decide if input data processed w/o interruption.
My application is similar to color_music. I'm looking to flash LEDs to beat of the music and change sequences of flashes to the beat as well.Think I can live with non-real time sampling... a "gap" 12-14 mS should be okay.


Magician

O'k man, I published my FFT code for musical note recognition. Have a look:
http://musicalnoterecognition.blogspot.com/
Timer and real-time features supported. Feel free to ask  questions in the comments section  8)

Go Up