Sound Activated LED Spectrum Analyzer




Introduction: Sound Activated LED Spectrum Analyzer

This guide will show you how to build an LED spectrum analyzer. I built this as an addition to my arcade cabinet, though you can repurpose this guide and use the light bar anywhere you want a sound-activated light display.

The light bar is using an Arduino with a Vu shield to control the LEDs. The LDP8806 LEDs are individually addressable so they can make some nifty patterns. The audio is fed directly through a 3.5mm audio cable coming from the PC (or other sound source). The frequency of the audio is converted to data through an FFT library which tells the lights how to behave.

This project uses code which describes how to create a spectrum analyzer with an equalizer visualization. Instead of a vertical equalizer, the bars are flipped on their side to create a “horizontal equalizer”. Every two bars are connected at the bottom so it gives the appearance of a single bar adjusting from the middle.

What You Need


Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

Step 1: Test Your LEDs

Get everything laid out on a decent sized working space. Plug in your soldering iron. The first thing you want to do is test your LEDs.

I quickly learned these lights don’t like to respond to power without data. If you jump ahead and try to test them with just power and they don’t work, chill out for a second. They might just need some code pumped through to activate the LEDs. Before cutting the LED strip, follow this guide to connect the strip to the Arduino/power. Then run the sample code found here.

Note: One end does have wires pre-soldered to it. Feel free to try with those. On the reel I received the pre-packaged wired just weren’t working (humbug) so I had to cut off two LEDs and start with a bare end of the reel.

Step 2: Solder the VU Shield

Grab the Shifty VU shield and the Arduino.

The VU shield comes with a set of header pins to connect to the Arduino. These need to be soldered as the connections are too loose to simply plug in even for testing purposes. For tips on how to solder the shield to the Arduino, see this great guide from Sparkfun.

Step 3: Cut the LED Strips

For this project I used 3 strips of 38 LEDs each.

You can decide how long you’d like the strips to be. Shorter strips (<10 LEDs) probably won’t give you a great effect, but decide what length works for your project and adjust the steps in this guide accordingly.

The LDP8806 strips come with two LEDs per segment, joined with solder every 16 LEDs. You can cut and connect at any point of the strip, however be sure to desolder if you need to disconnect the strip at a connection point. Check out this video which shows how to split this type of strip.

Step 4: Prep for Connecting

For this guide I’ll be using black, red, yellow and green wire. You can use whatever colours you want but keep in mind I’ll be referencing the colours in the following steps.

Strip the ends to get a few wires of each of the four colours.

Grab your reel of LEDs. You want to find the end with the arrow pointing away from the cut of the strip. Depending on how they were shipped this can be at either end of the reel.

Carefully cut off the end of the weatherstripping so you can get to the connectors (or just cut it away altogether).

Tin the connectors with solder. This makes it way easier to solder the wires. Again, pay attention to the direction of the arrow; notice how it’s pointing away from the solder. This is the direction data flows, and if you mix them up you could damage the strip.

Just checking, you have the arrow the right way yeah? If not you’ll bust your strip. You’ve been warned.

Step 5: Connecting the LEDs

These LEDs have four pins; ground, 5v, C (clock) and D (data). Some sections of the strip have values marked on them, some don’t. That’s okay, just be aware of which pin you’re soldering to. Refer to the wiring diagram as you go and double-check the direction your strips are facing.

Solder the strips together, making sure each output connects to its respective input.

Step 6: Connect to Arduino/power

Grab your 5V power supply and the Arduino.

From the beginning input side of the strip arrangement, connect the green data wire to Pin 2, and the yellow clock wire to Pin 3. The red 5V wire connects directly to the power supply, and both the power and LED strip share a common ground with the Arduino.

Refer to the wiring diagram above and double-check all connections.

Step 7: Code

Connect the Arduino to your PC. Grab your audio splitter and connect it to your PC. Use one audio cable to connect to the VU shield and the other to connect to a speaker. Connect the power adapter to a power outlet.

Once you have everything connected, run the test program from Step 0 to double-check everything lights up.

Download the project code from Github and add to your Arduino library. Open the Arduino IDE and upload.

