RMS volume reporting back 4 to 5 dBs quieter than it should be ..?

I’m trying to implement a volume meter and getting the RMS values in the normal way.
But I look at the variables for rmsLevelRight and rmsLevelLeft and they seem to be reporting quieter than is true. I have my plugin open and showing the RMS on the right hand side, and Izotopes Insight showing the RMS on the left (same audio track). Insight is reporting consistently 4 to 5 Db louder than my plugin, which is accurate. Why the discrepency?

PluginProcessor.h
  juce::LinearSmoothedValue<float> rmsLevelLeft, rmsLevelRight;

PluginProcessor.cpp
prepareToPlay()
    rmsLevelLeft.reset(sampleRate, 0.5);    //half a second decay
    rmsLevelRight.reset(sampleRate, 0.5);
    rmsLevelLeft.setCurrentAndTargetValue(-100.f);
    rmsLevelRight.setCurrentAndTargetValue(-100.f);
processBlock()
    rmsLevelLeft.skip(buffer.getNumSamples());                       
    rmsLevelRight.skip(buffer.getNumSamples());
//I also tried .getNextValue() but range was even narrower 

    const auto volume_valueL = juce::Decibels::gainToDecibels(buffer.getRMSLevel(0, 0, buffer.getNumSamples()));    //Left channel first
    if (volume_valueL < rmsLevelLeft.getCurrentValue()) {
        rmsLevelLeft.setTargetValue(volume_valueL);             
    }
    else {
        rmsLevelLeft.setCurrentAndTargetValue(volume_valueL);   
    }
    const auto volume_valueR = juce::Decibels::gainToDecibels(buffer.getRMSLevel(1, 0, buffer.getNumSamples()));    //do right channel
    if (volume_valueR < rmsLevelRight.getCurrentValue()) {
        rmsLevelRight.setTargetValue(volume_valueR);              
    }
    else {
        rmsLevelRight.setCurrentAndTargetValue(volume_valueR);    
    }

float myplugin::getRMSValue(const int channel) const
{
    if (channel == 0)
        return rmsLevelLeft.getCurrentValue();
    if(channel == 1)
        return rmsLevelRight.getCurrentValue();
    return 0.f;
}```

Most rms meters work on a window of about 300-400ms. Does it become more accurate if you crank up your buffer size? I’d suggest a ring buffer to hold the desired window and just query the rms of that data store, rather than the current buffer, which could be any size.

1 Like

I am now feeding it a continuous tone - constant volume - over thirty seconds to test my plugin, …its at 0dB.

My DAW is correctly reporting a constant 0dB, Izotope Insight is also reporting 0dB. My plugin is reporting -3dB.
I turn the tone volume down to -15dB, … my DAW correctly reports -15, so does Insight. My plugin says -18dB.
My plugin seems like its always off by exactly -3dB.
I can adjust for that by simply adding 3dB, but its curious why my code above is producing the discrepancy.
I do the RMS calculations before I do any other processing in the processBlock()

The RMS of a sine wave is 0.707 times its peak value, which is indeed -3 dB.

1 Like

This is likely a combined rms situation. There are a few interpretations of how you should calculate a single rms value on multichannel audio, which could explain the difference?

1 Like

Unfortunately, AES has caused this confusion with their AES17 standard which is mathematically correct RMS plus 3 dB. You can turn AES17 on or off in most metering software.

Best,
Stian

2 Likes