Dance party light:Adressable led strip controlled by software soundwave analyser


I'm trying to figure out how I can make sound-reactive adressable led strip lighting for a dance party. I am aware of the projects already out there that use a physical oscilloscope or a microphone in order to do this.

I am wondering if this is possible with a software soundwave analyzer instead of the physical oscilloscope. The microphone option is not possible as the music will be loud, and there will be sound pollution.

The music is being played through a Traktor control s4 controller, which supplies audio via RCA output to amplifiers. I can rout the sound through the sound card of the laptop the Trakor is connected with, as well as the RCA output. Perphaps this laptop can have a software soundwave analyzer, that can communicate with an Arduino, which in turn can control the led strip. The LED strip will have a WS2812b or similar interface.

Thanks in advance!

An oscilloscope is a time-domain instrument. It has a small display (unless you get a computer-based 'scope and plug-in a big monitor). It will show the waveform, which gets boring after a couple of minutes...

A spectrum analyzer is a frequency-domain instrument which gives you a more interesting display. You don't want a measurement instrument, but you CAN make an interesting spectrum analyzer-like effect.

The Arduino's default analog-to-digital converter's range is 0 to +5VDC. That's 5V peak-to-peak which just about right for a line-line audio signal (or a headphone-level signal) but audio signals are AC so the input has to be biased.

If you wanted to use a microphone (a few millivolts) you need a preamp. You can buy microphone boards with a microphone, preamp, and the required biased-output, but it's usually better to use a direct connection so you're not picking-up room noise.

There is a very-handy chip called the [u]MSGEQ7[/u]. It takes the audio signal, filters it into 7 frequency bands and gives you 7 DC signals, multiplexed so you can read all 7 bands with one Arduino analog input. For stereo you can use 2 MSGEQ7's and 2 analog inputs. (The chip is mis-named a "graphic equalizer chip", which it is NOT.)

With all of the "hard work" done in hardware, all your software has to do is take those 7 readings and control the display. (If you want less than 7 bands/channels you can combine or ignore some of the bands).

If you want more frequency bands there are [u]FFT[/u] and FHT libraries to the frequency analysis in software.

If you are NOT using the MSGEQ7 (or other circuitry), you'll need to [u]bias[/u] the input (2 equal-value resistors and a capacitor). This is because the Arduino can't read the negative-half of the AC audio signal. In fact, the Arduino can be damaged by negative voltages and or it can "damage" (distort) the negative half of the audio signal.

Thanks for your answer. I think I haven't made myself clear. What I'm trying to make is this, without a physical oscilloscope.

I would like a software oscilloscope, or any kind of software that can somehow analyse the signal, to supply data to the arduino, with which it can control the LED strip.

Is that possible?

I watched part of the video without the sound because... Shhhh…. I'm at work...

The 'scope is just a tool. It's not part of his lighting effect. Most of us are hobbyists and we don't own a 'scope. I use them at work but I don't have one at home. ...I brought a hobby-project to work once so I could use one. I've lusted for one, but I've never "needed one" badly enough to spend the money and I wouldn't use it that often so it would mostly be taking-up space, and I've got too much "junk" taking-up space already! (And that one time I brought something from home, it wasn't something I needed to do... It was just something that was interesting to check.)

So... Where are you at with your project? Do you have some LED strips and an Arduino? And, can you "program" some light-patterns (without the sound)? That might be a good place to start.

When is this party?

Or to get you started, when I get home this evening (California time) I'll post some code for "The worlds simplest effect". It's a "flicker effect" that flashes the LED (or light) on when the signal is above average and off when it's below average.

I've done some lighting effects in the past but the computer I was using for that crashed and it wasn't backed up, so I lost all of that code (Of course, the effects still run.)

But, I've been working on some new ideas and I started over again with the "simplest effect".

It's not that interesting so I classify it as a "special effect". It's not a "main effect" that you want to "run all night". But, I do use a real version of it with some variation and 2 floodlights (controlled with solid state relays). For example, sometimes the 2 floods operate together. Sometimes it's inverted so the lights flicker-on when the sound is below average, and sometimes one lamp is inverted so they operate oppositely with one coming-on whenever the other goes-off.

