Limiting fix_fft to a Band

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.

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/

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.

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.

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).

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?

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

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

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!

     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....

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.

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?

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.

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.

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.

O'k man, I published my FFT code for musical note recognition. Have a look:

Timer and real-time features supported. Feel free to ask questions in the comments section 8)

Wow... quite nice! Pretty close to what I'm looking for... will attempt to digest the code later.

So I like what was done in the Musical Notes Recognition code. Was able to input frequencies from a function generator and see energy in the corresponding bins. For music however, don't think there's enough dynamic range with the 8-bit FFT, even with range enhancement. I'd like to take the 16-bit code and wrap the features from the 8-bit code (command line, TIMER2, ...) around it to allow frequency range and Hz/bin control, and better dynamic range.

The things, for LED visualization of single musical instrument (piano), I skipped in the code one important part - expander. Basically, scaling procedure to fit input data in 8-bit array is nothing else than compression, and in order to get right values in the bins after processing complete, data have to be expanded back, using the exact values from amplification/shift variables.

How do I expand the array values back? Full 8-bit amplitude resolution should give me 1.9mv steps (5V/256) which seems enough to evaluate music.

1.9mv steps (5V/256)

Check your calculator, mine shows: 5 / 256 = 0.01953125
Expanding: sorry , I'm not gonna write code for you. If you 've made sqrt for 256 bins instead of 48, multiply pred_displ[] values according "ysilit" and "shift" variables. Put your imagination to work, it's elementary math :slight_smile:

You're right... I was off a factor of 10. 19mV/step is too much for music. As for the expander, I thought it was something you already had but but just didn't include... I can figure it out. Problem is, this FFT is just a small piece of a larger project, and I don't want to spend a lot on it.