I have created a circuit using an arduino that powers LED strips that listen to microphone inputs, and output the number of LEDs to light up depending on the noise level in the room. This works great for music etc.
My issue is that the output from the microphone is highly variable, and the LEDs are quite "flashy" in the sense that they respond too much to changes in decibel readings.
The levels I'm using are fine, and I'm happy with my gain settings.
The image above shows an example of a level meter (specifically for Logic Pro X). This level meter does the same as mine, however it has a "holding" period where the peak stays where it is and gradually drops off if the level reported by the audio is low.
This effect is important because it suits reduces the flashing between high and low volumes. Mine currently does not have this effect, which is why the LED's are so variable.
Does anyone know of any smoothing/fading methods I could investigate the use case of so my level meter doesn't appear so jumpy?
CodePudding user response:
Smoothing to make the readings less sporadic and gradually dropping the peak are two different effects commonly used in sound level meters like those on a graphic equalizer.
Smoothing can be pretty simple if you're reading a sensor at regular intervals. (You should probably check the datasheet to determine whether your sensor is already doing some filtering.) Instead of displaying the actual reading, you incorporate each reading into a weighted average, effectively making a low-pass filter.
current_reading = read_the_sensor();
value_to_display = k1 * value_to_display k2 * current_reading;
You choose two constants k1
and k2
such that k1 k2 == 1
and k1 > k2
. If you're working with integer arithmetic, you can approximate this by using integers for k1
and k2
and dividing the the result by their sum:
value_to_display = (k1 * value_to_display k2 * current_reading) / (k1 k2);
I usually start with values like k1 = 4
and k2 = 1
and adjust them until the displayed value feels right.
The falling peak effect can be accomplished in similar way.
if (value_to_display > peak) {
peak = value_to_display;
} else {
peak = k3 * peak / k4;
}
In this case, you want k3
to be slightly less than k4
, such as k3 = 9
and k4 = 10
. The exact values will depend on how frequently you're updating the values and how fast you want it to fall.
If the value is climbing, the peak rides it up. When the value drops, the peak will drop slowly.