With your LED strips you could very-simply do some color variations or make a "wave effect", etc, just using that above/below average concept.

Or, instead of just above/below average you can make multiple thresholds and make a "VU meter" effect. ...That's another of my older effects. My VU meter effect (and all of my effects) use the same-basic moving-average concept for lots of lighting-action with quiet or loud songs and with volume changes.

“Worlds Simplest Effect”

You’ll need the bias circuit for this, or almost any effect.

Ideally the bias will read 512 but for best results run the Read Analog Serial Example with no audio signal to get the actual bias and change the Bias variable.

It blinks/flickers the built-in pin 13 LED so all you all you need is the bias circuit on the input an a USB cable to load the program and power the Arduino. It’s really just a test-demonstration project but you can optionally connect a solid state relay to control an incandescent lamp, or you can wire-up a driver circuit for a “regular” LED strip, or you can modify the program to run your NeoPixels.

// SimplestEffect.ino
// "World's simplest" sound activated lighting effect
// Flickers the built-in pin-13 LED with the sound.  
// The LED flashes-on when the signal is above the moving average and off when below average.
// The LED is on half of the time for a good effect with loud or quiet songs.
// Works with a line-level or headphone-level signal.
// As usual, the input is biased at Vcc/2 for a reading of ~512 with no signal.
// Also works with most microphone boards that have amplified & biased outputs.
// Do NOT connect a "speaker" output as these can exceed the 0-5V limits and fry the Arduino
// It uses a 20-second moving average.  This array contains 20 "sampled" Max readings, not "the" maximum and not "the average".
// 20 seconds allows it to automatically adjust/calibrate to volume changes without getting out of calibration between songs. 
// With music or other "program material" wait 20 seconds for it to self-calibrate.
// Reads input A0

// Global Variables
int Bias = 512;                           //Nominally half of the 1023 range = 512.  Adjust as necessary
int NoiseThreshold = 6;                   //Increase to minimize false triggers with silence or background noise
int Analog;                               // The analog reading (with the bias subtracted-out)
int Max;                                  // The waveform peak over a short period of time
int Average;                              // A "sampled" moving average of Max values used as the LED-on threshold (not the true-average).

unsigned long ReadStartTime;             //millis() used to set time
int SampleTime = 50;                     //Sample for short time to find waveform peak 
unsigned long ArrayStartTime;            //millis() again 
int ArrayTime = 1000;                    //Update array once per second 

const int ArraySize = 20;                // 20 values in the moving-average array
int ArrayIndex = 0;                      // Index/pointer
int AverageArray[ArraySize];             // Saves a sample of 20 Max values for averaging

//Function prototype
int UpdateAverage(int Max);               //UpdateAverage() function prototype

void setup()
  pinMode(LED_BUILTIN, OUTPUT);        // initialize digital pin LED_BUILTIN as an output.

  for(int i = 0; i < 20; i++)
    AverageArray[i] = 0;              //initialize the array with zeros 

// Start main loop ============================================================================================
void loop()
  Max = 0;                                  //Initilize/reset before running while() loop
  ReadStartTime = millis();                 //Save/update loop-starting time

  // Find waveform peak loop ==================================================================================
  // Takes readings in a "fast loop" to find the waveform peak.
  // At 20Hz a half-cycle is 25mS, so 25ms is the minimum time to find the peak (at deep bass frequencies).
  // A longer sample of about 100mS may work better with incancescant lamps (allowing the light to reach full-brightness).  
  while (millis() - ReadStartTime < SampleTime)
    Analog = abs(analogRead(A0) - Bias);                 // Read, take out the 2.5V bias/offset, make positive. 

    if (Analog > Max)                                    //Find Max before exiting loop 
      Max = Analog; 
  }// End waveform peak loop ==================================================================================

  //TURN THE LED ON/OFF =================================================================================== 
  if (Average < NoiseThreshold)             // Make sure LED is off with silence or background noise
    Average = NoiseThreshold;         

  if(Max > Average)                         //If the latest Max reading is > average, turn-on the LED
    digitalWrite(LED_BUILTIN, HIGH);        //Turn the LED on
    digitalWrite(LED_BUILTIN, LOW);         //Turn the LED off

  if (millis() - ArrayStartTime > ArrayTime)  // Time to update array?
    Average = UpdateAverage(Max);            // Call the UpdateAverage() function once per second
}  // End of main loop ==========================================================================================

