#pragma once #include namespace rack { namespace dsp { /** Deprecated. Use VuMeter2 instead. */ struct VuMeter { /** Decibel level difference between adjacent meter lights */ float dBInterval = 3.0; float dBScaled; /** Value should be scaled so that 1.0 is clipping */ void setValue(float v) { dBScaled = std::log10(std::fabs(v)) * 20.0 / dBInterval; } /** Returns the brightness of the light indexed by i. Light 0 is a clip light (red) which is either on or off. All others are smooth lights which are fully bright at -dBInterval*i and higher, and fully off at -dBInterval*(i-1). */ float getBrightness(int i) { if (i == 0) { return (dBScaled >= 0.0) ? 1.0 : 0.0; } else { return math::clamp(dBScaled + i, 0.0, 1.0); } } }; DEPRECATED typedef VuMeter VUMeter; /** Models a VU meter with smoothing. Supports peak and RMS (root-mean-square) metering. Usage example for a strip of lights with 3dB increments: ``` // Update VuMeter state every frame. vuMeter.process(deltaTime, output); // Iterate lights every ~512 frames (less than a screen refresh). for (int i = 0; i < 6; i++) { float b = vuMeter.getBrightness(-3.f * (i + 1), -3.f * i); // No need to use setSmoothBrightness() since VuMeter2 smooths the value for you. lights[i].setBrightness(b); } ``` */ struct VuMeter2 { enum Mode { PEAK, RMS }; Mode mode = PEAK; /** Either the smoothed peak or the mean-square of the brightness, depending on the mode. */ float v = 0.f; /** Inverse time constant in 1/seconds */ float lambda = 30.f; void reset() { v = 0.f; } void process(float deltaTime, float value) { if (mode == RMS) { value = std::pow(value, 2); v += (value - v) * lambda * deltaTime; } else { value = std::fabs(value); if (value >= v) { v = value; } else { v += (value - v) * lambda * deltaTime; } } } /** Returns the LED brightness measuring tick marks between dbMin and dbMax. For example, `getBrightness(-6.f, 0.f)` will be at minimum brightness at -6dB and maximum brightness at 0dB. Set dbMin == dbMax == 0.f for a clip indicator that turns fully on when db >= dbMax. Expensive, so call this infrequently. */ float getBrightness(float dbMin, float dbMax) { float db = amplitudeToDb((mode == RMS) ? std::sqrt(v) : v); if (db >= dbMax) return 1.f; else if (db <= dbMin) return 0.f; else return math::rescale(db, dbMin, dbMax, 0.f, 1.f); } }; } // namespace dsp } // namespace rack