I’ve always found audio visualization to be pretty interesting — it combines the complex (hah, pun) mathematics of signal processing with the entertainment of watching cool effects. Many audio players have interesting audio visualizers built-in; others are available as addons. MilkDrop seems to be quite popular.
Funky patterns on a screen changing to music is cool, but for a while, I’ve wanted to create a more entertaining experience. Essentially, my idea has been to create a set of wall lamps powered by arrays of multicolored LEDs. A microprocessor would adjust the color and intensity of the lamps based on audio input.
From a high-level standpoint, this kind of system is not too complicated. A low-latency audio processor takes audio signals as an input, performs some frequency analysis on them, and generates PWM signals. These PWM signals are fed into LED arrays making up the wall lamps. As always, though, the devil’s in the details.
The final design will use an FPGA with some simple support hardware to do the audio processing. Overkill? Probably… A fast microcontroller is usually good enough for these kinds of things. But, I wanted to make this a hardware project. The FPGA I plan to use is a Spartan 3, available cheaply on this eval board.
To elaborate a bit, I’ll feed an audio signal into a high-frequency opamp, which will buffer the audio signal and send it to an 8-bit ADC, whose output is fed into the FPGA. The FPGA will take an FFT of the data and then, based on the color mixing algorithm I choose, will operate on the frequency data. Finally, after deciding the final desired color, the FPGA outputs PWM signals to the wall lamps, those internal circuitry amplifies and uses those signals to light up the desired color. I’m hoping for a total latency on the order of tens or hundreds of microseconds.
I’d like to put up three or four lamps. One will be on the left side of my room and another will be on the right. These two lamps will be controlled solely by their respective stereo components. The other lamps will be above my desk and will be controlled based on a combination of left and right audio data.
I was originally hoping to make the wall lamps interact wirelessly, but I don’t think that’ll be possible given the price of wireless modules. Also, there is a latency problem as well as a security issue involved with wireless.
Anyways, I’ve had a few ideas for the color mixing algorithm. One was to separate the frequency graph into three large chunks (e.g. “low” frequency, “medium,” and “high”) and then define some sort of color scale for each chunk. Next, for each chunk, the center of mass is determined and is used to locate a color on the chunk’s color scale. The relative intensities are compared and then a final color is mixed. This algorithm is actually very easy to implement. A friend of mine suggested another interesting algorithm (harder to implement, but definitely worth a try): split the frequency graph output from the FFT into octaves and then define the same color scale for each octave. Colors are mixed in proportion to their intensity. This guarantees that all equivalent pitches (across octaves) have the same color. You could also improve the algorithm a bit to make the lower octaves biased toward one color and the higher octaves biased toward another. There will be three multiplexers
to determine the FPGA input. The first will allow switching between 2 or 3 analog audio channels. The second can bypass the ADC and send digital data directly into the FPGA. The third will bypass the FPGA directly and allow some device (e.g. a microcontroller) to send in PWM signals to the LED arrays.
Finally, as a finishing touch to bring out the bass, I’d like to add blue backlighting to the wall lamps that lights up only to low frequency responses.
Right now, I’ve ordered and AVR and supporting hardware in order to use this project I discovered as a starting point. Instead of outputting a graph to an LCD, though, I am going to begin testing simple color mixing algorithms with whatever LEDs I can find. Using a microcontroller will allow me to quickly test algorithms, although the latency may be noticeable. In the future, I’ll switch the function of that AVR so that it can take input from other sources and control the lighting system.
As I begin building stuff, I’ll start posting my notes and diagrams.