I was looking for a simple arduino fft library to create an equalizer. I found lots of assembler code or 16 or 32 bit versions but nothing that was simple and out of the box usable. I have modified the fix_fft.c to use 8bit values. here is it for everyone with the same problem.

I did not test the inverse fft. I guess there is a bug with the scaling.

/* fix_fftr() - forward/inverse FFT on array of real numbers. Real FFT/iFFT using half-size complex FFT by distributing even/odd samples into real/imaginary arrays respectively. In order to save data space (i.e. to avoid two arrays, one for real, one for imaginary samples), we proceed in the following two steps: a) samples are rearranged in the real array so that all even samples are in places 0-(N/2-1) and all imaginary samples in places (N/2)-(N-1), and b) fix_fft is called with fr and fi pointing to index 0 and index N/2 respectively in the original array. The above guarantees that fix_fft "sees" consecutive real samples as alternating real and imaginary samples in the complex array.*/int fix_fftr(char f[], int m, int inverse);

/* fix_fft.c - Fixed-point in-place Fast Fourier Transform *//* All data are fixed-point short integers, in which -32768 to +32768 represent -1.0 to +1.0 respectively. Integer arithmetic is used for speed, instead of the more natural floating-point.

For the forward FFT (time -> freq), fixed scaling is performed to prevent arithmetic overflow, and to map a 0dB sine/cosine wave (i.e. amplitude = 32767) to two -6dB freq coefficients. The return value is always 0.

For the inverse FFT (freq -> time), fixed scaling cannot be done, as two 0dB coefficients would sum to a peak amplitude of 64K, overflowing the 32k range of the fixed-point integers. Thus, the fix_fft() routine performs variable scaling, and returns a value which is the number of bits LEFT by which the output must be shifted to get the actual amplitude (i.e. if fix_fft() returns 3, each value of fr[] and fi[] must be multiplied by 8 (2**3) for proper scaling. Clearly, this cannot be done within fixed-point short integers. In practice, if the result is to be used as a filter, the scale_shift can usually be ignored, as the result will be approximately correctly normalized as is.

/* fix_fftr() - forward/inverse FFT on array of real numbers. Real FFT/iFFT using half-size complex FFT by distributing even/odd samples into real/imaginary arrays respectively. In order to save data space (i.e. to avoid two arrays, one for real, one for imaginary samples), we proceed in the following two steps: a) samples are rearranged in the real array so that all even samples are in places 0-(N/2-1) and all imaginary samples in places (N/2)-(N-1), and b) fix_fft is called with fr and fi pointing to index 0 and index N/2 respectively in the original array. The above guarantees that fix_fft "sees" consecutive real samples as alternating real and imaginary samples in the complex array.*/int fix_fftr(char f[], int m, int inverse){ int i, N = 1<<(m-1), scale = 0; char tt, *fr=f, *fi=&f[N];

Hmm. Okay, here's the good news: I've used your code, and it works wonderfully for my purposes. Will be posting a project doc soon on it. This code is probably going to be useful for a number of projects, much praise for doing it, and even more for putting it up here for general use.

The "bad" news is that I'm still a little confused about the function call parameter "m". Note that I am not a mathematics expert- I've simply used your code as a black box audio-range FFT with 64 band resolution, just as you have. I then diddle with outputting the array in various ways. Works great, just working out gain on amplifier for electret mic. It works with a single-stage NPN, but the signals are pretty small.. later today going to add a second NPN (collector direct-coupled, E1-B2 coupled, with and without capacitor, to make a darlington of them) to see if the signal is better.. would be a nice thing if works out to be that easy (doubtful).

I'm trying to understand the underlying math, it's some pretty hardcore stuff.. matrix math and imaginary components.. erm... where's the aspirin? So instead, I'm starting with examining what you have done, to try to get a mental handle on the process from a practical standpoint- as the implementation works, I want to understand WHY it works.

I've got my head around the arrays and why they are needed, but what exactly is "m", in practical terms? It's cryptically referred to as a bit-shift parameter for the data, but that seems wrong too. Is it number of data bits (7 bits, 0-127) in the output array data?

Thanks for any insight, I'm amazed our little arduino can perform a transform reasonably... this code is perfect for my uses, so I want to understand at least the function call parameters, even if the rest remains a Black Box for the time being..

Thanks, Rusty... been reading the code and thought that was the case, thanks for the confirmation.

Syd, that would be very easy... what you are going to do is average bands together. The build I did with TvOut uses 64 bands.. I just display all 64 bands (0-32kHz approximately, 500Hz/band). What you want is to reduce the number of bands, and that's done by averaging across the data. Since you want four bands out, that means you want to take the first 16 data points, add 'em together, and divide by 16. That's your value for band #1, which would be 0-8Khz. The next 16 data points are the second band, etc.

This will give you four values, to do with as you please. Since you are using simple on/off, do a bit of testing (or put four potentiometers on the Arduino's A1-A4) to set a threshhold value to switch the SSR's on (light up when sound in that band is above threshhold level), send that on/off (High/Low, 1/0) to four digital pins, hook up your SSR's to those pins. If you have them around, the Pots are probably the easiest way to set threshholds as real-world input levels (and desired response) change.

Well Syd, you're going to be as shocked as I was with how fast the FFT runs.. in my implementation, not only is our little Arduino doing the sampling and FFT's, it's also generating composite video, completely in code, thanks to the TVout library. I'm still doing some tweaking (after which I will do actual timing to see the exact rate), but with the build I wrote up, I'm guessing it's updating (which means a sample/process/display pass) the screen at around 10 times per second. A 10Hz frame rate isn't going to be too good for an analytical device, but for a light show, it'll do just fine. The majority of the time is actually being consumed by the line-drawing routines for the bars, rather than the data transform math... since your code handling output will no doubt be less "weighty" than generating NTSC video, you will probably get a MUCH higher update rate.

By the way, Arduino has done it to me once again... a project is forcing me to learn more. My successful use of this code made me want to understand it better- wasn't happy with a black box, I like to see the inner workings and understand them if I can.

So, I've been reading through the code.. and then wiki.. and then EE society writeups.. and university papers... etc etc etc. The whole conversion to integer math makes the understanding even more difficult.. bit shift math aside, it's way to easy to get confused with the data format.

In any case, I'm now learning about the math behind this, because of you... dangit... lol.. Arduino strikes again!

The best part is that it is OPEN SOURCE. This allowed me to use the original work without needing to understand the complexities behind the scenes- but when I decided I wanted to see the inner workings, they are right there for the reading.. often with well-commented code and external references by the author for THEIR foundations. Simply put, you can pick it apart to the lowest level if you desire. Same with the TVout lib. These open source libs, on an open source platform- they allowed me to build a project far beyond my own technical abilities with relative ease. This kind of stuff is what Open Source and the Arduino project are really all about, in my humble opinion. If given enough time and reference material, could I have produced the project on my own? Maybe. Doubtful, in fact pretty unlikely. Even if I did, the effort level involved would just be too much to derive "fun" from it. Months of work, hardcore stuff. With Arduino (and the community), I went from idea to working prototype in a couple of hours. How can you beat that? I'll tell you how: by putting the source code out, it allows me to BACKTRACK to understand the parts I want to.. AFTER I've shown myself the idea works...

I'm currently trying to take an analog signal into my arduino in the frequency range of around 70-400 Hz with a few harmonics in each signal. Can this FFT code be used if i wanted to find the fundamental frequency of my signals? How would i go about doing that? Do i need to look for the highest magnitude in the FFT bins? I'm new to this stuff and need a little guidance.

Ricardo, yes.. that's going to be your best bet. There's a bit of error in the bands because of the use of Integer math, but it's at the cost of speed to go to floating point of any sort.

Unlike my above project, you are going to want to actually tune the sample code to actually get timed samples, as my approximation (or even "fast as you can" code) is NOT lab accurate by any means.

I've been reading up and am starting to get a grip on the math. By the way, to the other poster.. the output is N/2 where N is the number of samples, this gives 64 bins due to 128 byte sample space.

I might tweak this code at some point and stick it somewhere as a downloadable lib-- I haven't seen the author back to the thread, but this code shouldn't disappear.. far too useful, if even just for a light show..