Namespace: DadDSP::cVuMeter Files: cVuMeter.h / cVuMeter.cpp Directory: DAD_FORGE/DSP Description: VU meter class with peak detection, peak hold, and clipping monitoring for professional audio monitoring.
📋 Class Description
The cVuMeter class implements a complete audio level measurement system, inspired by traditional VU meters but with modern features essential for real-time DSP applications. It provides:
Smoothed RMS level measurement: Smooth level tracking with asymmetric attack and release
Peak detection with hold: Records maximum levels for a configurable duration (1 second)
Clipping monitoring: Automatic detection when signal exceeds 85% (-1.4 dB) with status held for 4 seconds
dB/percent conversion: Utility functions to display levels in decibels or percentage
Sample-rate configuration: Automatic coefficient adjustment according to sample rate
Typical Use Cases:
Audio monitoring in VST/AU plugins
Visual indicators for user interfaces (UI)
Overload detection and equipment protection
Spectral analysis and audio metrics
Limiters and compressors with visualization
🎯 Enumerations and Associated Structures
No associated enumerations or structures.
📚 Public Methods
cVuMeter (Constructor)
Element
Details
Method
cVuMeter()
Description
Default constructor that initializes the class without parameters. Parameters must be configured via the Init() method before use. The constructor is empty and does not configure any internal state.
Parameter(s)
None
Return
None (void)
Init
Element
Details
Method
void Init(float sampleRate)
Description
Fully initializes the VU meter with the specified audio sample rate. Calls reset() to initialize all internal states to their default values, then configures the sample rate which automatically calculates attack/release coefficients and hold counters in samples.
Parameter(s)
sampleRate
Audio sample rate in Hz (e.g., 44100, 48000). Used to calculate envelope coefficients and convert times to number of samples.
Return
None (void)
CalcPeakAndLevel
Element
Details
Method
void CalcPeakAndLevel(float input)
Description
Main processing method that calculates the current level, detects peaks, and monitors clipping from an audio sample. Applies asymmetric attack/release envelope for smooth level tracking, updates the peak level with hold for the configured duration, and detects if the signal exceeds the clipping threshold (85% = -1.4 dB) with status held for 4 seconds.
Parameter(s)
input
Input audio sample (float value between -1.0 and 1.0). The absolute value is used for level calculation.
Return
None (void)
getLevelPercent
Element
Details
Method
float getLevelPercent() const
Description
Returns the current audio level as a linear percentage between 0.0 and 1.0. Represents the smoothed RMS amplitude of the signal after attack/release envelope application. Useful for direct comparisons or simple mathematical calculations.
Parameter(s)
None
Return
Float value between 0.0 (silence) and 1.0 (maximum signal) representing the current level as linear percentage
getLevelDB
Element
Details
Method
float getLevelDB() const
Description
Returns the current audio level in decibels. Uses the standard logarithmic formula 20 * log10(linear) to convert linear amplitude to dB scale, with a minimum value of -45 dB to avoid infinite negative values. Useful for displaying conventional audio levels (e.g., -6 dBFS, -20 dBFS).
Parameter(s)
None
Return
Float value in decibels between -45.0 dB and 0.0 dB
getPeakPercent
Element
Details
Method
float getPeakPercent() const
Description
Returns the recorded peak level as a linear percentage between 0.0 and 1.0. Represents the maximum reached since the last reset or end of peak hold. Useful for displaying instantaneous peaks on a user interface.
Parameter(s)
None
Return
Float value between 0.0 and 1.0 representing the peak level as linear percentage
getPeakDB
Element
Details
Method
float getPeakDB() const
Description
Returns the recorded peak level in decibels. Converts the peak percentage to dB scale using the same logarithmic formula as getLevelDB(). Useful for displaying maximum reached peaks on a user interface or for overload alerts.
Parameter(s)
None
Return
Float value in decibels between -45.0 dB and 0.0 dB representing the maximum peak
getLevelPercentDB
Element
Details
Method
float getLevelPercentDB() const
Description
Returns the current level normalized within the [0.0, 1.0] range based on the configurable dB scale (-45 to -6 dB). First converts the level to dB, then linearly normalizes between the min and max bounds. Useful for displaying VU meters where 0% corresponds to -45 dB and 100% to -6 dB.
Parameter(s)
None
Return
Float value between 0.0 (-45 dB) and 1.0 (-6 dB) for normalized meter display
getPeakPercentDB
Element
Details
Method
float getPeakPercentDB() const
Description
Returns the peak level normalized within the [0.0, 1.0] range based on the configurable dB scale (-45 to -6 dB). First converts the peak to dB, then linearly normalizes between the min and max bounds. Useful for displaying peak levels on a VU meter where the range is explicitly defined.
Parameter(s)
None
Return
Float value between 0.0 (-45 dB) and 1.0 (-6 dB) for normalized meter display
isClipping
Element
Details
Method
bool isClipping() const
Description
Checks whether clipping is currently detected. Returns true if the signal has exceeded the 85% threshold (-1.4 dB) and the hold counter is not yet expired (4 seconds). Allows displaying red visual indicators or triggering protection actions.
Parameter(s)
None
Return
true if clipping is active, false otherwise
resetPeak
Element
Details
Method
void resetPeak()
Description
Manually resets the peak level to the current level and resets the peak hold counter to zero. Useful for synchronizing the meter with a specific audio event, or for forcing an immediate update of the peak display without waiting for the natural end of the hold period.
Parameter(s)
None
Return
None (void)
reset
Element
Details
Method
void reset()
Description
Resets all VU meter states to initial values. Resets current level and peak to 0.0, resets peak hold and clipping counters to zero, and disables the clipping flag. Must be called during initialization or to return the meter to a known state.
Parameter(s)
None
Return
None (void)
setSampleRate
Element
Details
Method
void setSampleRate(float sampleRate)
Description
Modifies the audio sample rate at runtime. Automatically recalculates all coefficients and counters based on the new sample rate, including the attack/release envelope and peak/clipping hold durations. Essential in systems with dynamic sample rate (VST plugins, etc.).
Parameter(s)
sampleRate
New sample rate in Hz (positive).
Return
None (void)
🔒 Protected / Private Methods
linearToDb
Member
Type
Description
linearToDb(float linear)
float
Utility conversion that transforms a linear amplitude value (0.0-1.0) into decibels. Uses the formula 20 * log10(linear) with a minimum bound of -45 dB to avoid infinite negative values. Protected method as it is only used by the class.
dbToPercent
Member
Type
Description
dbToPercent(float db)
float
Utility conversion that transforms a decibel value into percentage for meter display. Linearly normalizes between -45 dB (0%) and -6 dB (100%), with clamping to bounds. Protected method as it is only used by the class.
updateAttackRelease()
Member
Type
Description
updateAttackRelease()
void
Updates attack and release coefficients based on the sample rate. Also calculates the number of samples corresponding to peak hold times (1s) and clipping hold times (4s). Uses exponential formulas for natural transitions. Protected method as it is only called during initialization or sample rate changes.
🔒 Protected / Private Members
Member
Type
Description
m_sampleRate
float
Audio sample rate in Hz (default: 0). Used for all time calculations and conversion between time and number of samples.
m_currentLevel
float
Current signal level (default: 0.0). Represents the smoothed RMS amplitude after attack/release envelope application. Value between 0.0 and 1.0.
m_peakLevel
float
Signal peak level (default: 0.0). Represents the maximum reached with hold for the configured duration. Value between 0.0 and 1.0. Declines gradually at 0.999x per sample after peak hold time expires.
m_peakHoldCounter
uint32_t
Peak hold counter in samples (default: 0). Initialized to the total hold duration upon a new peak, decremented each sample. Controls how long the peak level remains held after a maximum is reached.
m_clipCounter
uint32_t
Clipping hold counter in samples (default: 0). Initialized to the total hold duration upon clipping detection, decremented each sample. Controls how long the clipping status remains active after the clipped signal ends.
m_clipActive
bool
Clipping detection flag (default: false). Indicates whether clipping is currently active or has been recently detected and the hold time has not expired.
m_peakHoldSamples
uint32_t
Peak hold duration in samples (default: calculated). Calculated as PEAK_HOLD_TIME * sampleRate (1 second × sample rate). Used to initialize the peak hold counter.
m_clipHoldSamples
uint32_t
Clipping hold duration in samples (default: calculated). Calculated as CLIP_HOLD_TIME * sampleRate (4 seconds × sample rate). Used to initialize the clipping hold counter.
m_attackCoeff
float
Attack coefficient for the envelope (default: calculated). Calculated using the formula 1 - exp(-1 / (ATTACK_TIME * sampleRate)). Controls the speed at which the current level rises toward a higher value. Typical value: 0.0067 at 48kHz.
m_releaseCoeff
float
Release coefficient for the envelope (default: calculated). Calculated using the formula 1 - exp(-1 / (RELEASE_TIME * sampleRate)). Controls the speed at which the current level falls toward a lower value. Typical value: 0.03 at 48kHz.
💡 Usage Example
#include"DadDSP/cVuMeter.h"usingnamespaceDadDSP;intmain(){// --- Scenario 1: Simple audio monitoring ---cVuMetervuMeter;// Initialize for 48kHz sample ratevuMeter.Init(48000.0f);floatinputSample=0.0f;floatcurrentLevel=0.0f;floatpeakLevel=0.0f;boolisClipped=false;// Process audio samplesfor(uint32_ti=0;i<48000;i++){// Example signal: A4 note (440Hz)inputSample=std::sin(2.0f*M_PI*440.0f*i/48000.0f);// Calculate level, peaks and clippingvuMeter.CalcPeakAndLevel(inputSample);// Retrieve values for displaycurrentLevel=vuMeter.getLevelPercent();// 0.0 - 1.0peakLevel=vuMeter.getPeakPercent();// 0.0 - 1.0isClipped=vuMeter.isClipping();// true/false// Display in dB (e.g., for a UI)floatlevelDb=vuMeter.getLevelDB();// e.g., -23.5 dBfloatpeakDb=vuMeter.getPeakDB();// e.g., -18.2 dB}// --- Scenario 2: Normalized VU meter display ---cVuMetermeterForDisplay;meterForDisplay.Init(48000.0f);for(uint32_ti=0;i<48000;i++){inputSample=std::sin(2.0f*M_PI*440.0f*i/48000.0f);meterForDisplay.CalcPeakAndLevel(inputSample);// Normalize for VU meter display (-45 dB to -6 dB)floatdisplayPercent=meterForDisplay.getLevelPercentDB();// Display: 0% = -45 dB, 100% = -6 dBprintf("VU Level: %.0f%% (%.2f dB)\n",displayPercent*100.0f,meterForDisplay.getLevelDB());}// --- Scenario 3: Clipping detection with alert ---cVuMeterclipDetector;clipDetector.Init(48000.0f);for(uint32_ti=0;i<48000;i++){// Signal that will exceed 0.70 (clipping)inputSample=std::sin(2.0f*M_PI*440.0f*i/48000.0f);clipDetector.CalcPeakAndLevel(inputSample);// Check for clippingif(clipDetector.isClipping()){printf("⚠️ CLIPPING DETECTED! Level: %.2f dB\n",clipDetector.getPeakDB());// Possible protection action:// - Reduce gain// - Activate a limiter// - Display a red LED}}// --- Scenario 4: Manual peak control ---cVuMetermanualControl;manualControl.Init(48000.0f);for(uint32_ti=0;i<48000;i++){inputSample=std::sin(2.0f*M_PI*440.0f*i/48000.0f);manualControl.CalcPeakAndLevel(inputSample);// Reset peak manually each sample// to display instantaneous current levelmanualControl.resetPeak();floatcurrent=manualControl.getLevelPercent();printf("Instant Level: %.2f%%\n",current*100.0f);}// --- Scenario 5: Dynamic sample rate adaptation ---cVuMeterdynamicRate;dynamicRate.Init(48000.0f);for(uint32_ti=0;i<48000;i++){inputSample=std::sin(2.0f*M_PI*440.0f*i/48000.0f);dynamicRate.CalcPeakAndLevel(inputSample);}// Change sample rate at runtime (e.g., VST plugin)dynamicRate.setSampleRate(96000.0f);// Switch to 96kHzfor(uint32_ti=48000;i<96000;i++){inputSample=std::sin(2.0f*M_PI*440.0f*i/96000.0f);dynamicRate.CalcPeakAndLevel(inputSample);}// --- Scenario 6: Multi-channel stereo monitoring ---cVuMeterleftChannel,rightChannel;leftChannel.Init(48000.0f);rightChannel.Init(48000.0f);floatleftInput=0.0f,rightInput=0.0f;for(uint32_ti=0;i<48000;i++){// Stereo signalleftInput=std::sin(2.0f*M_PI*440.0f*i/48000.0f);rightInput=std::cos(2.0f*M_PI*440.0f*i/48000.0f);leftChannel.CalcPeakAndLevel(leftInput);rightChannel.CalcPeakAndLevel(rightInput);// Display stereo levelsprintf("L: %.2f%% (%.2f dB) | R: %.2f%% (%.2f dB)\n",leftChannel.getLevelPercent()*100.0f,leftChannel.getLevelDB(),rightChannel.getLevelPercent()*100.0f,rightChannel.getLevelDB());}// Full reset if necessaryleftChannel.reset();rightChannel.reset();return0;}
📊 Default Configuration
Parameter
Value
Description
PEAK_HOLD_TIME
1.0s
Duration peaks are held after being reached
CLIP_THRESHOLD
0.70 (-1.4 dB)
Clipping detection threshold (85% of maximum)
CLIP_HOLD_TIME
4.0s
Duration clipping status remains active
DB_MIN
-45.0 dB
Minimum for dB conversion (avoids -∞)
DB_MAX
-6.0 dB
Maximum for meter normalization
ATTACK_TIME
0.15s
Envelope attack time (fast response)
RELEASE_TIME
0.30s
Envelope release time (slow response)
📊 Retrieval Method Comparison
Method
Returns
Range
Typical Use
getLevelPercent()
Linear percentage
0.0 - 1.0
Simple mathematical calculations
getLevelDB()
Decibels
-45.0 dB - 0.0 dB
Conventional audio display
getPeakPercent()
Linear peak percentage
0.0 - 1.0
UI peak indicators
getPeakDB()
Peaks in decibels
-45.0 dB - 0.0 dB
Overload alerts, monitoring
getLevelPercentDB()
Normalized meter percentage
0.0 - 1.0
VU meter display (-45 to -6 dB)
getPeakPercentDB()
Normalized peak percentage
0.0 - 1.0
VU meter peak indicators
📊 Clipping State Comparison
State
Condition
Behavior
No clipping
level < 0.70
isClipping() returns false
Clipping detected
level >= 0.70
isClipping() becomes true, counter initialized to 4s
Clipping held
counter > 0
isClipping() remains true during hold period
Return to normal
counter == 0
isClipping() becomes false
⚙️ Implementation Notes
Asymmetric Envelope: Attack is fast (0.15s) to track peaks quickly, while release is slower (0.30s) to avoid rapid fluctuations and provide stable reading. Coefficients are calculated using exponential formulas: coeff = 1 - exp(-1 / (time × sampleRate)).
Peak Hold: When a new peak is detected, the counter is initialized to the total hold duration (1 second). On each subsequent sample, the counter decrements. If the current level still exceeds the peak, the counter is reset. Once the counter reaches zero, the peak declines gradually by a factor of 0.999x per sample.
Clipping Detection: The 0.70 threshold (-1.4 dB) corresponds to 85% of the numerical maximum, a common value for early overload detection before actual clipping (0.0). The status remains active for 4 seconds after the clipped signal ends to avoid rapid blinking.
Logarithmic Conversion: The conversion to dB uses 20 * log10(linear) which is the standard formula for sound pressure and audio levels. The minimum bound of -45 dB avoids infinite negative values for silence.
Meter Normalization: The getLevelPercentDB() and getPeakPercentDB() methods linearly normalize between -45 dB (0%) and -6 dB (100%), which corresponds to a typical monitoring dynamic range where -6 dB is considered “hot” but not clipping.
Sample Rate Adaptation: All coefficients and counters are dynamically recalculated during sample rate changes, allowing use in VST/AU plugins with sample rate conversion.
Absolute Value: The CalcPeakAndLevel() method uses std::abs(input) to process level independently of signal polarity, which is correct for an RMS/VU meter.
Clamping: Input values are clamped to [0.0, 1.0] before processing to avoid artifacts from out-of-range samples.
DAD_FORGE/DSP - Dad Design DSP Library Copyright (c) 2024-2026 Dad Design.