#include "fix_fft.h"
#include "HSBColor.h" #include "LPD8806.h" #include "SPI.h" // Choose 2 pins for Arduino output
#define DATA_PIN 2
#define CLOCK_PIN 3
// Defines the number and arrangement of LEDs in the visualizer. For a vertical setup, this will determine the space to light ratio as they wrap
#define NUM_BARS 12
#define BAR_LENGTH 12
// The difference in hue for each bar after the first.
#define BAR_HUE_DIFF 8
// Create a LPD8806 instance to control the strip
// The current hue of the first strip of the bar
int curHue = 0;
// FFT data storage
char im[NUM_BARS * 2], data[NUM_BARS * 2];
int prev[NUM_BARS];

// HSB/RGB data buffer
int rColor[3];

// Converts a 2d visualizer point to it's location on the strip
int getStripLocation(int col, int row)

// Controls the strip in alternating directions. This allows for chaining horizontal bars end-to-end
if (col % 2 == 0)
row = BAR_LENGTH - row - 1;
return col * BAR_LENGTH + row;

void setup()

void loop()
uint16_t i, j, k;
uint32_t color;

// Read analog input
for (i = 0; i < NUM_BARS * 2; i++)
int val = (analogRead(3) + analogRead(2)) / 2;
data[i] = val * 2;
im[i] = 0;

// Set the background colour of the LEDs when they are not receiving music data
for (i = 0; i < NUM_BARS * BAR_LENGTH; i++)
strip.setPixelColor(i, 20, 20, 40);

// Set the proper pixels in each bar
for (i = 0; i < NUM_BARS; i++)
// Each LED bar has 2 FFT frequencies that are summed together
int fft_start = i * 2;
int fft_count = 2;

// Get a positive data point from the FFT
int curData = 0;
for (k = 0; k < fft_count; k++)
curData += sqrt(data[fft_start + k] * data[fft_start + k] + im[fft_start + k] * im[fft_start + k]);

// Account for the ShiftyVU's filtering
if (i == 0 || i == 7)
curData /= 2;

// Smoothly drop from peaks by only allowing data points to be one LED lower than the previous iteration.
// This prevents seizure-inducing flashes which might be caused by the ShiftyVU's filtering (?)
if (prev[i] > BAR_LENGTH && curData < prev[i] - BAR_LENGTH)
curData = prev[i] - BAR_LENGTH;

// Base color for each bar
H2R_HSBtoRGB((curHue + i * 8) % 360, 99, 99, rColor);
color = strip.Color(rColor[0] / 2, rColor[1] / 2, rColor[2] / 2);

// If only the first LED is lit, but not fully. This is outside the for loop because the subtraction of
// BAR_LENGTH causes the value to wrap around to a very high number.
if (curData < BAR_LENGTH)
int brightness = curData * 99 / BAR_LENGTH;
H2R_HSBtoRGB((curHue + i * BAR_HUE_DIFF) % 360, 99, brightness, rColor);

// Colour of the base of each bar. Change this to match the background colour of the LEDs
strip.setPixelColor(i, 20, 20, 40);

for (j = 0; j < BAR_LENGTH; j++)
// Light up each fully lit LED the same way.
if (curData - BAR_LENGTH > j * BAR_LENGTH)
strip.setPixelColor(getStripLocation(i, j), color);
else if (curData > j * BAR_LENGTH)
// Dims the last LED in the bar based on how close the data point is to the next LED.
int brightness = (j * BAR_LENGTH - curData) * 99 / BAR_LENGTH;
H2R_HSBtoRGB((curHue + i * BAR_HUE_DIFF) % 360, 99, brightness, rColor);
strip.setPixelColor(getStripLocation(i, j), strip.Color(rColor[0] / 2, rColor[1] / 2, rColor[2] / 2));

// Store all of the data points for filtering of the next iteration.
prev[i] = curData;

// Cycle through all the colors.
if (curHue == 359)
curHue = 0;

// Display the strip.;

Step 8: Play Some Music

Once everything is uploaded, play some music! You should now have something like this (mine is covered with a light panel sheet for diffusion).

Full Spectrum Laser Contest 2016

Participated in the
Full Spectrum Laser Contest 2016

Be the First to Share


    • Trash to Treasure Contest

      Trash to Treasure Contest
    • Raspberry Pi Contest 2020

      Raspberry Pi Contest 2020
    • Wearables Contest

      Wearables Contest



    3 years ago

    This would be a great party prop!