Need some help with making a VU Meter with a slow release time

Hey hey,

So I trying to make something that resembles a VU meter. Essentially it’s a component that depending on how strong the output signal is will animate faster or slower. I already have the animation parameters figured out, but Im having some trouble with the math.

So right now in my AudioProcessor::processBlock Method, Im calling a method which gets the RMS value of the block (found on the JUCE forum). I cast this to a variable, and then in my Editor, I have a timer which just gets the variable from the processor.

T getRMSLevel (dsp::AudioBlock<T> block, int channel, int startSample, int numSamples) noexcept


jassert (isPositiveAndBelow (channel, block.getNumChannels()));
jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= block.getNumSamples());

if (numSamples <= 0 || channel < 0 || channel >= block.getNumChannels() || block.getNumSamples() == 0)
     return T(0);

auto* data = block.getChannelPointer(channel) + startSample;

double sum = 0.0;

for ( int i = 0; i < numSamples; ++i)
     auto sample = data[i];
     sum += sample * sample;

return static_cast <T> (std::sqrt (sum / numSamples));


Now, this works okay, but I get pretty jumpy results, especially since the editor only calls 30 times a second compared the the hundreds of RMS outputs being generated by the processor. Because of this, Im looking for my animating component to have a more averaged value of many RMS block values, or what I think would essentially be a VU meter with a slower release. My main inclination is to make like a FIFObuffer with a size that would represent my ‘release’ time in the processor, average the FIFObuffer, and then send the result to my editor? Maybe that is the correct way to do it, but I just feel a little lost if anyone has some advice. Thanks in advance!

a common solution is to only “jump” for greater values and smooth for lower:

float current_amp = 0; // member of your editor

// Before your graphics
float new_amp = processor.get_current_whatever_amp

if (new_amp > current_amp) {
    current_amp = new_amp
} else {
    current_amp *= 0.95 // Smooth Release

// Now your graphics
float db = Decibels::gainToDecibels(current_amp)

// Blah Blah Blah

This seems like a much more sensible solution than what I was thinking lol, off to go implement this !

1 Like