commit f26b74d0bcb5b667d8b9b65b325f9ac748fb7c80
parent 2e846b3adc0cff68a327c3e961ba5e719a4e7199
Author: Matt Demanett <matt@demanett.net>
Date: Wed, 9 May 2018 00:31:25 -0400
VU meter module; revisions to VCAmp.
Diffstat:
10 files changed, 341 insertions(+), 23 deletions(-)
diff --git a/res-src/VCAmp-src.svg b/res-src/VCAmp-src.svg
@@ -35,7 +35,6 @@
<symbol id="sliderguide-db" viewBox="0 0 20px 183px">
<g transform="translate(0 6.5)">
<polyline points="0,0 5,0" stroke="#333" fille="none" transform="translate(11 0)" />
- <!-- <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-4 2.2)">12</text> -->
</g>
<g transform="translate(0 20.67)">
<polyline points="0,0 5,0" stroke="#333" fille="none" transform="translate(11 0)" />
@@ -57,18 +56,12 @@
<polyline points="0,0 5,0" stroke="#333" fille="none" transform="translate(11 0)" />
<text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-7 2.2)">-24</text>
</g>
- <g transform="translate(0 119.83)">
- <!-- <polyline points="0,0 5,0" stroke="#333" fille="none" transform="translate(11 0)" /> -->
- <!-- <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-7 2.2)">-36</text> -->
- <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-10 2.2)">- dB -</text>
- </g>
<g transform="translate(0 148.17)">
<polyline points="0,0 5,0" stroke="#333" fille="none" transform="translate(11 0)" />
<text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-7 2.2)">-48</text>
</g>
- <g transform="translate(0 176.5)">
- <polyline points="0,0 5,0" stroke="#333" fille="none" transform="translate(11 0)" />
- <!-- <text font-size="5.0pt" transform="translate(7 0) rotate(-90) translate(-5 2.2)">-∞</text> -->
+ <g transform="translate(0 170)">
+ <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-9 6)">dB</text>
</g>
</symbol>
diff --git a/res-src/VU-src.svg b/res-src/VU-src.svg
@@ -0,0 +1,145 @@
+<svg
+ version="1.1"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ width="45"
+ height="380"
+ viewBox="0 0 45 380"
+>
+ <style>
+ text {
+ fill: #333;
+ font-family: 'Roboto', sans-serif;
+ font-weight: bold;
+ }
+ text.title {
+ font-family: 'Comfortaa', sans-serif;
+ font-weight: normal;
+ }
+ text.brand {
+ font-family: 'Audiowide', sans-serif;
+ font-weight: bold;
+ }
+ </style>
+
+ <defs>
+ <symbol id="vu" viewBox="0 0 18px 180px">
+ <!-- <rect width="18" height="180" x="0" y="0" rx="0" fill="#ccc" /> -->
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(3 0)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(10 0)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(3 15)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(10 15)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(3 30)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(10 30)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(3 45)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(10 45)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(3 60)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(10 60)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(3 75)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(10 75)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(3 90)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(10 90)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(3 105)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(10 105)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(3 120)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(10 120)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(3 135)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(10 135)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(3 150)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(10 150)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(3 165)" />
+ <rect width="5" height="13" x="0" y="1" rx="0" fill="#aaa" transform="translate(10 165)" />
+ </symbol>
+
+ <symbol id="guide-db" viewBox="0 0 20px 183px">
+ <g transform="translate(0 15)">
+ <polyline points="0,0 3,0" stroke="#333" fille="none" transform="translate(11 0)" />
+ <text font-size="6.0pt" transform="translate(7 0) rotate(0) translate(-2.5 2.6)">6</text>
+ </g>
+ <g transform="translate(0 30)">
+ <polyline points="0,0 3,0" stroke="#333" fille="none" transform="translate(11 0)" />
+ <text font-size="6.0pt" transform="translate(7 0) rotate(0) translate(-2.5 2.6)">0</text>
+ </g>
+ <g transform="translate(0 45)">
+ <polyline points="0,0 3,0" stroke="#333" fille="none" transform="translate(11 0)" />
+ <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-4 2.2)">-6</text>
+ </g>
+ <g transform="translate(0 60)">
+ <polyline points="0,0 3,0" stroke="#333" fille="none" transform="translate(11 0)" />
+ <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-7 2.2)">-12</text>
+ </g>
+ <g transform="translate(0 90)">
+ <polyline points="0,0 3,0" stroke="#333" fille="none" transform="translate(11 0)" />
+ <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-7 2.2)">-24</text>
+ </g>
+ <g transform="translate(0 120)">
+ <!-- <polyline points="0,0 5,0" stroke="#333" fille="none" transform="translate(11 0)" /> -->
+ <!-- <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-7 2.2)">-36</text> -->
+ <!-- <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-10 2.2)">- dB -</text> -->
+ </g>
+ <g transform="translate(0 150)">
+ <polyline points="0,0 3,0" stroke="#333" fille="none" transform="translate(11 0)" />
+ <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-7 2.2)">-48</text>
+ </g>
+ <g transform="translate(0 170)">
+ <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-9 4.5)">dB</text>
+ </g>
+ </symbol>
+
+ <symbol id="input" viewBox="0 0 24px 24px">
+ <g transform="translate(12 12)">
+ <circle cx="0" cy="0" r="5" stroke-width="1" stroke="#0f0" fill="#0f0" />
+ <circle cx="0" cy="0" r="10.5" stroke-width="3" stroke="#0f0" fill="none" />
+ </g>
+ </symbol>
+
+ <symbol id="output" viewBox="0 0 24px 24px">
+ <g transform="translate(12 12)">
+ <circle cx="0" cy="0" r="5" stroke-width="1" stroke="#f00" fill="#f00" />
+ <circle cx="0" cy="0" r="10.5" stroke-width="3" stroke="#f00" fill="none" />
+ </g>
+ </symbol>
+ </defs>
+
+ <rect width="100%" height="100%" fill="#ddd" />
+ <polyline points="1,1 44,1 44,379 1,379 1,1" stroke="#e4e4e4" stroke-width="0.5" fill="none" />
+ <polyline points="0.5,0.5 44.5,0.5 44.5,379.5 0.5,379.5 0.5,0.5" stroke="#ebebeb" stroke-width="0.8" fill="none" />
+ <polyline points="0,0 45,0 45,380 0,380 0,0" stroke="#f2f2f2" stroke-width="1" fill="none" />
+
+ <!-- <polyline points="22.5,0 22.5,380" stroke-width="0.5" stroke="#0f0" /> -->
+ <!-- <rect width="45" height="10" fill="#0f0" transform="translate(0 68)" /> -->
+ <!-- <rect width="45" height="10" fill="#0f0" transform="translate(0 127)" /> -->
+ <!-- <rect width="45" height="10" fill="#0f0" transform="translate(0 177)" /> -->
+
+ <g transform="rotate(-90) translate(-376 13)">
+ <text class="title" font-size="7pt" letter-spacing="2.5px">VU</text>
+ <g transform="translate(0 12)">
+ <text class="brand" font-size="7pt" letter-spacing="2px">BGA</text>
+ <rect width="3.0" height="3" fill="#ddd" transform="translate(11.5 -5)" />
+ </g>
+ </g>
+
+ <g transform="translate(0 18)">
+ <use id="VU_WIDGET" xlink:href="#vu" transform="translate(13.5 -1)" />
+ <use xlink:href="#guide-db" transform="translate(0 -1)" />
+ </g>
+
+ <g transform="translate(0 200)">
+ <g transform="translate(5.5 0)">
+ <rect width="34" height="10" fill="#fafafa" transform="translate(0 63)" />
+ <rect width="34" height="70" rx="5" fill="#fafafa" />
+ <use id="L_INPUT" xlink:href="#input" transform="translate(5 3)" />
+ <text font-size="5pt" letter-spacing="2px" transform="translate(15 35)">L</text>
+ <use id="R_INPUT" xlink:href="#input" transform="translate(5 38)" />
+ <text font-size="5pt" letter-spacing="0.5px" transform="translate(9 70)">R (L)</text>
+ </g>
+ <g transform="translate(5.5 76)">
+ <rect width="34" height="10" fill="#bbb" transform="translate(0 -3)" />
+ <rect width="34" height="70" rx="5" fill="#bbb" />
+ <use id="L_OUTPUT" xlink:href="#output" transform="translate(5 0)" />
+ <text font-size="5pt" letter-spacing="2px" transform="translate(15 32)">L</text>
+ <use id="R_OUTPUT" xlink:href="#output" transform="translate(5 35)" />
+ <text font-size="5pt" letter-spacing="2px" transform="translate(15 67)">R</text>
+ </g>
+ </g>
+</svg>
diff --git a/res/VCAmp.svg b/res/VCAmp.svg
Binary files differ.
diff --git a/res/VU.svg b/res/VU.svg
Binary files differ.
diff --git a/src/VCAmp.cpp b/src/VCAmp.cpp
@@ -59,20 +59,10 @@ struct VUSlider : Knob {
float db = dynamic_cast<VCAmp*>(module)->_rmsLevel;
if (db > 0.0f) {
db = amplitudeToDecibels(db);
- if (db > -60.0f) {
- nvgBeginPath(vg);
- nvgRoundedRect(vg, 2, 4, 14, 5, 1.0);
- if (db < -24.0f) {
- nvgFillColor(vg, nvgRGBA(0x55, 0xff, 0x00, (1.0f - (db + 24.0f) / -36.0f) * (float)0xff));
- }
- else if (db < 0.0f) {
- nvgFillColor(vg, nvgRGBA((1.0f - db / -24.0f) * 0xff, 0xff, 0x00, 0xff));
- }
- else {
- nvgFillColor(vg, nvgRGBA(0xff, (1.0f - db / 18.0f) * 0xff, 0x00, 0xff));
- }
- nvgFill(vg);
- }
+ nvgBeginPath(vg);
+ nvgRoundedRect(vg, 2, 4, 14, 5, 1.0);
+ nvgFillColor(vg, decibelsToColor(db));
+ nvgFill(vg);
}
}
nvgRestore(vg);
diff --git a/src/VU.cpp b/src/VU.cpp
@@ -0,0 +1,124 @@
+
+#include "VU.hpp"
+
+void VU::onSampleRateChange() {
+ _lRms.setSampleRate(engineGetSampleRate());
+ _rRms.setSampleRate(engineGetSampleRate());
+}
+
+void VU::step() {
+ float left = 0.0f;
+ float right = 0.0f;
+ if (inputs[L_INPUT].active) {
+ left = inputs[L_INPUT].value;
+ }
+ if (inputs[R_INPUT].active) {
+ right = inputs[R_INPUT].value;
+ }
+ else {
+ right = left;
+ }
+ _lLevel = _lRms.next(left) / 5.0f;
+ _rLevel = _rRms.next(right) / 5.0f;
+ outputs[L_OUTPUT].value = left;
+ outputs[R_OUTPUT].value = right;
+}
+
+struct VUDisplay : OpaqueWidget {
+ struct Level {
+ float db;
+ NVGcolor color;
+ Level(float db, const NVGcolor& color) : db(db), color(color) {}
+ };
+
+ const NVGcolor bgColor = nvgRGBA(0xaa, 0xaa, 0xaa, 0xff);
+ VU* _module;
+ std::vector<Level> _levels;
+
+ VUDisplay(VU* module) : _module(module) {
+ for (int i = 1; i <= 36; ++i) {
+ float db = 12.0f - i*2.0f;
+ _levels.push_back(Level(db, decibelsToColor(db)));
+ }
+ }
+
+ virtual void draw(NVGcontext* vg) override {
+ float lDb = _module->_lLevel;
+ if (lDb > 0.0f) {
+ lDb = amplitudeToDecibels(lDb);
+ }
+ else {
+ lDb = -100.0f;
+ }
+ float rDb = _module->_rLevel;
+ if (rDb > 0.0f) {
+ rDb = amplitudeToDecibels(rDb);
+ }
+ else {
+ rDb = -100.0f;
+ }
+
+ nvgSave(vg);
+ for (int i = 0; i < 180; i += 5) {
+ const Level& l = _levels.at(i / 5);
+
+ nvgBeginPath(vg);
+ nvgRect(vg, 3, i + 1, 5, 4);
+ nvgFillColor(vg, bgColor);
+ nvgFill(vg);
+ if (lDb > l.db) {
+ nvgFillColor(vg, l.color);
+ nvgFill(vg);
+ }
+
+ nvgBeginPath(vg);
+ nvgRect(vg, 10, i + 1, 5, 4);
+ nvgFillColor(vg, bgColor);
+ nvgFill(vg);
+ if (rDb > l.db) {
+ nvgFillColor(vg, l.color);
+ nvgFill(vg);
+ }
+ }
+ nvgRestore(vg);
+ }
+};
+
+struct VUWidget : ModuleWidget {
+ VUWidget(VU* module) : ModuleWidget(module) {
+ box.size = Vec(RACK_GRID_WIDTH * 3, RACK_GRID_HEIGHT);
+
+ {
+ SVGPanel *panel = new SVGPanel();
+ panel->box.size = box.size;
+ panel->setBackground(SVG::load(assetPlugin(plugin, "res/VU.svg")));
+ addChild(panel);
+ }
+
+ {
+ auto display = new VUDisplay(module);
+ display->box.pos = Vec(13.5, 16.5);
+ display->box.size = Vec(18, 180);
+ addChild(display);
+ }
+
+ addChild(Widget::create<ScrewSilver>(Vec(0, 0)));
+ addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 15, 365)));
+
+ // generated by svg_widgets.rb
+ auto lInputPosition = Vec(10.5, 203.0);
+ auto rInputPosition = Vec(10.5, 238.0);
+
+ auto lOutputPosition = Vec(10.5, 276.0);
+ auto rOutputPosition = Vec(10.5, 311.0);
+ // end generated by svg_widgets.rb
+
+ addInput(Port::create<Port24>(lInputPosition, Port::INPUT, module, VU::L_INPUT));
+ addInput(Port::create<Port24>(rInputPosition, Port::INPUT, module, VU::R_INPUT));
+
+ addOutput(Port::create<Port24>(lOutputPosition, Port::OUTPUT, module, VU::L_OUTPUT));
+ addOutput(Port::create<Port24>(rOutputPosition, Port::OUTPUT, module, VU::R_OUTPUT));
+ }
+};
+
+Model* modelVU = Model::create<VU, VUWidget>("Bogaudio", "Bogaudio-VU", "VU", VISUAL_TAG, DUAL_TAG, UTILITY_TAG);
diff --git a/src/VU.hpp b/src/VU.hpp
@@ -0,0 +1,48 @@
+#pragma once
+
+#include "bogaudio.hpp"
+#include "dsp/signal.hpp"
+
+using namespace bogaudio::dsp;
+
+extern Model* modelVU;
+
+namespace bogaudio {
+
+struct VU : Module {
+ enum ParamsIds {
+ NUM_PARAMS
+ };
+
+ enum InputsIds {
+ L_INPUT,
+ R_INPUT,
+ NUM_INPUTS
+ };
+
+ enum OutputsIds {
+ L_OUTPUT,
+ R_OUTPUT,
+ NUM_OUTPUTS
+ };
+
+ enum LightsIds {
+ NUM_LIGHTS
+ };
+
+ RootMeanSquare _lRms;
+ RootMeanSquare _rRms;
+ float _lLevel = 0.0f;
+ float _rLevel = 0.0f;
+
+ VU() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
+ onSampleRateChange();
+ _lRms.setSensitivity(0.05f);
+ _rRms.setSensitivity(0.05f);
+ }
+
+ virtual void onSampleRateChange() override;
+ virtual void step() override;
+};
+
+} // namespace bogaudio
diff --git a/src/bogaudio.cpp b/src/bogaudio.cpp
@@ -34,6 +34,7 @@
#include "VCA.hpp"
#include "VCAL.hpp"
#include "VCAmp.hpp"
+#include "VU.hpp"
#include "Test.hpp"
#include "Test2.hpp"
@@ -94,6 +95,7 @@ void init(rack::Plugin *p) {
#ifdef EXPERIMENTAL
p->addModel(modelVCAL);
p->addModel(modelVCAmp);
+ p->addModel(modelVU);
#endif
#ifdef TEST
diff --git a/src/widgets.cpp b/src/widgets.cpp
@@ -107,3 +107,17 @@ void StatefulButton::onDragEnd(EventDragEnd& e) {
StatefulButton9::StatefulButton9() : StatefulButton("res/button_9px_0.svg", "res/button_9px_1.svg") {
}
+
+
+NVGcolor bogaudio::decibelsToColor(float db) {
+ if (db < -80.0f) {
+ return nvgRGBA(0x00, 0x00, 0x00, 0x00);
+ }
+ if (db < -24.0f) {
+ return nvgRGBA(0x55, 0xff, 0x00, (1.0f - (db + 24.0f) / -56.0f) * (float)0xff);
+ }
+ if (db < 0.0f) {
+ return nvgRGBA((1.0f - db / -24.0f) * 0xff, 0xff, 0x00, 0xff);
+ }
+ return nvgRGBA(0xff, (1.0f - db / 18.0f) * 0xff, 0x00, 0xff);
+}
diff --git a/src/widgets.hpp b/src/widgets.hpp
@@ -62,4 +62,6 @@ struct StatefulButton9 : StatefulButton {
StatefulButton9();
};
+NVGcolor decibelsToColor(float db);
+
} // namespace bogaudio