Arduino Realtime Spectrum Analyzer with Video Out

After only minor tweaking, a project I had in mind worked on the first try... a (near) Real-time audio spectrum analyzer light show. The goal was to produce an amusing party display, and isn't intended to be used for any real purposes.. just fun!

There's a lot of room for improvement, feel free to tweak the design- the single-transistor amplifier is barely enough to use, my next version will chain two transistors in a Darlington array to increase the gain. The Fast Fourier Transformation (FFT) is thanks to a Arduino forum post- 8-bit FFT in C. Coupled with the TVout library also found here, it's a working design if not optimal!

Link to Project:

Link to 8bit FFT code in C that made this possible:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1286718155

No video? ;D

Nice short code and implementation.

Taking forever for the video to be processed by blogger software. My little Kodak does it's filming in Quicktime MOV's, which for some reason takes forever for vendors to process into post-able format. For what it's worth, posting the video to YouTube also just in case, they are usually a little better..

Hmm.. well, converted to AVI and YouTube preferred that. Here's video of it running, "listening" to a little AC/DC.

Nice. What kind of fps are you getting out of that?

A bit noisy but that's to be expected without a direct audio input.

It doesn't help that the music is coming from a cheap speaker held by hand over a breadboard-mounted microphone either, I'm willing to bet. Since the amplifier gain is not really where it should be for clean samples, a bit of data noise is also the result. The fact that it worked at all the first time through is nothing short of a miracle- I'm cleaning up the circuit a bit before I post it also, as it is a total trainwreck on the board (see the pictures in the blog).

As for FPS, I'm going to time it after I do a few tweaks. Right now, it's actually skipping the first band, due to a large amount of 60hz hum. I may have to put some filtration in to take some of it out, also it will help if I run from battery rather than a half-wave rectified wall wart, I'm sure.

However, happened upon some hockey game tickets for tonight's game (Boston Bruins v New Jersey Devils).. I'm not a lunatic fan, but I like going to almost any kind of live event, if only to people watch. It's a good way to reassure yourself that you really AREN'T the biggest freak of nature on the planet. The Bruins will be getting my attention for the next few hours.. but I'll probably be doing some twiddling with the beastie over the next day or so.

If I had to venture a guess, I'd say it's probably in the 10-12 FPS range.. the Tvout line drawing is actually the big cpu hog... I find that amazing, as the transformation provides 64-band data, roughly 500Hz per band, to give us 0-32kHz (roughly) on the display in 64 bands, in realtime, in C, on an AVR. Very impressive, poor little AVR has got to be going flat out!

Incidentally, the code should work if you have another source feeding the Analog input... I used a microphone for this version (plug into TV, set it down, and it displays ambient sound on TV), but a direct-coupled version of course would be much cleaner. The resistors for the TVout library (one 330ohm, one 1kohm) are the only hardware required other than something feeding the A/D input. Conversion to whatever source is simply a matter of getting a decent signal to the A/D converter.

I'm considering a circuit that would use PWM to charge a capacitor to feed the aref pin... thereby making aref variable by changing the PWM ratio... giving me a sort of automatic gain control via software, on the analog inputs. Got any thoughts on the feasibility? As you know, I'm likely to attempt things that I don't know any better than to try.. and sometimes succeed...

Cool.

this leads to a related quesiton. lets say you are working with an audio source that only has headphone or speaker output. For example, a cheap car audio receiver that doesn't have a line out. What would be the best filter circuit to connect to the analog pin and how do you make the circuit?

Circuit is now posted (first Fritzing attempt.. bear with me!) and a second video is going up...

Six resistors, a capacitor, a microphone, and a transistor (I got six resistors and a microphone....)

Nicely done! Thanks for sharing it!

Nice short code there too! (I had to change the #include <fix_fft.h> to #include "fix_fft.h" to make it compile though. And you seem to have some extra semicolons in there, after for {} blocks etc. Not that it matters).

Thanks to this, and not least that 8-bit fixfft you link to, I managed to get FFT onto a 8x8 red-green matrix display I have :stuck_out_tongue: So not 64 bands, but 8 (or 9 probably). Still cool though. I did discover that my display PWM interfere a bit with the signal reading, unless I set it to lowest setting. Then I did get rid of the noise in the lowest band - until I changed something that is - my code and not least my simple mic preamp might be a bit buggy, still testing). But it works pretty well imho (I can't claim it worked on first try though).

FFT alorithms are pretty magic btw!

Also, I think, if you have N samples, you get N/2+1 frequency bands back, the first band (band 0) being the DC component, and the last band (in your code the 65th band, which is element 64, not 63), being the samplerate/2 component.

In other words I think you can do this in the last loop of your code:

  for (i=1; i< 65;i++)
  {                                              // In the current design, 60Hz and noise
    data[i] = sqrt(data[i] * data[i] + im[i] * im[i]);  // in general are a problem.  Future designs
    TV.draw_line(i+x,lastpass[i],i+x,ylim,0);    // and code may fix this, but for now, I
    TV.draw_line(i+x,ylim,i+x,ylim-data[i],1);   // skip displaying the 0-500hz band completely.
    lastpass[i]=ylim-data[i];                    // if you insist, initialize the loop with 0
  }                                              // rather than 1.
}

Note the "I think".. I tried to make FFT a while back from scratch but gave up intending to get back to it. I just had to check my very brief notes about it, and I have yet to test my own 9th frequency band on the 8x8 display.. it was just something I noticed now while writing this. I'm no expert on FFT.

I had been looking at the stats for the blog, which includes the URL's followed to reach the site.. which then showed me two things... I made the Arduino blog the other day with this the project (grinz) and here's the one that I'm kind of proud of:

http://blog.makezine.com/archive/2010/11/real-time_spectrum_analyzer_powered.html

Referenced in Make magazine's blog, too!

I really ought to fix up that amp circuit, huh? I was thinking of using an op amp instead of beefing up the simple transistor amp, but then it would lose the shine of all being run from a single chip (yes, I know, but let's just play along with the misnomer). Guess a darlington pair might be the right solution.. the amp "design" was "hey what's laying around in the bin?" and hasn't exactly been designed for ideal operation..

After turkey day, I'll take a shot at the circuit. Three main design changes, hopefully without much added complexity:

  1. increased gain on the microphone for better sensitivity
  2. adding a direct-coupled input, for taking in line-level and/or headphone-jack-level input, so it can be "fed" from an audio device or mp3 player
  3. maybe some type of filter cap to reduce AC hum

A few changes in code also make sense, maybe beefing up the graphics a bit too, as they are meant to be a light show, not an analytical device... not to mention, the circuit as posted shows the capacitor reversed, etc... "Fritzing" isn't something you just load and get right the first time, methinks..