How to implement moving thresholds for music visualisation with neopixel?

Hi there,

I´m trying to control a neopixel ring so that it reacts to music.

My current setup looks like this:
For the controllor I´m using a NodeMCU ESP8266, the music gets analyzed by a breakout board with a MSGEQ7 chip, which filters the incoming frequencies with 7 filters from low frequency to high, and puts out a value from 0-1024 based on the current strength for each frequency band.

The code that I wrote up to this point takes every band and checks if the current reading exceeds a set threshold, if that is the case a set of pixels on the ring lights up in a color of my choice and starts to fade back to black if the next reading is below the threshold. This kinda works and looks surprisingly nice, but only at a certain volume. When the volume is increased, the readings of each band increase with it, so at some point all leds are just constantly fully light, because the readings are then always above the threshold.

My current plan is to design a function that dynamicly adjusts the threshold according to the strength (value) of each band, so that the threshold gets heightened when the volume increases, and lowers when it decreases. Right now I have to manually find the right volume on each device (PC, Smartphone etc.) I tried it with manually, but I want it to be independent of the device and set itself according to the current audio level right away.

Can someone help me find a solution for this or has dealt with something like this too?

I would be very glad if you could help me.

I have done something similar... I save a "loudness" sample once per second in a 20-element (20 second) circular buffer. Then depending on the effect I'll use the average* or the peak from that array as my threshold or reference. I made a "VU meter" effect where the bottom of the meter is the average and the top is the peak.

Take a look at my [u]World's Simplest Lighting Effect[/u] that turns an LED (or light) on when it's louder than average and off when below average. The LED/light is on half of the time and off half of the time for lots of "lighting action" no-matter what the volume.

20 seconds is just a number I chose. It seems to be quick enough to adjust to loud & quiet songs, but slow enough that it doesn't get totally fouled-up by gaps between songs, or by fade-ins and fade-outs.

  • In my application I'm not taking a true-average. It's an average of the "randomly" sampled peaks. But, the whole thing works off peaks so it works fine. Also, the peak value in the array is "the" true-peak, it's just the biggest peak value I happened to sample/save.

Another solution is to use an AGC ( Automatic Gain Control ) amplifier sometimes called a Vogad amplifier. Basically it produces a fixed output signal for a wide range of input signals. The gain is automatically adjusted so that the output is always the same.