commit 27b60de91bcb4d343eae456359cb6fbdcbb56920
parent 95df46aed71e15004143541c3442b8f515a7ceb5
Author: Matt Demanett <matt@demanett.net>
Date: Tue, 18 Aug 2020 14:31:20 -0400
CHIRP: a swept sine wave oscillator.
Diffstat:
16 files changed, 1362 insertions(+), 57 deletions(-)
diff --git a/README-prerelease.md b/README-prerelease.md
@@ -140,6 +140,18 @@ A sine-wave oscillator and simple synth voice designed to allow patching up the
_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/OCT input.
+#### <a name="chirp"></a> CHIRP
+
+Part VCO and part sound effect, CHIRP produces swept sine waves. On each cycle, the output sine wave sweeps in frequency from FREQ1 to FREQ2, over the course of TIME. If LOOP is enabled, the cycle repeats, otherwise it may be triggered manually with the TRIGGER button, or by CV at the TRIG input. A pulse is emitted at output EOC each time a cycle ends.
+
+TIME takes a unipolar CV (0-10V), which is attenuated by the knob if in use. FREQ1 and FREQ2 take bipolar (+/-5V) 1V/octave inputs at ports V/O1 and V/O2, which CVs are added to the corresponding knobs.
+
+The frequency sweep can be linear in time, or exponential, under the control of the EXP toggle.
+
+The sweep is upwards in frequency if FREQ1 is less than FREQ2, and downwards otherwise.
+
+_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/O1 input.
+
### <a name="lfos"></a> LFOs
diff --git a/plugin.json b/plugin.json
@@ -84,6 +84,16 @@
]
},
{
+ "slug": "Bogaudio-Chirp",
+ "name": "CHIRP",
+ "description": "Swept-sine oscillator",
+ "manualUrl": "https://github.com/bogaudio/BogaudioModules/blob/master/README.md#chirp",
+ "tags": [
+ "Oscillator",
+ "Polyphonic"
+ ]
+ },
+ {
"slug": "Bogaudio-LFO",
"name": "LFO",
"description": "Low frequency oscillator",
diff --git a/res-pp/Chirp-dark-pp.svg b/res-pp/Chirp-dark-pp.svg
@@ -0,0 +1,326 @@
+<?xml version="1.0"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="75.0" height="380.0" viewBox="0 0 75.0 380.0">
+ <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;
+}
+
+polyline {
+ stroke: #333;
+}
+path {
+ stroke: #333;
+}
+
+rect.module-background, .background-fill {
+ fill: #ddd;
+}
+polyline.module-border-inner {
+ stroke: #e4e4e4;
+}
+polyline.module-border-middle {
+ stroke: #ebebeb;
+}
+polyline.module-border-outer {
+ stroke: #f2f2f2;
+}
+
+g.io-group {
+}
+rect.input-background, rect.input-background-filler {
+ fill: #fafafa;
+}
+rect.output-background, rect.output-background-filler {
+ fill: #bbb;
+}
+text.input-label, text.output-label {
+ /* font-size: 6pt; */
+}
+polyline.input-label, polyline.output-label {
+}
+path.input-label, path.output-label {
+}
+
+circle.port-rim {
+ stroke: #f0f0f0;
+}
+circle.port-barrel {
+ stroke: #222;
+ fill: #222;
+}
+circle.knob-center {
+ fill: #eee;
+}
+circle.knob-rim {
+ fill: #333;
+}
+circle.knob-tick {
+ fill: #fff;
+}
+polyline.knob-tick {
+ stroke: #fff;
+}
+
+
+text {
+ fill: #eee;
+}
+
+polyline {
+ stroke: #ccc;
+}
+path {
+ stroke: #ccc;
+}
+
+rect.module-background, .background-fill {
+ fill: #111;
+}
+polyline.module-border-inner {
+ stroke: #191919;
+}
+polyline.module-border-middle {
+ stroke: #111;
+}
+polyline.module-border-outer {
+ stroke: #000;
+}
+
+rect.input-background, rect.input-background-filler {
+ fill: #aaa;
+}
+rect.output-background, rect.output-background-filler {
+ fill: #666;
+}
+text.input-label {
+ fill: #222;
+}
+polyline.input-label, path.input-label {
+ stroke: #222;
+}
+text.output-label {
+ fill: #ddd;
+}
+polyline.output-label, path.output-label {
+ stroke: #ddd;
+}
+
+circle.port-rim {
+ stroke: #c0c0c0;
+}
+circle.port-barrel {
+ stroke: #222;
+ fill: #222;
+}
+circle.knob-center {
+ fill: #888;
+}
+circle.knob-rim {
+ fill: #444;
+}
+circle.knob-tick {
+ fill: #fff;
+}
+polyline.knob-tick {
+ stroke: #fff;
+}
+</style>
+
+ <defs>
+ <symbol id="dial-time-chirp" viewBox="0 0 75.0px 75.0px">
+ <g transform="translate(37.5 37.5)">
+ <text font-size="7pt" text-anchor="middle" transform="rotate(-240) translate(27 0) rotate(240.0) translate(0 3)">50ms</text>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-192.4468031288819) translate(22 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-172.74962405066697) translate(22 0)"/>
+ <text font-size="7pt" text-anchor="middle" transform="rotate(-144.8936062577638) translate(26 0) rotate(144.8936062577638) translate(0 3)">1</text>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-105.4992481013339) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-75.27089391379613) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-49.787212515527585) translate(22 0)"/>
+ <text font-size="7pt" text-anchor="middle" transform="rotate(-27.335638497499218) translate(26 0) rotate(27.335638497499218) translate(0 3)">5</text>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-7.037864055294165) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(11.627865934146627) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(29.00150379733219) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(45.319181226708565) translate(22 0)"/>
+ <text font-size="7pt" text-anchor="middle" transform="rotate(60) translate(27 0) rotate(-60) translate(0 3)">10s</text>
+ </g>
+ </symbol>
+ </defs>
+
+
+
+ <rect class="module-background background-fill" width="75.0" height="380.0"/>
+
+
+ <polyline class="module-border-inner" points="1,1 74.0,1 74.0,379.0 1,379.0 1,1" stroke-width="0.5" fill="none"/>
+ <polyline class="module-border-middle" points="0.5,0.5 74.5,0.5 74.5,379.5 0.5,379.5 0.5,0.5" stroke-width="0.8" fill="none"/>
+ <polyline class="module-border-outer" points="0,0 75.0,0 75.0,380.0 0,380.0 0,0" stroke-width="1" fill="none"/>
+
+ <text class="title" font-size="9pt" letter-spacing="3px" text-anchor="end" transform="translate(72.0 17)">CHIRP</text>
+ <g transform="translate(25 374)">
+ <text class="brand" font-size="6.5pt" letter-spacing="2px">BGA</text>
+ <rect class="background-fill" width="2" height="2" fill="#ddd" transform="translate(11.5 -4)"/>
+ </g>
+
+
+ <g transform="translate(0 35)">
+ <text font-size="8pt" letter-spacing="2px" text-anchor="middle" transform="translate(37.5 0)">TIME</text>
+ <g transform="translate(18.5 11)"><svg id="TIME_PARAM">
+ <g transform="translate(19 19)">
+ <polyline points="-5,0 5,0" stroke-width="1" stroke="#00f"/>
+ <polyline points="0,-5 0,5" stroke-width="1" stroke="#00f"/>
+ <circle cx="0" cy="0" r="18.5" stroke-width="1" stroke="#00f" fill="none"/>
+ </g>
+ </svg></g>
+ <use xlink:href="#dial-time-chirp" transform="translate(0 -7.5)" href="#dial-time-chirp"/>
+ </g>
+
+ <g transform="translate(0 111)">
+ <text font-size="8pt" letter-spacing="2px" text-anchor="middle" transform="translate(37.5 0)">FREQ 1</text>
+ <g transform="translate(24.5 11)"><svg id="FREQUENCY1_PARAM">
+ <g transform="translate(13 13)">
+ <polyline points="-3,0 3,0" stroke-width="1" stroke="#00f"/>
+ <polyline points="0,-3 0,3" stroke-width="1" stroke="#00f"/>
+ <circle cx="0" cy="0" r="12.5" stroke-width="1" stroke="#00f" fill="none"/>
+ </g>
+ </svg></g>
+ <g transform="translate(15.0 1.5)">
+ <g transform="translate(22.5 22.5)">
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-240) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-206.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-173.33) translate(15 0)"/>
+
+ <g transform="rotate(-140) translate(14 0)">
+ <polyline points="0,0 2.5,0" stroke-width="1.0" transform="translate(0 0)"/>
+ <text font-size="5.0pt" transform="translate(5 0) rotate(140) translate(-5.5 0)">OV</text>
+ </g>
+
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-106.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-73.33) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-40) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-6.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(26.67) translate(15 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(60) translate(15 0)"/>
+ </g>
+ </g>
+ </g>
+
+ <g transform="translate(0 168)">
+ <text font-size="8pt" letter-spacing="2px" text-anchor="middle" transform="translate(37.5 0)">FREQ 2</text>
+ <g transform="translate(24.5 11)"><svg id="FREQUENCY2_PARAM">
+ <g transform="translate(13 13)">
+ <polyline points="-3,0 3,0" stroke-width="1" stroke="#00f"/>
+ <polyline points="0,-3 0,3" stroke-width="1" stroke="#00f"/>
+ <circle cx="0" cy="0" r="12.5" stroke-width="1" stroke="#00f" fill="none"/>
+ </g>
+ </svg></g>
+ <g transform="translate(15.0 1.5)">
+ <g transform="translate(22.5 22.5)">
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-240) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-206.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-173.33) translate(15 0)"/>
+
+ <g transform="rotate(-140) translate(14 0)">
+ <polyline points="0,0 2.5,0" stroke-width="1.0" transform="translate(0 0)"/>
+ <text font-size="5.0pt" transform="translate(5 0) rotate(140) translate(-5.5 0)">OV</text>
+ </g>
+
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-106.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-73.33) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-40) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-6.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(26.67) translate(15 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(60) translate(15 0)"/>
+ </g>
+ </g>
+ </g>
+
+ <g transform="translate(0 220)">
+ <g transform="translate(10 -4)">
+ <g transform="translate(0 0)"><svg id="TRIGGER_PARAM">
+ <g transform="translate(9 9)">
+ <circle cx="0" cy="0" r="8.5" stroke-width="1" stroke="#00f" fill="#f00"/>
+ </g>
+ </svg></g>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(9 26)">TRIG</text>
+ </g>
+
+ <g transform="translate(44.5 0)">
+ <g transform="translate(0 -1)">
+ <text font-size="5pt" letter-spacing="1.5px" transform="translate(-3 6)">EXP</text>
+ <g transform="translate(15 -1)"><svg id="EXPONENTIAL_PARAM">
+ <g transform="translate(4.5 4.5)">
+ <circle r="4" stroke-width="1" stroke="#00f" fill="#f00"/>
+ </g>
+ </svg></g>
+ </g>
+ <g transform="translate(0 13)">
+ <text font-size="5pt" letter-spacing="1.5px" transform="translate(-9 6)">LOOP</text>
+ <g transform="translate(15 -1)"><svg id="LOOP_PARAM">
+ <g transform="translate(4.5 4.5)">
+ <circle r="4" stroke-width="1" stroke="#00f" fill="#f00"/>
+ </g>
+ </svg></g>
+ </g>
+ </g>
+ </g>
+
+ <g transform="translate(0 248)">
+ <rect class="input-background" width="64" height="112" rx="5" transform="translate(5.5 0)"/>
+ <g transform="translate(10.5 3)"><svg id="FREQUENCY1_INPUT">
+ <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>
+ </svg></g>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 35)">V/O1</text>
+ <g transform="translate(40.5 3)"><svg id="FREQUENCY2_INPUT">
+ <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>
+ </svg></g>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(52.5 35)">V/O2</text>
+ <g transform="translate(10.5 40)"><svg id="TIME_INPUT">
+ <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>
+ </svg></g>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 72)">TIME</text>
+ <g transform="translate(10.5 77)"><svg id="TRIGGER_INPUT">
+ <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>
+ </svg></g>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 109)">TRIG</text>
+ <g class="io-group" transform="translate(30 36)">
+ <rect class="output-background" width="32" height="74" rx="5" transform="translate(7.5 2)"/>
+ <rect class="output-background-filler" width="32" height="10" transform="translate(7.5 2)"/>
+ <rect class="output-background-filler" width="10" height="10" transform="translate(7.5 66)"/>
+ <g transform="translate(10.5 4)"><svg id="EOC_OUTPUT">
+ <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>
+ </svg></g>
+ <text class="output-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 36)">EOC</text>
+ <g transform="translate(10.5 41)"><svg id="OUT_OUTPUT">
+ <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>
+ </svg></g>
+ <text class="output-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 73)">OUT</text>
+ </g>
+ </g>
+</svg>
diff --git a/res-pp/Chirp-lowcontrast-pp.svg b/res-pp/Chirp-lowcontrast-pp.svg
@@ -0,0 +1,326 @@
+<?xml version="1.0"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="75.0" height="380.0" viewBox="0 0 75.0 380.0">
+ <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;
+}
+
+polyline {
+ stroke: #333;
+}
+path {
+ stroke: #333;
+}
+
+rect.module-background, .background-fill {
+ fill: #ddd;
+}
+polyline.module-border-inner {
+ stroke: #e4e4e4;
+}
+polyline.module-border-middle {
+ stroke: #ebebeb;
+}
+polyline.module-border-outer {
+ stroke: #f2f2f2;
+}
+
+g.io-group {
+}
+rect.input-background, rect.input-background-filler {
+ fill: #fafafa;
+}
+rect.output-background, rect.output-background-filler {
+ fill: #bbb;
+}
+text.input-label, text.output-label {
+ /* font-size: 6pt; */
+}
+polyline.input-label, polyline.output-label {
+}
+path.input-label, path.output-label {
+}
+
+circle.port-rim {
+ stroke: #f0f0f0;
+}
+circle.port-barrel {
+ stroke: #222;
+ fill: #222;
+}
+circle.knob-center {
+ fill: #eee;
+}
+circle.knob-rim {
+ fill: #333;
+}
+circle.knob-tick {
+ fill: #fff;
+}
+polyline.knob-tick {
+ stroke: #fff;
+}
+
+
+text {
+ fill: #b3b3b3;
+}
+
+polyline {
+ stroke: #b3b3b3;
+}
+path {
+ stroke: #b3b3b3;
+}
+
+rect.module-background, .background-fill {
+ fill: #333;
+}
+polyline.module-border-inner {
+ stroke: #191919;
+}
+polyline.module-border-middle {
+ stroke: #111;
+}
+polyline.module-border-outer {
+ stroke: #000;
+}
+
+rect.input-background, rect.input-background-filler {
+ fill: #b3b3b3;
+}
+rect.output-background, rect.output-background-filler {
+ fill: #888;
+}
+text.input-label {
+ fill: #666;
+}
+polyline.input-label, path.input-label {
+ stroke: #666;
+}
+text.output-label {
+ fill: #ccc;
+}
+polyline.output-label, path.output-label {
+ stroke: #ccc;
+}
+
+circle.port-rim {
+ stroke: #bbb;
+}
+circle.port-barrel {
+ stroke: #222;
+ fill: #222;
+}
+circle.knob-center {
+ fill: #bbb;
+}
+circle.knob-rim {
+ fill: #555;
+}
+circle.knob-tick {
+ fill: #fff;
+}
+polyline.knob-tick {
+ stroke: #fff;
+}
+</style>
+
+ <defs>
+ <symbol id="dial-time-chirp" viewBox="0 0 75.0px 75.0px">
+ <g transform="translate(37.5 37.5)">
+ <text font-size="7pt" text-anchor="middle" transform="rotate(-240) translate(27 0) rotate(240.0) translate(0 3)">50ms</text>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-192.4468031288819) translate(22 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-172.74962405066697) translate(22 0)"/>
+ <text font-size="7pt" text-anchor="middle" transform="rotate(-144.8936062577638) translate(26 0) rotate(144.8936062577638) translate(0 3)">1</text>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-105.4992481013339) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-75.27089391379613) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-49.787212515527585) translate(22 0)"/>
+ <text font-size="7pt" text-anchor="middle" transform="rotate(-27.335638497499218) translate(26 0) rotate(27.335638497499218) translate(0 3)">5</text>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-7.037864055294165) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(11.627865934146627) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(29.00150379733219) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(45.319181226708565) translate(22 0)"/>
+ <text font-size="7pt" text-anchor="middle" transform="rotate(60) translate(27 0) rotate(-60) translate(0 3)">10s</text>
+ </g>
+ </symbol>
+ </defs>
+
+
+
+ <rect class="module-background background-fill" width="75.0" height="380.0"/>
+
+
+ <polyline class="module-border-inner" points="1,1 74.0,1 74.0,379.0 1,379.0 1,1" stroke-width="0.5" fill="none"/>
+ <polyline class="module-border-middle" points="0.5,0.5 74.5,0.5 74.5,379.5 0.5,379.5 0.5,0.5" stroke-width="0.8" fill="none"/>
+ <polyline class="module-border-outer" points="0,0 75.0,0 75.0,380.0 0,380.0 0,0" stroke-width="1" fill="none"/>
+
+ <text class="title" font-size="9pt" letter-spacing="3px" text-anchor="end" transform="translate(72.0 17)">CHIRP</text>
+ <g transform="translate(25 374)">
+ <text class="brand" font-size="6.5pt" letter-spacing="2px">BGA</text>
+ <rect class="background-fill" width="2" height="2" fill="#ddd" transform="translate(11.5 -4)"/>
+ </g>
+
+
+ <g transform="translate(0 35)">
+ <text font-size="8pt" letter-spacing="2px" text-anchor="middle" transform="translate(37.5 0)">TIME</text>
+ <g transform="translate(18.5 11)"><svg id="TIME_PARAM">
+ <g transform="translate(19 19)">
+ <polyline points="-5,0 5,0" stroke-width="1" stroke="#00f"/>
+ <polyline points="0,-5 0,5" stroke-width="1" stroke="#00f"/>
+ <circle cx="0" cy="0" r="18.5" stroke-width="1" stroke="#00f" fill="none"/>
+ </g>
+ </svg></g>
+ <use xlink:href="#dial-time-chirp" transform="translate(0 -7.5)" href="#dial-time-chirp"/>
+ </g>
+
+ <g transform="translate(0 111)">
+ <text font-size="8pt" letter-spacing="2px" text-anchor="middle" transform="translate(37.5 0)">FREQ 1</text>
+ <g transform="translate(24.5 11)"><svg id="FREQUENCY1_PARAM">
+ <g transform="translate(13 13)">
+ <polyline points="-3,0 3,0" stroke-width="1" stroke="#00f"/>
+ <polyline points="0,-3 0,3" stroke-width="1" stroke="#00f"/>
+ <circle cx="0" cy="0" r="12.5" stroke-width="1" stroke="#00f" fill="none"/>
+ </g>
+ </svg></g>
+ <g transform="translate(15.0 1.5)">
+ <g transform="translate(22.5 22.5)">
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-240) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-206.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-173.33) translate(15 0)"/>
+
+ <g transform="rotate(-140) translate(14 0)">
+ <polyline points="0,0 2.5,0" stroke-width="1.0" transform="translate(0 0)"/>
+ <text font-size="5.0pt" transform="translate(5 0) rotate(140) translate(-5.5 0)">OV</text>
+ </g>
+
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-106.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-73.33) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-40) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-6.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(26.67) translate(15 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(60) translate(15 0)"/>
+ </g>
+ </g>
+ </g>
+
+ <g transform="translate(0 168)">
+ <text font-size="8pt" letter-spacing="2px" text-anchor="middle" transform="translate(37.5 0)">FREQ 2</text>
+ <g transform="translate(24.5 11)"><svg id="FREQUENCY2_PARAM">
+ <g transform="translate(13 13)">
+ <polyline points="-3,0 3,0" stroke-width="1" stroke="#00f"/>
+ <polyline points="0,-3 0,3" stroke-width="1" stroke="#00f"/>
+ <circle cx="0" cy="0" r="12.5" stroke-width="1" stroke="#00f" fill="none"/>
+ </g>
+ </svg></g>
+ <g transform="translate(15.0 1.5)">
+ <g transform="translate(22.5 22.5)">
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-240) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-206.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-173.33) translate(15 0)"/>
+
+ <g transform="rotate(-140) translate(14 0)">
+ <polyline points="0,0 2.5,0" stroke-width="1.0" transform="translate(0 0)"/>
+ <text font-size="5.0pt" transform="translate(5 0) rotate(140) translate(-5.5 0)">OV</text>
+ </g>
+
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-106.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-73.33) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-40) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-6.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(26.67) translate(15 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(60) translate(15 0)"/>
+ </g>
+ </g>
+ </g>
+
+ <g transform="translate(0 220)">
+ <g transform="translate(10 -4)">
+ <g transform="translate(0 0)"><svg id="TRIGGER_PARAM">
+ <g transform="translate(9 9)">
+ <circle cx="0" cy="0" r="8.5" stroke-width="1" stroke="#00f" fill="#f00"/>
+ </g>
+ </svg></g>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(9 26)">TRIG</text>
+ </g>
+
+ <g transform="translate(44.5 0)">
+ <g transform="translate(0 -1)">
+ <text font-size="5pt" letter-spacing="1.5px" transform="translate(-3 6)">EXP</text>
+ <g transform="translate(15 -1)"><svg id="EXPONENTIAL_PARAM">
+ <g transform="translate(4.5 4.5)">
+ <circle r="4" stroke-width="1" stroke="#00f" fill="#f00"/>
+ </g>
+ </svg></g>
+ </g>
+ <g transform="translate(0 13)">
+ <text font-size="5pt" letter-spacing="1.5px" transform="translate(-9 6)">LOOP</text>
+ <g transform="translate(15 -1)"><svg id="LOOP_PARAM">
+ <g transform="translate(4.5 4.5)">
+ <circle r="4" stroke-width="1" stroke="#00f" fill="#f00"/>
+ </g>
+ </svg></g>
+ </g>
+ </g>
+ </g>
+
+ <g transform="translate(0 248)">
+ <rect class="input-background" width="64" height="112" rx="5" transform="translate(5.5 0)"/>
+ <g transform="translate(10.5 3)"><svg id="FREQUENCY1_INPUT">
+ <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>
+ </svg></g>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 35)">V/O1</text>
+ <g transform="translate(40.5 3)"><svg id="FREQUENCY2_INPUT">
+ <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>
+ </svg></g>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(52.5 35)">V/O2</text>
+ <g transform="translate(10.5 40)"><svg id="TIME_INPUT">
+ <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>
+ </svg></g>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 72)">TIME</text>
+ <g transform="translate(10.5 77)"><svg id="TRIGGER_INPUT">
+ <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>
+ </svg></g>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 109)">TRIG</text>
+ <g class="io-group" transform="translate(30 36)">
+ <rect class="output-background" width="32" height="74" rx="5" transform="translate(7.5 2)"/>
+ <rect class="output-background-filler" width="32" height="10" transform="translate(7.5 2)"/>
+ <rect class="output-background-filler" width="10" height="10" transform="translate(7.5 66)"/>
+ <g transform="translate(10.5 4)"><svg id="EOC_OUTPUT">
+ <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>
+ </svg></g>
+ <text class="output-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 36)">EOC</text>
+ <g transform="translate(10.5 41)"><svg id="OUT_OUTPUT">
+ <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>
+ </svg></g>
+ <text class="output-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 73)">OUT</text>
+ </g>
+ </g>
+</svg>
diff --git a/res-pp/Chirp-pp.svg b/res-pp/Chirp-pp.svg
@@ -0,0 +1,262 @@
+<?xml version="1.0"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="75.0" height="380.0" viewBox="0 0 75.0 380.0">
+ <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;
+}
+
+polyline {
+ stroke: #333;
+}
+path {
+ stroke: #333;
+}
+
+rect.module-background, .background-fill {
+ fill: #ddd;
+}
+polyline.module-border-inner {
+ stroke: #e4e4e4;
+}
+polyline.module-border-middle {
+ stroke: #ebebeb;
+}
+polyline.module-border-outer {
+ stroke: #f2f2f2;
+}
+
+g.io-group {
+}
+rect.input-background, rect.input-background-filler {
+ fill: #fafafa;
+}
+rect.output-background, rect.output-background-filler {
+ fill: #bbb;
+}
+text.input-label, text.output-label {
+ /* font-size: 6pt; */
+}
+polyline.input-label, polyline.output-label {
+}
+path.input-label, path.output-label {
+}
+
+circle.port-rim {
+ stroke: #f0f0f0;
+}
+circle.port-barrel {
+ stroke: #222;
+ fill: #222;
+}
+circle.knob-center {
+ fill: #eee;
+}
+circle.knob-rim {
+ fill: #333;
+}
+circle.knob-tick {
+ fill: #fff;
+}
+polyline.knob-tick {
+ stroke: #fff;
+}
+</style>
+
+ <defs>
+ <symbol id="dial-time-chirp" viewBox="0 0 75.0px 75.0px">
+ <g transform="translate(37.5 37.5)">
+ <text font-size="7pt" text-anchor="middle" transform="rotate(-240) translate(27 0) rotate(240.0) translate(0 3)">50ms</text>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-192.4468031288819) translate(22 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-172.74962405066697) translate(22 0)"/>
+ <text font-size="7pt" text-anchor="middle" transform="rotate(-144.8936062577638) translate(26 0) rotate(144.8936062577638) translate(0 3)">1</text>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-105.4992481013339) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-75.27089391379613) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-49.787212515527585) translate(22 0)"/>
+ <text font-size="7pt" text-anchor="middle" transform="rotate(-27.335638497499218) translate(26 0) rotate(27.335638497499218) translate(0 3)">5</text>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-7.037864055294165) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(11.627865934146627) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(29.00150379733219) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(45.319181226708565) translate(22 0)"/>
+ <text font-size="7pt" text-anchor="middle" transform="rotate(60) translate(27 0) rotate(-60) translate(0 3)">10s</text>
+ </g>
+ </symbol>
+ </defs>
+
+
+
+ <rect class="module-background background-fill" width="75.0" height="380.0"/>
+
+
+ <polyline class="module-border-inner" points="1,1 74.0,1 74.0,379.0 1,379.0 1,1" stroke-width="0.5" fill="none"/>
+ <polyline class="module-border-middle" points="0.5,0.5 74.5,0.5 74.5,379.5 0.5,379.5 0.5,0.5" stroke-width="0.8" fill="none"/>
+ <polyline class="module-border-outer" points="0,0 75.0,0 75.0,380.0 0,380.0 0,0" stroke-width="1" fill="none"/>
+
+ <text class="title" font-size="9pt" letter-spacing="3px" text-anchor="end" transform="translate(72.0 17)">CHIRP</text>
+ <g transform="translate(25 374)">
+ <text class="brand" font-size="6.5pt" letter-spacing="2px">BGA</text>
+ <rect class="background-fill" width="2" height="2" fill="#ddd" transform="translate(11.5 -4)"/>
+ </g>
+
+
+ <g transform="translate(0 35)">
+ <text font-size="8pt" letter-spacing="2px" text-anchor="middle" transform="translate(37.5 0)">TIME</text>
+ <g transform="translate(18.5 11)"><svg id="TIME_PARAM">
+ <g transform="translate(19 19)">
+ <polyline points="-5,0 5,0" stroke-width="1" stroke="#00f"/>
+ <polyline points="0,-5 0,5" stroke-width="1" stroke="#00f"/>
+ <circle cx="0" cy="0" r="18.5" stroke-width="1" stroke="#00f" fill="none"/>
+ </g>
+ </svg></g>
+ <use xlink:href="#dial-time-chirp" transform="translate(0 -7.5)" href="#dial-time-chirp"/>
+ </g>
+
+ <g transform="translate(0 111)">
+ <text font-size="8pt" letter-spacing="2px" text-anchor="middle" transform="translate(37.5 0)">FREQ 1</text>
+ <g transform="translate(24.5 11)"><svg id="FREQUENCY1_PARAM">
+ <g transform="translate(13 13)">
+ <polyline points="-3,0 3,0" stroke-width="1" stroke="#00f"/>
+ <polyline points="0,-3 0,3" stroke-width="1" stroke="#00f"/>
+ <circle cx="0" cy="0" r="12.5" stroke-width="1" stroke="#00f" fill="none"/>
+ </g>
+ </svg></g>
+ <g transform="translate(15.0 1.5)">
+ <g transform="translate(22.5 22.5)">
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-240) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-206.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-173.33) translate(15 0)"/>
+
+ <g transform="rotate(-140) translate(14 0)">
+ <polyline points="0,0 2.5,0" stroke-width="1.0" transform="translate(0 0)"/>
+ <text font-size="5.0pt" transform="translate(5 0) rotate(140) translate(-5.5 0)">OV</text>
+ </g>
+
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-106.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-73.33) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-40) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-6.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(26.67) translate(15 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(60) translate(15 0)"/>
+ </g>
+ </g>
+ </g>
+
+ <g transform="translate(0 168)">
+ <text font-size="8pt" letter-spacing="2px" text-anchor="middle" transform="translate(37.5 0)">FREQ 2</text>
+ <g transform="translate(24.5 11)"><svg id="FREQUENCY2_PARAM">
+ <g transform="translate(13 13)">
+ <polyline points="-3,0 3,0" stroke-width="1" stroke="#00f"/>
+ <polyline points="0,-3 0,3" stroke-width="1" stroke="#00f"/>
+ <circle cx="0" cy="0" r="12.5" stroke-width="1" stroke="#00f" fill="none"/>
+ </g>
+ </svg></g>
+ <g transform="translate(15.0 1.5)">
+ <g transform="translate(22.5 22.5)">
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-240) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-206.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-173.33) translate(15 0)"/>
+
+ <g transform="rotate(-140) translate(14 0)">
+ <polyline points="0,0 2.5,0" stroke-width="1.0" transform="translate(0 0)"/>
+ <text font-size="5.0pt" transform="translate(5 0) rotate(140) translate(-5.5 0)">OV</text>
+ </g>
+
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-106.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-73.33) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-40) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-6.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(26.67) translate(15 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(60) translate(15 0)"/>
+ </g>
+ </g>
+ </g>
+
+ <g transform="translate(0 220)">
+ <g transform="translate(10 -4)">
+ <g transform="translate(0 0)"><svg id="TRIGGER_PARAM">
+ <g transform="translate(9 9)">
+ <circle cx="0" cy="0" r="8.5" stroke-width="1" stroke="#00f" fill="#f00"/>
+ </g>
+ </svg></g>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(9 26)">TRIG</text>
+ </g>
+
+ <g transform="translate(44.5 0)">
+ <g transform="translate(0 -1)">
+ <text font-size="5pt" letter-spacing="1.5px" transform="translate(-3 6)">EXP</text>
+ <g transform="translate(15 -1)"><svg id="EXPONENTIAL_PARAM">
+ <g transform="translate(4.5 4.5)">
+ <circle r="4" stroke-width="1" stroke="#00f" fill="#f00"/>
+ </g>
+ </svg></g>
+ </g>
+ <g transform="translate(0 13)">
+ <text font-size="5pt" letter-spacing="1.5px" transform="translate(-9 6)">LOOP</text>
+ <g transform="translate(15 -1)"><svg id="LOOP_PARAM">
+ <g transform="translate(4.5 4.5)">
+ <circle r="4" stroke-width="1" stroke="#00f" fill="#f00"/>
+ </g>
+ </svg></g>
+ </g>
+ </g>
+ </g>
+
+ <g transform="translate(0 248)">
+ <rect class="input-background" width="64" height="112" rx="5" transform="translate(5.5 0)"/>
+ <g transform="translate(10.5 3)"><svg id="FREQUENCY1_INPUT">
+ <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>
+ </svg></g>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 35)">V/O1</text>
+ <g transform="translate(40.5 3)"><svg id="FREQUENCY2_INPUT">
+ <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>
+ </svg></g>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(52.5 35)">V/O2</text>
+ <g transform="translate(10.5 40)"><svg id="TIME_INPUT">
+ <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>
+ </svg></g>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 72)">TIME</text>
+ <g transform="translate(10.5 77)"><svg id="TRIGGER_INPUT">
+ <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>
+ </svg></g>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 109)">TRIG</text>
+ <g class="io-group" transform="translate(30 36)">
+ <rect class="output-background" width="32" height="74" rx="5" transform="translate(7.5 2)"/>
+ <rect class="output-background-filler" width="32" height="10" transform="translate(7.5 2)"/>
+ <rect class="output-background-filler" width="10" height="10" transform="translate(7.5 66)"/>
+ <g transform="translate(10.5 4)"><svg id="EOC_OUTPUT">
+ <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>
+ </svg></g>
+ <text class="output-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 36)">EOC</text>
+ <g transform="translate(10.5 41)"><svg id="OUT_OUTPUT">
+ <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>
+ </svg></g>
+ <text class="output-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 73)">OUT</text>
+ </g>
+ </g>
+</svg>
diff --git a/res-src/Chirp-src.svg b/res-src/Chirp-src.svg
@@ -0,0 +1,82 @@
+<module hp="5">
+ <style/>
+
+ <defs>
+ <symbol id="dial-time-chirp" viewBox="0 0 ${width}px ${width}px">
+ <g transform="translate($width/2.0 $width/2.0)" var-scale="10000.0-50.0">
+ <text font-size="7pt" text-anchor="middle" var-r="-240" transform="rotate($r) translate(27 0) rotate(-1.0*$r) translate(0 3)">50ms</text>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(250.0**0.5/$scale**0.5*300.0-240.0) translate(22 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(500.0**0.5/$scale**0.5*300.0-240.0) translate(22 0)"/>
+ <text font-size="7pt" text-anchor="middle" var-r="1000.0**0.5/$scale**0.5*300.0-240.0" transform="rotate($r) translate(26 0) rotate(-1.0*$r) translate(0 3)">1</text>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(2000.0**0.5/$scale**0.5*300.0-240.0) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(3000.0**0.5/$scale**0.5*300.0-240.0) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(4000.0**0.5/$scale**0.5*300.0-240.0) translate(22 0)"/>
+ <text font-size="7pt" text-anchor="middle" var-r="5000.0**0.5/$scale**0.5*300.0-240.0" transform="rotate($r) translate(26 0) rotate(-1.0*$r) translate(0 3)">5</text>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(6000.0**0.5/$scale**0.5*300.0-240.0) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(7000.0**0.5/$scale**0.5*300.0-240.0) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(8000.0**0.5/$scale**0.5*300.0-240.0) translate(22 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(9000.0**0.5/$scale**0.5*300.0-240.0) translate(22 0)"/>
+ <text font-size="7pt" text-anchor="middle" transform="rotate(60) translate(27 0) rotate(-60) translate(0 3)">10s</text>
+ </g>
+ </symbol>
+ </defs>
+
+ <def xlink:href="#module5" var-name="CHIRP"/>
+
+ <g transform="translate(0 35)" var-pad="11">
+ <text font-size="8pt" letter-spacing="2px" text-anchor="middle" transform="translate($width/2.0 0)">TIME</text>
+ <def id="TIME_PARAM" xlink:href="#knob38" transform="translate($width/2.0-19 $pad)"/>
+ <use xlink:href="#dial-time-chirp" transform="translate(0 $pad+19-$width/2.0)"/>
+ </g>
+
+ <g transform="translate(0 111)" var-pad="11">
+ <text font-size="8pt" letter-spacing="2px" text-anchor="middle" transform="translate($width/2.0 0)">FREQ 1</text>
+ <def id="FREQUENCY1_PARAM" xlink:href="#knob26" transform="translate($width/2.0-13.0 $pad)"/>
+ <def xlink:href="#dial-frequency-26" transform="translate($width/2.0-22.5 $pad-9.5)"/>
+ </g>
+
+ <g transform="translate(0 168)" var-pad="11">
+ <text font-size="8pt" letter-spacing="2px" text-anchor="middle" transform="translate($width/2 0)">FREQ 2</text>
+ <def id="FREQUENCY2_PARAM" xlink:href="#knob26" transform="translate($width/2.0-13.0 $pad)"/>
+ <def xlink:href="#dial-frequency-26" transform="translate($width/2.0-22.5 $pad-9.5)"/>
+ </g>
+
+ <g transform="translate(0 220)">
+ <g transform="translate(10 -4)">
+ <def id="TRIGGER_PARAM" xlink:href="#button" transform="translate(0 0)"/>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(9 26)">TRIG</text>
+ </g>
+
+ <g transform="translate($width/2.0+7.0 0)">
+ <g transform="translate(0 -1)">
+ <text font-size="5pt" letter-spacing="1.5px" transform="translate(-3 6)">EXP</text>
+ <def id="EXPONENTIAL_PARAM" xlink:href="#button-small" transform="translate(15 -1)"/>
+ </g>
+ <g transform="translate(0 13)">
+ <text font-size="5pt" letter-spacing="1.5px" transform="translate(-9 6)">LOOP</text>
+ <def id="LOOP_PARAM" xlink:href="#button-small" transform="translate(15 -1)"/>
+ </g>
+ </g>
+ </g>
+
+ <g transform="translate(0 248)">
+ <rect class="input-background" width="64" height="112" rx="5" transform="translate(5.5 0)" />
+ <def id="FREQUENCY1_INPUT" xlink:href="#input" transform="translate(10.5 3)"/>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 35)">V/O1</text>
+ <def id="FREQUENCY2_INPUT" xlink:href="#input" transform="translate(40.5 3)"/>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(52.5 35)">V/O2</text>
+ <def id="TIME_INPUT" xlink:href="#input" transform="translate(10.5 40)"/>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 72)">TIME</text>
+ <def id="TRIGGER_INPUT" xlink:href="#input" transform="translate(10.5 77)"/>
+ <text class="input-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 109)">TRIG</text>
+ <g class="io-group" transform="translate(30 36)">
+ <rect class="output-background" width="32" height="74" rx="5" transform="translate(7.5 2)"/>
+ <rect class="output-background-filler" width="32" height="10" transform="translate(7.5 2)"/>
+ <rect class="output-background-filler" width="10" height="10" transform="translate(7.5 66)"/>
+ <def id="EOC_OUTPUT" xlink:href="#output" transform="translate(10.5 4)"/>
+ <text class="output-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 36)">EOC</text>
+ <def id="OUT_OUTPUT" xlink:href="#output" transform="translate(10.5 41)"/>
+ <text class="output-label" font-size="5pt" letter-spacing="2px" text-anchor="middle" transform="translate(22.5 73)">OUT</text>
+ </g>
+ </g>
+</module>
diff --git a/res-src/LVCO-src.svg b/res-src/LVCO-src.svg
@@ -2,28 +2,6 @@
<module hp="3">
<style/>
- <defs>
- <symbol id="dial-frequency-lvco" viewBox="0 0 45px 45px">
- <g transform="translate(22.5 22.5)">
- <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-240) translate(15 0)"/>
- <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-206.67) translate(15 0)"/>
- <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-173.33) translate(15 0)"/>
-
- <g transform="rotate(-140) translate(14 0)">
- <polyline points="0,0 2.5,0" stroke-width="1.0" transform="translate(0 0)"/>
- <text font-size="5.0pt" transform="translate(5 0) rotate(140) translate(-5.5 0)">OV</text>
- </g>
-
- <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-106.67) translate(15 0)"/>
- <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-73.33) translate(15 0)"/>
- <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-40) translate(15 0)"/>
- <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-6.67) translate(15 0)"/>
- <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(26.67) translate(15 0)"/>
- <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(60) translate(15 0)"/>
- </g>
- </symbol>
- </defs>
-
<def xlink:href="#module3" var-name="LVCO"/>
<!-- <polyline points="0,0 0,380" stroke="#0f0" stroke-width="1" fill="none" transform="translate(22.5 0)" /> -->
@@ -31,7 +9,7 @@
<g transform="translate(0 25)">
<!-- <polyline points="0,0 45,0" stroke="#0f0" stroke-width="1" fill="none" transform="translate(0 0)" /> -->
<def id="FREQUENCY_PARAM" xlink:href="#knob26" transform="translate(9.5 2)"/>
- <use xlink:href="#dial-frequency-lvco" transform="translate(0 -7.5)"/>
+ <def xlink:href="#dial-frequency-26" transform="translate(0 -7.5)"/>
</g>
<g transform="translate(0 63)">
diff --git a/res-src/defs.svg b/res-src/defs.svg
@@ -465,6 +465,26 @@
</g>
</symbol>
+ <symbol id="dial-frequency-26" viewBox="0 0 45px 45px">
+ <g transform="translate(22.5 22.5)">
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(-240) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-206.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-173.33) translate(15 0)"/>
+
+ <g transform="rotate(-140) translate(14 0)">
+ <polyline points="0,0 2.5,0" stroke-width="1.0" transform="translate(0 0)"/>
+ <text font-size="5.0pt" transform="translate(5 0) rotate(140) translate(-5.5 0)">OV</text>
+ </g>
+
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-106.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-73.33) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-40) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(-6.67) translate(15 0)"/>
+ <polyline points="0,0 2.5,0" stroke-width="0.7" transform="rotate(26.67) translate(15 0)"/>
+ <polyline points="0,0 3.5,0" stroke-width="0.7" transform="rotate(60) translate(15 0)"/>
+ </g>
+ </symbol>
+
<symbol id="dial-frequency-lfo" viewBox="0 0 128px 128px">
<g transform="translate(64 64)">
<g transform="rotate(-225.08) translate(34 0)">
@@ -546,23 +566,31 @@
</g>
</symbol>
+ <symbol id="dial-mintick-base">
+ <g>
+ <polyline points="0,0 $radius/3.0,0" stroke-width="1" transform="rotate(-240) translate($radius-2.5 0)"/>
+ <path class="$class" d="M 0 $radius*-1.0 A $radius $radius 0 0 1 $radius 0" stroke-width="0.7" stroke-linecap="round" stroke="#333" fill="none" transform="rotate(0)"/>
+ <path class="$class" d="M 0 $radius*-1.0 A $radius $radius 0 0 1 $radius 0" stroke-width="0.7" stroke-linecap="round" stroke="#333" fill="none" transform="rotate(43)"/>
+ <path class="$class" d="M 0 $radius*-1.0 A $radius $radius 0 0 0 $radius*-1.0 0" stroke-width="0.7" stroke-linecap="round" stroke="#333" fill="none" transform="rotate(0)"/>
+ <path class="$class" d="M 0 $radius*-1.0 A $radius $radius 0 0 0 $radius*-1.0 0" stroke-width="0.7" stroke-linecap="round" stroke="#333" fill="none" transform="rotate(-43)"/>
+ </g>
+ </symbol>
+
<symbol id="dial-mintick" viewBox="0 0 40px 40px">
<g transform="translate(20 20)">
- <polyline points="0,0 4,0" stroke-width="1" transform="rotate(-240) translate(10 0)"/>
- <path d="M 0 -12.5 A 12.5 12.5 0 0 1 12.5 0" stroke-width="0.7" stroke-linecap="round" stroke="#333" fill="none" transform="rotate(0)"/>
- <path d="M 0 -12.5 A 12.5 12.5 0 0 1 12.5 0" stroke-width="0.7" stroke-linecap="round" stroke="#333" fill="none" transform="rotate(43)"/>
- <path d="M 0 -12.5 A 12.5 12.5 0 0 0 -12.5 0" stroke-width="0.7" stroke-linecap="round" stroke="#333" fill="none" transform="rotate(0)"/>
- <path d="M 0 -12.5 A 12.5 12.5 0 0 0 -12.5 0" stroke-width="0.7" stroke-linecap="round" stroke="#333" fill="none" transform="rotate(-43)"/>
+ <def xlink:href="#dial-mintick-base" var-radius="12.5"/>
</g>
</symbol>
<symbol id="dial-mintick-input" viewBox="0 0 40px 40px">
<g transform="translate(20 20)">
- <polyline class="input-label" points="0,0 4,0" stroke-width="1" transform="rotate(-240) translate(10 0)"/>
- <path class="input-label" d="M 0 -12.5 A 12.5 12.5 0 0 1 12.5 0" stroke-width="0.7" stroke-linecap="round" stroke="#333" fill="none" transform="rotate(0)"/>
- <path class="input-label" d="M 0 -12.5 A 12.5 12.5 0 0 1 12.5 0" stroke-width="0.7" stroke-linecap="round" stroke="#333" fill="none" transform="rotate(43)"/>
- <path class="input-label" d="M 0 -12.5 A 12.5 12.5 0 0 0 -12.5 0" stroke-width="0.7" stroke-linecap="round" stroke="#333" fill="none" transform="rotate(0)"/>
- <path class="input-label" d="M 0 -12.5 A 12.5 12.5 0 0 0 -12.5 0" stroke-width="0.7" stroke-linecap="round" stroke="#333" fill="none" transform="rotate(-43)"/>
+ <def xlink:href="#dial-mintick-base" var-radius="12.5" class="input-label"/>
+ </g>
+ </symbol>
+
+ <symbol id="dial-mintick26" viewBox="0 0 40px 40px">
+ <g transform="translate(20 20)">
+ <def xlink:href="#dial-mintick-base" var-radius="19"/>
</g>
</symbol>
diff --git a/res/Chirp-dark.svg b/res/Chirp-dark.svg
Binary files differ.
diff --git a/res/Chirp-lowcontrast.svg b/res/Chirp-lowcontrast.svg
Binary files differ.
diff --git a/res/Chirp.svg b/res/Chirp.svg
Binary files differ.
diff --git a/src/Chirp.cpp b/src/Chirp.cpp
@@ -0,0 +1,155 @@
+
+#include "Chirp.hpp"
+#include "vco_base.hpp"
+#include "dsp/pitch.hpp"
+
+void Chirp::Engine::reset() {
+ trigger.reset();
+ eocPulseGen.process(10.0f);
+}
+
+void Chirp::Engine::sampleRateChange(float sr) {
+ chirp.setSampleRate(sr);
+ ampSL.setParams(sr, Chirp::cycleSlewSeconds * 1000.0f, -Amplifier::minDecibels);
+}
+
+void Chirp::reset() {
+ for (int c = 0; c < _channels; ++c) {
+ _engines[c]->reset();
+ }
+}
+
+void Chirp::sampleRateChange() {
+ float sr = APP->engine->getSampleRate();
+ _sampleTime = 1.0f / sr;
+ for (int c = 0; c < _channels; ++c) {
+ _engines[c]->sampleRateChange(sr);
+ }
+}
+
+bool Chirp::active() {
+ return outputs[OUT_OUTPUT].isConnected() || outputs[EOC_OUTPUT].isConnected();
+}
+
+int Chirp::channels() {
+ return inputs[FREQUENCY1_INPUT].getChannels();
+}
+
+void Chirp::addChannel(int c) {
+ _engines[c] = new Engine();
+ _engines[c]->reset();
+ _engines[c]->sampleRateChange(APP->engine->getSampleRate());
+}
+
+void Chirp::removeChannel(int c) {
+ delete _engines[c];
+ _engines[c] = NULL;
+}
+
+void Chirp::modulate() {
+ _exponential = params[EXPONENTIAL_PARAM].getValue() > 0.5f;
+ _loop = params[LOOP_PARAM].getValue() > 0.5f;
+}
+
+void Chirp::modulateChannel(int c) {
+ Engine& e = *_engines[c];
+
+ float time = clamp(params[TIME_PARAM].getValue(), 0.0f, 1.0f);
+ if (inputs[TIME_INPUT].isConnected()) {
+ time *= clamp(inputs[TIME_INPUT].getPolyVoltage(c) / 10.0f, 0.0f, 1.0f);
+ }
+ time *= time;
+ time *= maxTimeSeconds - minTimeSeconds;
+ time += minTimeSeconds;
+
+ float maxF = roundf(maxFrequencyNyquistRatio * APP->engine->getSampleRate());
+ float f1 = params[FREQUENCY1_PARAM].getValue();
+ if (inputs[FREQUENCY1_INPUT].isConnected()) {
+ f1 += clamp(inputs[FREQUENCY1_INPUT].getVoltage(c), -5.0f, 5.0f);
+ }
+ f1 = cvToFrequency(f1);
+ f1 = clamp(f1, minFrequency, maxF);
+
+ float f2 = params[FREQUENCY2_PARAM].getValue();
+ if (inputs[FREQUENCY2_INPUT].isConnected()) {
+ f2 += clamp(inputs[FREQUENCY2_INPUT].getVoltage(c), -5.0f, 5.0f);
+ }
+ f2 = cvToFrequency(f2);
+ f2 = clamp(f2, minFrequency, maxF);
+
+ e.chirp.setParams(f1, f2, time, !_exponential);
+}
+
+void Chirp::processChannel(const ProcessArgs& args, int c) {
+ Engine& e = *_engines[c];
+
+ bool triggered = e.trigger.process(params[TRIGGER_PARAM].getValue()*5.0f + inputs[TRIGGER_INPUT].getPolyVoltage(c));
+ _run = _run || triggered || _loop;
+ float out = 0.0f;
+ if (_run) {
+ out = e.chirp.next() * 5.0f;
+ if (e.chirp.isCycleComplete()) {
+ _run = false;
+ e.eocPulseGen.trigger(0.001f);
+ e.targetAmplitude = 0.0f;
+ }
+ else if (e.chirp.isCycleNearlyComplete(cycleSlewSeconds)) {
+ e.targetAmplitude = Amplifier::minDecibels;
+ }
+
+ e.amp.setLevel(e.ampSL.next(e.targetAmplitude));
+ out = e.amp.next(out);
+ }
+
+ outputs[OUT_OUTPUT].setChannels(_channels);
+ outputs[OUT_OUTPUT].setVoltage(out, c);
+ outputs[EOC_OUTPUT].setChannels(_channels);
+ outputs[EOC_OUTPUT].setVoltage(e.eocPulseGen.process(_sampleTime) * 5.0f, c);
+}
+
+struct ChirpWidget : BGModuleWidget {
+ static constexpr int hp = 5;
+
+ ChirpWidget(Chirp* module) {
+ setModule(module);
+ box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT);
+ setPanel(box.size, "Chirp");
+
+ addChild(createWidget<ScrewSilver>(Vec(0, 0)));
+ addChild(createWidget<ScrewSilver>(Vec(box.size.x - 15, 365)));
+
+ // generated by svg_widgets.rb
+ auto timeParamPosition = Vec(18.5, 46.0);
+ auto frequency1ParamPosition = Vec(24.5, 122.0);
+ auto frequency2ParamPosition = Vec(24.5, 179.0);
+ auto triggerParamPosition = Vec(10.0, 216.0);
+ auto exponentialParamPosition = Vec(59.5, 218.0);
+ auto loopParamPosition = Vec(59.5, 232.0);
+
+ auto frequency1InputPosition = Vec(10.5, 251.0);
+ auto frequency2InputPosition = Vec(40.5, 251.0);
+ auto timeInputPosition = Vec(10.5, 288.0);
+ auto triggerInputPosition = Vec(10.5, 325.0);
+
+ auto eocOutputPosition = Vec(40.5, 288.0);
+ auto outOutputPosition = Vec(40.5, 325.0);
+ // end generated by svg_widgets.rb
+
+ addParam(createParam<Knob38>(timeParamPosition, module, Chirp::TIME_PARAM));
+ addParam(createParam<Knob26>(frequency1ParamPosition, module, Chirp::FREQUENCY1_PARAM));
+ addParam(createParam<Knob26>(frequency2ParamPosition, module, Chirp::FREQUENCY2_PARAM));
+ addParam(createParam<Button18>(triggerParamPosition, module, Chirp::TRIGGER_PARAM));
+ addParam(createParam<IndicatorButtonGreen9>(exponentialParamPosition, module, Chirp::EXPONENTIAL_PARAM));
+ addParam(createParam<IndicatorButtonGreen9>(loopParamPosition, module, Chirp::LOOP_PARAM));
+
+ addInput(createInput<Port24>(frequency1InputPosition, module, Chirp::FREQUENCY1_INPUT));
+ addInput(createInput<Port24>(frequency2InputPosition, module, Chirp::FREQUENCY2_INPUT));
+ addInput(createInput<Port24>(timeInputPosition, module, Chirp::TIME_INPUT));
+ addInput(createInput<Port24>(triggerInputPosition, module, Chirp::TRIGGER_INPUT));
+
+ addOutput(createOutput<Port24>(eocOutputPosition, module, Chirp::EOC_OUTPUT));
+ addOutput(createOutput<Port24>(outOutputPosition, module, Chirp::OUT_OUTPUT));
+ }
+};
+
+Model* modelChirp = createModel<Chirp, ChirpWidget>("Bogaudio-Chirp", "CHIRP", "Swept-sine oscillator", "Oscillator", "Polyphonic");
diff --git a/src/Chirp.hpp b/src/Chirp.hpp
@@ -0,0 +1,133 @@
+#pragma once
+
+#include "bogaudio.hpp"
+#include "dsp/oscillator.hpp"
+#include "dsp/signal.hpp"
+
+extern Model* modelChirp;
+
+using namespace bogaudio::dsp;
+
+namespace bogaudio {
+
+struct Chirp : BGModule {
+ enum ParamsIds {
+ TIME_PARAM,
+ FREQUENCY1_PARAM,
+ FREQUENCY2_PARAM,
+ TRIGGER_PARAM,
+ EXPONENTIAL_PARAM,
+ LOOP_PARAM,
+ NUM_PARAMS
+ };
+
+ enum InputsIds {
+ FREQUENCY1_INPUT,
+ FREQUENCY2_INPUT,
+ TIME_INPUT,
+ TRIGGER_INPUT,
+ NUM_INPUTS
+ };
+
+ enum OutputsIds {
+ EOC_OUTPUT,
+ OUT_OUTPUT,
+ NUM_OUTPUTS
+ };
+
+ static constexpr float minTimeSeconds = 0.05f;
+ static constexpr float maxTimeSeconds = 10.0f;
+ static constexpr float minFrequency = 1.0f;
+ static constexpr float maxFrequencyNyquistRatio = 0.49f;
+ static constexpr float cycleSlewSeconds = 0.01f;
+
+ struct TimeParamQuantity : ParamQuantity {
+ float getDisplayValue() override {
+ float v = getValue();
+ if (!module) {
+ return v;
+ }
+
+ float vv = v * v;
+ vv *= Chirp::maxTimeSeconds - Chirp::minTimeSeconds;
+ vv += Chirp::minTimeSeconds;
+ return vv;
+ }
+
+ void setDisplayValue(float displayValue) override {
+ if (!module) {
+ return;
+ }
+ displayValue -= Chirp::minTimeSeconds;
+ displayValue = std::max(0.0f, displayValue);
+ float v = displayValue / (Chirp::maxTimeSeconds - Chirp::minTimeSeconds);
+ v = powf(v, 0.5f);
+ setValue(v);
+ }
+ };
+
+ struct FrequencyParamQuantity : ParamQuantity {
+ float getDisplayValue() override {
+ float v = getValue();
+ if (!module) {
+ return v;
+ }
+
+ float vv = v * v;
+ vv *= roundf(APP->engine->getSampleRate() * Chirp::maxFrequencyNyquistRatio) - Chirp::minFrequency;
+ vv += Chirp::minFrequency;
+ return vv;
+ }
+
+ void setDisplayValue(float displayValue) override {
+ if (!module) {
+ return;
+ }
+ displayValue -= Chirp::minFrequency;
+ displayValue = std::max(0.0f, displayValue);
+ float v = displayValue / (roundf(APP->engine->getSampleRate() * Chirp::maxFrequencyNyquistRatio) - Chirp::minFrequency);
+ v = powf(v, 0.5f);
+ setValue(v);
+ }
+ };
+
+ struct Engine {
+ ChirpOscillator chirp;
+ Trigger trigger;
+ rack::dsp::PulseGenerator eocPulseGen;
+ Amplifier amp;
+ bogaudio::dsp::SlewLimiter ampSL;
+ float targetAmplitude = 0.0f;
+
+ void reset();
+ void sampleRateChange(float sr);
+ };
+
+ Engine* _engines[maxChannels] {};
+ float _sampleTime;
+ bool _run = false;
+ bool _exponential = false;
+ bool _loop = false;
+
+ Chirp() {
+ config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
+ configParam<TimeParamQuantity>(TIME_PARAM, 0.0f, 1.0f, 0.30899415, "Time", "s");
+ configParam<FrequencyParamQuantity>(FREQUENCY1_PARAM, -3.0f, 6.0f, -3.0f, "Frequency 1", " Hz");
+ configParam<FrequencyParamQuantity>(FREQUENCY2_PARAM, -3.0f, 6.0f, 6.0f, "Frequency 2", " Hz");
+ configParam(TRIGGER_PARAM, 0.0f, 1.0f, 0.0f, "Trigger");
+ configParam(EXPONENTIAL_PARAM, 0.0f, 1.0f, 1.0f, "Exponential");
+ configParam(LOOP_PARAM, 0.0f, 1.0f, 1.0f, "Loop");
+ }
+
+ void reset() override;
+ void sampleRateChange() override;
+ bool active() override;
+ int channels() override;
+ void addChannel(int c) override;
+ void removeChannel(int c) override;
+ void modulate() override;
+ void modulateChannel(int c) override;
+ void processChannel(const ProcessArgs& args, int c) override;
+};
+
+} // namespace bogaudio
diff --git a/src/bogaudio.cpp b/src/bogaudio.cpp
@@ -14,6 +14,7 @@
#include "Blank3.hpp"
#include "Blank6.hpp"
#include "Bool.hpp"
+#include "Chirp.hpp"
#include "Clpr.hpp"
#include "Cmp.hpp"
#include "CmpDist.hpp"
@@ -120,6 +121,7 @@ void init(rack::Plugin *p) {
p->addModel(modelXCO);
p->addModel(modelAdditator);
p->addModel(modelFMOp);
+ p->addModel(modelChirp);
p->addModel(modelLFO);
p->addModel(modelEightFO);
diff --git a/src/dsp/oscillator.cpp b/src/dsp/oscillator.cpp
@@ -323,36 +323,29 @@ void ChirpOscillator::setParams(float frequency1, float frequency2, float time,
_f2 = frequency2;
_Time = time;
_linear = linear;
- update();
+
+ _k = pow((double)(_f2 / _f1), 1.0f / (double)_Time);
}
}
void ChirpOscillator::_sampleRateChanged() {
+ _oscillator.setSampleRate(_sampleRate);
_sampleTime = 1.0f / _sampleRate;
- update();
-}
-
-void ChirpOscillator::update() {
- _Time = std::max(2.0f * _sampleTime, _Time);
- _c = (double)(_f2 - _f1) / (double)_Time;
- _k = pow((double)(_f2 / _f1), (double)(1.0f / _Time));
- _invlogk = 1.0 / log(_k);
}
float ChirpOscillator::_next() {
- float phase = 0.0f;
- if (_linear) {
- phase = 2.0 * M_PI * (0.5 * _c * (double)(_time * _time) + (double)(_f1 * _time));
- }
- else {
- phase = 2.0 * M_PI * (double)_f1 * ((pow(_k, (double)_time) - 1.0) * _invlogk);
- }
-
_time += _sampleTime;
+ _complete = false;
if (_time >= _Time) {
_time = 0.0f;
_complete = true;
}
- return _phasor.nextForPhase(Phasor::radiansToPhase(phase));
+ if (_linear) {
+ _oscillator.setFrequency(_f1 + (_time / _Time) * (_f2 - _f1));
+ }
+ else {
+ _oscillator.setFrequency((double)_f1 * pow(_k, (double)_time));
+ }
+ return _oscillator.next();
}
diff --git a/src/dsp/oscillator.hpp b/src/dsp/oscillator.hpp
@@ -336,7 +336,7 @@ struct ChirpOscillator : OscillatorGenerator {
static constexpr float minFrequency = 1.0f;
static constexpr float minTimeSeconds = 0.025f;
- TablePhasor _phasor;
+ SineTableOscillator _oscillator;
float _f1 = -1.0f;
float _f2 = -1.0f;
float _Time = -1.0f;
@@ -345,9 +345,7 @@ struct ChirpOscillator : OscillatorGenerator {
float _sampleTime = 0.0f;
float _time = 0.0f;
bool _complete = false;
- double _c = 0.0;
double _k = 0.0;
- double _invlogk = 0.0;
ChirpOscillator(
float sampleRate = 1000.0f,
@@ -356,15 +354,15 @@ struct ChirpOscillator : OscillatorGenerator {
float time = 1.0f,
bool linear = true
)
- : _phasor(StaticSineTable::table(), sampleRate, frequency1)
+ : _oscillator(sampleRate)
{
setParams(frequency1, frequency2, time, linear);
}
inline bool isCycleComplete() { return _complete; }
- void setParams(float frequency1, float frequency2, float, bool linear);
+ inline bool isCycleNearlyComplete(float seconds) { return _time > _Time - seconds; }
+ void setParams(float frequency1, float frequency2, float time, bool linear);
void _sampleRateChanged() override;
- void update();
float _next() override;
};