// UpdateAverage() function =================================================================================
// Takes-in latest Max reading, updates the array, returns the average
int UpdateAverage(int Max) 
  int Sum = 0;    // Inialize/reset Sum before calculating average
  AverageArray[ArrayIndex] = Max;                //Update one array element with the latest Max 

  for(int i = 0; i < 20; i++)                    //Sum-up the data in the array
    Sum = Sum + AverageArray[i];  

  Average = Sum/20;                              // Find average of the saved Max values

  ArrayIndex++;                                  //Next index for next time
  if (ArrayIndex > 19)
    ArrayIndex = 0;                              //Back to the beginning of the circuar buffer

  //Print information (Optional, once per second for testing/debugging)
  //Serial.print (" Average = ");
  //Serial.print (Average);
  //Serial.print (" Max = ");
  //Serial.println (Max);
  ArrayStartTime = millis();                     //New Array Start Time  
  return Average;        
} // End UpdateAverage() ====================================================================================

Audio Input Schematic.png

Wow DVDdoug, thanks for your replies!

The party is at the 13th of november. I have ordered an arduino uno r3, some electrical components, and an LED adressable WS 2812 strip. I can solder and have some basic programming skills. I have never worked with any kind of microcontroller.

I think I can rout the audio through the s4, and the laptop it is connected to at the same time. The S4 will be connected to amplifiers. The 3,5mm audio port of the laptop can be connected to something else.

Some kind of frequency spectrum analyzer would be perfect. If I can set thresholds for a couple of frequency bands, and make LED's do something when the threshold for that frequency band is reached, we probably have a nice reactive effect going!

There are a couple of things I'm struggling with in order to achieve this.

-That chip you mentioned. Is it suitable for this task? -How would I connect the 3,5 mm jack to it? -How many LED's can one arduino control? Ideally I would have one arduino countrol 8 strips of 5 meter each, with 30 LED's per meter. I can use a seperate power supply to power the LED strip.

(There are probably more things I will get stuck at, but for now this is it)

If I can set thresholds for a couple of frequency bands, and make LED's do something when the threshold for that frequency band is reached, we probably have a nice reactive effect going!

…-That chip you mentioned. Is it suitable for this task?

Yes. It has 7 bands but you don't have to use them all. The color organs in the 1970s typically had 3 bands with red, blue, and green lights. You can so similar things with RGB LEDs but with all 3 colors coming from the same LED you can (optionally) combine for an unlimited number of colors.

I've never used it. All of my lighting effects work from the volume or "beat". There have been reports of trouble with MSGEQ7 and it's apparently no longer being made. See [u]this post[/u] or search the forum for "MSGEQ7".

, which supplies audio via RCA output to amplifiers...

…-How would I connect the 3,5 mm jack to it?

Typically, you start with an appropriate [u]Y-splitter[/u] so you can keep your amplifiers connected. Then you can solder a mating connector, or chop one end off an existing cable.

Or, you can make pass-through connectors on your lighting effect - Plug your Trackor into the lighting effect box, and also plug your amplifier into the lighting effect.

Then connect to the input of the MSGEQ7 chip, or an analog input on the Arduino.

-How many LED's can one arduino control? Ideally I would have one arduino countrol 8 strips of 5 meter each, with 30 LED's per meter.

It's virtually unlimited. They are serially addressed/controlled so the Arduino is actually only "talking to" the 1st one. (You could potentially run out of memory depending on how your software works.)

I can use a seperate power supply to power the LED strip.

They are serially addressed/controlled so that's a good idea. It doesn't have to be separate but there's a current limit if you try to power through the Arduino, so if you use a single supply, the LED strip(s) and the Arduino should have separate connections to the power supply.

Adafruit has a [u]NeoPixel Guide[/u].