I don't believe the Arduino ADC is fast enough for full-range (20-20khz) FFT...
But, it is plenty fast-enough if you do the frequency-filtering first, and it just has to read & process the voltage (volume) for each frequency-band.
You could build frequency-filters (bandpass filters) and peak-detectors with op-amps, but I think the simplest approach would be [u]this chip[/u] which gives you outputs for a 7-band spectrum analyzer. If you want, you can just use 3 of the bands and connect the output to 3 of Arduino's analog inputs.
I just finished an audio-lighting project and I have a couple of hints that might make your set-up work better by automatically-adjusting to the volume level... (My design doesn't have any knobs or controls.)
Once per second, I load the volume-reading into an array/buffer. The array holds 20 values, and when I get to the end, I start-over. This gives me 20 seconds worth of "data". I take an average and find the maximum every time I update it. (I'm not finding the minimum in my application, but of course you could.)
One of my effects simply compares the input to the average (in a loop, of course), and whenever the input is greater than average, the lights come-on, and if it's below average, they go-off. This makes the lights "flicker" to the music.
Another effect is a VU meter effect. The bottom light comes on whenever the signal is above average, and the top-light comes-on when the signal is slightly-less than the maximum. The in-between lights are scaled to come-on proportionally in-between. Of course, this is not a good "meter" because the display is meaningless, but it works as a great meter-effect.
In addition, I check the maximum value in the array to select the 1.1V or 5V ADC reference. If the maximum value is 1023, the ADC is clipping. If I'm using the 1.1V reference and I get 1023, I change to the 5V reference. If I'm using the 5.5V reference and the maximum is below 200, I switch to the more-sensitive 1.1V reference. When I switch ADC reference levels i re-calculate the values in the array, so that I dont' have to wait 20 seconds for the array to re-fill with good-data.)