commit 0dd5802890781b0ba6227b244e11f6f018da31c3
parent 4e54bc3a48b7745587485ae6c966c6b82c1e6a3d
Author: Matt Demanett <matt@demanett.net>
Date: Sun, 14 Jul 2019 00:26:31 -0400
Add peak meters (or something like) to VU. #50
Diffstat:
M | src/VU.cpp | | | 76 | ++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ |
M | src/VU.hpp | | | 15 | +++++++++++++-- |
2 files changed, 65 insertions(+), 26 deletions(-)
diff --git a/src/VU.cpp b/src/VU.cpp
@@ -2,24 +2,54 @@
#include "VU.hpp"
void VU::onSampleRateChange() {
- _lRms.setSampleRate(APP->engine->getSampleRate());
- _rRms.setSampleRate(APP->engine->getSampleRate());
+ float sr = APP->engine->getSampleRate();
+ _lRms.setSampleRate(sr);
+ _rRms.setSampleRate(sr);
+ _lPeakRms.setSampleRate(sr);
+ _rPeakRms.setSampleRate(sr);
+ _lPeakSlew.setParams(sr, 750.0f, 1.0f);
+ _rPeakSlew.setParams(sr, 750.0f, 1.0f);
}
void VU::process(const ProcessArgs& args) {
- float left = 0.0f;
+ float left = inputs[L_INPUT].getVoltage();
float right = 0.0f;
- if (inputs[L_INPUT].isConnected()) {
- left = inputs[L_INPUT].getVoltage();
- }
if (inputs[R_INPUT].isConnected()) {
right = inputs[R_INPUT].getVoltage();
}
else {
right = left;
}
+
_lLevel = _lRms.next(left) / 5.0f;
_rLevel = _rRms.next(right) / 5.0f;
+
+ float lPeak = _lPeakRms.next(fabsf(left)) / 5.0f;
+ if (lPeak < _lPeakLevel) {
+ if (!_lPeakFalling) {
+ _lPeakFalling = true;
+ _lPeakSlew._last = _lPeakLevel;
+ }
+ lPeak = _lPeakSlew.next(lPeak);
+ }
+ else {
+ _lPeakFalling = false;
+ }
+ _lPeakLevel = lPeak;
+
+ float rPeak = _rPeakRms.next(fabsf(right)) / 5.0f;
+ if (rPeak < _rPeakLevel) {
+ if (!_rPeakFalling) {
+ _rPeakFalling = true;
+ _rPeakSlew._last = _rPeakLevel;
+ }
+ rPeak = _rPeakSlew.next(rPeak);
+ }
+ else {
+ _rPeakFalling = false;
+ }
+ _rPeakLevel = rPeak;
+
outputs[L_OUTPUT].setVoltage(left);
outputs[R_OUTPUT].setVoltage(right);
}
@@ -43,25 +73,15 @@ struct VUDisplay : OpaqueWidget {
}
void draw(const DrawArgs& args) override {
- float lDb = 0.0f;
- float rDb = 0.0f;
+ float lDb = -100.0f;
+ float rDb = -100.0f;
+ float lPeakDb = -100.0f;
+ float rPeakDb = -100.0f;
if (_module) {
- lDb = _module->_lLevel;
- rDb = _module->_rLevel;
- }
-
- if (lDb > 0.0f) {
- lDb = amplitudeToDecibels(lDb);
- }
- else {
- lDb = -100.0f;
- }
-
- if (rDb > 0.0f) {
- rDb = amplitudeToDecibels(rDb);
- }
- else {
- rDb = -100.0f;
+ lDb = amplitudeToDecibels(_module->_lLevel);
+ rDb = amplitudeToDecibels(_module->_rLevel);
+ lPeakDb = amplitudeToDecibels(_module->_lPeakLevel);
+ rPeakDb = amplitudeToDecibels(_module->_rPeakLevel);
}
nvgSave(args.vg);
@@ -72,6 +92,10 @@ struct VUDisplay : OpaqueWidget {
nvgRect(args.vg, 3, i + 1, 5, 4);
nvgFillColor(args.vg, bgColor);
nvgFill(args.vg);
+ if (lPeakDb > l.db && lPeakDb < l.db + 2.0f) {
+ nvgFillColor(args.vg, nvgRGBA(0x00, 0xdd, 0xff, 0xff));
+ nvgFill(args.vg);
+ }
if (lDb > l.db) {
nvgFillColor(args.vg, l.color);
nvgFill(args.vg);
@@ -81,6 +105,10 @@ struct VUDisplay : OpaqueWidget {
nvgRect(args.vg, 10, i + 1, 5, 4);
nvgFillColor(args.vg, bgColor);
nvgFill(args.vg);
+ if (rPeakDb > l.db && rPeakDb < l.db + 2.0f) {
+ nvgFillColor(args.vg, nvgRGBA(0x00, 0xdd, 0xff, 0xff));
+ nvgFill(args.vg);
+ }
if (rDb > l.db) {
nvgFillColor(args.vg, l.color);
nvgFill(args.vg);
diff --git a/src/VU.hpp b/src/VU.hpp
@@ -35,11 +35,22 @@ struct VU : Module {
float _lLevel = 0.0f;
float _rLevel = 0.0f;
+ RunningAverage _lPeakRms;
+ RunningAverage _rPeakRms;
+ bogaudio::dsp::SlewLimiter _lPeakSlew;
+ bogaudio::dsp::SlewLimiter _rPeakSlew;
+ float _lPeakFalling = 0.0f;
+ float _rPeakFalling = 0.0f;
+ float _lPeakLevel = 0.0f;
+ float _rPeakLevel = 0.0f;
+
VU() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
onSampleRateChange();
- _lRms.setSensitivity(0.05f);
- _rRms.setSensitivity(0.05f);
+ _lRms.setSensitivity(1.0f);
+ _rRms.setSensitivity(1.0f);
+ _lPeakRms.setSensitivity(0.025f);
+ _rPeakRms.setSensitivity(0.025f);
}
void onSampleRateChange() override;