Turn your favorite music into patterns of light and colors to be shown on the Neopixel LED strip.
This project is a music-responsive LED light strip driven by an Arduino and a Processing sketch. The LED colors and patterns change in real time according to the volume and timing of the music, turning sound into an immersive visual experience.
The aim was to explore how music can be translated into visual form through programmable LEDs. Each segment of the song triggers a distinct lighting behavior, creating a dynamic lightscape that mirrors the emotional flow and structure of the music.
Sensory Bridge by Lixie Lab
Connected a Neopixel LED strip to Arduino via serial communication
Developed the visualization logic in Processing
Used Processing Sound Library to analyze audio amplitude
Mapped volume data to light behavior (color, quantity, brightness)
Resolving index mismatches between array logic and LED addressing
Implementing symmetrical lighting from both ends using dual loops
Adding a keyPressed() toggle to pause and resume music playback in real time
Make use of media files in Processing.
Utilize analysis techniques to turn music into actionable data.
Come up with one or more visualization strategies for audio
Use arrays in combination with loops and conditionals to create a dynamic visualization
Explore the use of the Arduino in combination with Processing
Build light objects using NeoPixel RGB LED strips.
import processing.serial.*;
import processing.sound.*;
Amplitude analysis;
Serial serialPort;
SoundFile sound;
int NUM_LEDS = 60; // How many LEDs in your strip?
color[] leds = new color[NUM_LEDS]; // array of one color for each pixel
boolean isPlaying = true;
int ledIndex=0;
void setup() {
size(900, 600);
sound = new SoundFile(this, "OGUZ, Nyctonian - GOLDEN SZN.mp3");
sound.loop();
analysis = new Amplitude(this);
// use the soundfile as the input for the analysis
analysis.input(sound);
frameRate(50);
colorMode(HSB, 255);
serialPort = new Serial(this, "/dev/tty.usbmodem101", 115200);
println("Loading mp3...");
}
void draw() {
background(0);
float progress = sound.position() / sound.duration();
println(progress);
// analyze the audio for its volume level
float volume = analysis.analyze();
println(volume);
if (progress<0.168){
float light_num = map(volume, 0, 1, 0, NUM_LEDS);
for (int j=0; j < NUM_LEDS/2; j++) {
if (j < light_num) {
leds[j] = color(light_num/2,230,150);
println('l');
} else {
leds[j] = color(0, 0, 0); // or to black
}
}
for (int i = NUM_LEDS-1; i >=NUM_LEDS/2; i--) {
if (i > NUM_LEDS-light_num) {
leds[i] = color(light_num/2,230,150);
println('p');
} else {
leds[i] = color(0, 0, 0);
}
}
}
if (progress >= 0.168 && progress < 0.21){
float light_num = map(volume, 0, 0.8, 0, NUM_LEDS);
for (int i=0; i < NUM_LEDS; i++) {
if (i < light_num) {
leds[i] = color(22,138,160); // turn a pixel to red
} else {
leds[i] = color(0, 0, 0); // or to black
}
}
}
if (progress >= 0.21 && progress <0.252){
float light_num = map(volume, 0.5 , 0.9, 0, NUM_LEDS);
for (int i=0; i < NUM_LEDS; i++) {
if (i < light_num) {
leds[i] = color(49,149,239); // turn a pixel to red
} else {
leds[i] = color(0, 0, 0); // or to black
}
}
}
if (progress >= 0.252 && progress <0.296){
float light_num = map(volume, 0.7 , 1, 0, NUM_LEDS);
for (int i=0; i < NUM_LEDS; i++) {
if (i < light_num) {
leds[i] = color(210,180,180); // turn a pixel to red
} else {
leds[i] = color(0, 0, 0); // or to black
}
}
}
if (progress >= 0.296 && progress <0.35){
float light_num = map(volume, 0.5, 1, 0, NUM_LEDS);
for (int i=0; i < NUM_LEDS; i++) {
if (i < light_num) {
leds[i] = color(20,83,246); // turn a pixel to red
} else {
leds[i] = color(0, 0, 0); // or to black
}
}
}
if (progress >= 0.35 && progress <0.403){
float light_num = map(volume, 0., 1, 0, NUM_LEDS);
for (int i=0; i < NUM_LEDS; i++) {
if (i < light_num) {
leds[i] = color(105,159,79); // turn a pixel to red
} else {
leds[i] = color(0, 0, 0); // or to black
}
}
}
if (progress >= 0.403 && progress <0.441){
//float light_num = map(volume, 0., 1, 0, NUM_LEDS);
frameRate(50);
// for (int i=0; i < NUM_LEDS; i++) {
// if (volume > 0.55){
// leds[i] = color(68,189,123);
// leds[i+1] = color(68,189,123);
// } else {
// leds[i] = color(0, 0, 0);
// leds[i+1]= color(0, 0, 0);
// }
// }
//}
if (volume > 0.55) {
if (ledIndex < NUM_LEDS - 1) {
leds[ledIndex] = color(68, 189, 123);
leds[ledIndex + 1] = color(68, 189, 123);
}
ledIndex += 4;
} else {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = color(0, 0, 0) ;
}
}
}
if (progress >= 0.441 && progress <0.482){
float light_num = map(volume, 0., 1, 0, NUM_LEDS);
for (int i=0; i < NUM_LEDS; i++) {
if (i < light_num) {
leds[i] = color(45,149,220); // turn a pixel to red
} else {
leds[i] = color(0, 0, 0); // or to black
}
}
}
if (progress >= 0.482 && progress <0.533){
float light_num = map(volume, 0., 1, 0, NUM_LEDS);
for (int i=0; i < NUM_LEDS; i++) {
if (i < light_num) {
leds[i] = color(93,192,59); // turn a pixel to red
} else {
leds[i] = color(0, 0, 0); // or to black
}
}
}
if (progress >= 0.531 && progress <0.65){
float light_num = map(volume, 0., 1, 0, NUM_LEDS);
for (int i=0; i < NUM_LEDS; i++) {
if (i < light_num) {
leds[i] = color(93,192,59); // turn a pixel to red
} else {
leds[i] = color(0, 0, 0); // or to black
}
}
}
if (progress >= 0.65 && progress <0.69){
float light_num = map(volume, 0., 1, 0, NUM_LEDS);
for (int i=0; i < NUM_LEDS; i++) {
if (i < light_num) {
leds[i] = color(29,137,95); // turn a pixel to red
} else {
leds[i] = color(0, 0, 0); // or to black
}
}
}
if (progress >= 0.65 && progress <0.69){
float light_num = map(volume, 0., 1, 0, NUM_LEDS);
for (int i=0; i < NUM_LEDS; i++) {
if (i < light_num) {
leds[i] = color(29,137,95); // turn a pixel to red
} else {
leds[i] = color(0, 0, 0); // or to black
}
}
}
if (progress >= 0.734 && progress <0.775){
float light_num = map(volume, 0., 1, 0, NUM_LEDS);
for (int i=0; i < NUM_LEDS; i++) {
if (i < light_num) {
leds[i] = color(187,90,48); // turn a pixel to red
} else {
leds[i] = color(0, 0, 0); // or to black
}
}
}
if (progress >= 0.775 && progress <0.817){
float light_num = map(volume, 0., 1, 0, NUM_LEDS);
for (int i=0; i < NUM_LEDS; i++) {
if (i < light_num) {
leds[i] = color(60,98,80); // turn a pixel to red
} else {
leds[i] = color(0, 0, 0); // or to black
}
}
}
if (progress >= 0.817 && progress <0.869){
float light_num = map(volume, 0., 1, 0, NUM_LEDS);
for (int i=0; i < NUM_LEDS; i++) {
if (i < light_num) {
leds[i] = color(320,100,69); // turn a pixel to red
} else {
leds[i] = color(0, 0, 0); // or to black
}
}
}
if (progress >= 0.869 && progress <0.967){
float light_num = map(volume, 0., 1, 0, NUM_LEDS);
for (int i=0; i < NUM_LEDS; i++) {
if (i < light_num) {
leds[i] = color(109,96,92); // turn a pixel to red
} else {
leds[i] = color(0, 0, 0); // or to black
}
}
}
if (progress >= 0.967 && progress <1){
float light_num = map(volume, 0., 1, 0, NUM_LEDS);
for (int i=0; i < NUM_LEDS; i++) {
if (i < light_num) {
leds[i] = color(189,109,49); // turn a pixel to red
} else {
leds[i] = color(0, 0, 0); // or to black
}
}
}
sendColors();// send the array of colors to Arduino
}
void keyPressed() {
if (key==' '){
if (isPlaying) {
sound.pause(); // Pause the music
} else {
sound.play(); // Resume playing
}
}
isPlaying = !isPlaying; // Update the playback status
}
void sendColors() {
byte[] out = new byte[NUM_LEDS*3];
for (int i=0; i < NUM_LEDS; i++) {
out[i*3] = (byte)(floor(hue(leds[i])) >> 1);
if (i == 0) {
out[0] |= 1 << 7;
}
out[i*3+1] = (byte)(floor(saturation(leds[i])) >> 1);
out[i*3+2] = (byte)(floor(brightness(leds[i])) >> 1);
}
serialPort.write(out);
}