BogaudioModules

BogaudioModules for VCV Rack
Log | Files | Refs | README | LICENSE

commit 07019a8aeda019d1aaa875cbf9cd003f009eaacf
parent 36627cceac18e412711ca138b9f4f54c6e074270
Author: Matt Demanett <matt@demanett.net>
Date:   Thu, 17 May 2018 00:06:05 -0400

MIX4 module; VCAmp fixes.

Diffstat:
Ares-src/Mix4-src.svg | 230+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mres-src/VCAmp-src.svg | 28++++++++++++++++++----------
Mres-src/VU-src.svg | 14+++++++-------
Ares/Mix4.svg | 0
Mres/VCAmp.svg | 0
Mres/VU.svg | 0
Asrc/Mix4.cpp | 188+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/Mix4.hpp | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/VCAmp.cpp | 56++++----------------------------------------------------
Msrc/bogaudio.cpp | 2++
Asrc/mixer.cpp | 34++++++++++++++++++++++++++++++++++
Asrc/mixer.hpp | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/widgets.cpp | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/widgets.hpp | 18++++++++++++++++++
14 files changed, 690 insertions(+), 69 deletions(-)

diff --git a/res-src/Mix4-src.svg b/res-src/Mix4-src.svg @@ -0,0 +1,230 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + width="225" + height="380" + viewBox="0 0 225 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="slider" viewBox="0 0 18px 183px"> + <rect width="6" height="177" x="6" y="3" rx="2" stroke-width="1" stroke="#888" fill="#222" /> + <g transform="translate(0 85)"> + <rect width="18" height="13" rx="1.5" fill="#777" /> + <rect width="18" height="9" x="0" y="2" fill="#444" /> + <polyline points="0,6.5 18,6.5" stroke="#fafafa" stroke-width="1" fill="none" /> + <rect width="14" height="5" x="2" y="4" rx="1.0" fill="#ddd" transform="translate(0 0)" /> + </g> + </symbol> + + <symbol id="sliderguide-db" viewBox="0 0 20px 183px"> + <g transform="translate(0 6.5)"> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 0)" /> + </g> + <g transform="translate(0 20.67)"> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 0)" /> + <text font-size="6.0pt" transform="translate(7 0) rotate(0) translate(-2.5 2.6)">6</text> + </g> + <g transform="translate(0 34.83)"> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 0)" /> + <text font-size="6.0pt" transform="translate(7 0) rotate(0) translate(-2.5 2.6)">0</text> + </g> + <g transform="translate(0 49)"> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 0)" /> + <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-4 2.2)">-6</text> + </g> + <g transform="translate(0 63.17)"> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 0)" /> + <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-7 2.2)">-12</text> + </g> + <g transform="translate(0 91.5)"> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 0)" /> + <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-7 2.2)">-24</text> + </g> + <g transform="translate(0 148.17)"> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 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)">dB</text> + </g> + </symbol> + + <symbol id="knob-smallest" viewBox="0 0 16px 16px"> + <g transform="translate(8 8)"> + <polyline points="-3,0 3,0" stroke-width="1" stroke="#00f" /> + <polyline points="0,-3 0,3" stroke-width="1" stroke="#00f" /> + <circle r="7.5" stroke-width="1" stroke="#00f" fill="none" /> + </g> + </symbol> + + <symbol id="knobguide-centertick" viewBox="0 0 40px 40px"> + <g transform="translate(20 20)"> + <g transform="rotate(-90) translate(10 0)"> + <polyline points="0,0 4,0" stroke-width="1" stroke="#333" /> + </g> + <path d="M 0 -12.5 A 12.5 12.5 0 0 1 12.5 0" stroke="#333" stroke-width="0.5" stroke-linecap="round" fill="none" transform="rotate(20)" /> + <path d="M 0 -12.5 A 12.5 12.5 0 0 1 12.5 0" stroke="#333" stroke-width="0.5" stroke-linecap="round" fill="none" transform="rotate(43)" /> + <path d="M 0 -12.5 A 12.5 12.5 0 0 0 -12.5 0" stroke="#333" stroke-width="0.5" stroke-linecap="round" fill="none" transform="rotate(-20)" /> + <path d="M 0 -12.5 A 12.5 12.5 0 0 0 -12.5 0" stroke="#333" stroke-width="0.5" stroke-linecap="round" fill="none" transform="rotate(-43)" /> + </g> + </symbol> + + <symbol id="button" viewBox="0 0 20px 20px"> + <g transform="translate(10 10)"> + <circle cx="0" cy="0" r="8.8" stroke-width="1" stroke="#00f" fill="#f00" /> + </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 269,1 269,379 1,379 1,1" stroke="#e4e4e4" stroke-width="0.5" fill="none" /> + <polyline points="0.5,0.5 269.5,0.5 269.5,379.5 0.5,379.5 0.5,0.5" stroke="#ebebeb" stroke-width="0.8" fill="none" /> + <polyline points="0,0 270,0 270,380 0,380 0,0" stroke="#f2f2f2" stroke-width="1" fill="none" /> + + <!-- <rect width="85" height="20" fill="#0f0" transform="translate(0 0)" /> --> + <!-- <rect width="85" height="20" fill="#0f0" transform="translate(140 0)" /> --> + <!-- <polyline points="0,0 0,380" stroke="#0f0" stroke-width="1" fill="none" transform="translate(10 0)" /> --> + <!-- <polyline points="0,0 0,380" stroke="#0f0" stroke-width="1" fill="none" transform="translate(215 0)" /> --> + + <text class="title" x="85" y="19" font-size="12pt" letter-spacing="4px">MIX4</text> + <g transform="translate(72.5 374)"> + <text class="brand" font-size="8pt" letter-spacing="2px">BOGAUDIO</text> + <rect width="3.0" height="3" fill="#ddd" transform="translate(24 -5)" /> + </g> + + <g transform="translate(4 20)"> + <!-- <rect width="39" height="344" fill="#ccc" transform="translate(3 0)" /> --> + <text font-size="5pt" letter-spacing="2px" transform="translate(13.7 9)">CH1</text> + <use xlink:href="#sliderguide-db" transform="translate(0 10)" /> + <use id="LEVEL1_PARAM" xlink:href="#slider" transform="translate(13.5 10)" /> + <use id="PAN1_PARAM" xlink:href="#knob-smallest" transform="translate(14.5 201)" /> + <use xlink:href="#knobguide-centertick" transform="translate(2.5 189)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(14 226)">PAN</text> + <use id="MUTE1_PARAM" xlink:href="#button" transform="translate(12.5 232)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(10 260)">MUTE</text> + <g transform="translate(5.5 267)"> + <rect width="34" height="73" rx="5" fill="#fafafa" /> + <use id="CV1_INPUT" xlink:href="#input" transform="translate(5 3)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(11 35)">CV</text> + <use id="IN1_INPUT" xlink:href="#input" transform="translate(5 38)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(12.5 70)">IN</text> + </g> + <!-- <rect width="8" height="40" fill="#f00" transform="translate(39.5 300)" /> --> + </g> + + <g transform="translate(47 20)"> + <!-- <rect width="39" height="344" fill="#ccc" transform="translate(3 0)" /> --> + <text font-size="5pt" letter-spacing="2px" transform="translate(13.7 9)">CH2</text> + <use xlink:href="#sliderguide-db" transform="translate(0 10)" /> + <use id="LEVEL2_PARAM" xlink:href="#slider" transform="translate(13.5 10)" /> + <use id="PAN2_PARAM" xlink:href="#knob-smallest" transform="translate(14.5 201)" /> + <use xlink:href="#knobguide-centertick" transform="translate(2.5 189)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(14 226)">PAN</text> + <use id="MUTE2_PARAM" xlink:href="#button" transform="translate(12.5 232)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(10 260)">MUTE</text> + <g transform="translate(5.5 267)"> + <rect width="34" height="73" rx="5" fill="#fafafa" /> + <use id="CV2_INPUT" xlink:href="#input" transform="translate(5 3)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(11 35)">CV</text> + <use id="IN2_INPUT" xlink:href="#input" transform="translate(5 38)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(12.5 70)">IN</text> + </g> + <!-- <rect width="8" height="40" fill="#f00" transform="translate(39.5 300)" /> --> + </g> + + <g transform="translate(90 20)"> + <!-- <rect width="39" height="344" fill="#ccc" transform="translate(3 0)" /> --> + <text font-size="5pt" letter-spacing="2px" transform="translate(13.7 9)">CH3</text> + <use xlink:href="#sliderguide-db" transform="translate(0 10)" /> + <use id="LEVEL3_PARAM" xlink:href="#slider" transform="translate(13.5 10)" /> + <use id="PAN3_PARAM" xlink:href="#knob-smallest" transform="translate(14.5 201)" /> + <use xlink:href="#knobguide-centertick" transform="translate(2.5 189)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(14 226)">PAN</text> + <use id="MUTE3_PARAM" xlink:href="#button" transform="translate(12.5 232)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(10 260)">MUTE</text> + <g transform="translate(5.5 267)"> + <rect width="34" height="73" rx="5" fill="#fafafa" /> + <use id="CV3_INPUT" xlink:href="#input" transform="translate(5 3)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(11 35)">CV</text> + <use id="IN3_INPUT" xlink:href="#input" transform="translate(5 38)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(12.5 70)">IN</text> + </g> + <!-- <rect width="8" height="40" fill="#f00" transform="translate(39.5 300)" /> --> + </g> + + <g transform="translate(133 20)"> + <!-- <rect width="39" height="344" fill="#ccc" transform="translate(3 0)" /> --> + <text font-size="5pt" letter-spacing="2px" transform="translate(13.7 9)">CH4</text> + <use xlink:href="#sliderguide-db" transform="translate(0 10)" /> + <use id="LEVEL4_PARAM" xlink:href="#slider" transform="translate(13.5 10)" /> + <use id="PAN4_PARAM" xlink:href="#knob-smallest" transform="translate(14.5 201)" /> + <use xlink:href="#knobguide-centertick" transform="translate(2.5 189)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(14 226)">PAN</text> + <use id="MUTE4_PARAM" xlink:href="#button" transform="translate(12.5 232)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(10 260)">MUTE</text> + <g transform="translate(5.5 267)"> + <rect width="34" height="73" rx="5" fill="#fafafa" /> + <use id="CV4_INPUT" xlink:href="#input" transform="translate(5 3)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(11 35)">CV</text> + <use id="IN4_INPUT" xlink:href="#input" transform="translate(5 38)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(12.5 70)">IN</text> + </g> + <!-- <rect width="8" height="40" fill="#f00" transform="translate(39.5 300)" /> --> + </g> + + <g transform="translate(176 20)"> + <!-- <rect width="39" height="344" fill="#ccc" transform="translate(3 0)" /> --> + <text font-size="5pt" letter-spacing="2px" transform="translate(13.7 9)">MIX</text> + <use xlink:href="#sliderguide-db" transform="translate(0 10)" /> + <use id="MIX_PARAM" xlink:href="#slider" transform="translate(13.5 10)" /> + <g transform="translate(5.5 230)"> + <rect width="34" height="50" rx="5" fill="#fafafa" /> + <use id="MIX_CV_INPUT" xlink:href="#input" transform="translate(5 3)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(11 35)">CV</text> + <rect width="34" height="73" rx="5" fill="#bbb" transform="translate(0 38)" /> + <rect width="34" height="5" fill="#bbb" transform="translate(0 38)" /> + <use id="L_OUTPUT" xlink:href="#output" transform="translate(5 41)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(15.5 73)">L</text> + <use id="R_OUTPUT" xlink:href="#output" transform="translate(5 76)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(15 108)">R</text> + </g> + </g> +</svg> diff --git a/res-src/VCAmp-src.svg b/res-src/VCAmp-src.svg @@ -28,40 +28,48 @@ <g transform="translate(0 85)"> <rect width="18" height="13" rx="1.5" fill="#777" /> <rect width="18" height="9" x="0" y="2" fill="#444" /> + <polyline points="0,6.5 18,6.5" stroke="#fafafa" stroke-width="1" fill="none" /> <rect width="14" height="5" x="2" y="4" rx="1.0" fill="#ddd" transform="translate(0 0)" /> </g> </symbol> <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)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 0)" /> </g> <g transform="translate(0 20.67)"> - <polyline points="0,0 5,0" stroke="#333" fille="none" transform="translate(11 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 0)" /> <text font-size="6.0pt" transform="translate(7 0) rotate(0) translate(-2.5 2.6)">6</text> </g> - <g transform="translate(0 35.83)"> - <polyline points="0,0 5,0" stroke="#333" fille="none" transform="translate(11 0)" /> + <g transform="translate(0 34.83)"> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 0)" /> <text font-size="6.0pt" transform="translate(7 0) rotate(0) translate(-2.5 2.6)">0</text> </g> <g transform="translate(0 49)"> - <polyline points="0,0 5,0" stroke="#333" fille="none" transform="translate(11 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 0)" /> <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-4 2.2)">-6</text> </g> <g transform="translate(0 63.17)"> - <polyline points="0,0 5,0" stroke="#333" fille="none" transform="translate(11 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 0)" /> <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-7 2.2)">-12</text> </g> <g transform="translate(0 91.5)"> - <polyline points="0,0 5,0" stroke="#333" fille="none" transform="translate(11 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 0)" /> <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-7 2.2)">-24</text> </g> <g transform="translate(0 148.17)"> - <polyline points="0,0 5,0" stroke="#333" fille="none" transform="translate(11 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 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 6)">dB</text> + <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-9 4)">dB</text> </g> </symbol> @@ -108,7 +116,7 @@ <rect width="34" height="10" fill="#fafafa" transform="translate(0 63)" /> <rect width="34" height="70" rx="5" fill="#fafafa" /> <use id="CV_INPUT" xlink:href="#input" transform="translate(5 3)" /> - <text font-size="5pt" letter-spacing="2px" transform="translate(12.5 35)">CV</text> + <text font-size="5pt" letter-spacing="2px" transform="translate(11 35)">CV</text> <use id="IN_INPUT" xlink:href="#input" transform="translate(5 38)" /> <text font-size="5pt" letter-spacing="2px" transform="translate(12.5 70)">IN</text> </g> diff --git a/res-src/VU-src.svg b/res-src/VU-src.svg @@ -53,32 +53,32 @@ <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)" /> + <polyline points="0,0 3,0" stroke="#333" fill="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)" /> + <polyline points="0,0 3,0" stroke="#333" fill="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)" /> + <polyline points="0,0 3,0" stroke="#333" fill="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)" /> + <polyline points="0,0 3,0" stroke="#333" fill="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)" /> + <polyline points="0,0 3,0" stroke="#333" fill="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)" /> --> + <!-- <polyline points="0,0 5,0" stroke="#333" fill="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)" /> + <polyline points="0,0 3,0" stroke="#333" fill="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)"> diff --git a/res/Mix4.svg b/res/Mix4.svg Binary files differ. 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/Mix4.cpp b/src/Mix4.cpp @@ -0,0 +1,188 @@ + +#include "Mix4.hpp" + +void Mix4::onSampleRateChange() { + float sr = engineGetSampleRate(); + _channel1.setSampleRate(sr); + _channel2.setSampleRate(sr); + _channel3.setSampleRate(sr); + _channel4.setSampleRate(sr); + _slewLimiter.setParams(sr, slewTimeMS); + _rms.setSampleRate(sr); +} + +void Mix4::step() { + bool stereo = outputs[L_OUTPUT].active && outputs[R_OUTPUT].active; + _channel1.next(stereo); + _channel2.next(stereo); + _channel3.next(stereo); + _channel4.next(stereo); + + float level = params[MIX_PARAM].value; + if (inputs[MIX_CV_INPUT].active) { + level *= clamp(inputs[MIX_CV_INPUT].value / 10.0f, 0.0f, 1.0f); + } + level *= maxDecibels - minDecibels; + level += minDecibels; + _amplifier.setLevel(_slewLimiter.next(level)); + + float mono = 0.0f; + mono += _channel1.out; + mono += _channel2.out; + mono += _channel3.out; + mono += _channel4.out; + mono = _amplifier.next(mono); + _rmsLevel = _rms.next(mono) / 5.0f; + + if (stereo) { + float left = 0.0f; + left += _channel1.left; + left += _channel2.left; + left += _channel3.left; + left += _channel4.left; + left = _amplifier.next(left); + outputs[L_OUTPUT].value = left; + + float right = 0.0f; + right += _channel1.right; + right += _channel2.right; + right += _channel3.right; + right += _channel4.right; + right = _amplifier.next(right); + outputs[R_OUTPUT].value = right; + } + else { + outputs[L_OUTPUT].value = outputs[R_OUTPUT].value = mono; + } +} + +struct Mix4Widget : ModuleWidget { + Mix4Widget(Mix4* module) : ModuleWidget(module) { + box.size = Vec(RACK_GRID_WIDTH * 15, RACK_GRID_HEIGHT); + + { + SVGPanel *panel = new SVGPanel(); + panel->box.size = box.size; + panel->setBackground(SVG::load(assetPlugin(plugin, "res/Mix4.svg"))); + addChild(panel); + } + + addChild(Widget::create<ScrewSilver>(Vec(15, 0))); + addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 0))); + addChild(Widget::create<ScrewSilver>(Vec(15, 365))); + addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 365))); + + // generated by svg_widgets.rb + auto level1ParamPosition = Vec(17.5, 32.5); + auto pan1ParamPosition = Vec(18.5, 221.0); + auto mute1ParamPosition = Vec(17.2, 252.7); + auto level2ParamPosition = Vec(60.5, 32.5); + auto pan2ParamPosition = Vec(61.5, 221.0); + auto mute2ParamPosition = Vec(60.2, 252.7); + auto level3ParamPosition = Vec(103.5, 32.5); + auto pan3ParamPosition = Vec(104.5, 221.0); + auto mute3ParamPosition = Vec(103.2, 252.7); + auto level4ParamPosition = Vec(146.5, 32.5); + auto pan4ParamPosition = Vec(147.5, 221.0); + auto mute4ParamPosition = Vec(146.2, 252.7); + auto mixParamPosition = Vec(189.5, 32.5); + + auto cv1InputPosition = Vec(14.5, 290.0); + auto in1InputPosition = Vec(14.5, 325.0); + auto cv2InputPosition = Vec(57.5, 290.0); + auto in2InputPosition = Vec(57.5, 325.0); + auto cv3InputPosition = Vec(100.5, 290.0); + auto in3InputPosition = Vec(100.5, 325.0); + auto cv4InputPosition = Vec(143.5, 290.0); + auto in4InputPosition = Vec(143.5, 325.0); + auto mixCvInputPosition = Vec(186.5, 253.0); + + auto lOutputPosition = Vec(186.5, 291.0); + auto rOutputPosition = Vec(186.5, 326.0); + // end generated by svg_widgets.rb + + { + auto slider = ParamWidget::create<VUSlider>( + level1ParamPosition, + module, + Mix4::LEVEL1_PARAM, + 0.0, + 1.0, + abs(module->minDecibels) / (module->maxDecibels - module->minDecibels) + ); + dynamic_cast<VUSlider*>(slider)->setVULevel(&(module->_channel1.rms)); + addParam(slider); + } + addParam(ParamWidget::create<Knob16>(pan1ParamPosition, module, Mix4::PAN1_PARAM, -1.0, 1.0, 0.0)); + addParam(ParamWidget::create<StatefulButton18>(mute1ParamPosition, module, Mix4::MUTE1_PARAM, 0.0, 1.0, 0.0)); + { + auto slider = ParamWidget::create<VUSlider>( + level2ParamPosition, + module, + Mix4::LEVEL2_PARAM, + 0.0, + 1.0, + abs(module->minDecibels) / (module->maxDecibels - module->minDecibels) + ); + dynamic_cast<VUSlider*>(slider)->setVULevel(&(module->_channel2.rms)); + addParam(slider); + } + addParam(ParamWidget::create<Knob16>(pan2ParamPosition, module, Mix4::PAN2_PARAM, -1.0, 1.0, 0.0)); + addParam(ParamWidget::create<StatefulButton18>(mute2ParamPosition, module, Mix4::MUTE2_PARAM, 0.0, 1.0, 0.0)); + { + auto slider = ParamWidget::create<VUSlider>( + level3ParamPosition, + module, + Mix4::LEVEL3_PARAM, + 0.0, + 1.0, + abs(module->minDecibels) / (module->maxDecibels - module->minDecibels) + ); + dynamic_cast<VUSlider*>(slider)->setVULevel(&(module->_channel3.rms)); + addParam(slider); + } + addParam(ParamWidget::create<Knob16>(pan3ParamPosition, module, Mix4::PAN3_PARAM, -1.0, 1.0, 0.0)); + addParam(ParamWidget::create<StatefulButton18>(mute3ParamPosition, module, Mix4::MUTE3_PARAM, 0.0, 1.0, 0.0)); + { + auto slider = ParamWidget::create<VUSlider>( + level4ParamPosition, + module, + Mix4::LEVEL4_PARAM, + 0.0, + 1.0, + abs(module->minDecibels) / (module->maxDecibels - module->minDecibels) + ); + dynamic_cast<VUSlider*>(slider)->setVULevel(&(module->_channel4.rms)); + addParam(slider); + } + addParam(ParamWidget::create<Knob16>(pan4ParamPosition, module, Mix4::PAN4_PARAM, -1.0, 1.0, 0.0)); + addParam(ParamWidget::create<StatefulButton18>(mute4ParamPosition, module, Mix4::MUTE4_PARAM, 0.0, 1.0, 0.0)); + { + auto slider = ParamWidget::create<VUSlider>( + mixParamPosition, + module, + Mix4::MIX_PARAM, + 0.0, + 1.0, + abs(module->minDecibels) / (module->maxDecibels - module->minDecibels) + ); + dynamic_cast<VUSlider*>(slider)->setVULevel(&(module->_rmsLevel)); + addParam(slider); + } + + addInput(Port::create<Port24>(cv1InputPosition, Port::INPUT, module, Mix4::CV1_INPUT)); + addInput(Port::create<Port24>(in1InputPosition, Port::INPUT, module, Mix4::IN1_INPUT)); + addInput(Port::create<Port24>(cv2InputPosition, Port::INPUT, module, Mix4::CV2_INPUT)); + addInput(Port::create<Port24>(in2InputPosition, Port::INPUT, module, Mix4::IN2_INPUT)); + addInput(Port::create<Port24>(cv3InputPosition, Port::INPUT, module, Mix4::CV3_INPUT)); + addInput(Port::create<Port24>(in3InputPosition, Port::INPUT, module, Mix4::IN3_INPUT)); + addInput(Port::create<Port24>(cv4InputPosition, Port::INPUT, module, Mix4::CV4_INPUT)); + addInput(Port::create<Port24>(in4InputPosition, Port::INPUT, module, Mix4::IN4_INPUT)); + addInput(Port::create<Port24>(mixCvInputPosition, Port::INPUT, module, Mix4::MIX_CV_INPUT)); + + addOutput(Port::create<Port24>(lOutputPosition, Port::OUTPUT, module, Mix4::L_OUTPUT)); + addOutput(Port::create<Port24>(rOutputPosition, Port::OUTPUT, module, Mix4::R_OUTPUT)); + } +}; + +Model* modelMix4 = Model::create<Mix4, Mix4Widget>("Bogaudio", "Bogaudio-Mix4", "Mix4", MIXER_TAG, PANNING_TAG, DUAL_TAG); diff --git a/src/Mix4.hpp b/src/Mix4.hpp @@ -0,0 +1,82 @@ +#pragma once + +#include "bogaudio.hpp" +#include "mixer.hpp" + +extern Model* modelMix4; +#include "dsp/signal.hpp" + +using namespace bogaudio::dsp; + +namespace bogaudio { + +struct Mix4 : Module { + enum ParamsIds { + LEVEL1_PARAM, + PAN1_PARAM, + MUTE1_PARAM, + LEVEL2_PARAM, + PAN2_PARAM, + MUTE2_PARAM, + LEVEL3_PARAM, + PAN3_PARAM, + MUTE3_PARAM, + LEVEL4_PARAM, + PAN4_PARAM, + MUTE4_PARAM, + MIX_PARAM, + NUM_PARAMS + }; + + enum InputsIds { + CV1_INPUT, + IN1_INPUT, + CV2_INPUT, + IN2_INPUT, + CV3_INPUT, + IN3_INPUT, + CV4_INPUT, + IN4_INPUT, + MIX_CV_INPUT, + NUM_INPUTS + }; + + enum OutputsIds { + L_OUTPUT, + R_OUTPUT, + NUM_OUTPUTS + }; + + enum LightsIds { + NUM_LIGHTS + }; + + const float maxDecibels = 12.0f; + const float minDecibels = Amplifier::minDecibels; + const float slewTimeMS = 1.0f; + + MixerChannel _channel1; + MixerChannel _channel2; + MixerChannel _channel3; + MixerChannel _channel4; + Amplifier _amplifier; + SlewLimiter _slewLimiter; + RootMeanSquare _rms; + float _rmsLevel = 0.0f; + + Mix4() + : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) + , _channel1(params[LEVEL1_PARAM], params[PAN1_PARAM], params[MUTE1_PARAM], inputs[IN1_INPUT], inputs[CV1_INPUT]) + , _channel2(params[LEVEL2_PARAM], params[PAN2_PARAM], params[MUTE2_PARAM], inputs[IN2_INPUT], inputs[CV2_INPUT]) + , _channel3(params[LEVEL3_PARAM], params[PAN3_PARAM], params[MUTE3_PARAM], inputs[IN3_INPUT], inputs[CV3_INPUT]) + , _channel4(params[LEVEL4_PARAM], params[PAN4_PARAM], params[MUTE4_PARAM], inputs[IN4_INPUT], inputs[CV4_INPUT]) + { + onSampleRateChange(); + _rms.setSensitivity(0.05f); + } + + virtual void onSampleRateChange() override; + virtual void step() override; +}; + +} // namespace bogaudio diff --git a/src/VCAmp.cpp b/src/VCAmp.cpp @@ -19,56 +19,6 @@ void VCAmp::step() { } } -struct VUSlider : Knob { - const float slideHeight = 13.0f; - - VUSlider() { - box.size = Vec(18.0f, 183.0f); - } - - virtual void draw(NVGcontext* vg) override { - nvgSave(vg); - { - nvgBeginPath(vg); - nvgRoundedRect(vg, 6, 3, 6, 177, 2); - nvgFillColor(vg, nvgRGBA(0x22, 0x22, 0x22, 0xff)); - nvgFill(vg); - nvgStrokeColor(vg, nvgRGBA(0x88, 0x88, 0x88, 0xff)); - nvgStroke(vg); - } - nvgRestore(vg); - - nvgSave(vg); - { - nvgTranslate(vg, 0, 170.0f * (1.0f - value)); - nvgBeginPath(vg); - nvgRoundedRect(vg, 0, 0, 18, 13, 1.5); - nvgFillColor(vg, nvgRGBA(0x77, 0x77, 0x77, 0xff)); - nvgFill(vg); - - nvgBeginPath(vg); - nvgRect(vg, 0, 2, 18, 9); - nvgFillColor(vg, nvgRGBA(0x44, 0x44, 0x44, 0xff)); - nvgFill(vg); - - nvgBeginPath(vg); - nvgRoundedRect(vg, 2, 4, 14, 5, 1.0); - nvgFillColor(vg, nvgRGBA(0xaa, 0xaa, 0xaa, 0xff)); - nvgFill(vg); - - float db = dynamic_cast<VCAmp*>(module)->_rmsLevel; - if (db > 0.0f) { - db = amplitudeToDecibels(db); - nvgBeginPath(vg); - nvgRoundedRect(vg, 2, 4, 14, 5, 1.0); - nvgFillColor(vg, decibelsToColor(db)); - nvgFill(vg); - } - } - nvgRestore(vg); - } -}; - struct VCAmpWidget : ModuleWidget { VCAmpWidget(VCAmp* module) : ModuleWidget(module) { box.size = Vec(RACK_GRID_WIDTH * 3, RACK_GRID_HEIGHT); @@ -92,14 +42,16 @@ struct VCAmpWidget : ModuleWidget { auto outOutputPosition = Vec(10.5, 286.0); // end generated by svg_widgets.rb - addParam(ParamWidget::create<VUSlider>( + auto slider = ParamWidget::create<VUSlider>( levelParamPosition, module, VCAmp::LEVEL_PARAM, 0.0, 1.0, abs(module->minDecibels) / (module->maxDecibels - module->minDecibels) - )); + ); + dynamic_cast<VUSlider*>(slider)->setVULevel(&(module->_rmsLevel)); + addParam(slider); addInput(Port::create<Port24>(cvInputPosition, Port::INPUT, module, VCAmp::CV_INPUT)); addInput(Port::create<Port24>(inInputPosition, Port::INPUT, module, VCAmp::IN_INPUT)); diff --git a/src/bogaudio.cpp b/src/bogaudio.cpp @@ -17,6 +17,7 @@ #include "RM.hpp" #include "VCM.hpp" +#include "Mix4.hpp" #include "ADSR.hpp" #include "Bool.hpp" @@ -73,6 +74,7 @@ void init(rack::Plugin *p) { #ifdef EXPERIMENTAL p->addModel(modelRM); p->addModel(modelVCM); + p->addModel(modelMix4); #endif #ifdef EXPERIMENTAL diff --git a/src/mixer.cpp b/src/mixer.cpp @@ -0,0 +1,34 @@ + +#include "mixer.hpp" + +void MixerChannel::setSampleRate(float sampleRate) { + _slewLimiter.setParams(sampleRate, slewTimeMS); + _rms.setSampleRate(sampleRate); +} + +void MixerChannel::next(bool stereo) { + if (!_inInput.active) { + rms = out = left = right = 0.0f; + return; + } + + if (_muteParam.value > 0.5f) { + _amplifier.setLevel(_slewLimiter.next(minDecibels)); + } + else { + float level = clamp(_levelParam.value, 0.0f, 1.0f); + if (_cvInput.active) { + level *= clamp(_cvInput.value / 10.0f, 0.0f, 1.0f); + } + level *= maxDecibels - minDecibels; + level += minDecibels; + _amplifier.setLevel(_slewLimiter.next(level)); + } + + out = _amplifier.next(_inInput.value); + rms = _rms.next(out) / 5.0f; + if (stereo) { + _panner.setPan(clamp(_panParam.value, -1.0f, 1.0f)); + _panner.next(out, left, right); + } +} diff --git a/src/mixer.hpp b/src/mixer.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include "bogaudio.hpp" +#include "dsp/signal.hpp" + +using namespace bogaudio::dsp; + +namespace bogaudio { + +struct MixerChannel { + const float maxDecibels = 12.0f; + const float minDecibels = Amplifier::minDecibels; + const float slewTimeMS = 1.0f; + + Amplifier _amplifier; + Panner _panner; + SlewLimiter _slewLimiter; + RootMeanSquare _rms; + + Param& _levelParam; + Param& _panParam; + Param& _muteParam; + Input& _inInput; + Input& _cvInput; + + float out = 0.0f; + float left = 0.0f; + float right = 0.0f; + float rms = 0.0f; + + MixerChannel( + Param& level, + Param& pan, + Param& mute, + Input& in, + Input& cv, + float sampleRate = 1000.0f + ) + : _levelParam(level) + , _panParam(pan) + , _muteParam(mute) + , _inInput(in) + , _cvInput(cv) + { + setSampleRate(sampleRate); + _rms.setSensitivity(0.05f); + } + + void setSampleRate(float sampleRate); + void next(bool stereo); // input from _in; outputs on out, left, right, rms. +}; + +} // namespace bogaudio diff --git a/src/widgets.cpp b/src/widgets.cpp @@ -1,7 +1,9 @@ #include "widgets.hpp" +#include "dsp/signal.hpp" using namespace bogaudio; +using namespace bogaudio::dsp; Button18::Button18() { addFrame(SVG::load(assetPlugin(plugin, "res/button_18px_0.svg"))); @@ -109,6 +111,10 @@ StatefulButton9::StatefulButton9() : StatefulButton("res/button_9px_0.svg", "res } +StatefulButton18::StatefulButton18() : StatefulButton("res/button_18px_0.svg", "res/button_18px_1.svg") { +} + + NVGcolor bogaudio::decibelsToColor(float db) { if (db < -80.0f) { return nvgRGBA(0x00, 0x00, 0x00, 0x00); @@ -121,3 +127,51 @@ NVGcolor bogaudio::decibelsToColor(float db) { } return nvgRGBA(0xff, (1.0f - db / 18.0f) * 0xff, 0x00, 0xff); } + + +void VUSlider::draw(NVGcontext* vg) { + nvgSave(vg); + { + nvgBeginPath(vg); + nvgRoundedRect(vg, 6, 3, 6, 177, 2); + nvgFillColor(vg, nvgRGBA(0x22, 0x22, 0x22, 0xff)); + nvgFill(vg); + nvgStrokeColor(vg, nvgRGBA(0x88, 0x88, 0x88, 0xff)); + nvgStroke(vg); + } + nvgRestore(vg); + + nvgSave(vg); + { + nvgTranslate(vg, 0, 170.0f * (1.0f - value)); + nvgBeginPath(vg); + nvgRoundedRect(vg, 0, 0, 18, 13, 1.5); + nvgFillColor(vg, nvgRGBA(0x77, 0x77, 0x77, 0xff)); + nvgFill(vg); + + nvgBeginPath(vg); + nvgRect(vg, 0, 2, 18, 9); + nvgFillColor(vg, nvgRGBA(0x44, 0x44, 0x44, 0xff)); + nvgFill(vg); + + nvgBeginPath(vg); + nvgRect(vg, 0, 6, 18, 1); + nvgFillColor(vg, nvgRGBA(0xfa, 0xfa, 0xfa, 0xff)); + nvgFill(vg); + + nvgBeginPath(vg); + nvgRoundedRect(vg, 2, 4, 14, 5, 1.0); + nvgFillColor(vg, nvgRGBA(0xaa, 0xaa, 0xaa, 0xff)); + nvgFill(vg); + + float db = _vuLevel ? *_vuLevel : 0.0f; + if (db > 0.0f) { + db = amplitudeToDecibels(db); + nvgBeginPath(vg); + nvgRoundedRect(vg, 2, 4, 14, 5, 1.0); + nvgFillColor(vg, decibelsToColor(db)); + nvgFill(vg); + } + } + nvgRestore(vg); +} diff --git a/src/widgets.hpp b/src/widgets.hpp @@ -62,6 +62,24 @@ struct StatefulButton9 : StatefulButton { StatefulButton9(); }; +struct StatefulButton18 : StatefulButton { + StatefulButton18(); +}; + NVGcolor decibelsToColor(float db); +struct VUSlider : Knob { + const float slideHeight = 13.0f; + float* _vuLevel = NULL; + + VUSlider() { + box.size = Vec(18.0f, 183.0f); + } + + void setVULevel(float* vuLevel) { + _vuLevel = vuLevel; + } + virtual void draw(NVGcontext* vg) override; +}; + } // namespace bogaudio