I have always been enamored by colorful displays that react to sound in real time. Being able to view the sound waves is mesmerizing, and it's even better when the wave is broken into its component parts. One method of viewing sound data is by using a frequency analyzer, where bars from left to right expand and contract based upon the amplitude for a given frequency band. I wanted to recreate this effect but with a twist — making it linear and far more colorful.
Required HardwareThe main processor for this project is a Teensy 4, and it's responsible for taking incoming sound data and processing it. After the audio has been broken down into frequency bins, it gets outputted along a string of LEDs, thereby creating a lightshow. As for the lights themselves, I went with a strip of 240 WS2812 LEDs.
With the Teensy 4, the builtin Audio library provides several methods for getting audio input. Some of these include the ADC, I2S, and even TDM. However, I went with SD card WAV audio because of its simplicity and ease of use when transferring music. The Teensy 4 then takes the WAV file and sends it over I2S to the audio shield for aux output, as well as over USB. This makes the Teensy appear as an audio input, akin to a USB microphone.
The USB audio input class allows for its two channels (left and right sound) to be "patched" into other blocks. This layout can be viewed with the Teensy Audio System Design Tool. For this project, the WAV file input goes into a mixer, where the stream is evenly amplified and then outputted into a 1024 bin FFT analyzer, a peak block, and finally, an I2S out block. The 1024 bin FFT analyzer uses a fast Fourier transformation to isolate certain frequencies from the single waveform and then place the amplitudes into 1024 bins. These are then combined into 16 bins by giving the lower frequencies more weight versus the higher ones. Additionally, the peak of the current waveform is read, and this determines the LEDs' brightness (louder sound = brighter).
The WS2812s work by reading in a series of pulses, parsing them into color information, and then passing on the rest. Since I wanted to quickly update the string without blocking everything else, I used the WS2812Serial library. It works with the Teensy 4 by using direct memory access (DMA) which uses dedicated hardware to send data from a buffer to the serial port while bypassing the CPU. This frees up some much-needed cycles that can instead be used to process more audio information and analysis.
The Audio library sends auditory data directly from the wav stream reader to both the FFT1024 object and Peak object. The Peak analyzer measures the current overall amplitude of the sound wave and sets the LED strip's brightness with WS2812Serial.setBrightness()
. A given bin's value (after scaling) can range from 0 to 8. And since there are 15 LEDs in a bin, a 0 means none light up, 1 means the middle one lights up, 2 means the middle and the ones immediately to the left and right light up, etc.
Colors are determined randomly when the Teensy receives power and starts, so it's nearly impossible for two lightshows to be the same.
This was a very fun project to build and even more interesting to watch. There are so many other ways to modify this project into something even better, such as adding an effects switch bank, other ways to input audio, and more lights.
Comments
Please log in or sign up to comment.