commit f6de9792ed7efe3111bad564d061d11540a4e18d
parent 6756ef3d4774e85ed030cce2a0d2806f96e55d7a
Author: Matt Demanett <matt@demanett.net>
Date: Sun, 21 Nov 2021 14:19:35 -0500
Merge branch 'rack2'
Diffstat:
256 files changed, 3321 insertions(+), 1326 deletions(-)
diff --git a/README-prerelease.md b/README-prerelease.md
@@ -20,29 +20,32 @@ Modules for [VCV Rack](https://github.com/VCVRack/Rack), an open-source Eurorack
Most Bogaudio modules support VCV Rack's polyphony feature; see <a href="#polyphony">Note on Polyphony</a>.
-Some modules have expanders; see <a href="#expanders">notes on expanders</a>.
+Some modules have expanders; see <a href="#expanders">Note on Expanders</a>.
-
+Many modules support bypassing in a non-default way; see <a href="#bypassing">Note on Bypassing</a>.
-
+
-
+
-
+
-
+
+
+
The modules have two <a href="#alternate_panels">alternate panel designs</a>, "Dark":
-
+
+
+And "Dark (low-contrast)":
-And "Dark {low-contrast)":
+
-
## Builds/Releases
-Mac, Linux and Windows builds of the latest version are available through [Rack's Plugin Manager](https://vcvrack.com/plugins.html). Find release notes on the [releases page](https://github.com/bogaudio/BogaudioModules/releases).
+Mac, Linux and Windows builds of the latest version are available through the [VCV Rack Library](https://library.vcvrack.com). Find release notes on the [releases page](https://github.com/bogaudio/BogaudioModules/releases).
## Building
@@ -55,14 +58,14 @@ You'll need to be set up to build [VCV Rack](https://github.com/VCVRack/Rack) it
make
```
-The master branch of this module currently builds against Rack 1.1.x.
+The master branch of this module currently builds against Rack 2.0.x.
## Modules
### <a name="oscillators"></a> Oscillators
-
+
#### <a name="vco"></a> VCO
@@ -80,7 +83,9 @@ In linear mode, the frequency 1000HZ times the pitch voltage (as determined by t
The context menu option "DC offset correction", on by default, removes DC offset from the outputs. Presently, this only affects the square output when the pulse width is set to anything besides 50%. When this is enabled, and viewing the output on a scope, the waveform will move up and down relative to 0V as the pulse width is changed -- this is the DC offset removal in action. When disabled, the waveform stays centered on 0V, which is useful if using the output as CV.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/OCT input. The poly port can be changed to the FM input on the context menu.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/OCT input. The poly port can be changed to the FM input on the context menu.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="lvco"></a> LVCO
@@ -90,6 +95,8 @@ Context menu option "Reset phase on wave change", if enabled, causes the wavefor
_Polyphony:_ Same as VCO.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="sine"></a> SINE
A 3HP subset of VCO, designed in particular for use making synth drums. The waveform defaults to sine but is selectable on the context menu, with the same options as LVCO, with the addition of a ramp (inverse saw) wave.
@@ -98,11 +105,15 @@ Additionally, there is a phase control with CV borrowed from XCO (if CV is used,
_Polyphony:_ Same as VCO.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="pulse"></a> PULSE
A 3HP subset of VCO, oriented toward pulse-width modulation. The only output waveform is square/pulse, and there is no FM. However, the PWM CV input has a dedicated attenuverter, and unlike VCO, the result CV value is summed with the PW knob position.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="xco"></a> XCO
@@ -116,11 +127,13 @@ Includes all the features of VCO, adding:
The context menu option "DC offset correction" works as documented on <a href="#vco">VCO</a>.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="additator"></a> ADDITATOR
-
+
An additive oscillator, where the output is the sum of up to 100 individual sine/cosine waves (partials). Various parameter knobs/CVs allow control over the number, frequencies and amplitudes of the partials:
- PARTIALS: sets the partial count.
@@ -132,7 +145,9 @@ An additive oscillator, where the output is the sum of up to 100 individual sine
- BALANCE: cuts the amplitudes of the odd or even partials.
- FILTER: manipulates the partial amplitudes to simulate low or high-pass filter effects.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="fmop"></a> FM-OP
@@ -146,7 +161,9 @@ A sine-wave oscillator and simple synth voice designed to allow patching up the
Anti-aliasing techniques are applied when feedback or external FM are in use. Either condition for anti-aliasing can be disabled on the context menu. Prior to version 1.1.36, due to a long-standing bug, there was no anti-aliasing for external FM, unless feedback was also on. To get that behavior back, **the true vintage FM-OP sound**, disable "Anti-alias external FM" on the menu.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="chirp"></a> CHIRP
@@ -158,7 +175,9 @@ The frequency sweep can be linear in time, or exponential, under the control of
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.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/O1 input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
### <a name="lfos"></a> LFOs
@@ -190,7 +209,9 @@ Output smoothing is applied to the signal last, after offset and scale. Smoothi
To save space, offset and smoothing share a CV input port. By default this will route CV to offset. A context-menu option allows the CV to be routed to smoothing instead.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="llfo"></a> LLFO
@@ -200,7 +221,9 @@ Sampling and smoothing functions are available on the context menu.
Context menu option "Reset phase on wave change", if enabled, causes the waveform phase to be set to zero when the waveform is changed. By default the continues to advance from wherever it was. In either case, the output will typically jump to a new value, which may cause clicks or other undesirable effects depending on how the output is used; adding a bit of smoothing may help.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="fourfo"></a> 4FO
@@ -210,13 +233,17 @@ A quadrature LFO, with outputs at 4 different phases. The phases may be set by
Note that with the stepped random output, each output will update its output when its phase crosses 0 degrees. Each draws from the same random sequence, rather than separate ones -- the outputs only vary in phase.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="eightfo"></a> 8FO
An "octature" LFO, like 4FO, but with outputs at 8 phases. By default the phases are 0, 45, 90, etc, degrees from the fundamental.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
### <a name="filters"></a> Filters
@@ -252,13 +279,17 @@ Note: due to limitations in the filter's implementation, it has a couple workaro
- There is a fixed two-pole highpass filter on the filter output, at a cutoff of 80hz.
- While the module's frequency knob goes to zero, the filter's cutoff won't actually go below 3hz.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="lvcf"></a> LVCF
A compact version of VCF. The filter slope may be set on the context menu.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="ffb"></a> FFB
@@ -273,7 +304,9 @@ There are three outputs:
- ODD: a mix of the LP, HP, and odd-numbered band filters (125HZ, 250 HZ, etc).
- EVEN: a mix of the LP, HP, and even-numbered band filters (175HZ, 350 HZ, etc).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to each of ALL, ODD and EVEN.
#### <a name="eq"></a> EQ
@@ -284,17 +317,21 @@ The cutoff/center frequencies of the three filters are:
- MID: 350HZ
- HIGH: 1000HZ
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="eqs"></a> EQS
A stereo version of EQ. The left and right inputs are processed by separate filters, but the filter parameters are set by the shared three knobs.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the L input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the L input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes left and right inputs unmodified to the corresponding outputs.
#### <a name="lpg"></a> LPG
-
+
LPG is a "low-pass gate", where an envelope generator, low-pass filter (LPF) and amplifier (VCA) are combined into a single sound-shaping unit. It lends itself to percussive or plucked sounds, though longer notes are possible.
@@ -304,7 +341,9 @@ The signal received at IN is processed by an LPF and VCA in series before being
If LINEAR is enabled, the VCA has a linear-in-amplitude response to its BIAS, CV and the envelope; otherwise it has a linear-in-decibels response.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the TRIG input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the TRIG input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="llpg"></a> LLPG
@@ -313,7 +352,9 @@ LLPG is a compact, simplified version of <a href="#LPG">LPG</a>, where:
- There are no ENV knobs; the envelope applies in full to both the filter and VCA.
- There are no CV inputs, and no linear VCA mode.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the TRIG input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the TRIG input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="megagate"></a> MEGAGATE
@@ -339,9 +380,11 @@ The final cutoff and level settings are determined by scaling (multiplying) the
If LIN VCA is enabled, the VCA has a linear-in-amplitude response to its BIAS, CV and the evelope; otherwise it has a linear-in-decibels response.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the GATE input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the GATE input.
-
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
+
#### <a name="peq"></a> PEQ
@@ -355,7 +398,9 @@ Likewise each channel has an FCV input for frequency modulation, and additionall
Finally, each channel has a BW (bandwidth) setting, that applies if the channel is a bandpass filter, and controls the width of the filter's frequency response. These have unipolar CVs per channel.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="peq6"></a> PEQ6
@@ -365,12 +410,16 @@ A six channel parametric EQ. It generally works as PEQ does, except:
- The "FCV RNG" option controls the scaling of the frequency CV inputs; if set to OCTV, the full CV range will alter the band frequencies up to an octave in either direction; if set to FULL, the CV can run the frequencies over the full range, as on PEQ.
- On the context (right-click) menu, there is an option "Exclude direct-output bands from mix"; if this is enabled, any band that has its direct output in use (if something is patched to its output) does not get its output mixed into the main output. Usually, the main output includes all bands.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="peq6xf"></a> PEQ6XF
Expands PEQ6 with envelope follower outputs, per band. The DAMP and GAIN knobs control the followers; see the description of the <a href="#follow">FOLLOW</a> module for a description of how these work.
+
+
#### <a name="peq14"></a> PEQ14
A fourteen channel parametric EQ. The control scheme is as with PEQ6.
@@ -379,7 +428,9 @@ It adds ODD and EVEN outputs: these are mixes of the odd and even channels, resp
The "Exclude direct-output bands..." option, if enabled, applies to ODD and EVEN as well as the main OUT.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to each of OUT, ODD and EVEN.
#### <a name="peq14xf"></a> PEQ14XF
@@ -392,43 +443,53 @@ Expands PEQ14 with envelope follower outputs, per band. The DAMP and GAIN knobs
DADSRH (Delay, Attack, Decay, Sustain, Release, Hold) is an envelope generator, augmenting a standard ADSR design with a delay stage and a self-gating (hold) mode.
-
+
Features:
- When the MODE switch is set to GATE, DADSRH is a more-or-less standard ADSR envelope generator, with an additional pre-attack delay stage. The envelope is controlled by a gate CV at the trigger port, or by holding the TRIGGER button.
- When MODE is TRIG, a trigger CV or press of the TRIGGER button will start a normal DADSR cycle, but controlled by an internal gate CV. The internal gate persists for the time set by the HOLD knob.
- The envelope is output as a 0-10 signal at port ENV. Its inverse (10V - ENV) is output at INV. When a release stage completes, a trigger is emitted at END.
- When MODE is TRIGGER, the CYCLE switch controls whether the envelope loops or not upon completion of a release stage.
- - Toggles allow selection of linear, exponential or inverse-exponential shapes for the attack, decay and release stages.
+ - Toggles allow selection of linear, exponential or inverse-exponential ("logarithmic", more or less) shapes for the attack, decay and release stages.
+ - The SPEED switch slows down the timing of segments by 10x.
- The RETRIG switch controls the retrigger behavior (when a new gate or trigger happens while the envelope is running): ATT immediately attacks from the current envelope value (this is the typical behavior with many ADSRs), while RST causes a full reset of the envelope (restarting it at the delay stage).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the TRIGGER input. Pressing the trigger button will trigger all channels.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the TRIGGER input. Pressing the trigger button will trigger all channels.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="dadsrhplus"></a> DADSRH+
DADSRH+ is a DADSRH, with the addition of CV inputs for each knob, and gate outputs for each stage (a stage's gate output will be high for the duration of the stage).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the TRIGGER input. Pressing the trigger button will trigger all channels.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the TRIGGER input. Pressing the trigger button will trigger all channels.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="shaper"></a> SHAPER
SHAPER emulates the function of the Envelope Generator section of the classic [EMS VC3](https://en.wikipedia.org/wiki/EMS_VCS_3) and related synths. It combines an envelope with a VCA. Unlike an ADSR, the envelope stages are attack, on, decay and off, producing a signature trapezoidal envelope shape.
-
+
Features:
- The ATTACK, ON, DECAY and OFF knobs specify times from nearly zero to 10 seconds. The SPEED switch allows these times to be multiplied by 10.
- The trapezoid envelope is output as a 0-10V control signal at port ENV, subject to attenuation by the ENV knob. (INV outputs 10V - ENV.)
- Audio input at port IN is sent through the internal VCA -- controlled by knob SIGNAL and the envelope -- to port OUT. Turning up the SIGNAL knob can dramatically amplify the signal. [This is actually a design error, but enough people have used it this way that we leave it be.]
- A trigger CV at the TRIGGER port, or a press of the TRIGGER button, will start the envelope cycle. When the off stage completes, a trigger is emitted at port END. If the CYCLE switch is set to LOOP, the envelope restarts immediately.
+ - The SPEED switch slows down the timing of segments by 10x.
+
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the TRIGGER input. Pressing the trigger button will trigger all channels.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the TRIGGER input. Pressing the trigger button will trigger all channels.
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="shaperplus"></a> SHAPER+
SHAPER+ is a SHAPER, with the addition of CV inputs for each knob, and gate outputs for each stage (a stage's gate output will be high for the duration of the stage).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the TRIGGER input. Pressing the trigger button will trigger all channels.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the TRIGGER input. Pressing the trigger button will trigger all channels.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="ad"></a> AD
@@ -440,23 +501,29 @@ If the RT (retrigger) toggle is enabled, if TRIG receives a new trigger while th
If the LP (loop) toggle is enabled, the envelope cycles continuously (it doesn't need a trigger to start it). If RT is also enabled, triggers at TRIG will restart the cycle (this is similar to syncing an LFO).
-By default, the attack and decay envelope segments have an exponential curve -- in linear mode (the LIN toggle), the segments are linear.
+By default, the attack and decay envelope segments have a logarithmic (more or less) curve -- in linear mode (the LIN toggle), the segments are linear.
+
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the TRIG input.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the TRIG input.
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="asr"></a> ASR
-ASR is AR (if triggered) or ASR (Attack, Sustain, Release -- if gated) envelope generator. It has CV inputs for the attack and release times (if CVs are used, they are attenuated by the corresponding knob values). The sustain level may be set by the small knob marked S. The attack and release segments have an exponential shape by default, but can be made linear with the LIN toggle.
+ASR is AR (if triggered) or ASR (Attack, Sustain, Release -- if gated) envelope generator. It has CV inputs for the attack and release times (if CVs are used, they are attenuated by the corresponding knob values). The sustain level may be set by the small knob marked S. The attack and release segments are curved by default, but can be made linear with the LIN toggle.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the TRIG input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the TRIG input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="adsr"></a> ADSR
A standard ADSR (Attack, Decay, Sustain, Release) envelope generator in 3HP. The attack, decay and release knobs are exponentially scaled with durations up to 10 seconds. The sustain knob is linearly scaled, setting the sustain level from 0 to 10 volts. Lights below each stage knob indicate which stage is active.
-By default, the attack, decay and release envelope segments have an exponential curve -- in linear mode (the LIN button), the segments are linear.
+By default, the attack, decay and release envelope segments have a curve -- in linear mode (the LIN button), the segments are linear.
+
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the GATE input.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the GATE input.
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="vish"></a> VISH
@@ -475,15 +542,19 @@ The slew limiter is controlled by the RISE and FALL controls, which behave exact
If the TIMES 10X option is enabled, the values of the rise and fall times, and MIN GATE, subject to their CVs, are multiplied by 10. Thus fall and MIN GATE can go to a maximum of 10 seconds, and rise to 3 seconds.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the GATE input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the GATE input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="dgate"></a> DGATE
-
+
A trigger-to-gate utility, with gate duration up to 10 seconds, and an optional pre-delay of up to 10 seconds. A trigger pulse is emitted at END when a delay/gate cycle ends. If the STOP/LOOP switch is set to LOOP, or if the trigger is high when the cycle ends, the cycle repeats.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the TRIG input. Pressing the trigger button will trigger all channels.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the TRIG input. Pressing the trigger button will trigger all channels.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="rgate"></a> RGATE
@@ -510,13 +581,17 @@ The module is usable as a general clock divider/multiplier; in this case it's ad
The module can also be used to generate pulse waves from incoming audio, where the output pitch is some ratio of the input, according to CLK DIV and CLK MUL. For example, with CLK DIV set to 2, and CLK MUL to 1, and with a square wave input, the output will be a pulse wave tracking an octave below the input. LENGTH becomes a pulse-width control in this case. CLK MUL will multiply the increasing frequency to a point; at some point the output frequency would be faster than the internals of RGate update, and nothing happens. If using the module this way, it makes sense to set the output to bipolar.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the CLOCK input, by default, or the LENGTH input, if so set on the context menu.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the CLOCK input, by default, or the LENGTH input, if so set on the context menu.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="edge"></a> EDGE
A trigger-to-gate utility, comparator and rising/falling edge detector. RISE and FALL set voltage levels: when the input goes above RISE, the module switches to "high" state and outputs a voltage at the HIGH output. HOLD sets a minimum time that the module stays in the high state; this can be used to avoid jitter on the output if using high-frequency inputs. 1ms trigger pulses are output at RISE and FALL on the corresponding changes (note that if you switch the module state at audio rates, these will essentially always be high).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="follow"></a> FOLLOW
@@ -524,7 +599,9 @@ An envelope follower (a utility that converts its input to a CV proportional to
The GAIN knob and CV (+/-5V) can attenuate or amplify the output. Turning the knob counter-clockwise form center will cut the output up to -36dB; turning it clockwise will amplify it up to +12dB.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
### <a name="mixers"></a> Mixers, Panners and VCAs
@@ -533,7 +610,7 @@ _Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the I
An eight-channel mixer/panner with mutes.
-
+
Features:
- Eight input channels with decibel-calibrated level faders.
@@ -552,6 +629,8 @@ _Polyphony:_ The module is monophonic: if a polyphonic cable is present at an in
However, there is a non-standard polyphonic feature: on the context (right-click) menu, there are options to "spread" a polyphonic input connected to input channel 1 (only) across the mixer's inputs, as if the poly input had been split into eight mono inputs and each connected to the mixer. This can be applied to channels 1-8 of the input, or channels 9-16. Any input patched to an input other than input 1 will override the spread signal.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="mix8x"></a> MIX8X
An expander for MIX8, adding an EQ for each mixer channel, and two sends and stereo returns.
@@ -566,29 +645,37 @@ Return A and B are each stereo, with the right input being normalled to the left
MIX8X must be positioned to the right of, and ajacent to, the base MIX8 module it will pair with. See <a href="#expanders">notes on expanders</a>.
+
+
#### <a name="mix4"></a> MIX4
A four-channel version of MIX8 with the same features.
_Polyphony:_ As with MIX8, this is a monophonic module, but with the same non-standard "spread" feature (in groups of four channels).
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="mix4x"></a> MIX4X
An expander for MIX4, with functionality identical to what MIX8X adds to MIX8.
-
+
#### <a name="mix1"></a> MIX1
A 3HP fader/VCA, with mute.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="mix2"></a> MIX2
-A stereo version of MIX1.
+A stereo version of MIX1. The left input is normalled to the right.
+
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the L input.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the L input.
+_When <a href="#bypassing">bypassed</a>:_ passes left and right inputs unmodified to the corresponding outputs; left is passed to right if right is unpatched.
#### <a name="umix"></a> UMIX
@@ -599,7 +686,9 @@ The context (right-click) menu has a few options:
- "Output clipping" sets the manner of output clipping: "Soft" applies saturation or soft clipping, which is better for audio, and which is the default; "Hard" simply clips the output at +/-12V. "Hard" is better for CVs, as this mode will achieve precise summing of CVs; otherwise the saturator will slightly affect (reduce) the sums at all levels.
- "Average" causes the module to average, rather than sum, its inputs.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphonic channels defined by the first/topmost input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphonic channels defined by the first/topmost input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="mumix"></a> MUMIX
@@ -611,6 +700,8 @@ See also <a href="switch81">SWITCH81</a>, which is similar to this, with options
_Polyphony:_ same as UMIX.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="mute8"></a> MUTE8
MUTE8 provides 8 independent manual or CV-controlled mutes. Each channel is muted if its button is toggled on or if there is a positive voltage at its CV input. Otherwise the input is passed to the output.
@@ -619,7 +710,9 @@ As with MIX4 and MIX8, a right-click on a mute button will solo that channel (pa
If context menu option "Latching CV triggers" is enabled, triggers on the CV inputs toggle muting on and off.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, where each of the 8 channels may be independently polyphonic, as defined by the cable at the channel's input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, where each of the 8 channels may be independently polyphonic, as defined by the cable at the channel's input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes each input unmodified to the corresponding output.
#### <a name="vcm"></a> VCM
@@ -631,13 +724,17 @@ Features:
By default, the output is hard clipped at +/-12V (this is a standard in Rack). A context menu option allows this limit to be disabled.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphonic channels defined by the first IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphonic channels defined by the first IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="pan"></a> PAN
-A stereo panner with dual inputs channels. Each channel's panner may be controlled with a +/-5 volt CV; when CV is in use, it is attenuverted the corresponding knob. The output saturates (soft clips) to +/-12 volts.
+A stereo panner with dual input channels. Each channel's panner may be controlled with a +/-5 volt CV; when CV is in use, it is attenuverted by the corresponding knob. The output saturates (soft clips) to +/-12 volts.
+
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the first/top IN input.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the first/top IN input.
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="xfade"></a> XFADE
@@ -650,21 +747,27 @@ The SHAPE knob affects the attenuation curves of the two channels as MIX changes
Linear mode (the LIN button) makes the level attenuation response of MIX linear in amplitude (useful when processing CV); otherwise and by default the response is linear in decibels (and therefore exponential in amplitude).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the A input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the A input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="matrix81"></a> MATRIX81
-
+
An eight input, one output version of <a href="#matrix44">MATRIX44</a>, below.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, as on MATRIX44.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, as on MATRIX44.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="matrix18"></a> MATRIX18
A one input, eight output version of <a href="#matrix44">MATRIX44</a>, below.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, as on MATRIX44.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, as on MATRIX44.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="matrix44"></a> MATRIX44
@@ -682,7 +785,9 @@ The knobs visually indicate their values with green/orange colors. This can be
Option "Unipolar" sets the knobs to travel from zero to 100% over their full travel (which is to say that they can no longer be set to invert the input). The panel does not update; the tick at noon for each knob indicates 50% in this mode.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphonic channels defined by input 1.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphonic channels defined by input 1.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="matrix44cvm"></a> MX44CVM
@@ -694,11 +799,13 @@ MX44CVM must be positioned to the right of, and adjacent to, the MATRIX44 module
#### <a name="matrix88"></a> MATRIX88
-
+
An 8x8 version of MATRIX44. It is expanable with <a href="matrix88cv">MX88CV</a> and <a href="matrix88m">MX88M</a>.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphonic channels defined by the first/topmost input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphonic channels defined by the first/topmost input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="matrix88cv"></a> MX88CV
@@ -716,7 +823,7 @@ MX88M must be positioned to the right of, and adjacent to, the MATRIX88 module i
#### <a name="switch81"></a> SWITCH81
-
+
An eight input, one output version of <a href="#switch44">SWITCH44</a>, below.
@@ -724,7 +831,9 @@ SWITCH81 is related to <a href="#mumix">MUMIX</a>, with the difference that a sw
If the option "Exclusive switching" is enabled, on the context menu, then only one switch may be active at once (only one input will be routed to the output).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, as on SWITCH44.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, as on SWITCH44.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="switch18"></a> SWITCH18
@@ -732,7 +841,9 @@ A one input, eight output version of <a href="#switch44">SWITCH44</a>, below.
If the option "Exclusive switching" is enabled, on the context menu, then only one switch may be active at once (the input is only routed to one of the outputs).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, as on SWITCH44.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, as on SWITCH44.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="switch44"></a> SWITCH44
@@ -751,26 +862,32 @@ Two other options, "Exclusive switching by row" and "Exclusive switching by colu
Every switch applies a bit of slew limitation when it changes values, as an anti-popping measure.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphonic channels defined by input 1.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphonic channels defined by input 1.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="switch88"></a> SWITCH88
An 8x8 version of SWITCH44.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphonic channels defined by the first/topmost input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphonic channels defined by the first/topmost input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="switch1616"></a> SWITCH1616
A 16x16 version of SWITCH44.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphonic channels defined by input 1.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphonic channels defined by input 1.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
### <a name="dynamics"></a> VCAs and Dynamics
#### <a name="vca"></a> VCA
-
+
A two-channel voltage-controlled attenuator. (An attenuator can only reduce a signal.)
@@ -778,7 +895,9 @@ Each channel's level may be controlled with a 0-10V CV; when CV is in use, it is
In linear mode (the LIN button), the knob/CV response is linear in amplitude (useful when processing CV); otherwise and by default the response is linear in decibels (and therefore exponential in amplitude).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the IN input, independently for the top and bottom sections of the module.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the IN input, independently for the top and bottom sections of the module.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT independently in each channel.
#### <a name="vcamp"></a> VCAMP
@@ -786,9 +905,9 @@ A voltage-controlled amplifier, capable of adding 12 decibels gain to the input.
The level may be controlled with a 0-10V CV -- when CV is in use, it is attenuated by the corresponding slider. The slider's toggle has a light indicating the output signal level. The output saturates (soft clips) to +/-12V.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the IN input.
-
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="velo"></a> VELO
@@ -808,7 +927,11 @@ The bipolar CV is optionally coupled to the LEVEL knob/input, but this coupling
Using the bipolar CV, it's possible to drive the VCA past unity gain, up to +12db (4x amplitude). The module soft-clips at +/-12V, and driving the signal into the clipper will result in distortion.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
+
+
#### <a name="amrm"></a> AM/RM
@@ -822,7 +945,9 @@ The RECT inputs expects a bipolar (+/-5V) CV, which is added to the RECTIFY knob
Note: AM/RM is calibrated to expect +/-5V, 10V peak-to-peak signals (i.e. the output of a typical oscillator). A modulator signal with a negative value in excess of -5V will be affected by the rectifier circuit even if the RECTIFY is zero. To avoid this effect, you may need to attenuate a hot signal you wish to use as the modulator.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the CAR input. The polyphony input can be switched to MOD on the context menu.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the CAR input. The polyphony input can be switched to MOD on the context menu.
+
+_When <a href="#bypassing">bypassed</a>:_ passes the CAR (carrier) input unmodified to OUT; the RECT output is 0V.
#### <a name="pressor"></a> PRESSOR
@@ -844,7 +969,9 @@ The various controls and ports work as follows:
Several of the settings can take fairly extreme values (e.g. OUT GAIN); this allows the module to be used as a distortion effect.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the L input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the L input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes left and right inputs unmodified to the corresponding outputs.
#### <a name="clpr"></a> CLPR
@@ -852,7 +979,9 @@ CLPR is a compact (6HP) [clipper](https://en.wikipedia.org/wiki/Clipping_%28audi
In contrast to LMTR, CLPR chops a signal at a voltage threshold corresponding to the selected amplitude, significantly distorting the signal.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the L input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the L input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes left and right inputs unmodified to the corresponding outputs.
#### <a name="lmtr"></a> LMTR
@@ -860,13 +989,17 @@ LMTR is a compact (6HP) [limiter](https://en.wikipedia.org/wiki/Dynamic_range_co
In contrast to CLPR, LMTR does not distort the signal very much; it just reduces the amplitude of the signal to keep it below the threshold.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the L input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the L input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes left and right inputs unmodified to the corresponding outputs.
#### <a name="nsgt"></a> NSGT
NSGT is a compact (6HP) [noise gate](https://en.wikipedia.org/wiki/Noise_gate). Its controls behave the same as the corresponding controls on PRESSOR. Controls for attack and release times are on the context menu.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the L input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the L input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes left and right inputs unmodified to the corresponding outputs.
#### <a name="cmpdist"></a> CMPDIST
@@ -888,7 +1021,9 @@ The MIX output is also subject to the DRY/WET setting, where the dry signal is c
**Note:** this module is intended for audio-rate use, as a distortion effect; if you want a proper window comparator for use with CV, take a look at <a href="#cmp">CMP</a>.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the A input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the A input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
### <a name="random"></a> Noise/Random, Sample and Hold
@@ -903,6 +1038,8 @@ Additionally, NOISE has an absolute value circuit. Patch audio into ABS to get
_Polyphony:_ For the noise outputs, the number of polyphonic channels is set on the context (right-click) menu. Independently, the ABS circuit is <a href="#polyphony">polyphonic</a>, with polyphony defined by the IN input.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="samplehold"></a> S&H
A dual sample-and-hold and trigger-and-hold. Sampling may be triggered by CV (on the rising edge of a trigger or gate) or button press.
@@ -917,7 +1054,9 @@ The GATE input on the lower section is normalled to GATE in the top section (but
The GLIDE context menu option applies linear glide (slew limitation, smoothing) to the outputs. The time value, which defaults to 0, determines how long the output will take to change (slew) 10V. This option is ignored in track-and-hold mode.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the GATE input in each section. If the bottom GATE is patched, the two sections will independently take their channels from their respective GATE inputs; if only the top GATE is patched, the bottom section normals to the top input and both sections have the same number of channels. The polyphony port can be changed to IN on the context menu (this change applies to both top and bottom sections of the module; IN does not normal to the bottom section, and both sections will set their channels independently, from whatever is patched to their own IN).
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the GATE input in each section. If the bottom GATE is patched, the two sections will independently take their channels from their respective GATE inputs; if only the top GATE is patched, the bottom section normals to the top input and both sections have the same number of channels. The polyphony port can be changed to IN on the context menu (this change applies to both top and bottom sections of the module; IN does not normal to the bottom section, and both sections will set their channels independently, from whatever is patched to their own IN).
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="walk2"></a> WALK2
@@ -946,16 +1085,20 @@ Various options on the context (right-click) menu allow customization of the dis
_Polyphony:_ The module is monophonic (note that WALK is polyphonic).
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="walk"></a> WALK
WALK is a single-channel random walk, identical to one channel of WALK2, in 3HP. It has a JUMP input rather than a TRIG input, but the same S&H and T&H modes are available on the context menu.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the RATE input. The polyphony port can be changed to OFFSET, SCALE or JUMP on the context menu.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the RATE input. The polyphony port can be changed to OFFSET, SCALE or JUMP on the context menu.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
### <a name="sequencers"></a> Sequential Switches and Sequencers
-
+
#### <a name="eightone"></a> 8:1
@@ -973,7 +1116,9 @@ If option "Select on clock mode" is selected, then the select value (knob and CV
Option "Triggered select mode" changes how the SELECT feature works, replacing the continuous voltage selection with a second internal sequence that offsets (adds to) the primary sequential switch step. In this mode, the SELECT input expects trigger pulses, which advance the secondary sequence, while the SELECT knob sets the length of the secondary sequence (and a trigger at RESET will reset it). Thus different clocks and step lengths can be used to create complex output step patterns. "Select on clock mode" has no effect if "Triggered select mode" is enabled.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the CLOCK input. This can be set to the SELECT CV input on the context menu.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the CLOCK input. This can be set to the SELECT CV input on the context menu.
+
+_When <a href="#bypassing">bypassed</a>:_ passes input 1 unmodified to the output.
#### <a name="oneeight"></a> 1:8
@@ -981,6 +1126,8 @@ _Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the
_Polyphony:_ Same as 8:1.
+_When <a href="#bypassing">bypassed</a>:_ passes the input unmodified to output 1.
+
#### <a name="addrseq"></a> ADDR-SEQ
ADDR-SEQ is an 8-step sequencer where the step values are set by 8 knobs (with default output range of +/-10V). It has the same clocked or voltage-addressed control circuit as 8:1 and 1:8. It can be expanded to more steps, 8 at a time, with <a href="#addrseqx">ASX</a>.
@@ -989,6 +1136,8 @@ The output range of the knobs may be set on the context (right-click) menu to a
_Polyphony:_ Same as 8:1.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="addrseqx"></a> ASX
ASX is a chainable expander for <a href="addrseq">ADDR-SEQ</a>, adding 8 steps to the base sequence.
@@ -997,7 +1146,7 @@ When ASXs are added to an ADDR-SEQ, ADDR-SEQ's STEPS and SELECT knobs (and selec
Each ASX in a chain must be positioned to the right of, and adjacent to, the previous ASX in the chain, or the base ADDR-SEQ module. See <a href="#expanders">notes on expanders</a>.
-
+
#### <a name="pgmr"></a> PGMR
@@ -1009,9 +1158,13 @@ The current step can be selected many ways:
- By pressing the button, or sending a trigger to the SELECT input, for a given step.
- By inputs to CLOCK and/or SELECT, subject to the FWD and S.O.C. ("Select On Clock") toggles. The behavior of these is the same as it is on <a href="#eightone">8:1</a> (and 1:8 and ADDR-SEQ), with the exception that the voltage range to the SELECT input is divided by the number of steps present on PGMR and all its connected PGMRX instances (where the division is always by 8 -- 16 if you consider negative voltages -- on 8:1).
+The leftmost bottom output emits a trigger whenever the step changes. The outputs below each channel selector emit a trigger when that step is selected.
+
Any PGMRX expanders must be positioned to the right of, and ajacent to, the base PGMR module, or the previous PGMRX in the chain. See <a href="#expanders">notes on expanders</a>.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the CLOCK input. This can be set to the SELECT CV input on the context menu.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the CLOCK input. This can be set to the SELECT CV input on the context menu.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="pgmrx"></a> PGMRX
@@ -1022,7 +1175,7 @@ Each PGMRX in a chain must be positioned to the right of, and ajacent to, the pr
### <a name="visualizers"></a> Visualizers
-
+
#### <a name="vu"></a> VU
@@ -1030,6 +1183,8 @@ A stereo signal level visualizer/meter. The L channel is sent to both displays
_Polyphony:_ Monophonic, but if an input is polyphonic, its channels are summed, and summed value is used to compute the level displayed (independently for the left and right inputs).
+_When <a href="#bypassing">bypassed</a>:_ passes left and right inputs unmodified to the corresponding outputs.
+
#### <a name="analyzer"></a> ANALYZER
A four-channel spectrum analyzer.
@@ -1054,7 +1209,7 @@ _Polyphony:_ Monophonic, with two exceptions:
#### <a name="analyzerxl"></a> ANALYZER-XL
-
+
An eight-channel, 42HP version of ANALYZER, with edge-to-edge-screen design. Options corresponding to ANALYZER's panel controls are available on the context (right-click) menu. An extra "Quality" setting, "Ultra+" is available; this uses an FFT size of 16384 (or 32768 if Rack's sample rate is 96khz or higher).
@@ -1064,7 +1219,7 @@ _Polyphony:_ Monophonic, but if an input is polyphonic, its channels are summed,
#### <a name="ranalyzer"></a> RANALYZER
-
+
RANALYZER is a frequency response analyzer: it passes a test signal to another module, expecting the output of that module to be patched back, and then displays the frequency spectrum of the response relative to the test signal.
@@ -1093,12 +1248,14 @@ _Polyphony:_ Monophonic.
### <a name="poly"></a> Polyphony Utilities
-
+
#### <a name="mono"></a> MONO
MONO mixes down the channels of a polyphonic cable to a single-channel mono output. It is an alternative to the SUM module that comes with VCV Rack, but adds a basic onboard compressor, to even out the level differences when only a few, or many, channels on the input are sounding. The COMP control sets the amount of compression; at zero there is no effect and the behavior of this module is essentially equivalent to Rack's SUM. As with SUM, the LEVEL control simply attenuates the output. The output, post-LEVEL, is saturated (soft-clipped) at +/-12V.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="arp"></a> ARP
ARP is a performance-oriented arpeggiator, where the arpeggiated notes come from polyphonic pitch and gate inputs. It is designed to patched directly to Rack's MIDI-CV (with polyphony enabled) and be played with a MIDI keyboard. As below, it can be controlled by other modules as well, though this needs to be done carefully.
@@ -1132,6 +1289,8 @@ The outputs are always monophonic -- patch ARP into ASSIGN to play an arpeggio t
Note that the HOLD toggle and "Use new notes" menu setting still apply however you control ARP. If not playing from a keyboard, it will usually make sense to toggle HOLD on and set "Use new notes" to "Immediately".
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="assign"></a> ASSIGN
ASSIGN is a mono-to-poly voice assigner and poly-to-poly voice reassigner (where the in and out channel counts may be different). Mono vs poly operation is defined the poly channel count on the GATE input.
@@ -1142,6 +1301,8 @@ With mono inputs, on each gate received at GATE, the current pitch at V/OCT is a
With polyphonic inputs, when a gate goes high on an input channel, the gate and corresponding pitch are assigned to an output channel. Up to the number of channels defined by the CHAN knob may be output at once. The module attempts to reuse free channels; if none are free the oldest assignment is replaced.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="unison"></a> UNISON
UNISON allows for unison-mode play of a polyphonic voice, where monophonic pitch and gate inputs are copied out to multiple polyphonic channels, as set by the CHAN knob.
@@ -1155,20 +1316,26 @@ The behavior of DETUNE depends on the number of output channels:
- With four channels, a channel gets each of: up and down the full amount and up and down half the amount.
- And so on, such that the detune amounts are evenly spread, and one channel gets the unaltered pitch if and only if the channel count is odd.
-
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
+
#### <a name="polycon"></a> POLYCON16
-POLYCON16 allows fixed voltages to be sent directly to some number of channels, by channel number, of a polyphonic output. The number of output channels is set the CHAN knob, unless an input is present at the CHAN input, in which case the channel count is taken from that input, and the knob is ignored.
+POLYCON16 allows fixed voltages to be sent directly to some number of channels, by channel number, of a polyphonic output. The number of output channels is set by the CHAN knob, unless an input is present at the CHAN input, in which case the channel count is taken from that input, and the knob is ignored.
This can be used to introduce a bit of fixed variation across the channels of a poly voice.
The context menu option range allows the output voltages to be set from several bipolar and unipolar ranges. Note that when a unipolar range is used, 0V will be output when the knob is fully counter-clockwise, even though the knobs are drawn with a bipolar dial (such that 0V is usually at noon).
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="polycon8"></a> POLYCON8
A compact version of POLYCON16, that only works with polyphony channels 1-8. The channel count must be set on the context (right-click) menu.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="polyoff16"></a> POLYOFF16
POLYOFF16 allows for the independent offset and scaling of voltages on each channel of a polyphonic signal. It can also be used as a replacement for Rack's MERGE, which combines monophonic signals into a polyphonic signal, but here with per-channel offset and scale controls.
@@ -1187,16 +1354,22 @@ The module has the same "Range" context-menu options as POLYCON16, here altering
The context-menu option "Order of operations" sets the order in which OFFSET and SCALE are applied to each channel. The default is to scale, then offset. This behavior was the opposite prior to version 1.1.36. See <a href="#offset">OFFSET</a> for more detail on this; the behavior is the same here.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="polyoff8"></a> POLYOFF8
A half-width version of POLYCON16, that only works with polyphony channels 1-8.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="polymult"></a> POLYMULT
POLYMULT will turn a mono signal into a polyphonic signal, with a given number of channels, where each channel gets a copy of the input voltage. The number of channels is set by the CHAN knob, unless an input is present at the CHAN input, in which case the channel count is taken from that input, and the knob is ignored. Each OUT output is identical.
To simply make copies of an already-polyphonic signal, use the regular <a href="#mult">MULT</a> module.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
### <a name="pitch"></a> Pitch CV Utilities
@@ -1208,7 +1381,9 @@ Utilities related to processing pitch CVs (1 volt / octave CVs, for controlling
A 1V/octave pitch processor, for controlling a detuned oscillator pair. A reference pitch in raised and lowered by the number of cents (hundredths of a semitone) specified by the knob and CV, and emitted at OUT+ and OUT-. The input pitch is emitted at THRU.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes V/OCT unmodified to each of the three outputs.
#### <a name="stack"></a> STACK
@@ -1216,7 +1391,9 @@ A 1V/octave pitch processor for stacking oscillators. The SEMIS, OCTAVE and FIN
The CV input expects +/-5V; the value modifies the interval set by the knobs in the amount of one semitone per tenth volt. If QZ (quantize) is active, the CV-controlled interval is quantized to the nearest semitone. This specialized CV is output at the THRU port, with a value set by the knobs and CV in, when there is no input pitch.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes V/OCT unmodified to both THRU and OUT.
#### <a name="reftone"></a> REFTONE
@@ -1224,6 +1401,8 @@ A tuner that outputs a selectable (Western, chromatic) pitch as CV (1V/octave, f
_Polyphony:_ Monophonic.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
### <a name="utilities"></a> Utilities
@@ -1233,7 +1412,9 @@ _Polyphony:_ Monophonic.
A boolean logic utility. Inputs are considered true if the input voltage is greater than 1V. The top section takes two inputs and computes AND, OR and XOR at the outputs. The lower section computes the negation of its input. Output is 5V if an output is true, 0V otherwise.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the first/topmost input. The NOT circuit is independently polyphonic based on its input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the first/topmost input. The NOT circuit is independently polyphonic based on its input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="cmp"></a> CMP
@@ -1248,7 +1429,9 @@ The WINDOW knob specifies the window voltage. LAG specifies a time of up to one
The OUTPUT switch sets the high and low voltage values for the outputs: 0V low/+10V high, or -5V low/+5V high.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the A input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the A input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="cvd"></a> CVD
@@ -1258,13 +1441,17 @@ The large TIME knob sets the delay time, in seconds, as scaled by the small knob
CVD may be used for lag/latency correction; using parameter entry (by right-clicking the TIME knob) is handy here, to set a precise delay. You can get sample-accurate delays by dividing the desired number of delay samples by Rack's current sample rate, and setting TIME to that number (leave the time scale knob at 1).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="flipflop"></a> FLIPFLOP
A boolean memory utility with two independent channels. A high voltage at TRIGGER will cause the state of a channel to change from A to B. A subsequent trigger will flip it back. Output is 5V at whichever of A and B is selected, 0V at the other. A trigger voltage at RESET sets the channel back to state A.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the channels at the TRIG input, independently for the two sections of the module.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the channels at the TRIG input, independently for the two sections of the module.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="inv"></a> INV
@@ -1272,16 +1459,20 @@ A dual signal inverter, with CV or manual control, and optional latching. In ea
If LATCH is enabled, a button press or high voltage toggles the state of the inverter. A context menu option "Save latched state to patch" will, if latching is enabled, save the latched state to the patch and restore it on patch load.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the channels at the IN input, independently for the two sections of the module.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the channels at the IN input, independently for the two sections of the module.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT independently in each channel.
#### <a name="manual"></a> MANUAL
A manual trigger/gate with 8 outputs. A constant +5V is sent from each output for as long as the TRIG button is held; 0V is output otherwise. The high output voltage may be set to +10V on the context menu.
-MANUAL may be set to output a trigger pulse (the high output voltage for 10ms) on patch load (akin to a Max/Msp loadbang). This is off by default; enable clicking "Trigger on Load" on the module's context (right-click) menu. The pulse is emitted 100ms after the patch starts processing samples.
+MANUAL may be set to output a trigger pulse (the high output voltage for 10ms) on patch load (akin to a Max/Msp loadbang). This is off by default; enable clicking "Trigger on load" on the module's context (right-click) menu. The pulse is emitted 100ms after the patch starts processing samples.
_Polyphony:_ Monophonic.
+_When <a href="#bypassing">bypassed</a>:_ no output; disables "Trigger on load".
+
#### <a name="fourman"></a> 4MAN
A version of MANUAL with four independent trigger buttons with separate outputs.
@@ -1290,12 +1481,16 @@ The "Trigger on load" and "Output" options, as on MANUAL, apply to all four outp
_Polyphony:_ Monophonic.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="mult"></a> MULT
A 3 HP multiple (signal splitter or duplicator). There are two 1-to-3 channels. There is also a 1-to-6 mode: if nothing is patched to the second channel's input, the input to the first channel is copied to all six outputs.
_Polyphony:_ Polyphonic inputs are duplicated (channels intact) at their corresponding outputs.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="offset"></a> OFFSET
An offset and scaler. The OFFSET and SCALE knobs have CV inputs (unipolar, 0-10V). There are two operating modes, as set by the "Order of operations" context (right-click) menu option:
@@ -1308,7 +1503,9 @@ Note that prior to version 1.1.36, there was no mode setting, and the behavior w
By default, the output is capped at +/-12 volts (this is a standard in Rack). A context menu option allows this limit to be disabled.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the channels of the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the channels of the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="slew"></a> SLEW
@@ -1322,7 +1519,9 @@ RISE and FALL each have a unipolar (0-10V) CV input affecting the corresponding
If SLOW is enabled, the slew rates for both RISE and FALL are 10x slower what they would otherwise be, based on the knobs and CVs.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the channels of the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the channels of the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="sums"></a> SUMS
@@ -1330,7 +1529,9 @@ An arithmetic logic utility. The top section outputs the sum, difference, maxim
By default, the output is capped at +/-12 volts (this is a standard in Rack). A context menu option allows this limit to be disabled.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the first/topmost input. The NEG circuit is independently polyphonic based on its input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the first/topmost input. The NEG circuit is independently polyphonic based on its input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="switch"></a> SWITCH
@@ -1342,6 +1543,8 @@ If the context menu option "Save latched state to patch" is enabled, and latchin
_Polyphony:_ If polyphonic input is present at GATE, then the module is polyphonic in the standard way, independently switching the independent polyphonic channels on the high/low inputs (the button will switch all channels). Additionally, if the input at GATE is not present or monophonic, but polyphonic cables are are present at any high/low inputs, and such an input is switched to the output, it is duplicated to the output with channels intact.
+_When <a href="#bypassing">bypassed</a>:_ passes LOW unmodified to OUT independently in each channel.
+
#### <a name="lgsw"></a> LGSW
LGSW is a version of <a href="#switch">SWITCH</a> with two gate inputs and onboard logic.
@@ -1368,9 +1571,11 @@ The logic mode can be set by CV. Using a CV for the logic overrides whatever se
_Polyphony:_ Same as <a href="#switch">SWITCH</a>, except that the polyphony channel count is set by the topmost gate input only.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
### <a name="misc"></a> Miscellaneous
-
+
#### <a name="blank3"></a> BLANK3
@@ -1418,6 +1623,17 @@ Rack allows left expanders as well as right, but to simplify things we've chosen
Some expanders may be chainable: multiple instances can be added to continue expanding the base. In this case, the expanders must all be to the right of the base, and all touching.
+## <a name="bypassing"></a> Note on Bypassing
+
+Rack adds a "Bypass" option to the context (right-click) menu on every module. By default, this fully disables the module (while allowing it to remain patched), such that the module produces no output (or more precisely, constantly outputs 0V). For some modules, however, it makes more sense to pass the module's unmodified input to the output.
+
+Most Bogaudio modules implement bypassing according these general rules:
+ - Modules that generate a signal (VCOs, LFOs, noise/random generators, envelope generators), or combine signals (mixers, logic), typically produce no output.
+ - Modules that modify a signal (filters, effects, VCAs, attenuators) typically pass their input to the output.
+
+There are various exceptions and special or ambiguous cases; see the documentation for each module for details on that module's behavior.
+
+
## <a name="alternate_panels"></a> Alternate Panels

diff --git a/README.md b/README.md
@@ -20,29 +20,32 @@ Modules for [VCV Rack](https://github.com/VCVRack/Rack), an open-source Eurorack
Most Bogaudio modules support VCV Rack's polyphony feature; see <a href="#polyphony">Note on Polyphony</a>.
-Some modules have expanders; see <a href="#expanders">notes on expanders</a>.
+Some modules have expanders; see <a href="#expanders">Note on Expanders</a>.
-
+Many modules support bypassing in a non-default way; see <a href="#bypassing">Note on Bypassing</a>.
-
+
-
+
-
+
-
+
+
+
The modules have two <a href="#alternate_panels">alternate panel designs</a>, "Dark":
-
+
+
+And "Dark (low-contrast)":
-And "Dark {low-contrast)":
+
-
## Builds/Releases
-Mac, Linux and Windows builds of the latest version are available through [Rack's Plugin Manager](https://vcvrack.com/plugins.html). Find release notes on the [releases page](https://github.com/bogaudio/BogaudioModules/releases).
+Mac, Linux and Windows builds of the latest version are available through the [VCV Rack Library](https://library.vcvrack.com). Find release notes on the [releases page](https://github.com/bogaudio/BogaudioModules/releases).
## Building
@@ -55,14 +58,14 @@ You'll need to be set up to build [VCV Rack](https://github.com/VCVRack/Rack) it
make
```
-The master branch of this module currently builds against Rack 1.1.x.
+The master branch of this module currently builds against Rack 2.0.x.
## Modules
### <a name="oscillators"></a> Oscillators
-
+
#### <a name="vco"></a> VCO
@@ -80,7 +83,9 @@ In linear mode, the frequency 1000HZ times the pitch voltage (as determined by t
The context menu option "DC offset correction", on by default, removes DC offset from the outputs. Presently, this only affects the square output when the pulse width is set to anything besides 50%. When this is enabled, and viewing the output on a scope, the waveform will move up and down relative to 0V as the pulse width is changed -- this is the DC offset removal in action. When disabled, the waveform stays centered on 0V, which is useful if using the output as CV.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/OCT input. The poly port can be changed to the FM input on the context menu.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/OCT input. The poly port can be changed to the FM input on the context menu.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="lvco"></a> LVCO
@@ -90,6 +95,8 @@ Context menu option "Reset phase on wave change", if enabled, causes the wavefor
_Polyphony:_ Same as VCO.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="sine"></a> SINE
A 3HP subset of VCO, designed in particular for use making synth drums. The waveform defaults to sine but is selectable on the context menu, with the same options as LVCO, with the addition of a ramp (inverse saw) wave.
@@ -98,11 +105,15 @@ Additionally, there is a phase control with CV borrowed from XCO (if CV is used,
_Polyphony:_ Same as VCO.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="pulse"></a> PULSE
A 3HP subset of VCO, oriented toward pulse-width modulation. The only output waveform is square/pulse, and there is no FM. However, the PWM CV input has a dedicated attenuverter, and unlike VCO, the result CV value is summed with the PW knob position.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="xco"></a> XCO
@@ -116,11 +127,13 @@ Includes all the features of VCO, adding:
The context menu option "DC offset correction" works as documented on <a href="#vco">VCO</a>.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="additator"></a> ADDITATOR
-
+
An additive oscillator, where the output is the sum of up to 100 individual sine/cosine waves (partials). Various parameter knobs/CVs allow control over the number, frequencies and amplitudes of the partials:
- PARTIALS: sets the partial count.
@@ -132,7 +145,9 @@ An additive oscillator, where the output is the sum of up to 100 individual sine
- BALANCE: cuts the amplitudes of the odd or even partials.
- FILTER: manipulates the partial amplitudes to simulate low or high-pass filter effects.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="fmop"></a> FM-OP
@@ -146,7 +161,9 @@ A sine-wave oscillator and simple synth voice designed to allow patching up the
Anti-aliasing techniques are applied when feedback or external FM are in use. Either condition for anti-aliasing can be disabled on the context menu. Prior to version 1.1.36, due to a long-standing bug, there was no anti-aliasing for external FM, unless feedback was also on. To get that behavior back, **the true vintage FM-OP sound**, disable "Anti-alias external FM" on the menu.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="chirp"></a> CHIRP
@@ -158,7 +175,9 @@ The frequency sweep can be linear in time, or exponential, under the control of
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.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/O1 input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
### <a name="lfos"></a> LFOs
@@ -190,7 +209,9 @@ Output smoothing is applied to the signal last, after offset and scale. Smoothi
To save space, offset and smoothing share a CV input port. By default this will route CV to offset. A context-menu option allows the CV to be routed to smoothing instead.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="llfo"></a> LLFO
@@ -200,7 +221,9 @@ Sampling and smoothing functions are available on the context menu.
Context menu option "Reset phase on wave change", if enabled, causes the waveform phase to be set to zero when the waveform is changed. By default the continues to advance from wherever it was. In either case, the output will typically jump to a new value, which may cause clicks or other undesirable effects depending on how the output is used; adding a bit of smoothing may help.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="fourfo"></a> 4FO
@@ -210,13 +233,17 @@ A quadrature LFO, with outputs at 4 different phases. The phases may be set by
Note that with the stepped random output, each output will update its output when its phase crosses 0 degrees. Each draws from the same random sequence, rather than separate ones -- the outputs only vary in phase.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="eightfo"></a> 8FO
An "octature" LFO, like 4FO, but with outputs at 8 phases. By default the phases are 0, 45, 90, etc, degrees from the fundamental.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
### <a name="filters"></a> Filters
@@ -252,13 +279,17 @@ Note: due to limitations in the filter's implementation, it has a couple workaro
- There is a fixed two-pole highpass filter on the filter output, at a cutoff of 80hz.
- While the module's frequency knob goes to zero, the filter's cutoff won't actually go below 3hz.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="lvcf"></a> LVCF
A compact version of VCF. The filter slope may be set on the context menu.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="ffb"></a> FFB
@@ -273,7 +304,9 @@ There are three outputs:
- ODD: a mix of the LP, HP, and odd-numbered band filters (125HZ, 250 HZ, etc).
- EVEN: a mix of the LP, HP, and even-numbered band filters (175HZ, 350 HZ, etc).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to each of ALL, ODD and EVEN.
#### <a name="eq"></a> EQ
@@ -284,17 +317,21 @@ The cutoff/center frequencies of the three filters are:
- MID: 350HZ
- HIGH: 1000HZ
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="eqs"></a> EQS
A stereo version of EQ. The left and right inputs are processed by separate filters, but the filter parameters are set by the shared three knobs.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the L input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the L input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes left and right inputs unmodified to the corresponding outputs.
#### <a name="lpg"></a> LPG
-
+
LPG is a "low-pass gate", where an envelope generator, low-pass filter (LPF) and amplifier (VCA) are combined into a single sound-shaping unit. It lends itself to percussive or plucked sounds, though longer notes are possible.
@@ -304,7 +341,9 @@ The signal received at IN is processed by an LPF and VCA in series before being
If LINEAR is enabled, the VCA has a linear-in-amplitude response to its BIAS, CV and the envelope; otherwise it has a linear-in-decibels response.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the TRIG input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the TRIG input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="llpg"></a> LLPG
@@ -313,7 +352,9 @@ LLPG is a compact, simplified version of <a href="#LPG">LPG</a>, where:
- There are no ENV knobs; the envelope applies in full to both the filter and VCA.
- There are no CV inputs, and no linear VCA mode.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the TRIG input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the TRIG input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="megagate"></a> MEGAGATE
@@ -339,9 +380,11 @@ The final cutoff and level settings are determined by scaling (multiplying) the
If LIN VCA is enabled, the VCA has a linear-in-amplitude response to its BIAS, CV and the evelope; otherwise it has a linear-in-decibels response.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the GATE input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the GATE input.
-
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
+
#### <a name="peq"></a> PEQ
@@ -355,7 +398,9 @@ Likewise each channel has an FCV input for frequency modulation, and additionall
Finally, each channel has a BW (bandwidth) setting, that applies if the channel is a bandpass filter, and controls the width of the filter's frequency response. These have unipolar CVs per channel.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="peq6"></a> PEQ6
@@ -365,12 +410,16 @@ A six channel parametric EQ. It generally works as PEQ does, except:
- The "FCV RNG" option controls the scaling of the frequency CV inputs; if set to OCTV, the full CV range will alter the band frequencies up to an octave in either direction; if set to FULL, the CV can run the frequencies over the full range, as on PEQ.
- On the context (right-click) menu, there is an option "Exclude direct-output bands from mix"; if this is enabled, any band that has its direct output in use (if something is patched to its output) does not get its output mixed into the main output. Usually, the main output includes all bands.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="peq6xf"></a> PEQ6XF
Expands PEQ6 with envelope follower outputs, per band. The DAMP and GAIN knobs control the followers; see the description of the <a href="#follow">FOLLOW</a> module for a description of how these work.
+
+
#### <a name="peq14"></a> PEQ14
A fourteen channel parametric EQ. The control scheme is as with PEQ6.
@@ -379,7 +428,9 @@ It adds ODD and EVEN outputs: these are mixes of the odd and even channels, resp
The "Exclude direct-output bands..." option, if enabled, applies to ODD and EVEN as well as the main OUT.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to each of OUT, ODD and EVEN.
#### <a name="peq14xf"></a> PEQ14XF
@@ -392,43 +443,53 @@ Expands PEQ14 with envelope follower outputs, per band. The DAMP and GAIN knobs
DADSRH (Delay, Attack, Decay, Sustain, Release, Hold) is an envelope generator, augmenting a standard ADSR design with a delay stage and a self-gating (hold) mode.
-
+
Features:
- When the MODE switch is set to GATE, DADSRH is a more-or-less standard ADSR envelope generator, with an additional pre-attack delay stage. The envelope is controlled by a gate CV at the trigger port, or by holding the TRIGGER button.
- When MODE is TRIG, a trigger CV or press of the TRIGGER button will start a normal DADSR cycle, but controlled by an internal gate CV. The internal gate persists for the time set by the HOLD knob.
- The envelope is output as a 0-10 signal at port ENV. Its inverse (10V - ENV) is output at INV. When a release stage completes, a trigger is emitted at END.
- When MODE is TRIGGER, the CYCLE switch controls whether the envelope loops or not upon completion of a release stage.
- - Toggles allow selection of linear, exponential or inverse-exponential shapes for the attack, decay and release stages.
+ - Toggles allow selection of linear, exponential or inverse-exponential ("logarithmic", more or less) shapes for the attack, decay and release stages.
+ - The SPEED switch slows down the timing of segments by 10x.
- The RETRIG switch controls the retrigger behavior (when a new gate or trigger happens while the envelope is running): ATT immediately attacks from the current envelope value (this is the typical behavior with many ADSRs), while RST causes a full reset of the envelope (restarting it at the delay stage).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the TRIGGER input. Pressing the trigger button will trigger all channels.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the TRIGGER input. Pressing the trigger button will trigger all channels.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="dadsrhplus"></a> DADSRH+
DADSRH+ is a DADSRH, with the addition of CV inputs for each knob, and gate outputs for each stage (a stage's gate output will be high for the duration of the stage).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the TRIGGER input. Pressing the trigger button will trigger all channels.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the TRIGGER input. Pressing the trigger button will trigger all channels.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="shaper"></a> SHAPER
SHAPER emulates the function of the Envelope Generator section of the classic [EMS VC3](https://en.wikipedia.org/wiki/EMS_VCS_3) and related synths. It combines an envelope with a VCA. Unlike an ADSR, the envelope stages are attack, on, decay and off, producing a signature trapezoidal envelope shape.
-
+
Features:
- The ATTACK, ON, DECAY and OFF knobs specify times from nearly zero to 10 seconds. The SPEED switch allows these times to be multiplied by 10.
- The trapezoid envelope is output as a 0-10V control signal at port ENV, subject to attenuation by the ENV knob. (INV outputs 10V - ENV.)
- Audio input at port IN is sent through the internal VCA -- controlled by knob SIGNAL and the envelope -- to port OUT. Turning up the SIGNAL knob can dramatically amplify the signal. [This is actually a design error, but enough people have used it this way that we leave it be.]
- A trigger CV at the TRIGGER port, or a press of the TRIGGER button, will start the envelope cycle. When the off stage completes, a trigger is emitted at port END. If the CYCLE switch is set to LOOP, the envelope restarts immediately.
+ - The SPEED switch slows down the timing of segments by 10x.
+
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the TRIGGER input. Pressing the trigger button will trigger all channels.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the TRIGGER input. Pressing the trigger button will trigger all channels.
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="shaperplus"></a> SHAPER+
SHAPER+ is a SHAPER, with the addition of CV inputs for each knob, and gate outputs for each stage (a stage's gate output will be high for the duration of the stage).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the TRIGGER input. Pressing the trigger button will trigger all channels.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the TRIGGER input. Pressing the trigger button will trigger all channels.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="ad"></a> AD
@@ -440,23 +501,29 @@ If the RT (retrigger) toggle is enabled, if TRIG receives a new trigger while th
If the LP (loop) toggle is enabled, the envelope cycles continuously (it doesn't need a trigger to start it). If RT is also enabled, triggers at TRIG will restart the cycle (this is similar to syncing an LFO).
-By default, the attack and decay envelope segments have an exponential curve -- in linear mode (the LIN toggle), the segments are linear.
+By default, the attack and decay envelope segments have a logarithmic (more or less) curve -- in linear mode (the LIN toggle), the segments are linear.
+
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the TRIG input.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the TRIG input.
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="asr"></a> ASR
-ASR is AR (if triggered) or ASR (Attack, Sustain, Release -- if gated) envelope generator. It has CV inputs for the attack and release times (if CVs are used, they are attenuated by the corresponding knob values). The sustain level may be set by the small knob marked S. The attack and release segments have an exponential shape by default, but can be made linear with the LIN toggle.
+ASR is AR (if triggered) or ASR (Attack, Sustain, Release -- if gated) envelope generator. It has CV inputs for the attack and release times (if CVs are used, they are attenuated by the corresponding knob values). The sustain level may be set by the small knob marked S. The attack and release segments are curved by default, but can be made linear with the LIN toggle.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the TRIG input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the TRIG input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="adsr"></a> ADSR
A standard ADSR (Attack, Decay, Sustain, Release) envelope generator in 3HP. The attack, decay and release knobs are exponentially scaled with durations up to 10 seconds. The sustain knob is linearly scaled, setting the sustain level from 0 to 10 volts. Lights below each stage knob indicate which stage is active.
-By default, the attack, decay and release envelope segments have an exponential curve -- in linear mode (the LIN button), the segments are linear.
+By default, the attack, decay and release envelope segments have a curve -- in linear mode (the LIN button), the segments are linear.
+
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the GATE input.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the GATE input.
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="vish"></a> VISH
@@ -475,15 +542,19 @@ The slew limiter is controlled by the RISE and FALL controls, which behave exact
If the TIMES 10X option is enabled, the values of the rise and fall times, and MIN GATE, subject to their CVs, are multiplied by 10. Thus fall and MIN GATE can go to a maximum of 10 seconds, and rise to 3 seconds.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the GATE input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the GATE input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="dgate"></a> DGATE
-
+
A trigger-to-gate utility, with gate duration up to 10 seconds, and an optional pre-delay of up to 10 seconds. A trigger pulse is emitted at END when a delay/gate cycle ends. If the STOP/LOOP switch is set to LOOP, or if the trigger is high when the cycle ends, the cycle repeats.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the TRIG input. Pressing the trigger button will trigger all channels.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the TRIG input. Pressing the trigger button will trigger all channels.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="rgate"></a> RGATE
@@ -510,13 +581,17 @@ The module is usable as a general clock divider/multiplier; in this case it's ad
The module can also be used to generate pulse waves from incoming audio, where the output pitch is some ratio of the input, according to CLK DIV and CLK MUL. For example, with CLK DIV set to 2, and CLK MUL to 1, and with a square wave input, the output will be a pulse wave tracking an octave below the input. LENGTH becomes a pulse-width control in this case. CLK MUL will multiply the increasing frequency to a point; at some point the output frequency would be faster than the internals of RGate update, and nothing happens. If using the module this way, it makes sense to set the output to bipolar.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the CLOCK input, by default, or the LENGTH input, if so set on the context menu.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the CLOCK input, by default, or the LENGTH input, if so set on the context menu.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="edge"></a> EDGE
A trigger-to-gate utility, comparator and rising/falling edge detector. RISE and FALL set voltage levels: when the input goes above RISE, the module switches to "high" state and outputs a voltage at the HIGH output. HOLD sets a minimum time that the module stays in the high state; this can be used to avoid jitter on the output if using high-frequency inputs. 1ms trigger pulses are output at RISE and FALL on the corresponding changes (note that if you switch the module state at audio rates, these will essentially always be high).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="follow"></a> FOLLOW
@@ -524,7 +599,9 @@ An envelope follower (a utility that converts its input to a CV proportional to
The GAIN knob and CV (+/-5V) can attenuate or amplify the output. Turning the knob counter-clockwise form center will cut the output up to -36dB; turning it clockwise will amplify it up to +12dB.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
### <a name="mixers"></a> Mixers, Panners and VCAs
@@ -533,7 +610,7 @@ _Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the I
An eight-channel mixer/panner with mutes.
-
+
Features:
- Eight input channels with decibel-calibrated level faders.
@@ -552,6 +629,8 @@ _Polyphony:_ The module is monophonic: if a polyphonic cable is present at an in
However, there is a non-standard polyphonic feature: on the context (right-click) menu, there are options to "spread" a polyphonic input connected to input channel 1 (only) across the mixer's inputs, as if the poly input had been split into eight mono inputs and each connected to the mixer. This can be applied to channels 1-8 of the input, or channels 9-16. Any input patched to an input other than input 1 will override the spread signal.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="mix8x"></a> MIX8X
An expander for MIX8, adding an EQ for each mixer channel, and two sends and stereo returns.
@@ -566,29 +645,37 @@ Return A and B are each stereo, with the right input being normalled to the left
MIX8X must be positioned to the right of, and ajacent to, the base MIX8 module it will pair with. See <a href="#expanders">notes on expanders</a>.
+
+
#### <a name="mix4"></a> MIX4
A four-channel version of MIX8 with the same features.
_Polyphony:_ As with MIX8, this is a monophonic module, but with the same non-standard "spread" feature (in groups of four channels).
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="mix4x"></a> MIX4X
An expander for MIX4, with functionality identical to what MIX8X adds to MIX8.
-
+
#### <a name="mix1"></a> MIX1
A 3HP fader/VCA, with mute.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="mix2"></a> MIX2
-A stereo version of MIX1.
+A stereo version of MIX1. The left input is normalled to the right.
+
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with channels defined by the L input.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with channels defined by the L input.
+_When <a href="#bypassing">bypassed</a>:_ passes left and right inputs unmodified to the corresponding outputs; left is passed to right if right is unpatched.
#### <a name="umix"></a> UMIX
@@ -599,7 +686,9 @@ The context (right-click) menu has a few options:
- "Output clipping" sets the manner of output clipping: "Soft" applies saturation or soft clipping, which is better for audio, and which is the default; "Hard" simply clips the output at +/-12V. "Hard" is better for CVs, as this mode will achieve precise summing of CVs; otherwise the saturator will slightly affect (reduce) the sums at all levels.
- "Average" causes the module to average, rather than sum, its inputs.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphonic channels defined by the first/topmost input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphonic channels defined by the first/topmost input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="mumix"></a> MUMIX
@@ -611,6 +700,8 @@ See also <a href="switch81">SWITCH81</a>, which is similar to this, with options
_Polyphony:_ same as UMIX.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="mute8"></a> MUTE8
MUTE8 provides 8 independent manual or CV-controlled mutes. Each channel is muted if its button is toggled on or if there is a positive voltage at its CV input. Otherwise the input is passed to the output.
@@ -619,7 +710,9 @@ As with MIX4 and MIX8, a right-click on a mute button will solo that channel (pa
If context menu option "Latching CV triggers" is enabled, triggers on the CV inputs toggle muting on and off.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, where each of the 8 channels may be independently polyphonic, as defined by the cable at the channel's input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, where each of the 8 channels may be independently polyphonic, as defined by the cable at the channel's input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes each input unmodified to the corresponding output.
#### <a name="vcm"></a> VCM
@@ -631,13 +724,17 @@ Features:
By default, the output is hard clipped at +/-12V (this is a standard in Rack). A context menu option allows this limit to be disabled.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphonic channels defined by the first IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphonic channels defined by the first IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="pan"></a> PAN
-A stereo panner with dual inputs channels. Each channel's panner may be controlled with a +/-5 volt CV; when CV is in use, it is attenuverted the corresponding knob. The output saturates (soft clips) to +/-12 volts.
+A stereo panner with dual input channels. Each channel's panner may be controlled with a +/-5 volt CV; when CV is in use, it is attenuverted by the corresponding knob. The output saturates (soft clips) to +/-12 volts.
+
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the first/top IN input.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the first/top IN input.
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="xfade"></a> XFADE
@@ -650,21 +747,27 @@ The SHAPE knob affects the attenuation curves of the two channels as MIX changes
Linear mode (the LIN button) makes the level attenuation response of MIX linear in amplitude (useful when processing CV); otherwise and by default the response is linear in decibels (and therefore exponential in amplitude).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the A input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the A input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="matrix81"></a> MATRIX81
-
+
An eight input, one output version of <a href="#matrix44">MATRIX44</a>, below.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, as on MATRIX44.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, as on MATRIX44.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="matrix18"></a> MATRIX18
A one input, eight output version of <a href="#matrix44">MATRIX44</a>, below.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, as on MATRIX44.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, as on MATRIX44.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="matrix44"></a> MATRIX44
@@ -682,7 +785,9 @@ The knobs visually indicate their values with green/orange colors. This can be
Option "Unipolar" sets the knobs to travel from zero to 100% over their full travel (which is to say that they can no longer be set to invert the input). The panel does not update; the tick at noon for each knob indicates 50% in this mode.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphonic channels defined by input 1.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphonic channels defined by input 1.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="matrix44cvm"></a> MX44CVM
@@ -694,11 +799,13 @@ MX44CVM must be positioned to the right of, and adjacent to, the MATRIX44 module
#### <a name="matrix88"></a> MATRIX88
-
+
An 8x8 version of MATRIX44. It is expanable with <a href="matrix88cv">MX88CV</a> and <a href="matrix88m">MX88M</a>.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphonic channels defined by the first/topmost input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphonic channels defined by the first/topmost input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="matrix88cv"></a> MX88CV
@@ -716,7 +823,7 @@ MX88M must be positioned to the right of, and adjacent to, the MATRIX88 module i
#### <a name="switch81"></a> SWITCH81
-
+
An eight input, one output version of <a href="#switch44">SWITCH44</a>, below.
@@ -724,7 +831,9 @@ SWITCH81 is related to <a href="#mumix">MUMIX</a>, with the difference that a sw
If the option "Exclusive switching" is enabled, on the context menu, then only one switch may be active at once (only one input will be routed to the output).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, as on SWITCH44.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, as on SWITCH44.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="switch18"></a> SWITCH18
@@ -732,7 +841,9 @@ A one input, eight output version of <a href="#switch44">SWITCH44</a>, below.
If the option "Exclusive switching" is enabled, on the context menu, then only one switch may be active at once (the input is only routed to one of the outputs).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, as on SWITCH44.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, as on SWITCH44.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="switch44"></a> SWITCH44
@@ -751,26 +862,32 @@ Two other options, "Exclusive switching by row" and "Exclusive switching by colu
Every switch applies a bit of slew limitation when it changes values, as an anti-popping measure.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphonic channels defined by input 1.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphonic channels defined by input 1.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="switch88"></a> SWITCH88
An 8x8 version of SWITCH44.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphonic channels defined by the first/topmost input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphonic channels defined by the first/topmost input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="switch1616"></a> SWITCH1616
A 16x16 version of SWITCH44.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphonic channels defined by input 1.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphonic channels defined by input 1.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
### <a name="dynamics"></a> VCAs and Dynamics
#### <a name="vca"></a> VCA
-
+
A two-channel voltage-controlled attenuator. (An attenuator can only reduce a signal.)
@@ -778,7 +895,9 @@ Each channel's level may be controlled with a 0-10V CV; when CV is in use, it is
In linear mode (the LIN button), the knob/CV response is linear in amplitude (useful when processing CV); otherwise and by default the response is linear in decibels (and therefore exponential in amplitude).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the IN input, independently for the top and bottom sections of the module.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the IN input, independently for the top and bottom sections of the module.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT independently in each channel.
#### <a name="vcamp"></a> VCAMP
@@ -786,9 +905,9 @@ A voltage-controlled amplifier, capable of adding 12 decibels gain to the input.
The level may be controlled with a 0-10V CV -- when CV is in use, it is attenuated by the corresponding slider. The slider's toggle has a light indicating the output signal level. The output saturates (soft clips) to +/-12V.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the IN input.
-
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="velo"></a> VELO
@@ -808,7 +927,11 @@ The bipolar CV is optionally coupled to the LEVEL knob/input, but this coupling
Using the bipolar CV, it's possible to drive the VCA past unity gain, up to +12db (4x amplitude). The module soft-clips at +/-12V, and driving the signal into the clipper will result in distortion.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
+
+
#### <a name="amrm"></a> AM/RM
@@ -822,7 +945,9 @@ The RECT inputs expects a bipolar (+/-5V) CV, which is added to the RECTIFY knob
Note: AM/RM is calibrated to expect +/-5V, 10V peak-to-peak signals (i.e. the output of a typical oscillator). A modulator signal with a negative value in excess of -5V will be affected by the rectifier circuit even if the RECTIFY is zero. To avoid this effect, you may need to attenuate a hot signal you wish to use as the modulator.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the CAR input. The polyphony input can be switched to MOD on the context menu.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the CAR input. The polyphony input can be switched to MOD on the context menu.
+
+_When <a href="#bypassing">bypassed</a>:_ passes the CAR (carrier) input unmodified to OUT; the RECT output is 0V.
#### <a name="pressor"></a> PRESSOR
@@ -844,7 +969,9 @@ The various controls and ports work as follows:
Several of the settings can take fairly extreme values (e.g. OUT GAIN); this allows the module to be used as a distortion effect.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the L input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the L input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes left and right inputs unmodified to the corresponding outputs.
#### <a name="clpr"></a> CLPR
@@ -852,7 +979,9 @@ CLPR is a compact (6HP) [clipper](https://en.wikipedia.org/wiki/Clipping_%28audi
In contrast to LMTR, CLPR chops a signal at a voltage threshold corresponding to the selected amplitude, significantly distorting the signal.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the L input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the L input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes left and right inputs unmodified to the corresponding outputs.
#### <a name="lmtr"></a> LMTR
@@ -860,13 +989,17 @@ LMTR is a compact (6HP) [limiter](https://en.wikipedia.org/wiki/Dynamic_range_co
In contrast to CLPR, LMTR does not distort the signal very much; it just reduces the amplitude of the signal to keep it below the threshold.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the L input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the L input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes left and right inputs unmodified to the corresponding outputs.
#### <a name="nsgt"></a> NSGT
NSGT is a compact (6HP) [noise gate](https://en.wikipedia.org/wiki/Noise_gate). Its controls behave the same as the corresponding controls on PRESSOR. Controls for attack and release times are on the context menu.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the L input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the L input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes left and right inputs unmodified to the corresponding outputs.
#### <a name="cmpdist"></a> CMPDIST
@@ -888,7 +1021,9 @@ The MIX output is also subject to the DRY/WET setting, where the dry signal is c
**Note:** this module is intended for audio-rate use, as a distortion effect; if you want a proper window comparator for use with CV, take a look at <a href="#cmp">CMP</a>.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the A input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the A input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
### <a name="random"></a> Noise/Random, Sample and Hold
@@ -903,6 +1038,8 @@ Additionally, NOISE has an absolute value circuit. Patch audio into ABS to get
_Polyphony:_ For the noise outputs, the number of polyphonic channels is set on the context (right-click) menu. Independently, the ABS circuit is <a href="#polyphony">polyphonic</a>, with polyphony defined by the IN input.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="samplehold"></a> S&H
A dual sample-and-hold and trigger-and-hold. Sampling may be triggered by CV (on the rising edge of a trigger or gate) or button press.
@@ -917,7 +1054,9 @@ The GATE input on the lower section is normalled to GATE in the top section (but
The GLIDE context menu option applies linear glide (slew limitation, smoothing) to the outputs. The time value, which defaults to 0, determines how long the output will take to change (slew) 10V. This option is ignored in track-and-hold mode.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the GATE input in each section. If the bottom GATE is patched, the two sections will independently take their channels from their respective GATE inputs; if only the top GATE is patched, the bottom section normals to the top input and both sections have the same number of channels. The polyphony port can be changed to IN on the context menu (this change applies to both top and bottom sections of the module; IN does not normal to the bottom section, and both sections will set their channels independently, from whatever is patched to their own IN).
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the GATE input in each section. If the bottom GATE is patched, the two sections will independently take their channels from their respective GATE inputs; if only the top GATE is patched, the bottom section normals to the top input and both sections have the same number of channels. The polyphony port can be changed to IN on the context menu (this change applies to both top and bottom sections of the module; IN does not normal to the bottom section, and both sections will set their channels independently, from whatever is patched to their own IN).
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="walk2"></a> WALK2
@@ -946,16 +1085,20 @@ Various options on the context (right-click) menu allow customization of the dis
_Polyphony:_ The module is monophonic (note that WALK is polyphonic).
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="walk"></a> WALK
WALK is a single-channel random walk, identical to one channel of WALK2, in 3HP. It has a JUMP input rather than a TRIG input, but the same S&H and T&H modes are available on the context menu.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the RATE input. The polyphony port can be changed to OFFSET, SCALE or JUMP on the context menu.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the RATE input. The polyphony port can be changed to OFFSET, SCALE or JUMP on the context menu.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
### <a name="sequencers"></a> Sequential Switches and Sequencers
-
+
#### <a name="eightone"></a> 8:1
@@ -973,7 +1116,9 @@ If option "Select on clock mode" is selected, then the select value (knob and CV
Option "Triggered select mode" changes how the SELECT feature works, replacing the continuous voltage selection with a second internal sequence that offsets (adds to) the primary sequential switch step. In this mode, the SELECT input expects trigger pulses, which advance the secondary sequence, while the SELECT knob sets the length of the secondary sequence (and a trigger at RESET will reset it). Thus different clocks and step lengths can be used to create complex output step patterns. "Select on clock mode" has no effect if "Triggered select mode" is enabled.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the CLOCK input. This can be set to the SELECT CV input on the context menu.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the CLOCK input. This can be set to the SELECT CV input on the context menu.
+
+_When <a href="#bypassing">bypassed</a>:_ passes input 1 unmodified to the output.
#### <a name="oneeight"></a> 1:8
@@ -981,6 +1126,8 @@ _Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the
_Polyphony:_ Same as 8:1.
+_When <a href="#bypassing">bypassed</a>:_ passes the input unmodified to output 1.
+
#### <a name="addrseq"></a> ADDR-SEQ
ADDR-SEQ is an 8-step sequencer where the step values are set by 8 knobs (with default output range of +/-10V). It has the same clocked or voltage-addressed control circuit as 8:1 and 1:8. It can be expanded to more steps, 8 at a time, with <a href="#addrseqx">ASX</a>.
@@ -989,6 +1136,8 @@ The output range of the knobs may be set on the context (right-click) menu to a
_Polyphony:_ Same as 8:1.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="addrseqx"></a> ASX
ASX is a chainable expander for <a href="addrseq">ADDR-SEQ</a>, adding 8 steps to the base sequence.
@@ -997,7 +1146,7 @@ When ASXs are added to an ADDR-SEQ, ADDR-SEQ's STEPS and SELECT knobs (and selec
Each ASX in a chain must be positioned to the right of, and adjacent to, the previous ASX in the chain, or the base ADDR-SEQ module. See <a href="#expanders">notes on expanders</a>.
-
+
#### <a name="pgmr"></a> PGMR
@@ -1009,9 +1158,13 @@ The current step can be selected many ways:
- By pressing the button, or sending a trigger to the SELECT input, for a given step.
- By inputs to CLOCK and/or SELECT, subject to the FWD and S.O.C. ("Select On Clock") toggles. The behavior of these is the same as it is on <a href="#eightone">8:1</a> (and 1:8 and ADDR-SEQ), with the exception that the voltage range to the SELECT input is divided by the number of steps present on PGMR and all its connected PGMRX instances (where the division is always by 8 -- 16 if you consider negative voltages -- on 8:1).
+The leftmost bottom output emits a trigger whenever the step changes. The outputs below each channel selector emit a trigger when that step is selected.
+
Any PGMRX expanders must be positioned to the right of, and ajacent to, the base PGMR module, or the previous PGMRX in the chain. See <a href="#expanders">notes on expanders</a>.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the CLOCK input. This can be set to the SELECT CV input on the context menu.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the CLOCK input. This can be set to the SELECT CV input on the context menu.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="pgmrx"></a> PGMRX
@@ -1022,7 +1175,7 @@ Each PGMRX in a chain must be positioned to the right of, and ajacent to, the pr
### <a name="visualizers"></a> Visualizers
-
+
#### <a name="vu"></a> VU
@@ -1030,6 +1183,8 @@ A stereo signal level visualizer/meter. The L channel is sent to both displays
_Polyphony:_ Monophonic, but if an input is polyphonic, its channels are summed, and summed value is used to compute the level displayed (independently for the left and right inputs).
+_When <a href="#bypassing">bypassed</a>:_ passes left and right inputs unmodified to the corresponding outputs.
+
#### <a name="analyzer"></a> ANALYZER
A four-channel spectrum analyzer.
@@ -1054,7 +1209,7 @@ _Polyphony:_ Monophonic, with two exceptions:
#### <a name="analyzerxl"></a> ANALYZER-XL
-
+
An eight-channel, 42HP version of ANALYZER, with edge-to-edge-screen design. Options corresponding to ANALYZER's panel controls are available on the context (right-click) menu. An extra "Quality" setting, "Ultra+" is available; this uses an FFT size of 16384 (or 32768 if Rack's sample rate is 96khz or higher).
@@ -1064,7 +1219,7 @@ _Polyphony:_ Monophonic, but if an input is polyphonic, its channels are summed,
#### <a name="ranalyzer"></a> RANALYZER
-
+
RANALYZER is a frequency response analyzer: it passes a test signal to another module, expecting the output of that module to be patched back, and then displays the frequency spectrum of the response relative to the test signal.
@@ -1093,12 +1248,14 @@ _Polyphony:_ Monophonic.
### <a name="poly"></a> Polyphony Utilities
-
+
#### <a name="mono"></a> MONO
MONO mixes down the channels of a polyphonic cable to a single-channel mono output. It is an alternative to the SUM module that comes with VCV Rack, but adds a basic onboard compressor, to even out the level differences when only a few, or many, channels on the input are sounding. The COMP control sets the amount of compression; at zero there is no effect and the behavior of this module is essentially equivalent to Rack's SUM. As with SUM, the LEVEL control simply attenuates the output. The output, post-LEVEL, is saturated (soft-clipped) at +/-12V.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="arp"></a> ARP
ARP is a performance-oriented arpeggiator, where the arpeggiated notes come from polyphonic pitch and gate inputs. It is designed to patched directly to Rack's MIDI-CV (with polyphony enabled) and be played with a MIDI keyboard. As below, it can be controlled by other modules as well, though this needs to be done carefully.
@@ -1132,6 +1289,8 @@ The outputs are always monophonic -- patch ARP into ASSIGN to play an arpeggio t
Note that the HOLD toggle and "Use new notes" menu setting still apply however you control ARP. If not playing from a keyboard, it will usually make sense to toggle HOLD on and set "Use new notes" to "Immediately".
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="assign"></a> ASSIGN
ASSIGN is a mono-to-poly voice assigner and poly-to-poly voice reassigner (where the in and out channel counts may be different). Mono vs poly operation is defined the poly channel count on the GATE input.
@@ -1142,6 +1301,8 @@ With mono inputs, on each gate received at GATE, the current pitch at V/OCT is a
With polyphonic inputs, when a gate goes high on an input channel, the gate and corresponding pitch are assigned to an output channel. Up to the number of channels defined by the CHAN knob may be output at once. The module attempts to reuse free channels; if none are free the oldest assignment is replaced.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="unison"></a> UNISON
UNISON allows for unison-mode play of a polyphonic voice, where monophonic pitch and gate inputs are copied out to multiple polyphonic channels, as set by the CHAN knob.
@@ -1155,20 +1316,26 @@ The behavior of DETUNE depends on the number of output channels:
- With four channels, a channel gets each of: up and down the full amount and up and down half the amount.
- And so on, such that the detune amounts are evenly spread, and one channel gets the unaltered pitch if and only if the channel count is odd.
-
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
+
#### <a name="polycon"></a> POLYCON16
-POLYCON16 allows fixed voltages to be sent directly to some number of channels, by channel number, of a polyphonic output. The number of output channels is set the CHAN knob, unless an input is present at the CHAN input, in which case the channel count is taken from that input, and the knob is ignored.
+POLYCON16 allows fixed voltages to be sent directly to some number of channels, by channel number, of a polyphonic output. The number of output channels is set by the CHAN knob, unless an input is present at the CHAN input, in which case the channel count is taken from that input, and the knob is ignored.
This can be used to introduce a bit of fixed variation across the channels of a poly voice.
The context menu option range allows the output voltages to be set from several bipolar and unipolar ranges. Note that when a unipolar range is used, 0V will be output when the knob is fully counter-clockwise, even though the knobs are drawn with a bipolar dial (such that 0V is usually at noon).
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="polycon8"></a> POLYCON8
A compact version of POLYCON16, that only works with polyphony channels 1-8. The channel count must be set on the context (right-click) menu.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="polyoff16"></a> POLYOFF16
POLYOFF16 allows for the independent offset and scaling of voltages on each channel of a polyphonic signal. It can also be used as a replacement for Rack's MERGE, which combines monophonic signals into a polyphonic signal, but here with per-channel offset and scale controls.
@@ -1187,16 +1354,22 @@ The module has the same "Range" context-menu options as POLYCON16, here altering
The context-menu option "Order of operations" sets the order in which OFFSET and SCALE are applied to each channel. The default is to scale, then offset. This behavior was the opposite prior to version 1.1.36. See <a href="#offset">OFFSET</a> for more detail on this; the behavior is the same here.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="polyoff8"></a> POLYOFF8
A half-width version of POLYCON16, that only works with polyphony channels 1-8.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="polymult"></a> POLYMULT
POLYMULT will turn a mono signal into a polyphonic signal, with a given number of channels, where each channel gets a copy of the input voltage. The number of channels is set by the CHAN knob, unless an input is present at the CHAN input, in which case the channel count is taken from that input, and the knob is ignored. Each OUT output is identical.
To simply make copies of an already-polyphonic signal, use the regular <a href="#mult">MULT</a> module.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
### <a name="pitch"></a> Pitch CV Utilities
@@ -1208,7 +1381,9 @@ Utilities related to processing pitch CVs (1 volt / octave CVs, for controlling
A 1V/octave pitch processor, for controlling a detuned oscillator pair. A reference pitch in raised and lowered by the number of cents (hundredths of a semitone) specified by the knob and CV, and emitted at OUT+ and OUT-. The input pitch is emitted at THRU.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes V/OCT unmodified to each of the three outputs.
#### <a name="stack"></a> STACK
@@ -1216,7 +1391,9 @@ A 1V/octave pitch processor for stacking oscillators. The SEMIS, OCTAVE and FIN
The CV input expects +/-5V; the value modifies the interval set by the knobs in the amount of one semitone per tenth volt. If QZ (quantize) is active, the CV-controlled interval is quantized to the nearest semitone. This specialized CV is output at the THRU port, with a value set by the knobs and CV in, when there is no input pitch.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the V/OCT input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the V/OCT input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes V/OCT unmodified to both THRU and OUT.
#### <a name="reftone"></a> REFTONE
@@ -1224,6 +1401,8 @@ A tuner that outputs a selectable (Western, chromatic) pitch as CV (1V/octave, f
_Polyphony:_ Monophonic.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
### <a name="utilities"></a> Utilities
@@ -1233,7 +1412,9 @@ _Polyphony:_ Monophonic.
A boolean logic utility. Inputs are considered true if the input voltage is greater than 1V. The top section takes two inputs and computes AND, OR and XOR at the outputs. The lower section computes the negation of its input. Output is 5V if an output is true, 0V otherwise.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the first/topmost input. The NOT circuit is independently polyphonic based on its input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the first/topmost input. The NOT circuit is independently polyphonic based on its input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="cmp"></a> CMP
@@ -1248,7 +1429,9 @@ The WINDOW knob specifies the window voltage. LAG specifies a time of up to one
The OUTPUT switch sets the high and low voltage values for the outputs: 0V low/+10V high, or -5V low/+5V high.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the A input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the A input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="cvd"></a> CVD
@@ -1258,13 +1441,17 @@ The large TIME knob sets the delay time, in seconds, as scaled by the small knob
CVD may be used for lag/latency correction; using parameter entry (by right-clicking the TIME knob) is handy here, to set a precise delay. You can get sample-accurate delays by dividing the desired number of delay samples by Rack's current sample rate, and setting TIME to that number (leave the time scale knob at 1).
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="flipflop"></a> FLIPFLOP
A boolean memory utility with two independent channels. A high voltage at TRIGGER will cause the state of a channel to change from A to B. A subsequent trigger will flip it back. Output is 5V at whichever of A and B is selected, 0V at the other. A trigger voltage at RESET sets the channel back to state A.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the channels at the TRIG input, independently for the two sections of the module.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the channels at the TRIG input, independently for the two sections of the module.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="inv"></a> INV
@@ -1272,16 +1459,20 @@ A dual signal inverter, with CV or manual control, and optional latching. In ea
If LATCH is enabled, a button press or high voltage toggles the state of the inverter. A context menu option "Save latched state to patch" will, if latching is enabled, save the latched state to the patch and restore it on patch load.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the channels at the IN input, independently for the two sections of the module.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the channels at the IN input, independently for the two sections of the module.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT independently in each channel.
#### <a name="manual"></a> MANUAL
A manual trigger/gate with 8 outputs. A constant +5V is sent from each output for as long as the TRIG button is held; 0V is output otherwise. The high output voltage may be set to +10V on the context menu.
-MANUAL may be set to output a trigger pulse (the high output voltage for 10ms) on patch load (akin to a Max/Msp loadbang). This is off by default; enable clicking "Trigger on Load" on the module's context (right-click) menu. The pulse is emitted 100ms after the patch starts processing samples.
+MANUAL may be set to output a trigger pulse (the high output voltage for 10ms) on patch load (akin to a Max/Msp loadbang). This is off by default; enable clicking "Trigger on load" on the module's context (right-click) menu. The pulse is emitted 100ms after the patch starts processing samples.
_Polyphony:_ Monophonic.
+_When <a href="#bypassing">bypassed</a>:_ no output; disables "Trigger on load".
+
#### <a name="fourman"></a> 4MAN
A version of MANUAL with four independent trigger buttons with separate outputs.
@@ -1290,12 +1481,16 @@ The "Trigger on load" and "Output" options, as on MANUAL, apply to all four outp
_Polyphony:_ Monophonic.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="mult"></a> MULT
A 3 HP multiple (signal splitter or duplicator). There are two 1-to-3 channels. There is also a 1-to-6 mode: if nothing is patched to the second channel's input, the input to the first channel is copied to all six outputs.
_Polyphony:_ Polyphonic inputs are duplicated (channels intact) at their corresponding outputs.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
#### <a name="offset"></a> OFFSET
An offset and scaler. The OFFSET and SCALE knobs have CV inputs (unipolar, 0-10V). There are two operating modes, as set by the "Order of operations" context (right-click) menu option:
@@ -1308,7 +1503,9 @@ Note that prior to version 1.1.36, there was no mode setting, and the behavior w
By default, the output is capped at +/-12 volts (this is a standard in Rack). A context menu option allows this limit to be disabled.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the channels of the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the channels of the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="slew"></a> SLEW
@@ -1322,7 +1519,9 @@ RISE and FALL each have a unipolar (0-10V) CV input affecting the corresponding
If SLOW is enabled, the slew rates for both RISE and FALL are 10x slower what they would otherwise be, based on the knobs and CVs.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the channels of the IN input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the channels of the IN input.
+
+_When <a href="#bypassing">bypassed</a>:_ passes IN unmodified to OUT.
#### <a name="sums"></a> SUMS
@@ -1330,7 +1529,9 @@ An arithmetic logic utility. The top section outputs the sum, difference, maxim
By default, the output is capped at +/-12 volts (this is a standard in Rack). A context menu option allows this limit to be disabled.
-_Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphony defined by the first/topmost input. The NEG circuit is independently polyphonic based on its input.
+_Polyphony:_ <a href="#polyphony">polyphonic</a>, with polyphony defined by the first/topmost input. The NEG circuit is independently polyphonic based on its input.
+
+_When <a href="#bypassing">bypassed</a>:_ no output.
#### <a name="switch"></a> SWITCH
@@ -1342,6 +1543,8 @@ If the context menu option "Save latched state to patch" is enabled, and latchin
_Polyphony:_ If polyphonic input is present at GATE, then the module is polyphonic in the standard way, independently switching the independent polyphonic channels on the high/low inputs (the button will switch all channels). Additionally, if the input at GATE is not present or monophonic, but polyphonic cables are are present at any high/low inputs, and such an input is switched to the output, it is duplicated to the output with channels intact.
+_When <a href="#bypassing">bypassed</a>:_ passes LOW unmodified to OUT independently in each channel.
+
#### <a name="lgsw"></a> LGSW
LGSW is a version of <a href="#switch">SWITCH</a> with two gate inputs and onboard logic.
@@ -1368,9 +1571,11 @@ The logic mode can be set by CV. Using a CV for the logic overrides whatever se
_Polyphony:_ Same as <a href="#switch">SWITCH</a>, except that the polyphony channel count is set by the topmost gate input only.
+_When <a href="#bypassing">bypassed</a>:_ no output.
+
### <a name="misc"></a> Miscellaneous
-
+
#### <a name="blank3"></a> BLANK3
@@ -1418,6 +1623,17 @@ Rack allows left expanders as well as right, but to simplify things we've chosen
Some expanders may be chainable: multiple instances can be added to continue expanding the base. In this case, the expanders must all be to the right of the base, and all touching.
+## <a name="bypassing"></a> Note on Bypassing
+
+Rack adds a "Bypass" option to the context (right-click) menu on every module. By default, this fully disables the module (while allowing it to remain patched), such that the module produces no output (or more precisely, constantly outputs 0V). For some modules, however, it makes more sense to pass the module's unmodified input to the output.
+
+Most Bogaudio modules implement bypassing according these general rules:
+ - Modules that generate a signal (VCOs, LFOs, noise/random generators, envelope generators), or combine signals (mixers, logic), typically produce no output.
+ - Modules that modify a signal (filters, effects, VCAs, attenuators) typically pass their input to the output.
+
+There are various exceptions and special or ambiguous cases; see the documentation for each module for details on that module's behavior.
+
+
## <a name="alternate_panels"></a> Alternate Panels

diff --git a/doc/www/dynamics.png b/doc/www/dynamics.png
Binary files differ.
diff --git a/doc/www/envelopes1.png b/doc/www/envelopes1.png
Binary files differ.
diff --git a/doc/www/envelopes2.png b/doc/www/envelopes2.png
Binary files differ.
diff --git a/doc/www/envelopes3.png b/doc/www/envelopes3.png
Binary files differ.
diff --git a/doc/www/filters.png b/doc/www/filters.png
Binary files differ.
diff --git a/doc/www/lfos.png b/doc/www/lfos.png
Binary files differ.
diff --git a/doc/www/lpgs.png b/doc/www/lpgs.png
Binary files differ.
diff --git a/doc/www/misc.png b/doc/www/misc.png
Binary files differ.
diff --git a/doc/www/mixers1.png b/doc/www/mixers1.png
Binary files differ.
diff --git a/doc/www/mixers2.png b/doc/www/mixers2.png
Binary files differ.
diff --git a/doc/www/mixers3.png b/doc/www/mixers3.png
Binary files differ.
diff --git a/doc/www/mixers4.png b/doc/www/mixers4.png
Binary files differ.
diff --git a/doc/www/mixers5.png b/doc/www/mixers5.png
Binary files differ.
diff --git a/doc/www/mixers6.png b/doc/www/mixers6.png
Binary files differ.
diff --git a/doc/www/modules1.png b/doc/www/modules1.png
Binary files differ.
diff --git a/doc/www/modules2.png b/doc/www/modules2.png
Binary files differ.
diff --git a/doc/www/modules3.png b/doc/www/modules3.png
Binary files differ.
diff --git a/doc/www/modules4.png b/doc/www/modules4.png
Binary files differ.
diff --git a/doc/www/modules5.png b/doc/www/modules5.png
Binary files differ.
diff --git a/doc/www/noise.png b/doc/www/noise.png
Binary files differ.
diff --git a/doc/www/oscillators1.png b/doc/www/oscillators1.png
Binary files differ.
diff --git a/doc/www/oscillators2.png b/doc/www/oscillators2.png
Binary files differ.
diff --git a/doc/www/parametric_eqs1.png b/doc/www/parametric_eqs1.png
Binary files differ.
diff --git a/doc/www/parametric_eqs2.png b/doc/www/parametric_eqs2.png
Binary files differ.
diff --git a/doc/www/pitch.png b/doc/www/pitch.png
Binary files differ.
diff --git a/doc/www/poly1.png b/doc/www/poly1.png
Binary files differ.
diff --git a/doc/www/poly2.png b/doc/www/poly2.png
Binary files differ.
diff --git a/doc/www/sequencers1.png b/doc/www/sequencers1.png
Binary files differ.
diff --git a/doc/www/sequencers2.png b/doc/www/sequencers2.png
Binary files differ.
diff --git a/doc/www/skin-dark.png b/doc/www/skin-dark.png
Binary files differ.
diff --git a/doc/www/skin-lowcontrast.png b/doc/www/skin-lowcontrast.png
Binary files differ.
diff --git a/doc/www/utilities.png b/doc/www/utilities.png
Binary files differ.
diff --git a/doc/www/vcas.png b/doc/www/vcas.png
Binary files differ.
diff --git a/doc/www/visualizers.png b/doc/www/visualizers.png
Binary files differ.
diff --git a/doc/www/visualizers3.png b/doc/www/visualizers3.png
Binary files differ.
diff --git a/plugin.json b/plugin.json
@@ -1,7 +1,7 @@
{
"slug": "Bogaudio",
"name": "Bogaudio",
- "version": "1.1.38",
+ "version": "2.0.39",
"license": "GPL-3.0-or-later",
"brand": "Bogaudio",
"author": "Matt Demanett",
diff --git a/scripts/make_module_screenshots.rb b/scripts/make_module_screenshots.rb
@@ -48,7 +48,7 @@ skins.each do |skin|
end
FileUtils.cd(rack_dir)
- out = `./Rack -d -t 1 Bogaudio 2>&1`
+ out = `./Rack -d -t 1 2>&1`
unless $?.success?
STDERR.puts "Calling Rack failed:\n#{out}"
exit 1
diff --git a/scripts/make_screenshots.rb b/scripts/make_screenshots.rb
@@ -37,7 +37,7 @@ screens = [
file: 'modules4.png',
crop: false,
rows: [
- ['VCA', 'VCAmp', 'Velo', '-', 'AMRM', 'Pressor', 'Lmtr', 'Nsgt', 'CmpDist'],
+ ['VCA', 'VCAmp', 'Velo', '-', 'AMRM', 'Pressor', 'Clpr', 'Lmtr', 'Nsgt', 'CmpDist'],
['Noise', 'SampleHold', 'Walk2', 'Walk', '-', 'EightOne', 'OneEight', 'AddrSeq', 'AddrSeqX', 'PGMR', 'PGMRX'],
['VU', 'Analyzer', 'AnalyzerXL'],
['Ranalyzer']
@@ -109,10 +109,17 @@ screens = [
]
},
{
- file: 'parametric_eqs.png',
+ file: 'parametric_eqs1.png',
crop: true,
rows: [
- ['PEQ', 'PEQ6', 'PEQ6XF', 'PEQ14', 'PEQ14XF']
+ ['PEQ', 'PEQ6', 'PEQ6XF']
+ ]
+ },
+ {
+ file: 'parametric_eqs2.png',
+ crop: true,
+ rows: [
+ ['PEQ14', 'PEQ14XF']
]
},
{
@@ -147,34 +154,41 @@ screens = [
file: 'mixers1.png',
crop: true,
rows: [
- ['Mix8', 'Mix8x', 'Mix4', 'Mix4x']
+ ['Mix8', 'Mix8x']
]
},
{
file: 'mixers2.png',
crop: true,
rows: [
- ['Mix1', 'Mix2', 'UMix', 'Mumix', 'Mute8', 'VCM', 'Pan', 'XFade']
+ ['Mix4', 'Mix4x']
]
},
{
file: 'mixers3.png',
crop: true,
rows: [
- ['Matrix81', 'Matrix18', 'Matrix44', 'Matrix44Cvm']
+ ['Mix1', 'Mix2', 'UMix', 'Mumix', 'Mute8', 'VCM', 'Pan', 'XFade']
]
},
{
file: 'mixers4.png',
crop: true,
rows: [
- ['Matrix88', 'Matrix88Cv', 'Matrix88M']
+ ['Matrix81', 'Matrix18', 'Matrix44', 'Matrix44Cvm']
]
},
{
file: 'mixers5.png',
crop: true,
rows: [
+ ['Matrix88', 'Matrix88Cv', 'Matrix88M']
+ ]
+ },
+ {
+ file: 'mixers6.png',
+ crop: true,
+ rows: [
['Switch81', 'Switch18', 'Switch44', 'Switch88', 'Switch1616']
]
},
@@ -189,7 +203,7 @@ screens = [
file: 'dynamics.png',
crop: true,
rows: [
- ['AMRM', 'Pressor', 'Lmtr', 'Nsgt', 'CmpDist']
+ ['AMRM', 'Pressor', 'Clpr', 'Lmtr', 'Nsgt', 'CmpDist']
]
},
{
diff --git a/src/AD.cpp b/src/AD.cpp
@@ -29,12 +29,12 @@ void AD::sampleRateChange() {
}
}
-json_t* AD::toJson(json_t* root) {
+json_t* AD::saveToJson(json_t* root) {
json_object_set_new(root, INVERT, json_real(_invert));
return root;
}
-void AD::fromJson(json_t* root) {
+void AD::loadFromJson(json_t* root) {
json_t* i = json_object_get(root, INVERT);
if (i) {
_invert = json_real_value(i);
@@ -164,8 +164,8 @@ struct ADWidget : BGModuleWidget {
addOutput(createOutput<Port24>(envOutputPosition, module, AD::ENV_OUTPUT));
addOutput(createOutput<Port24>(eocOutputPosition, module, AD::EOC_OUTPUT));
- addChild(createLight<TinyLight<GreenLight>>(attackLightPosition, module, AD::ATTACK_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(decayLightPosition, module, AD::DECAY_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(attackLightPosition, module, AD::ATTACK_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(decayLightPosition, module, AD::DECAY_LIGHT));
}
void contextMenu(Menu* menu) override {
diff --git a/src/AD.hpp b/src/AD.hpp
@@ -69,15 +69,22 @@ struct AD : BGModule {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
configParam<EnvelopeSegmentParamQuantity>(ATTACK_PARAM, 0.0f, 1.0f, 0.141421f, "Attack", " s");
configParam<EnvelopeSegmentParamQuantity>(DECAY_PARAM, 0.0f, 1.0f, 0.31623f, "Decay", " s");
- configParam(LOOP_PARAM, 0.0f, 1.0f, 0.0f, "Loop");
- configParam(LINEAR_PARAM, 0.0f, 1.0f, 0.0f, "Linear");
- configParam(RETRIGGER_PARAM, 0.0f, 1.0f, 1.0f, "Retrigger");
+ configSwitch(LOOP_PARAM, 0.0f, 1.0f, 0.0f, "Loop", {"Disabled (stop)", "Enabled"});
+ configSwitch(LINEAR_PARAM, 0.0f, 1.0f, 0.0f, "Linear", {"Disabled (logarithmic)", "Enabled"});
+ configSwitch(RETRIGGER_PARAM, 0.0f, 1.0f, 1.0f, "Retrigger", {"Disabled (finish cycle)", "Enabled"});
+
+ configInput(TRIGGER_INPUT, "Trigger");
+ configInput(ATTACK_INPUT, "Attack CV");
+ configInput(DECAY_INPUT, "Decay CV");
+
+ configOutput(ENV_OUTPUT, "Envelope");
+ configOutput(EOC_OUTPUT, "End-of-cycle trigger");
}
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
bool active() override;
int channels() override;
void addChannel(int c) override;
diff --git a/src/ADSR.cpp b/src/ADSR.cpp
@@ -24,12 +24,12 @@ void ADSR::sampleRateChange() {
}
}
-json_t* ADSR::toJson(json_t* root) {
+json_t* ADSR::saveToJson(json_t* root) {
json_object_set_new(root, INVERT, json_real(_invert));
return root;
}
-void ADSR::fromJson(json_t* root) {
+void ADSR::loadFromJson(json_t* root) {
json_t* i = json_object_get(root, INVERT);
if (i) {
_invert = json_real_value(i);
@@ -130,10 +130,10 @@ struct ADSRWidget : BGModuleWidget {
addOutput(createOutput<Port24>(outOutputPosition, module, ADSR::OUT_OUTPUT));
- addChild(createLight<TinyLight<GreenLight>>(attackLightPosition, module, ADSR::ATTACK_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(decayLightPosition, module, ADSR::DECAY_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(sustainLightPosition, module, ADSR::SUSTAIN_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(releaseLightPosition, module, ADSR::RELEASE_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(attackLightPosition, module, ADSR::ATTACK_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(decayLightPosition, module, ADSR::DECAY_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(sustainLightPosition, module, ADSR::SUSTAIN_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(releaseLightPosition, module, ADSR::RELEASE_LIGHT));
}
void contextMenu(Menu* menu) override {
diff --git a/src/ADSR.hpp b/src/ADSR.hpp
@@ -62,13 +62,17 @@ struct ADSR : BGModule {
configParam<EnvelopeSegmentParamQuantity>(DECAY_PARAM, 0.0f, 1.0f, 0.31623f, "Decay", " s");
configParam(SUSTAIN_PARAM, 0.0f, 1.0f, 1.0f, "Sustain", "%", 0.0f, 100.0f);
configParam<EnvelopeSegmentParamQuantity>(RELEASE_PARAM, 0.0f, 1.0f, 0.31623f, "Release", " s");
- configParam(LINEAR_PARAM, 0.0f, 1.0f, 0.0f, "Linear");
+ configSwitch(LINEAR_PARAM, 0.0f, 1.0f, 0.0f, "Linear", {"Disabled (logarithmic)", "Enabled"});
+
+ configInput(GATE_INPUT, "Gate");
+
+ configOutput(OUT_OUTPUT, "Envelope");
}
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
bool active() override;
int channels() override;
void addChannel(int c) override;
diff --git a/src/AMRM.cpp b/src/AMRM.cpp
@@ -3,12 +3,12 @@
#define POLY_INPUT "poly_input"
-json_t* AMRM::toJson(json_t* root) {
+json_t* AMRM::saveToJson(json_t* root) {
json_object_set_new(root, POLY_INPUT, json_integer(_polyInputID));
return root;
}
-void AMRM::fromJson(json_t* root) {
+void AMRM::loadFromJson(json_t* root) {
json_t* p = json_object_get(root, POLY_INPUT);
if (p) {
_polyInputID = json_integer_value(p);
diff --git a/src/AMRM.hpp b/src/AMRM.hpp
@@ -37,10 +37,19 @@ struct AMRM : BGModule {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam(RECTIFY_PARAM, 0.0f, 1.0f, 0.0f, "Rectification", "%", 0.0f, 100.0f);
configParam(DRYWET_PARAM, 0.0f, 1.0f, 1.0f, "Wet mix", "%", 0.0f, 100.0f);
+ configBypass(CARRIER_INPUT, OUT_OUTPUT);
+
+ configInput(MODULATOR_INPUT, "Modulator signal");
+ configInput(CARRIER_INPUT, "Carrier signal");
+ configInput(RECTIFY_INPUT, "Rectify CV");
+ configInput(DRYWET_INPUT, "Dry/wet CV");
+
+ configOutput(OUT_OUTPUT, "Modulated carrier signal");
+ configOutput(RECTIFY_OUTPUT, "Rectified modulator signal");
}
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
bool active() override;
int channels() override;
void processChannel(const ProcessArgs& args, int c) override;
diff --git a/src/ASR.cpp b/src/ASR.cpp
@@ -29,12 +29,12 @@ void ASR::sampleRateChange() {
}
}
-json_t* ASR::toJson(json_t* root) {
+json_t* ASR::saveToJson(json_t* root) {
json_object_set_new(root, INVERT, json_real(_invert));
return root;
}
-void ASR::fromJson(json_t* root) {
+void ASR::loadFromJson(json_t* root) {
json_t* i = json_object_get(root, INVERT);
if (i) {
_invert = json_real_value(i);
@@ -149,8 +149,8 @@ struct ASRWidget : BGModuleWidget {
addOutput(createOutput<Port24>(envOutputPosition, module, ASR::ENV_OUTPUT));
addOutput(createOutput<Port24>(eocOutputPosition, module, ASR::EOC_OUTPUT));
- addChild(createLight<TinyLight<GreenLight>>(attackLightPosition, module, ASR::ATTACK_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(releaseLightPosition, module, ASR::RELEASE_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(attackLightPosition, module, ASR::ATTACK_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(releaseLightPosition, module, ASR::RELEASE_LIGHT));
}
};
diff --git a/src/ASR.hpp b/src/ASR.hpp
@@ -66,13 +66,20 @@ struct ASR : BGModule {
configParam<EnvelopeSegmentParamQuantity>(ATTACK_PARAM, 0.0f, 1.0f, 0.141421f, "Attack", " s");
configParam<EnvelopeSegmentParamQuantity>(RELEASE_PARAM, 0.0f, 1.0f, 0.31623f, "Release", " s");
configParam(SUSTAIN_PARAM, 0.0f, 1.0f, 1.0f, "Sustain", "", 0.0f, 10.0f);
- configParam(LINEAR_PARAM, 0.0f, 1.0f, 0.0f, "Linear");
+ configSwitch(LINEAR_PARAM, 0.0f, 1.0f, 0.0f, "Linear", {"Disabled (logarithmic)", "Enabled"});
+
+ configInput(TRIGGER_INPUT, "Trigger");
+ configInput(ATTACK_INPUT, "Attack CV");
+ configInput(RELEASE_INPUT, "Release CV");
+
+ configOutput(ENV_OUTPUT, "Envelope");
+ configOutput(EOC_OUTPUT, "End-of-cycle trigger");
}
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
bool active() override;
int channels() override;
void addChannel(int c) override;
diff --git a/src/Additator.cpp b/src/Additator.cpp
@@ -253,11 +253,7 @@ struct AdditatorWidget : BGModuleWidget {
// end generated by svg_widgets.rb
addParam(createParam<Knob68>(frequencyParamPosition, module, Additator::FREQUENCY_PARAM));
- {
- auto w = createParam<Knob38>(partialsParamPosition, module, Additator::PARTIALS_PARAM);
- dynamic_cast<Knob*>(w)->snap = true;
- addParam(w);
- }
+ addParam(createParam<Knob38>(partialsParamPosition, module, Additator::PARTIALS_PARAM));
addParam(createParam<Knob16>(fineParamPosition, module, Additator::FINE_PARAM));
addParam(createParam<Knob26>(widthParamPosition, module, Additator::WIDTH_PARAM));
addParam(createParam<Knob26>(oddSkewParamPosition, module, Additator::ODD_SKEW_PARAM));
@@ -281,8 +277,8 @@ struct AdditatorWidget : BGModuleWidget {
addOutput(createOutput<Port24>(audioOutputPosition, module, Additator::AUDIO_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(sineLightPosition, module, Additator::SINE_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(cosineLightPosition, module, Additator::COSINE_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(sineLightPosition, module, Additator::SINE_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(cosineLightPosition, module, Additator::COSINE_LIGHT));
}
};
diff --git a/src/Additator.hpp b/src/Additator.hpp
@@ -103,6 +103,7 @@ struct Additator : BGModule {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
configParam<FrequencyParamQuantity>(FREQUENCY_PARAM, -3.0f, 6.0f, 0.0f, "Frequency", " Hz");
configParam(PARTIALS_PARAM, 1.0f, Additator::maxPartials, Additator::maxPartials / 5.0f, "Partials");
+ paramQuantities[PARTIALS_PARAM]->snapEnabled = true;
configParam(FINE_PARAM, -1.0f, 1.0f, 0.0f, "Fine tune", " cents", 0.0f, 100.0f);
configParam(WIDTH_PARAM, 0.0f, maxWidth, maxWidth / 2.0f, "Width", "%", 0.0f, 2.0f * (1.0f / maxWidth) * 100.0f, -100.0f);
configParam(ODD_SKEW_PARAM, -maxSkew, maxSkew, 0.0f, "Odd skew", "%", 0.0f, (1.0f / maxSkew) * 100.0f);
@@ -111,7 +112,20 @@ struct Additator : BGModule {
configParam(DECAY_PARAM, minDecay, maxDecay, (maxDecay - minDecay) / 2.0 + minDecay, "Decay");
configParam(BALANCE_PARAM, -1.0f, 1.0f, 0.0f, "Balance", "%", 0.0f, 100.0f);
configParam(FILTER_PARAM, minFilter, maxFilter, (maxFilter - minFilter) / 2.0 + minFilter, "Filter");
- configParam(PHASE_PARAM, 1.0f, 2.0f, 1.0f, "Phase");
+ configSwitch(PHASE_PARAM, 1.0f, 2.0f, 1.0f, "Phase", {"Sine", "Cosine"});
+
+ configInput(PITCH_INPUT, "Pitch (1V/octave)");
+ configInput(SYNC_INPUT, "Sync");
+ configInput(PARTIALS_INPUT, "Partials CV");
+ configInput(WIDTH_INPUT, "Width CV");
+ configInput(ODD_SKEW_INPUT, "Odd skew CV");
+ configInput(EVEN_SKEW_INPUT, "Even skew CV");
+ configInput(GAIN_INPUT, "Gain CV");
+ configInput(DECAY_INPUT, "Decay CV");
+ configInput(BALANCE_INPUT, "Balance CV");
+ configInput(FILTER_INPUT, "Filter CV");
+
+ configOutput(AUDIO_OUTPUT, "Signal");
}
void reset() override;
diff --git a/src/AddrSeq.cpp b/src/AddrSeq.cpp
@@ -104,14 +104,14 @@ struct AddrSeqWidget : AddressableSequenceModuleWidget {
addOutput(createOutput<Port24>(outOutputPosition, module, AddrSeq::OUT_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(out1LightPosition, module, AddrSeq::OUT1_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out2LightPosition, module, AddrSeq::OUT2_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out3LightPosition, module, AddrSeq::OUT3_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out4LightPosition, module, AddrSeq::OUT4_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out5LightPosition, module, AddrSeq::OUT5_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out6LightPosition, module, AddrSeq::OUT6_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out7LightPosition, module, AddrSeq::OUT7_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out8LightPosition, module, AddrSeq::OUT8_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out1LightPosition, module, AddrSeq::OUT1_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out2LightPosition, module, AddrSeq::OUT2_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out3LightPosition, module, AddrSeq::OUT3_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out4LightPosition, module, AddrSeq::OUT4_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out5LightPosition, module, AddrSeq::OUT5_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out6LightPosition, module, AddrSeq::OUT6_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out7LightPosition, module, AddrSeq::OUT7_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out8LightPosition, module, AddrSeq::OUT8_LIGHT));
}
void contextMenu(Menu* menu) override {
diff --git a/src/AddrSeq.hpp b/src/AddrSeq.hpp
@@ -117,7 +117,7 @@ struct AddrSeq : AddrSeqBase {
AddrSeq() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
configParam<StepsParamQuantity>(STEPS_PARAM, 1.0f, 8.0f, 8.0f, "Steps");
- configParam(DIRECTION_PARAM, 0.0f, 1.0f, 1.0f, "Direction");
+ configSwitch(DIRECTION_PARAM, 0.0f, 1.0f, 1.0f, "Direction", {"Reverse", "Forward"});
configParam<SelectParamQuantity>(SELECT_PARAM, 0.0f, 7.0f, 0.0f, "Select step");
configParam<OutputRangeParamQuantity>(OUT1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1", " V");
configParam<OutputRangeParamQuantity>(OUT2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2", " V");
@@ -127,8 +127,14 @@ struct AddrSeq : AddrSeqBase {
configParam<OutputRangeParamQuantity>(OUT6_PARAM, -1.0f, 1.0f, 0.0f, "Step 6", " V");
configParam<OutputRangeParamQuantity>(OUT7_PARAM, -1.0f, 1.0f, 0.0f, "Step 7", " V");
configParam<OutputRangeParamQuantity>(OUT8_PARAM, -1.0f, 1.0f, 0.0f, "Step 8", " V");
- setInputIDs(CLOCK_INPUT, SELECT_INPUT);
+ configInput(CLOCK_INPUT, "Clock");
+ configInput(RESET_INPUT, "Reset");
+ configInput(SELECT_INPUT, "Select CV");
+
+ configOutput(OUT_OUTPUT, "Sequence");
+
+ setInputIDs(CLOCK_INPUT, SELECT_INPUT);
setLocalElements({
new AddrSeqStep(params[OUT1_PARAM], lights[OUT1_LIGHT]),
new AddrSeqStep(params[OUT2_PARAM], lights[OUT2_LIGHT]),
diff --git a/src/AddrSeqX.cpp b/src/AddrSeqX.cpp
@@ -65,14 +65,14 @@ struct AddrSeqXWidget : BGModuleWidget {
addParam(createParam<Knob16>(out7ParamPosition, module, AddrSeqX::OUT7_PARAM));
addParam(createParam<Knob16>(out8ParamPosition, module, AddrSeqX::OUT8_PARAM));
- addChild(createLight<SmallLight<GreenLight>>(out1LightPosition, module, AddrSeqX::OUT1_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out2LightPosition, module, AddrSeqX::OUT2_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out3LightPosition, module, AddrSeqX::OUT3_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out4LightPosition, module, AddrSeqX::OUT4_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out5LightPosition, module, AddrSeqX::OUT5_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out6LightPosition, module, AddrSeqX::OUT6_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out7LightPosition, module, AddrSeqX::OUT7_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out8LightPosition, module, AddrSeqX::OUT8_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out1LightPosition, module, AddrSeqX::OUT1_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out2LightPosition, module, AddrSeqX::OUT2_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out3LightPosition, module, AddrSeqX::OUT3_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out4LightPosition, module, AddrSeqX::OUT4_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out5LightPosition, module, AddrSeqX::OUT5_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out6LightPosition, module, AddrSeqX::OUT6_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out7LightPosition, module, AddrSeqX::OUT7_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out8LightPosition, module, AddrSeqX::OUT8_LIGHT));
}
};
diff --git a/src/Analyzer.cpp b/src/Analyzer.cpp
@@ -9,13 +9,13 @@ void Analyzer::sampleRateChange() {
_sampleRate = APP->engine->getSampleRate();
}
-json_t* Analyzer::toJson(json_t* root) {
+json_t* Analyzer::saveToJson(json_t* root) {
frequencyPlotToJson(root);
amplitudePlotToJson(root);
return root;
}
-void Analyzer::fromJson(json_t* root) {
+void Analyzer::loadFromJson(json_t* root) {
frequencyPlotFromJson(root);
amplitudePlotFromJson(root);
}
@@ -131,12 +131,12 @@ struct AnalyzerWidget : AnalyzerBaseWidget {
addOutput(createOutput<Port24>(signalcOutputPosition, module, Analyzer::SIGNALC_OUTPUT));
addOutput(createOutput<Port24>(signaldOutputPosition, module, Analyzer::SIGNALD_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(qualityUltraLightPosition, module, Analyzer::QUALITY_ULTRA_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(qualityHighLightPosition, module, Analyzer::QUALITY_HIGH_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(qualityGoodLightPosition, module, Analyzer::QUALITY_GOOD_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(windowNoneLightPosition, module, Analyzer::WINDOW_NONE_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(windowHammingLightPosition, module, Analyzer::WINDOW_HAMMING_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(windowKaiserLightPosition, module, Analyzer::WINDOW_KAISER_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(qualityUltraLightPosition, module, Analyzer::QUALITY_ULTRA_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(qualityHighLightPosition, module, Analyzer::QUALITY_HIGH_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(qualityGoodLightPosition, module, Analyzer::QUALITY_GOOD_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(windowNoneLightPosition, module, Analyzer::WINDOW_NONE_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(windowHammingLightPosition, module, Analyzer::WINDOW_HAMMING_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(windowKaiserLightPosition, module, Analyzer::WINDOW_KAISER_LIGHT));
}
void contextMenu(Menu* menu) override {
diff --git a/src/Analyzer.hpp b/src/Analyzer.hpp
@@ -50,8 +50,18 @@ struct Analyzer : AnalyzerBase {
Analyzer() : AnalyzerBase(4, NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
configParam(RANGE2_PARAM, -1.0f, 1.0f, 0.0f, "Range");
configParam(SMOOTH_PARAM, 0.0f, 1.0f, 0.5f, "Smoothing", " ms", 0.0f, 500.0f);
- configParam(QUALITY_PARAM, 1.0f, 3.0f, 1.0f, "Analysis quality");
- configParam(WINDOW_PARAM, 1.0f, 3.0f, 1.0f, "Analysis window type");
+ configSwitch(QUALITY_PARAM, 1.0f, 3.0f, 1.0f, "Analysis quality", {"Good", "High", "Ultra"});
+ configSwitch(WINDOW_PARAM, 1.0f, 3.0f, 1.0f, "Analysis window type", {"Kaiser", "Hamming", "None"});
+
+ configInput(SIGNALA_INPUT, "Signal A");
+ configInput(SIGNALB_INPUT, "Signal B");
+ configInput(SIGNALC_INPUT, "Signal C");
+ configInput(SIGNALD_INPUT, "Signal D");
+
+ configOutput(SIGNALA_OUTPUT, "Signal A");
+ configOutput(SIGNALB_OUTPUT, "Signal B");
+ configOutput(SIGNALC_OUTPUT, "Signal C");
+ configOutput(SIGNALD_OUTPUT, "Signal D");
}
virtual ~Analyzer() {
reset();
@@ -59,8 +69,8 @@ struct Analyzer : AnalyzerBase {
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void modulate() override;
void processAll(const ProcessArgs& args) override;
};
diff --git a/src/AnalyzerXL.cpp b/src/AnalyzerXL.cpp
@@ -22,7 +22,7 @@ void AnalyzerXL::sampleRateChange() {
_sampleRate = APP->engine->getSampleRate();
}
-json_t* AnalyzerXL::toJson(json_t* root) {
+json_t* AnalyzerXL::saveToJson(json_t* root) {
frequencyPlotToJson(root);
frequencyRangeToJson(root);
amplitudePlotToJson(root);
@@ -66,7 +66,7 @@ json_t* AnalyzerXL::toJson(json_t* root) {
return root;
}
-void AnalyzerXL::fromJson(json_t* root) {
+void AnalyzerXL::loadFromJson(json_t* root) {
frequencyPlotFromJson(root);
frequencyRangeFromJson(root);
amplitudePlotFromJson(root);
diff --git a/src/AnalyzerXL.hpp b/src/AnalyzerXL.hpp
@@ -34,13 +34,22 @@ struct AnalyzerXL : AnalyzerBase {
AnalyzerCore::Window _window = AnalyzerCore::WINDOW_KAISER;
AnalyzerXL() : AnalyzerBase(8, NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {
+ configInput(SIGNALA_INPUT, "Signal A");
+ configInput(SIGNALB_INPUT, "Signal B");
+ configInput(SIGNALC_INPUT, "Signal C");
+ configInput(SIGNALD_INPUT, "Signal D");
+ configInput(SIGNALE_INPUT, "Signal E");
+ configInput(SIGNALF_INPUT, "Signal F");
+ configInput(SIGNALG_INPUT, "Signal G");
+ configInput(SIGNALH_INPUT, "Signal H");
+
_skinnable = false;
}
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void modulate() override;
void processAll(const ProcessArgs& args) override;
};
diff --git a/src/Arp.cpp b/src/Arp.cpp
@@ -229,13 +229,13 @@ void Arp::sampleRateChange() {
_sampleTime = APP->engine->getSampleTime();
}
-json_t* Arp::toJson(json_t* root) {
+json_t* Arp::saveToJson(json_t* root) {
json_object_set_new(root, NOTES_IMMEDIATE_MODE, json_boolean(_notesImmediate));
json_object_set_new(root, FIXED_GATE_MODE, json_boolean(_fixedGate));
return root;
}
-void Arp::fromJson(json_t* root) {
+void Arp::loadFromJson(json_t* root) {
json_t* ni = json_object_get(root, NOTES_IMMEDIATE_MODE);
if (ni) {
_notesImmediate = json_is_true(ni);
@@ -394,13 +394,13 @@ struct ArpWidget : BGModuleWidget {
addOutput(createOutput<Port24>(pitchOutputPosition, module, Arp::PITCH_OUTPUT));
addOutput(createOutput<Port24>(gateOutputPosition, module, Arp::GATE_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(upLightPosition, module, Arp::UP_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(downLightPosition, module, Arp::DOWN_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(upDownLightPosition, module, Arp::UP_DOWN_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(upDownRepeatLightPosition, module, Arp::UP_DOWN_REPEAT_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(inOrderLightPosition, module, Arp::IN_ORDER_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(randomLightPosition, module, Arp::RANDOM_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(shuffleLightPosition, module, Arp::SHUFFLE_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(upLightPosition, module, Arp::UP_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(downLightPosition, module, Arp::DOWN_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(upDownLightPosition, module, Arp::UP_DOWN_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(upDownRepeatLightPosition, module, Arp::UP_DOWN_REPEAT_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(inOrderLightPosition, module, Arp::IN_ORDER_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(randomLightPosition, module, Arp::RANDOM_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(shuffleLightPosition, module, Arp::SHUFFLE_LIGHT));
}
void contextMenu(Menu* menu) override {
diff --git a/src/Arp.hpp b/src/Arp.hpp
@@ -136,7 +136,15 @@ struct Arp : BGModule {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
configParam(MODE_PARAM, 0.0f, 6.0f, 0.0f, "Playback mode");
configParam<GateLengthParamQuantity>(GATE_LENGTH_PARAM, 0.0f, 1.0f, 0.5f, "Gate length");
- configParam(HOLD_PARAM, 0.0f, 1.0f, 0.0f, "Hold/latch");
+ configSwitch(HOLD_PARAM, 0.0f, 1.0f, 0.0f, "Hold/latch", {"Disabled", "Enabled"});
+
+ configInput(CLOCK_INPUT, "Clock");
+ configInput(RESET_INPUT, "Reset");
+ configInput(PITCH_INPUT, "Pitch (1V/octave)");
+ configInput(GATE_INPUT, "Gate");
+
+ configOutput(PITCH_OUTPUT, "Pitch (1V/octave)");
+ configOutput(GATE_OUTPUT, "Gate");
_currentNotes = new NoteSet();
_playbackNotes = new NoteSet(_currentNotes);
@@ -148,8 +156,8 @@ struct Arp : BGModule {
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
int channels() override;
void addChannel(int c) override;
void removeChannel(int c) override;
diff --git a/src/Assign.cpp b/src/Assign.cpp
@@ -125,11 +125,7 @@ struct AssignWidget : BGModuleWidget {
auto gateOutputPosition = Vec(10.5, 221.0);
// end generated by svg_widgets.rb
- {
- auto w = createParam<Knob26>(channelsParamPosition, module, Assign::CHANNELS_PARAM);
- dynamic_cast<Knob*>(w)->snap = true;
- addParam(w);
- }
+ addParam(createParam<Knob26>(channelsParamPosition, module, Assign::CHANNELS_PARAM));
addInput(createInput<Port24>(pitchInputPosition, module, Assign::PITCH_INPUT));
addInput(createInput<Port24>(gateInputPosition, module, Assign::GATE_INPUT));
diff --git a/src/Assign.hpp b/src/Assign.hpp
@@ -41,6 +41,14 @@ struct Assign : BGModule {
Assign() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam(CHANNELS_PARAM, 1.0f, 16.0f, 0.0f, "Channels");
+ paramQuantities[CHANNELS_PARAM]->snapEnabled = true;
+
+ configInput(PITCH_INPUT, "Pitch (1V/octave)");
+ configInput(GATE_INPUT, "Gate");
+ configInput(RESET_INPUT, "Reset");
+
+ configOutput(PITCH_OUTPUT, "Pitch (1V/octave)");
+ configOutput(GATE_OUTPUT, "Gate");
}
void reset() override;
diff --git a/src/Blank3.cpp b/src/Blank3.cpp
@@ -17,50 +17,57 @@ void Blank3::processAll(const ProcessArgs& args) {
}
}
-struct Blank3Display : OpaqueWidget {
+struct Blank3Display : DisplayWidget {
Blank3* _module;
const char* _text;
- std::shared_ptr<Font> _font;
+ std::string _fontPath;
Blank3Display(Blank3* module, const char* text)
- : _module(module)
+ : DisplayWidget(module)
+ , _module(module)
, _text(text)
- , _font(APP->window->loadFont(asset::plugin(pluginInstance, "res/fonts/audiowide.ttf")))
+ , _fontPath(asset::plugin(pluginInstance, "res/fonts/audiowide.ttf"))
{
}
- void draw(const DrawArgs& args) override {
+ void drawOnce(const DrawArgs& args, bool screenshot, bool lit) override {
const Skins& skins = Skins::skins();
std::string skin = skins.defaultKey();
bool haveLevel = false;
float level = 0.0f;
- if (_module) {
+ if (lit) {
haveLevel = _module->_level;
level = _module->_level;
skin = _module->_skin;
}
NVGcolor textColor = nvgRGBA(0x33, 0x33, 0x33, 0xff);
- // NVGcolor bgTextColor = nvgRGBA(0xaa, 0xaa, 0xaa, 0xff);
NVGcolor bgColor = nvgRGBA(0xdd, 0xdd, 0xdd, 0xff);
const char* pathStroke = skins.skinCssValue(skin, "path-stroke");
if (pathStroke) {
textColor = Skins::cssColorToNVGColor(pathStroke, textColor);
}
- const char* backgroundFill = skins.skinCssValue(skin, "background-fill");
- if (backgroundFill) {
- bgColor = Skins::cssColorToNVGColor(backgroundFill, bgColor);
- }
NVGcolor bgTextColor = nvgRGBAf(0.5f * (textColor.r + bgColor.r), 0.5f * (textColor.g + bgColor.g), 0.5f * (textColor.b + bgColor.b), 1.0f);
+ const int split = 65;
+ drawText(args, 0, 0, box.size.x, split - 10, haveLevel, level, textColor, bgTextColor);
+ drawText(args, 0, split, box.size.x, box.size.y, haveLevel, level, textColor, bgTextColor);
+ drawText(args, 0, split - 10, box.size.x / 2 - 5, 10, haveLevel, level, textColor, bgTextColor);
+ drawText(args, box.size.x / 2 + 5, split - 10, box.size.x, 10, haveLevel, level, textColor, bgTextColor);
+ }
+
+ void drawText(const DrawArgs& args, int sx, int sy, int sw, int sh, bool haveLevel, float level, const NVGcolor& textColor, const NVGcolor& bgTextColor) {
+ std::shared_ptr<Font> font = APP->window->loadFont(_fontPath);
float offsetX = box.size.x / 2.0f;
float offsetY = box.size.y / 2.0f;
nvgSave(args.vg);
+ nvgScissor(args.vg, 0, 0, box.size.x, box.size.y);
+ nvgIntersectScissor(args.vg, sx, sy, sw, sh);
nvgTranslate(args.vg, offsetX, offsetY);
nvgRotate(args.vg, M_PI/2.0f);
nvgTranslate(args.vg, -offsetY, offsetX);
nvgFontSize(args.vg, 54.0f);
- nvgFontFaceId(args.vg, _font->handle);
+ nvgFontFaceId(args.vg, font->handle);
nvgTextLetterSpacing(args.vg, 9.0f);
if (!haveLevel) {
nvgFillColor(args.vg, textColor);
@@ -74,10 +81,6 @@ struct Blank3Display : OpaqueWidget {
nvgText(args.vg, 0, 0, _text, NULL);
}
}
- nvgBeginPath(args.vg);
- nvgRect(args.vg, 55, -20, 10, 10);
- nvgFillColor(args.vg, bgColor);
- nvgFill(args.vg);
nvgRestore(args.vg);
}
};
diff --git a/src/Blank3.hpp b/src/Blank3.hpp
@@ -29,6 +29,9 @@ struct Blank3 : BGModule {
Blank3() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
+
+ configInput(IN_INPUT, "Easter egg");
+
sampleRateChange();
}
diff --git a/src/Blank6.cpp b/src/Blank6.cpp
@@ -17,50 +17,57 @@ void Blank6::processAll(const ProcessArgs& args) {
}
}
-struct Blank6Display : OpaqueWidget {
+struct Blank6Display : DisplayWidget {
Blank6* _module;
const char* _text;
- std::shared_ptr<Font> _font;
+ std::string _fontPath;
Blank6Display(Blank6* module, const char* text)
- : _module(module)
+ : DisplayWidget(module)
+ , _module(module)
, _text(text)
- , _font(APP->window->loadFont(asset::plugin(pluginInstance, "res/fonts/audiowide.ttf")))
+ , _fontPath(asset::plugin(pluginInstance, "res/fonts/audiowide.ttf"))
{
}
- void draw(const DrawArgs& args) override {
+ void drawOnce(const DrawArgs& args, bool screenshot, bool lit) override {
const Skins& skins = Skins::skins();
std::string skin = skins.defaultKey();
bool haveLevel = false;
float level = 0.0f;
- if (_module) {
+ if (lit) {
haveLevel = _module->_level;
level = _module->_level;
skin = _module->_skin;
}
NVGcolor textColor = nvgRGBA(0x33, 0x33, 0x33, 0xff);
- // NVGcolor bgTextColor = nvgRGBA(0xaa, 0xaa, 0xaa, 0xff);
NVGcolor bgColor = nvgRGBA(0xdd, 0xdd, 0xdd, 0xff);
const char* pathStroke = skins.skinCssValue(skin, "path-stroke");
if (pathStroke) {
textColor = Skins::cssColorToNVGColor(pathStroke, textColor);
}
- const char* backgroundFill = skins.skinCssValue(skin, "background-fill");
- if (backgroundFill) {
- bgColor = Skins::cssColorToNVGColor(backgroundFill, bgColor);
- }
NVGcolor bgTextColor = nvgRGBAf(0.5f * (textColor.r + bgColor.r), 0.5f * (textColor.g + bgColor.g), 0.5f * (textColor.b + bgColor.b), 1.0f);
+ const int split = 107;
+ drawText(args, 0, 0, box.size.x, split - 10, haveLevel, level, textColor, bgTextColor);
+ drawText(args, 0, split, box.size.x, box.size.y, haveLevel, level, textColor, bgTextColor);
+ drawText(args, 0, split - 10, box.size.x / 2 - 5, 10, haveLevel, level, textColor, bgTextColor);
+ drawText(args, box.size.x / 2 + 5, split - 10, box.size.x, 10, haveLevel, level, textColor, bgTextColor);
+ }
+
+ void drawText(const DrawArgs& args, int sx, int sy, int sw, int sh, bool haveLevel, float level, const NVGcolor& textColor, const NVGcolor& bgTextColor) {
+ std::shared_ptr<Font> font = APP->window->loadFont(_fontPath);
float offsetX = box.size.x / 2.0f;
float offsetY = box.size.y / 2.0f;
nvgSave(args.vg);
+ nvgScissor(args.vg, 0, 0, box.size.x, box.size.y);
+ nvgIntersectScissor(args.vg, sx, sy, sw, sh);
nvgTranslate(args.vg, offsetX, offsetY);
nvgRotate(args.vg, M_PI/2.0f);
nvgTranslate(args.vg, -offsetY, offsetX);
nvgFontSize(args.vg, 52.0f);
- nvgFontFaceId(args.vg, _font->handle);
+ nvgFontFaceId(args.vg, font->handle);
nvgTextLetterSpacing(args.vg, 9.0f);
if (!haveLevel) {
nvgFillColor(args.vg, textColor);
@@ -74,10 +81,6 @@ struct Blank6Display : OpaqueWidget {
nvgText(args.vg, 0, 0, _text, NULL);
}
}
- nvgBeginPath(args.vg);
- nvgRect(args.vg, 97, -20, 10, 10);
- nvgFillColor(args.vg, bgColor);
- nvgFill(args.vg);
nvgRestore(args.vg);
}
};
diff --git a/src/Blank6.hpp b/src/Blank6.hpp
@@ -29,6 +29,9 @@ struct Blank6 : BGModule {
Blank6() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
+
+ configInput(IN_INPUT, "Easter egg");
+
sampleRateChange();
}
diff --git a/src/Bool.hpp b/src/Bool.hpp
@@ -28,6 +28,15 @@ struct Bool : BGModule {
Bool() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
+
+ configInput(A_INPUT, "Logic signal A");
+ configInput(B_INPUT, "Logic signal B");
+ configInput(NOT_INPUT, "NOT signal");
+
+ configOutput(AND_OUTPUT, "AND");
+ configOutput(OR_OUTPUT, "OR");
+ configOutput(XOR_OUTPUT, "XOR");
+ configOutput(NOT_OUTPUT, "NOT");
}
void processAll(const ProcessArgs& args) override;
diff --git a/src/CVD.cpp b/src/CVD.cpp
@@ -85,7 +85,6 @@ struct CVDWidget : BGModuleWidget {
{
auto w = createParam<Knob16>(timeScaleParamPosition, module, CVD::TIME_SCALE_PARAM);
auto k = dynamic_cast<SvgKnob*>(w);
- k->snap = true;
k->minAngle = -M_PI / 4.0f;
k->maxAngle = M_PI / 4.0f;
k->speed = 3.0;
diff --git a/src/CVD.hpp b/src/CVD.hpp
@@ -43,7 +43,15 @@ struct CVD : BGModule {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam(TIME_PARAM, 0.0f, 1.0f, 0.5f, "Time base", " s");
configParam(TIME_SCALE_PARAM, 0.0f, 2.0f, 1.0f, "Time scale", "", 10.0f, 0.1f);
+ paramQuantities[TIME_SCALE_PARAM]->snapEnabled = true;
configParam(MIX_PARAM, -1.0f, 1.0f, 0.0f, "Dry wet mix", "%", 0.0f, 100.0f);
+ configBypass(IN_INPUT, OUT_OUTPUT);
+
+ configInput(TIME_INPUT, "Time CV");
+ configInput(MIX_INPUT, "Dry/wet CV");
+ configInput(IN_INPUT, "Signal");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
void sampleRateChange() override;
diff --git a/src/Chirp.hpp b/src/Chirp.hpp
@@ -89,9 +89,17 @@ struct Chirp : BGModule {
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");
+ configButton(TRIGGER_PARAM, "Trigger");
+ configButton(EXPONENTIAL_PARAM, "Exponential");
+ configButton(LOOP_PARAM, "Loop");
+
+ configInput(FREQUENCY1_INPUT, "Frequency 1 (1V/octave)");
+ configInput(FREQUENCY2_INPUT, "Frequency 2 (1V/octave)");
+ configInput(TIME_INPUT, "Time CV");
+ configInput(TRIGGER_INPUT, "Trigger");
+
+ configOutput(EOC_OUTPUT, "End-of-cycle trigger");
+ configOutput(OUT_OUTPUT, "Signal");
}
void reset() override;
diff --git a/src/Clpr.cpp b/src/Clpr.cpp
@@ -27,12 +27,12 @@ void Clpr::ThresholdParamQuantity::setDisplayValue(float v) {
setValue(v);
}
-json_t* Clpr::toJson(json_t* root) {
+json_t* Clpr::saveToJson(json_t* root) {
json_object_set_new(root, THRESHOLD_RANGE, json_real(_thresholdRange));
return root;
}
-void Clpr::fromJson(json_t* root) {
+void Clpr::loadFromJson(json_t* root) {
json_t* tr = json_object_get(root, THRESHOLD_RANGE);
if (tr) {
_thresholdRange = std::max(0.0f, (float)json_real_value(tr));
diff --git a/src/Clpr.hpp b/src/Clpr.hpp
@@ -54,11 +54,21 @@ struct Clpr : BGModule {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam<ThresholdParamQuantity>(THRESHOLD_PARAM, 0.0f, 1.0f, 0.8f, "Threshold", " dB");
configParam(OUTPUT_GAIN_PARAM, 0.0f, 1.0f, 0.0f, "Output gain", " dB", 0.0f, 24.0f);
- configParam(KNEE_PARAM, 0.0f, 1.0f, 0.0f, "Knee");
+ configSwitch(KNEE_PARAM, 0.0f, 1.0f, 1.0f, "Knee", {"Hard", "Soft"});
+ configBypass(LEFT_INPUT, LEFT_OUTPUT);
+ configBypass(RIGHT_INPUT, RIGHT_OUTPUT);
+
+ configInput(LEFT_INPUT, "Left signal");
+ configInput(RIGHT_INPUT, "Right signal");
+ configInput(THRESHOLD_INPUT, "Threshold CV");
+ configInput(OUTPUT_GAIN_INPUT, "Output gain CV");
+
+ configOutput(LEFT_OUTPUT, "Left signal");
+ configOutput(RIGHT_OUTPUT, "Right signal");
}
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
bool active() override;
int channels() override;
void addChannel(int c) override;
diff --git a/src/Cmp.cpp b/src/Cmp.cpp
@@ -184,7 +184,6 @@ struct CmpWidget : BGModuleWidget {
{
auto w = createParam<Knob16>(outputParamPosition, module, Cmp::OUTPUT_PARAM);
auto k = dynamic_cast<SvgKnob*>(w);
- k->snap = true;
k->minAngle = 3.0f * (M_PI / 8.0f);
k->maxAngle = 5.0f * (M_PI / 8.0f);
k->speed = 3.0;
diff --git a/src/Cmp.hpp b/src/Cmp.hpp
@@ -53,7 +53,18 @@ struct Cmp : BGModule {
configParam(B_PARAM, -1.0f, 1.0f, 0.0f, "B", " V", 0.0f, 10.0f);
configParam(WINDOW_PARAM, 0.0f, 1.0f, 0.5f, "Window", " V", 0.0f, 10.0f);
configParam<ScaledSquaringParamQuantity<1>>(LAG_PARAM, 0.0f, 1.0f, 0.1f, "Lag", " s");
- configParam(OUTPUT_PARAM, 0.0f, 1.0f, 0.0f, "Output");
+ configSwitch(OUTPUT_PARAM, 0.0f, 1.0f, 0.0f, "Output", {"+10V", "+/-5V"});
+ paramQuantities[OUTPUT_PARAM]->snapEnabled = true;
+
+ configInput(A_INPUT, "Signal A");
+ configInput(B_INPUT, "Signal B");
+ configInput(WINDOW_INPUT, "Window CV");
+ configInput(LAG_INPUT, "Lag CV");
+
+ configOutput(GREATER_OUTPUT, "Greater than");
+ configOutput(LESS_OUTPUT, "Less than");
+ configOutput(EQUAL_OUTPUT, "Equal");
+ configOutput(NOT_EQUAL_OUTPUT, "Not equal");
}
void reset() override;
diff --git a/src/CmpDist.hpp b/src/CmpDist.hpp
@@ -68,6 +68,20 @@ struct CmpDist : BGModule {
configParam(DRY_WET_PARAM, -1.0f, 1.0f, 0.0f, "Dry/wet mix", "%", 0.0f, 100.0f);
configParam<AmplifierParamQuantity>(A_DRY_PARAM, 0.0f, 1.0f, 1.0f, "A dry level");
configParam<AmplifierParamQuantity>(B_DRY_PARAM, 0.0f, 1.0f, 1.0f, "B dry level");
+
+ configInput(GT_MIX_INPUT, "Greater-than mix CV");
+ configInput(LT_MIX_INPUT, "Less-than mix CV");
+ configInput(WINDOW_INPUT, "Window CV");
+ configInput(DRY_WET_INPUT, "Dry/wet CV");
+ configInput(A_INPUT, "Signal A");
+ configInput(A_SCALE_INPUT, "Scale A CV");
+ configInput(B_INPUT, "Signal B");
+ configInput(B_SCALE_INPUT, "Scale B CV");
+
+ configOutput(GT_OUTPUT, "Greater than");
+ configOutput(LT_OUTPUT, "Less than");
+ configOutput(EQ_OUTPUT, "Equal");
+ configOutput(MIX_OUTPUT, "Mix");
}
bool active() override;
diff --git a/src/DADSRH.cpp b/src/DADSRH.cpp
@@ -171,20 +171,20 @@ struct DADSRHWidget : TriggerOnLoadModuleWidget {
addOutput(createOutput<Port24>(invOutputPosition, module, DADSRH::INV_OUTPUT));
addOutput(createOutput<Port24>(triggerOutputPosition, module, DADSRH::TRIGGER_OUTPUT));
- addChild(createLight<TinyLight<GreenLight>>(delayLightPosition, module, DADSRH::DELAY_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(attackLightPosition, module, DADSRH::ATTACK_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(decayLightPosition, module, DADSRH::DECAY_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(sustainLightPosition, module, DADSRH::SUSTAIN_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(releaseLightPosition, module, DADSRH::RELEASE_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(attackShape1LightPosition, module, DADSRH::ATTACK_SHAPE1_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(attackShape2LightPosition, module, DADSRH::ATTACK_SHAPE2_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(attackShape3LightPosition, module, DADSRH::ATTACK_SHAPE3_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(decayShape1LightPosition, module, DADSRH::DECAY_SHAPE1_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(decayShape2LightPosition, module, DADSRH::DECAY_SHAPE2_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(decayShape3LightPosition, module, DADSRH::DECAY_SHAPE3_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(releaseShape1LightPosition, module, DADSRH::RELEASE_SHAPE1_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(releaseShape2LightPosition, module, DADSRH::RELEASE_SHAPE2_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(releaseShape3LightPosition, module, DADSRH::RELEASE_SHAPE3_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(delayLightPosition, module, DADSRH::DELAY_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(attackLightPosition, module, DADSRH::ATTACK_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(decayLightPosition, module, DADSRH::DECAY_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(sustainLightPosition, module, DADSRH::SUSTAIN_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(releaseLightPosition, module, DADSRH::RELEASE_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(attackShape1LightPosition, module, DADSRH::ATTACK_SHAPE1_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(attackShape2LightPosition, module, DADSRH::ATTACK_SHAPE2_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(attackShape3LightPosition, module, DADSRH::ATTACK_SHAPE3_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(decayShape1LightPosition, module, DADSRH::DECAY_SHAPE1_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(decayShape2LightPosition, module, DADSRH::DECAY_SHAPE2_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(decayShape3LightPosition, module, DADSRH::DECAY_SHAPE3_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(releaseShape1LightPosition, module, DADSRH::RELEASE_SHAPE1_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(releaseShape2LightPosition, module, DADSRH::RELEASE_SHAPE2_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(releaseShape3LightPosition, module, DADSRH::RELEASE_SHAPE3_LIGHT));
}
};
diff --git a/src/DADSRH.hpp b/src/DADSRH.hpp
@@ -72,14 +72,20 @@ struct DADSRH : TriggerOnLoadModule {
configParam(SUSTAIN_PARAM, 0.0f, 1.0f, 0.5f, "Sustain", "%", 0.0f, 100.0f);
configParam<EnvelopeSegmentParamQuantity>(RELEASE_PARAM, 0.0f, 1.0f, 0.31623f, "Release", " s");
configParam<EnvelopeSegmentParamQuantity>(HOLD_PARAM, 0.0f, 1.0f, 0.44721f, "Hold", " s");
- configParam(ATTACK_SHAPE_PARAM, 1.0f, 3.0f, 1.0f, "Attack shape");
- configParam(DECAY_SHAPE_PARAM, 1.0f, 3.0f, 1.0f, "Decay shape");
- configParam(RELEASE_SHAPE_PARAM, 1.0f, 3.0f, 1.0f, "Release shape");
- configParam(TRIGGER_PARAM, 0.0f, 1.0f, 0.0f, "Trigger");
- configParam(MODE_PARAM, 0.0f, 1.0f, 1.0f, "Mode");
- configParam(LOOP_PARAM, 0.0f, 1.0f, 1.0f, "Loop");
- configParam(SPEED_PARAM, 0.0f, 1.0f, 1.0f, "Speed");
- configParam(RETRIGGER_PARAM, 0.0f, 1.0f, 1.0f, "Retrigger");
+ configSwitch(ATTACK_SHAPE_PARAM, 1.0f, 3.0f, 1.0f, "Attack shape", {"Logarithmic", "Linear", "Exponential"});
+ configSwitch(DECAY_SHAPE_PARAM, 1.0f, 3.0f, 1.0f, "Decay shape", {"Exponential", "Linear", "Logarithmic"});
+ configSwitch(RELEASE_SHAPE_PARAM, 1.0f, 3.0f, 1.0f, "Release shape", {"Exponential", "Linear", "Logarithmic"});
+ configButton(TRIGGER_PARAM, "Trigger");
+ configSwitch(MODE_PARAM, 0.0f, 1.0f, 1.0f, "Mode", {"Triggered", "Gated"});
+ configSwitch(LOOP_PARAM, 0.0f, 1.0f, 1.0f, "Loop", {"Loop", "Stop"});
+ configSwitch(SPEED_PARAM, 0.0f, 1.0f, 1.0f, "Speed", {"Slow", "Normal"});
+ configSwitch(RETRIGGER_PARAM, 0.0f, 1.0f, 1.0f, "Retrigger", {"Reset", "Resume attack"});
+
+ configInput(TRIGGER_INPUT, "Trigger");
+
+ configOutput(ENV_OUTPUT, "Envelope");
+ configOutput(INV_OUTPUT, "Inverted envelope");
+ configOutput(TRIGGER_OUTPUT, "End-of-cycle trigger");
}
void reset() override;
diff --git a/src/DADSRHPlus.cpp b/src/DADSRHPlus.cpp
@@ -193,20 +193,20 @@ struct DADSRHPlusWidget : TriggerOnLoadModuleWidget {
addOutput(createOutput<Port24>(invOutputPosition, module, DADSRHPlus::INV_OUTPUT));
addOutput(createOutput<Port24>(triggerOutputPosition, module, DADSRHPlus::TRIGGER_OUTPUT));
- addChild(createLight<TinyLight<GreenLight>>(delayLightPosition, module, DADSRHPlus::DELAY_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(attackLightPosition, module, DADSRHPlus::ATTACK_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(decayLightPosition, module, DADSRHPlus::DECAY_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(sustainLightPosition, module, DADSRHPlus::SUSTAIN_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(releaseLightPosition, module, DADSRHPlus::RELEASE_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(attackShape1LightPosition, module, DADSRHPlus::ATTACK_SHAPE1_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(attackShape2LightPosition, module, DADSRHPlus::ATTACK_SHAPE2_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(attackShape3LightPosition, module, DADSRHPlus::ATTACK_SHAPE3_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(decayShape1LightPosition, module, DADSRHPlus::DECAY_SHAPE1_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(decayShape2LightPosition, module, DADSRHPlus::DECAY_SHAPE2_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(decayShape3LightPosition, module, DADSRHPlus::DECAY_SHAPE3_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(releaseShape1LightPosition, module, DADSRHPlus::RELEASE_SHAPE1_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(releaseShape2LightPosition, module, DADSRHPlus::RELEASE_SHAPE2_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(releaseShape3LightPosition, module, DADSRHPlus::RELEASE_SHAPE3_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(delayLightPosition, module, DADSRHPlus::DELAY_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(attackLightPosition, module, DADSRHPlus::ATTACK_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(decayLightPosition, module, DADSRHPlus::DECAY_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(sustainLightPosition, module, DADSRHPlus::SUSTAIN_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(releaseLightPosition, module, DADSRHPlus::RELEASE_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(attackShape1LightPosition, module, DADSRHPlus::ATTACK_SHAPE1_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(attackShape2LightPosition, module, DADSRHPlus::ATTACK_SHAPE2_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(attackShape3LightPosition, module, DADSRHPlus::ATTACK_SHAPE3_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(decayShape1LightPosition, module, DADSRHPlus::DECAY_SHAPE1_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(decayShape2LightPosition, module, DADSRHPlus::DECAY_SHAPE2_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(decayShape3LightPosition, module, DADSRHPlus::DECAY_SHAPE3_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(releaseShape1LightPosition, module, DADSRHPlus::RELEASE_SHAPE1_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(releaseShape2LightPosition, module, DADSRHPlus::RELEASE_SHAPE2_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(releaseShape3LightPosition, module, DADSRHPlus::RELEASE_SHAPE3_LIGHT));
}
};
diff --git a/src/DADSRHPlus.hpp b/src/DADSRHPlus.hpp
@@ -83,14 +83,31 @@ struct DADSRHPlus : TriggerOnLoadModule {
configParam(SUSTAIN_PARAM, 0.0f, 1.0f, 0.5f, "Sustain", "%", 0.0f, 100.0f);
configParam<EnvelopeSegmentParamQuantity>(RELEASE_PARAM, 0.0f, 1.0f, 0.31623f, "Release", " s");
configParam<EnvelopeSegmentParamQuantity>(HOLD_PARAM, 0.0f, 1.0f, 0.44721f, "Hold", " s");
- configParam(ATTACK_SHAPE_PARAM, 1.0f, 3.0f, 1.0f, "Attack shape");
- configParam(DECAY_SHAPE_PARAM, 1.0f, 3.0f, 1.0f, "Decay shape");
- configParam(RELEASE_SHAPE_PARAM, 1.0f, 3.0f, 1.0f, "Release shape");
- configParam(TRIGGER_PARAM, 0.0f, 1.0f, 0.0f, "Trigger");
- configParam(MODE_PARAM, 0.0f, 1.0f, 1.0f, "Mode");
- configParam(LOOP_PARAM, 0.0f, 1.0f, 1.0f, "Loop");
- configParam(SPEED_PARAM, 0.0f, 1.0f, 1.0f, "Speed");
- configParam(RETRIGGER_PARAM, 0.0f, 1.0f, 1.0f, "Retrigger");
+ configSwitch(ATTACK_SHAPE_PARAM, 1.0f, 3.0f, 1.0f, "Attack shape", {"Logarithmic", "Linear", "Exponential"});
+ configSwitch(DECAY_SHAPE_PARAM, 1.0f, 3.0f, 1.0f, "Decay shape", {"Exponential", "Linear", "Logarithmic"});
+ configSwitch(RELEASE_SHAPE_PARAM, 1.0f, 3.0f, 1.0f, "Release shape", {"Exponential", "Linear", "Logarithmic"});
+ configButton(TRIGGER_PARAM, "Trigger");
+ configSwitch(MODE_PARAM, 0.0f, 1.0f, 1.0f, "Mode", {"Triggered", "Gated"});
+ configSwitch(LOOP_PARAM, 0.0f, 1.0f, 1.0f, "Loop", {"Loop", "Stop"});
+ configSwitch(SPEED_PARAM, 0.0f, 1.0f, 1.0f, "Speed", {"Slow", "Normal"});
+ configSwitch(RETRIGGER_PARAM, 0.0f, 1.0f, 1.0f, "Retrigger", {"Reset", "Resume attack"});
+
+ configInput(DELAY_INPUT, "Delay CV");
+ configInput(ATTACK_INPUT, "Attack CV");
+ configInput(DECAY_INPUT, "Decay CV");
+ configInput(SUSTAIN_INPUT, "Sustain CV");
+ configInput(RELEASE_INPUT, "Release CV");
+ configInput(HOLD_INPUT, "Hold CV");
+ configInput(TRIGGER_INPUT, "Trigger");
+
+ configOutput(DELAY_OUTPUT, "Delay stage gate");
+ configOutput(ATTACK_OUTPUT, "Attack stage gate");
+ configOutput(DECAY_OUTPUT, "Decay stage gate");
+ configOutput(SUSTAIN_OUTPUT, "Sustain stage gate");
+ configOutput(RELEASE_OUTPUT, "Release stage gate");
+ configOutput(ENV_OUTPUT, "Envelope");
+ configOutput(INV_OUTPUT, "Inverted envelope");
+ configOutput(TRIGGER_OUTPUT, "End-of-cycle trigger");
}
void reset() override;
diff --git a/src/DGate.cpp b/src/DGate.cpp
@@ -149,8 +149,8 @@ struct DGateWidget : TriggerOnLoadModuleWidget {
addOutput(createOutput<Port24>(gateOutputPosition, module, DGate::GATE_OUTPUT));
addOutput(createOutput<Port24>(endOutputPosition, module, DGate::END_OUTPUT));
- addChild(createLight<TinyLight<GreenLight>>(delayLightPosition, module, DGate::DELAY_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(gateLightPosition, module, DGate::GATE_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(delayLightPosition, module, DGate::DELAY_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(gateLightPosition, module, DGate::GATE_LIGHT));
}
};
diff --git a/src/DGate.hpp b/src/DGate.hpp
@@ -57,8 +57,13 @@ struct DGate : TriggerOnLoadModule {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
configParam<EnvelopeSegmentParamQuantity>(DELAY_PARAM, 0.0f, 1.0f, 0.0f, "Delay", " s");
configParam<EnvelopeSegmentParamQuantity>(GATE_PARAM, 0.0f, 1.0f, 0.31623f, "Gate", " s");
- configParam(LOOP_PARAM, 0.0f, 1.0f, 1.0f, "Loop");
- configParam(TRIGGER_PARAM, 0.0f, 1.0f, 0.0f, "Trigger");
+ configSwitch(LOOP_PARAM, 0.0f, 1.0f, 1.0f, "Loop", {"Loop", "Stop"});
+ configButton(TRIGGER_PARAM, "Trigger");
+
+ configInput(TRIGGER_INPUT, "Trigger");
+
+ configOutput(GATE_OUTPUT, "Gate");
+ configOutput(END_OUTPUT, "End-of-cycle trigger");
}
void reset() override;
diff --git a/src/Detune.cpp b/src/Detune.cpp
@@ -43,6 +43,19 @@ void Detune::processChannel(const ProcessArgs& args, int c) {
outputs[OUT_MINUS_OUTPUT].setVoltage(_minusCV[c], c);
}
+void Detune::processBypass(const ProcessArgs& args) {
+ int cn = channels();
+ outputs[THRU_OUTPUT].setChannels(cn);
+ outputs[OUT_PLUS_OUTPUT].setChannels(cn);
+ outputs[OUT_MINUS_OUTPUT].setChannels(cn);
+ for (int c = 0; c < cn; ++c) {
+ float out = inputs[IN_INPUT].getVoltage(c);
+ outputs[THRU_OUTPUT].setVoltage(out, c);
+ outputs[OUT_PLUS_OUTPUT].setVoltage(out, c);
+ outputs[OUT_MINUS_OUTPUT].setVoltage(out, c);
+ }
+}
+
struct DetuneWidget : BGModuleWidget {
static constexpr int hp = 3;
@@ -63,11 +76,7 @@ struct DetuneWidget : BGModuleWidget {
auto outMinusOutputPosition = Vec(10.5, 236.0);
// end generated by svg_widgets.rb
- {
- auto w = createParam<Knob26>(centsParamPosition, module, Detune::CENTS_PARAM);
- dynamic_cast<Knob*>(w)->snap = true;
- addParam(w);
- }
+ addParam(createParam<Knob26>(centsParamPosition, module, Detune::CENTS_PARAM));
addInput(createInput<Port24>(cvInputPosition, module, Detune::CV_INPUT));
addInput(createInput<Port24>(inInputPosition, module, Detune::IN_INPUT));
diff --git a/src/Detune.hpp b/src/Detune.hpp
@@ -37,6 +37,14 @@ struct Detune : BGModule {
Detune() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam(CENTS_PARAM, 0.0f, 50.0f, 0.0f, "Cents");
+ paramQuantities[CENTS_PARAM]->snapEnabled = true;
+
+ configInput(CV_INPUT, "Detune CV");
+ configInput(IN_INPUT, "Pitch (1V/octave)");
+
+ configOutput(THRU_OUTPUT, "Pitch through (1V/octave)");
+ configOutput(OUT_PLUS_OUTPUT, "Raised pitch (1V/octave)");
+ configOutput(OUT_MINUS_OUTPUT, "Lowered pitch (1V/octave)");
for (int i = 0; i < maxChannels; ++i) {
_lastCents[i] = -1.0f;
@@ -48,6 +56,7 @@ struct Detune : BGModule {
int channels() override;
void modulateChannel(int c) override;
void processChannel(const ProcessArgs& args, int c) override;
+ void processBypass(const ProcessArgs& args) override;
};
} // namespace bogaudio
diff --git a/src/EQ.hpp b/src/EQ.hpp
@@ -37,6 +37,11 @@ struct EQ : BGModule {
configParam<EQParamQuantity>(LOW_PARAM, -1.0f, 1.0f, 0.0f, "Low", " dB");
configParam<EQParamQuantity>(MID_PARAM, -1.0f, 1.0f, 0.0f, "Mid", " dB");
configParam<EQParamQuantity>(HIGH_PARAM, -1.0f, 1.0f, 0.0f, "High", " dB");
+ configBypass(IN_INPUT, OUT_OUTPUT);
+
+ configInput(IN_INPUT, "Signal");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
bool active() override;
diff --git a/src/EQS.hpp b/src/EQS.hpp
@@ -42,6 +42,14 @@ struct EQS : BGModule {
configParam<EQParamQuantity>(LOW_PARAM, -1.0f, 1.0f, 0.0f, "Low", " dB");
configParam<EQParamQuantity>(MID_PARAM, -1.0f, 1.0f, 0.0f, "Mid", " dB");
configParam<EQParamQuantity>(HIGH_PARAM, -1.0f, 1.0f, 0.0f, "High", " dB");
+ configBypass(LEFT_INPUT, LEFT_OUTPUT);
+ configBypass(RIGHT_INPUT, RIGHT_OUTPUT);
+
+ configInput(LEFT_INPUT, "Left signal");
+ configInput(RIGHT_INPUT, "Right signal");
+
+ configOutput(LEFT_OUTPUT, "Left signal");
+ configOutput(RIGHT_OUTPUT, "Right signal");
}
bool active() override;
diff --git a/src/Edge.cpp b/src/Edge.cpp
@@ -127,7 +127,7 @@ struct EdgeWidget : BGModuleWidget {
addOutput(createOutput<Port24>(riseOutputPosition, module, Edge::RISE_OUTPUT));
addOutput(createOutput<Port24>(fallOutputPosition, module, Edge::FALL_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(highLightPosition, module, Edge::HIGH_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(highLightPosition, module, Edge::HIGH_LIGHT));
}
};
diff --git a/src/Edge.hpp b/src/Edge.hpp
@@ -55,6 +55,12 @@ struct Edge : BGModule {
configParam(RISE_PARAM, -1.0f, 1.0f, 0.1f, "Rising threshold", " V", 0.0f, 10.0f);
configParam(FALL_PARAM, -1.0f, 1.0f, 0.01f, "Falling threshold", " V", 0.0f, 10.0f);
configParam<ScaledSquaringParamQuantity<1000>>(HOLD_PARAM, 0.0f, 1.0f, 0.031623f, "Hold/reset time", " ms");
+
+ configInput(IN_INPUT, "Signal");
+
+ configOutput(HIGH_OUTPUT, "High gate");
+ configOutput(RISE_OUTPUT, "Rising trigger");
+ configOutput(FALL_OUTPUT, "Falling trigger");
}
void reset() override;
diff --git a/src/EightFO.cpp b/src/EightFO.cpp
@@ -269,7 +269,6 @@ struct EightFOWidget : BGModuleWidget {
{
auto w = createParam<Knob16>(waveParamPosition, module, EightFO::WAVE_PARAM);
auto k = dynamic_cast<SvgKnob*>(w);
- k->snap = true;
k->minAngle = 0.0;
k->maxAngle = M_PI;
k->speed = 3.0;
diff --git a/src/EightFO.hpp b/src/EightFO.hpp
@@ -129,8 +129,9 @@ struct EightFO : LFOBase {
EightFO() : LFOBase(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {
configParam<LFOFrequencyParamQuantity>(FREQUENCY_PARAM, -5.0f, 8.0f, 0.0, "Frequency", " Hz");
- configParam(WAVE_PARAM, 1.0, 6.0, 3.0, "Waveform");
- configParam(SLOW_PARAM, 0.0, 1.0, 0.0, "Slow");
+ configSwitch(WAVE_PARAM, 1.0, 6.0, 3.0, "Waveform", {"Ramp up", "Ramp down", "Sine", "Triangle", "Square", "Stepped"});
+ paramQuantities[WAVE_PARAM]->snapEnabled = true;
+ configButton(SLOW_PARAM, "Slow");
configParam(SAMPLE_PWM_PARAM, -1.0, 1.0, 0.0, "Width", "%", 0.0f, 100.0f);
configParam(SMOOTH_PARAM, 0.0f, 1.0f, 0.0f, "Smoothing", "%", 0.0f, 100.0f);
configParam(OFFSET_PARAM, -1.0, 1.0, 0.0, "Offset", " V", 0.0f, 5.0f);
@@ -143,6 +144,30 @@ struct EightFO : LFOBase {
configParam(PHASE2_PARAM, -1.0, 1.0, 0.0, "Phase 90", "º", 0.0f, 180.0f);
configParam(PHASE1_PARAM, -1.0, 1.0, 0.0, "Phase 45", "º", 0.0f, 180.0f);
configParam(PHASE0_PARAM, -1.0, 1.0, 0.0f, "Phase 0", "º", 0.0f, 180.0f);
+
+ configInput(SAMPLE_PWM_INPUT, "Sample/PWM CV");
+ configInput(PHASE7_INPUT, "Phase 7 CV");
+ configInput(PHASE6_INPUT, "Phase 6 CV");
+ configInput(PHASE5_INPUT, "Phase 5 CV");
+ configInput(PHASE4_INPUT, "Phase 4 CV");
+ configInput(PHASE3_INPUT, "Phase 3 CV");
+ configInput(PHASE2_INPUT, "Phase 2 CV");
+ configInput(PHASE1_INPUT, "Phase 1 CV");
+ configInput(PHASE0_INPUT, "Phase 0 CV");
+ configInput(PITCH_INPUT, "Pitch (1V/octave)");
+ configInput(RESET_INPUT, "Reset");
+ configInput(OFFSET_INPUT, "Offset CV");
+ configInput(SCALE_INPUT, "Scale CV");
+ configInput(SMOOTH_INPUT, "Smoothing CV");
+
+ configOutput(PHASE7_OUTPUT, "Phase 7");
+ configOutput(PHASE6_OUTPUT, "Phase 6");
+ configOutput(PHASE5_OUTPUT, "Phase 5");
+ configOutput(PHASE4_OUTPUT, "Phase 4");
+ configOutput(PHASE3_OUTPUT, "Phase 3");
+ configOutput(PHASE2_OUTPUT, "Phase 2");
+ configOutput(PHASE1_OUTPUT, "Phase 1");
+ configOutput(PHASE0_OUTPUT, "Phase 0");
}
void reset() override;
diff --git a/src/EightOne.cpp b/src/EightOne.cpp
@@ -75,17 +75,9 @@ struct EightOneWidget : AddressableSequenceModuleWidget {
auto in8LightPosition = Vec(23.5, 350.5);
// end generated by svg_widgets.rb
- {
- auto w = createParam<Knob16>(stepsParamPosition, module, EightOne::STEPS_PARAM);
- dynamic_cast<Knob*>(w)->snap = true;
- addParam(w);
- }
+ addParam(createParam<Knob16>(stepsParamPosition, module, EightOne::STEPS_PARAM));
addParam(createParam<SliderSwitch2State14>(directionParamPosition, module, EightOne::DIRECTION_PARAM));
- {
- auto w = createParam<Knob29>(selectParamPosition, module, EightOne::SELECT_PARAM);
- dynamic_cast<Knob*>(w)->snap = true;
- addParam(w);
- }
+ addParam(createParam<Knob29>(selectParamPosition, module, EightOne::SELECT_PARAM));
addInput(createInput<Port24>(in1InputPosition, module, EightOne::IN1_INPUT));
addInput(createInput<Port24>(in2InputPosition, module, EightOne::IN2_INPUT));
@@ -101,14 +93,14 @@ struct EightOneWidget : AddressableSequenceModuleWidget {
addOutput(createOutput<Port24>(outOutputPosition, module, EightOne::OUT_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(in1LightPosition, module, EightOne::IN1_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(in2LightPosition, module, EightOne::IN2_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(in3LightPosition, module, EightOne::IN3_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(in4LightPosition, module, EightOne::IN4_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(in5LightPosition, module, EightOne::IN5_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(in6LightPosition, module, EightOne::IN6_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(in7LightPosition, module, EightOne::IN7_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(in8LightPosition, module, EightOne::IN8_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(in1LightPosition, module, EightOne::IN1_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(in2LightPosition, module, EightOne::IN2_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(in3LightPosition, module, EightOne::IN3_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(in4LightPosition, module, EightOne::IN4_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(in5LightPosition, module, EightOne::IN5_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(in6LightPosition, module, EightOne::IN6_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(in7LightPosition, module, EightOne::IN7_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(in8LightPosition, module, EightOne::IN8_LIGHT));
}
};
diff --git a/src/EightOne.hpp b/src/EightOne.hpp
@@ -55,9 +55,26 @@ struct EightOne : AddressableSequenceModule {
EightOne() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
configParam(STEPS_PARAM, 1.0f, 8.0f, 8.0f, "Steps");
- configParam(DIRECTION_PARAM, 0.0f, 1.0f, 1.0f, "Direction");
+ paramQuantities[STEPS_PARAM]->snapEnabled = true;
+ configSwitch(DIRECTION_PARAM, 0.0f, 1.0f, 1.0f, "Direction", {"Reverse", "Forward"});
configParam(SELECT_PARAM, 0.0f, 7.0f, 0.0f, "Select step");
+ paramQuantities[SELECT_PARAM]->snapEnabled = true;
setInputIDs(CLOCK_INPUT, SELECT_INPUT);
+ configBypass(IN1_INPUT, OUT_OUTPUT);
+
+ configInput(IN1_INPUT, "Signal 1");
+ configInput(IN2_INPUT, "Signal 2");
+ configInput(IN3_INPUT, "Signal 3");
+ configInput(IN4_INPUT, "Signal 4");
+ configInput(IN5_INPUT, "Signal 5");
+ configInput(IN6_INPUT, "Signal 6");
+ configInput(IN7_INPUT, "Signal 7");
+ configInput(IN8_INPUT, "Signal 8");
+ configInput(CLOCK_INPUT, "Clock");
+ configInput(RESET_INPUT, "Reset");
+ configInput(SELECT_INPUT, "Select CV");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
void processAlways(const ProcessArgs& args) override;
diff --git a/src/FFB.hpp b/src/FFB.hpp
@@ -85,6 +85,16 @@ struct FFB : BGModule {
configParam<AmplifierParamQuantity>(LOWPASS_PARAM, 0.0f, 1.0f, 1.0f, "Lowpass level");
configParam(CV_PARAM, -1.0f, 1.0f, 0.0f, "Frequency offset", " semitones", 0.0f, 12.0f);
configParam<AmplifierParamQuantity>(HIGHPASS_PARAM, 0.0f, 1.0f, 1.0f, "Highpass level");
+ configBypass(IN_INPUT, ALL_OUTPUT);
+ configBypass(IN_INPUT, ODD_OUTPUT);
+ configBypass(IN_INPUT, EVEN_OUTPUT);
+
+ configInput(IN_INPUT, "Signal");
+ configInput(CV_INPUT, "Frequency CV");
+
+ configOutput(ALL_OUTPUT, "All filters mix");
+ configOutput(ODD_OUTPUT, "Odd filters mix");
+ configOutput(EVEN_OUTPUT, "Even filters mix");
}
void sampleRateChange() override;
diff --git a/src/FMOp.cpp b/src/FMOp.cpp
@@ -56,14 +56,14 @@ void FMOp::Engine::sampleRateChange() {
sustainSL.setParams(sampleRate, 1.0f, 1.0f);
}
-json_t* FMOp::toJson(json_t* root) {
+json_t* FMOp::saveToJson(json_t* root) {
json_object_set_new(root, LINEAR_LEVEL, json_boolean(_linearLevel));
json_object_set_new(root, ANTIALIAS_FEEDBACK, json_boolean(_antiAliasFeedback));
json_object_set_new(root, ANTIALIAS_DEPTH, json_boolean(_antiAliasDepth));
return root;
}
-void FMOp::fromJson(json_t* root) {
+void FMOp::loadFromJson(json_t* root) {
json_t* ll = json_object_get(root, LINEAR_LEVEL);
if (ll) {
_linearLevel = json_is_true(ll);
@@ -337,10 +337,10 @@ struct FMOpWidget : BGModuleWidget {
addOutput(createOutput<Port24>(audioOutputPosition, module, FMOp::AUDIO_OUTPUT));
- addChild(createLight<TinyLight<GreenLight>>(attackLightPosition, module, FMOp::ATTACK_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(decayLightPosition, module, FMOp::DECAY_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(sustainLightPosition, module, FMOp::SUSTAIN_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(releaseLightPosition, module, FMOp::RELEASE_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(attackLightPosition, module, FMOp::ATTACK_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(decayLightPosition, module, FMOp::DECAY_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(sustainLightPosition, module, FMOp::SUSTAIN_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(releaseLightPosition, module, FMOp::RELEASE_LIGHT));
}
void contextMenu(Menu* menu) override {
diff --git a/src/FMOp.hpp b/src/FMOp.hpp
@@ -115,15 +115,25 @@ struct FMOp : BGModule {
configParam(DEPTH_PARAM, 0.0f, 1.0f, 0.0f, "FM depth", "%", 0.0f, 100.0f);
configParam(FEEDBACK_PARAM, 0.0f, 1.0f, 0.0f, "Feedback", "%", 0.0f, 100.0f);
configParam<LevelParamQuantity>(LEVEL_PARAM, 0.0f, 1.0f, 1.0f, "Level");
- configParam(ENV_TO_LEVEL_PARAM, 0.0f, 1.0f, 0.0f, "Level follows envelope");
- configParam(ENV_TO_FEEDBACK_PARAM, 0.0f, 1.0f, 0.0f, "Feedback follows envelope");
- configParam(ENV_TO_DEPTH_PARAM, 0.0f, 1.0f, 0.0f, "FM depth follows envelope");
+ configButton(ENV_TO_LEVEL_PARAM, "Level follows envelope");
+ configButton(ENV_TO_FEEDBACK_PARAM, "Feedback follows envelope");
+ configButton(ENV_TO_DEPTH_PARAM, "FM depth follows envelope");
+
+ configInput(SUSTAIN_INPUT, "Sustain CV");
+ configInput(DEPTH_INPUT, "Depth CV");
+ configInput(FEEDBACK_INPUT, "Feedback CV");
+ configInput(LEVEL_INPUT, "Level CV");
+ configInput(PITCH_INPUT, "Pitch (1V/octave)");
+ configInput(GATE_INPUT, "Gate");
+ configInput(FM_INPUT, "Frequency modulation");
+
+ configOutput(AUDIO_OUTPUT, "Signal");
}
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
bool active() override;
int channels() override;
void addChannel(int c) override;
diff --git a/src/FlipFlop.hpp b/src/FlipFlop.hpp
@@ -39,6 +39,16 @@ struct FlipFlop : BGModule {
FlipFlop() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
+
+ configInput(IN1_INPUT, "Trigger 1");
+ configInput(RESET1_INPUT, "Reset 1");
+ configInput(IN2_INPUT, "Trigger 2");
+ configInput(RESET2_INPUT, "Reset 2");
+
+ configOutput(A1_OUTPUT, "A1 gate");
+ configOutput(B1_OUTPUT, "B1 gate");
+ configOutput(A2_OUTPUT, "A2 gate");
+ configOutput(B2_OUTPUT, "B2 gate");
}
void reset() override;
diff --git a/src/Follow.hpp b/src/Follow.hpp
@@ -42,6 +42,12 @@ struct Follow : FollowerBase {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam(RESPONSE_PARAM, 0.0f, 1.0f, 0.3f, "Smoothing", "%", 0.0f, 100.0f);
configParam<EFGainParamQuantity>(GAIN_PARAM, -1.0f, 1.0f, 0.0f, "Gain", " dB");
+
+ configInput(RESPONSE_INPUT, "Response CV");
+ configInput(GAIN_INPUT, "Gain CV");
+ configInput(IN_INPUT, "Signal");
+
+ configOutput(OUT_OUTPUT, "Envelope");
}
bool active() override;
diff --git a/src/FourFO.cpp b/src/FourFO.cpp
@@ -237,7 +237,6 @@ struct FourFOWidget : BGModuleWidget {
{
auto w = createParam<Knob16>(waveParamPosition, module, FourFO::WAVE_PARAM);
auto k = dynamic_cast<SvgKnob*>(w);
- k->snap = true;
k->minAngle = 0.0;
k->maxAngle = M_PI;
k->speed = 3.0;
diff --git a/src/FourFO.hpp b/src/FourFO.hpp
@@ -101,8 +101,9 @@ struct FourFO : LFOBase {
FourFO() : LFOBase(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {
configParam<LFOFrequencyParamQuantity>(FREQUENCY_PARAM, -5.0f, 8.0f, 0.0, "Frequency", " Hz");
- configParam(WAVE_PARAM, 1.0, 6.0, 3.0, "Waveform");
- configParam(SLOW_PARAM, 0.0, 1.0, 0.0, "Slow");
+ configSwitch(WAVE_PARAM, 1.0, 6.0, 3.0, "Waveform", {"Ramp up", "Ramp down", "Sine", "Triangle", "Square", "Stepped"});
+ paramQuantities[WAVE_PARAM]->snapEnabled = true;
+ configButton(SLOW_PARAM, "Slow");
configParam(SAMPLE_PWM_PARAM, -1.0, 1.0, 0.0, "Width", "%", 0.0f, 100.0f);
configParam(SMOOTH_PARAM, 0.0f, 1.0f, 0.0f, "Smoothing", "%", 0.0f, 100.0f);
configParam(OFFSET_PARAM, -1.0, 1.0, 0.0, "Offset", " V", 0.0f, 5.0f);
@@ -111,6 +112,22 @@ struct FourFO : LFOBase {
configParam(PHASE2_PARAM, -1.0, 1.0, 0.0, "Phase 180", "º", 0.0f, 180.0f);
configParam(PHASE1_PARAM, -1.0, 1.0, 0.0, "Phase 90", "º", 0.0f, 180.0f);
configParam(PHASE0_PARAM, -1.0, 1.0, 0.0f, "Phase 0", "º", 0.0f, 180.0f);
+
+ configInput(SAMPLE_PWM_INPUT, "Sample/PWM CV");
+ configInput(SMOOTH_INPUT, "Smoothing CV");
+ configInput(OFFSET_INPUT, "Offset CV");
+ configInput(SCALE_INPUT, "Scale CV");
+ configInput(PITCH_INPUT, "Pitch (1V/octave)");
+ configInput(RESET_INPUT, "Reset");
+ configInput(PHASE0_INPUT, "Phase 0 CV");
+ configInput(PHASE1_INPUT, "Phase 1 CV");
+ configInput(PHASE2_INPUT, "Phase 2 CV");
+ configInput(PHASE3_INPUT, "Phase 3 CV");
+
+ configOutput(PHASE0_OUTPUT, "Phase 0");
+ configOutput(PHASE1_OUTPUT, "Phase 1");
+ configOutput(PHASE2_OUTPUT, "Phase 2");
+ configOutput(PHASE3_OUTPUT, "Phase 3");
}
void reset() override;
diff --git a/src/FourMan.cpp b/src/FourMan.cpp
@@ -14,14 +14,14 @@ void FourMan::sampleRateChange() {
_sampleTime = APP->engine->getSampleTime();
}
-json_t* FourMan::toJson(json_t* root) {
- root = TriggerOnLoadModule::toJson(root);
+json_t* FourMan::saveToJson(json_t* root) {
+ root = TriggerOnLoadModule::saveToJson(root);
json_object_set_new(root, OUTPUT_SCALE, json_real(_outputScale));
return root;
}
-void FourMan::fromJson(json_t* root) {
- TriggerOnLoadModule::fromJson(root);
+void FourMan::loadFromJson(json_t* root) {
+ TriggerOnLoadModule::loadFromJson(root);
json_t* os = json_object_get(root, OUTPUT_SCALE);
if (os) {
_outputScale = json_real_value(os);
diff --git a/src/FourMan.hpp b/src/FourMan.hpp
@@ -37,10 +37,16 @@ struct FourMan : TriggerOnLoadModule {
FourMan() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
- configParam(TRIGGER1_PARAM, 0.0f, 1.0f, 0.0f, "Trigger 1");
- configParam(TRIGGER2_PARAM, 0.0f, 1.0f, 0.0f, "Trigger 2");
- configParam(TRIGGER3_PARAM, 0.0f, 1.0f, 0.0f, "Trigger 3");
- configParam(TRIGGER4_PARAM, 0.0f, 1.0f, 0.0f, "Trigger 4");
+ configButton(TRIGGER1_PARAM, "Trigger 1");
+ configButton(TRIGGER2_PARAM, "Trigger 2");
+ configButton(TRIGGER3_PARAM, "Trigger 3");
+ configButton(TRIGGER4_PARAM, "Trigger 4");
+
+ configOutput(OUT1_OUTPUT, "Trigger 1");
+ configOutput(OUT2_OUTPUT, "Trigger 2");
+ configOutput(OUT3_OUTPUT, "Trigger 3");
+ configOutput(OUT4_OUTPUT, "Trigger 4");
+
_triggerOnLoad = false;
_initialDelay = new bogaudio::dsp::Timer(APP->engine->getSampleRate(), 0.01f);
}
@@ -52,8 +58,8 @@ struct FourMan : TriggerOnLoadModule {
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void processAll(const ProcessArgs& args) override;
bool shouldTriggerOnNextLoad() override {
return true;
diff --git a/src/Inv.cpp b/src/Inv.cpp
@@ -12,7 +12,7 @@ void Inv::reset() {
}
}
-json_t* Inv::toJson(json_t* root) {
+json_t* Inv::saveToJson(json_t* root) {
json_object_set_new(root, SAVE_LATCHED_TO_PATCH, json_boolean(_saveLatchedToPatch));
if (_saveLatchedToPatch) {
if (_latch[0]) {
@@ -34,7 +34,7 @@ json_t* Inv::toJson(json_t* root) {
return root;
}
-void Inv::fromJson(json_t* root) {
+void Inv::loadFromJson(json_t* root) {
json_t* sl = json_object_get(root, SAVE_LATCHED_TO_PATCH);
if (sl) {
_saveLatchedToPatch = json_is_true(sl);
@@ -140,8 +140,8 @@ struct InvWidget : BGModuleWidget {
addOutput(createOutput<Port24>(out1OutputPosition, module, Inv::OUT1_OUTPUT));
addOutput(createOutput<Port24>(out2OutputPosition, module, Inv::OUT2_OUTPUT));
- addChild(createLight<SmallLight<GreenRedLight>>(low1LightPosition, module, Inv::LOW1_LIGHT));
- addChild(createLight<SmallLight<GreenRedLight>>(low2LightPosition, module, Inv::LOW2_LIGHT));
+ addChild(createLight<BGSmallLight<GreenRedLight>>(low1LightPosition, module, Inv::LOW1_LIGHT));
+ addChild(createLight<BGSmallLight<GreenRedLight>>(low2LightPosition, module, Inv::LOW2_LIGHT));
}
void contextMenu(Menu* menu) override {
diff --git a/src/Inv.hpp b/src/Inv.hpp
@@ -45,14 +45,24 @@ struct Inv : BGModule {
Inv() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
configParam(GATE1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 gate");
- configParam(LATCH1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 latch");
+ configSwitch(LATCH1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 latch", {"Disabled", "Enabled"});
configParam(GATE2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 gate");
- configParam(LATCH2_PARAM, 0.0f, 1.0f, 0.0f, "Channle 2 latch");
+ configSwitch(LATCH2_PARAM, 0.0f, 1.0f, 0.0f, "Channle 2 latch", {"Disabled", "Enabled"});
+ configBypass(IN1_INPUT, OUT1_OUTPUT);
+ configBypass(IN2_INPUT, OUT2_OUTPUT);
+
+ configInput(GATE1_INPUT, "Gate 1");
+ configInput(IN1_INPUT, "Signal 1");
+ configInput(GATE2_INPUT, "Gate 2");
+ configInput(IN2_INPUT, "Signal 2");
+
+ configOutput(OUT1_OUTPUT, "Signal 1");
+ configOutput(OUT2_OUTPUT, "Signal 2");
}
void reset() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void modulate() override;
void processAll(const ProcessArgs& args) override;
void processDual(int i);
diff --git a/src/LFO.cpp b/src/LFO.cpp
@@ -25,12 +25,12 @@ void LFO::sampleRateChange() {
}
}
-json_t* LFO::toJson(json_t* root) {
+json_t* LFO::saveToJson(json_t* root) {
json_object_set_new(root, OFFSET_CV_TO_SMOOTHING, json_boolean(_useOffsetCvForSmooth));
return root;
}
-void LFO::fromJson(json_t* root) {
+void LFO::loadFromJson(json_t* root) {
json_t* ocv = json_object_get(root, OFFSET_CV_TO_SMOOTHING);
if (ocv) {
_useOffsetCvForSmooth = json_boolean_value(ocv);
diff --git a/src/LFO.hpp b/src/LFO.hpp
@@ -86,18 +86,32 @@ struct LFO : LFOBase {
LFO() : LFOBase(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {
configParam<LFOFrequencyParamQuantity>(FREQUENCY_PARAM, -5.0f, 8.0f, 0.0f, "Frequency", " Hz");
- configParam(SLOW_PARAM, 0.0f, 1.0f, 0.0f, "Slow");
+ configButton(SLOW_PARAM, "Slow");
configParam(SAMPLE_PARAM, 0.0f, 1.0f, 0.0f, "Output sampling", "%", 0.0f, 100.0f);
configParam(PW_PARAM, -1.0f, 1.0f, 0.0f, "Pulse width", "%", 0.0f, 100.0f*0.5f*(1.0f - 2.0f * SquareOscillator::minPulseWidth), 50.0f);
configParam(SMOOTH_PARAM, 0.0f, 1.0f, 0.0f, "Smoothing", "%", 0.0f, 100.0f);
configParam(OFFSET_PARAM, -1.0f, 1.0f, 0.0f, "Offset", " V", 0.0f, 5.0f);
configParam(SCALE_PARAM, 0.0f, 1.0f, 1.0f, "Scale", "%", 0.0f, 100.0f);
+
+ configInput(SAMPLE_INPUT, "Sample CV");
+ configInput(PW_INPUT, "Pulse width CV");
+ configInput(OFFSET_INPUT, "Offset CV");
+ configInput(SCALE_INPUT, "Scale CV");
+ configInput(PITCH_INPUT, "Pitch (1V/octave)");
+ configInput(RESET_INPUT, "Reset");
+
+ configOutput(RAMP_UP_OUTPUT, "Ramp up");
+ configOutput(RAMP_DOWN_OUTPUT, "Ramp down");
+ configOutput(SQUARE_OUTPUT, "Square");
+ configOutput(TRIANGLE_OUTPUT, "Triangle");
+ configOutput(SINE_OUTPUT, "Sine");
+ configOutput(STEPPED_OUTPUT, "Stepped");
}
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
bool active() override;
int channels() override;
void addChannel(int c) override;
diff --git a/src/LLFO.cpp b/src/LLFO.cpp
@@ -18,7 +18,7 @@ void LLFO::sampleRateChange() {
}
}
-json_t* LLFO::toJson(json_t* root) {
+json_t* LLFO::saveToJson(json_t* root) {
json_object_set_new(root, OUTPUT_SAMPLING, json_real(_sample));
json_object_set_new(root, PULSE_WIDTH, json_real(_pulseWidth));
json_object_set_new(root, SMOOTHING, json_real(_smooth));
@@ -26,7 +26,7 @@ json_t* LLFO::toJson(json_t* root) {
return root;
}
-void LLFO::fromJson(json_t* root) {
+void LLFO::loadFromJson(json_t* root) {
json_t* os = json_object_get(root, OUTPUT_SAMPLING);
if (os) {
_sample = json_real_value(os);
@@ -333,13 +333,13 @@ struct LLFOWidget : BGModuleWidget {
addOutput(createOutput<Port24>(outOutputPosition, module, LLFO::OUT_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(sineLightPosition, module, LLFO::SINE_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(rampUpLightPosition, module, LLFO::RAMP_UP_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(squareLightPosition, module, LLFO::SQUARE_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(steppedLightPosition, module, LLFO::STEPPED_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(triangleLightPosition, module, LLFO::TRIANGLE_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(rampDownLightPosition, module, LLFO::RAMP_DOWN_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(pulseLightPosition, module, LLFO::PULSE_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(sineLightPosition, module, LLFO::SINE_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(rampUpLightPosition, module, LLFO::RAMP_UP_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(squareLightPosition, module, LLFO::SQUARE_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(steppedLightPosition, module, LLFO::STEPPED_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(triangleLightPosition, module, LLFO::TRIANGLE_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(rampDownLightPosition, module, LLFO::RAMP_DOWN_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(pulseLightPosition, module, LLFO::PULSE_LIGHT));
}
void contextMenu(Menu* menu) override {
diff --git a/src/LLFO.hpp b/src/LLFO.hpp
@@ -87,16 +87,21 @@ struct LLFO : LFOBase {
, _oscillator(&_sine)
{
configParam<LFOFrequencyParamQuantity>(FREQUENCY_PARAM, -5.0f, 8.0f, 0.0f, "Frequency", " Hz");
- configParam(WAVE_PARAM, 0.0f, 6.0f, 0.0f, "Waveform");
- configParam(SLOW_PARAM, 0.0f, 1.0f, 0.0f, "Slow mode");
+ configSwitch(WAVE_PARAM, 0.0f, 6.0f, 0.0f, "Waveform", {"Sine", "Triangle", "Ramp up", "Ramp down", "Square", "Pulse", "Stepped"});
+ configButton(SLOW_PARAM, "Slow mode");
configParam(OFFSET_PARAM, -1.0f, 1.0f, 0.0f, "Offset", " V", 0.0f, 5.0f);
configParam(SCALE_PARAM, 0.0f, 1.0f, 1.0f, "Scale", "%", 0.0f, 100.0f);
+
+ configInput(PITCH_INPUT, "Pitch (1V/octave)");
+ configInput(RESET_INPUT, "Reset");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
bool active() override;
int channels() override;
void addChannel(int c) override;
diff --git a/src/LLPG.hpp b/src/LLPG.hpp
@@ -52,6 +52,11 @@ struct LLPG : BGModule {
configParam(SHAPE_PARAM, -1.0f, 1.0f, -0.25f, "Shape");
configParam<ScaledSquaringParamQuantity<(int)maxFilterCutoff>>(LPF_PARAM, 0.0f, 1.0f, 0.0f, "LPF cutoff", " HZ");
configParam(VCA_PARAM, 0.0f, 1.0f, 0.0f, "VCA level", "%", 0.0f, 100.0f);
+
+ configInput(GATE_INPUT, "Gate");
+ configInput(IN_INPUT, "Signal");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
void reset() override;
diff --git a/src/LPG.cpp b/src/LPG.cpp
@@ -26,12 +26,12 @@ void LPG::sampleRateChange() {
}
}
-json_t* LPG::toJson(json_t* root) {
+json_t* LPG::saveToJson(json_t* root) {
json_object_set_new(root, LPF_POLES, json_integer(_lpfPoles));
return root;
}
-void LPG::fromJson(json_t* root) {
+void LPG::loadFromJson(json_t* root) {
json_t* p = json_object_get(root, LPF_POLES);
if (p) {
_lpfPoles = json_integer_value(p);
diff --git a/src/LPG.hpp b/src/LPG.hpp
@@ -61,20 +61,28 @@ struct LPG : LPGEnvBaseModule {
{
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam(RESPONSE_PARAM, 0.0f, 1.0f, 0.5f, "Response", "%", 0.0f, 100.0f);
- configParam(LONG_PARAM, 0.0f, 1.0f, 0.0f, "Long mode");
+ configButton(LONG_PARAM, "Long mode");
configParam(RISE_SHAPE_PARAM, -1.0f, 1.0f, 0.0f, "Rise shape");
configParam(FALL_SHAPE_PARAM, -1.0f, 1.0f, -0.5f, "Fall shape");
configParam(LPF_ENV_PARAM, -1.0f, 1.0f, 0.8f, "LPF envelope amount", "%", 0.0f, 100.0f);
configParam<ScaledSquaringParamQuantity<(int)maxFilterCutoff>>(LPF_BIAS_PARAM, 0.0f, 1.0f, 0.0f, "LPF cutoff", " HZ");
configParam(VCA_ENV_PARAM, -1.0f, 1.0f, 1.0f, "VCA envelope amount", "%", 0.0f, 100.0f);
configParam(VCA_BIAS_PARAM, 0.0f, 1.0f, 0.0f, "VCA level", "%", 0.0f, 100.0f);
- configParam(LINEAR_VCA_PARAM, 0.0f, 1.0f, 0.0f, "Linear VCA mode");
+ configButton(LINEAR_VCA_PARAM, "Linear VCA mode");
+
+ configInput(RESPONSE_INPUT, "Response CV");
+ configInput(LPF_INPUT, "LPF envelope response CV");
+ configInput(VCA_INPUT, "VCA envelope response CV");
+ configInput(GATE_INPUT, "Gate");
+ configInput(IN_INPUT, "Signal");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
bool active() override;
int channels() override;
void addChannel(int c) override;
diff --git a/src/LVCF.cpp b/src/LVCF.cpp
@@ -42,7 +42,7 @@ float LVCF::Engine::next(float sample) {
return _finalHP.next(_filter.next(sample));
}
-json_t* LVCF::toJson(json_t* root) {
+json_t* LVCF::saveToJson(json_t* root) {
json_object_set_new(root, POLES_KEY, json_integer(_polesSetting));
switch (_bandwidthMode) {
@@ -60,7 +60,7 @@ json_t* LVCF::toJson(json_t* root) {
return root;
}
-void LVCF::fromJson(json_t* root) {
+void LVCF::loadFromJson(json_t* root) {
json_t* p = json_object_get(root, POLES_KEY);
if (p) {
_polesSetting = clamp(json_integer_value(p), 1, 12);
@@ -192,10 +192,10 @@ struct LVCFWidget : BGModuleWidget {
addOutput(createOutput<Port24>(outOutputPosition, module, LVCF::OUT_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(lowpassLightPosition, module, LVCF::LOWPASS_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(bandpassLightPosition, module, LVCF::BANDPASS_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(highpassLightPosition, module, LVCF::HIGHPASS_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(bandrejectLightPosition, module, LVCF::BANDREJECT_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(lowpassLightPosition, module, LVCF::LOWPASS_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(bandpassLightPosition, module, LVCF::BANDPASS_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(highpassLightPosition, module, LVCF::HIGHPASS_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(bandrejectLightPosition, module, LVCF::BANDREJECT_LIGHT));
}
void contextMenu(Menu* menu) override {
diff --git a/src/LVCF.hpp b/src/LVCF.hpp
@@ -73,11 +73,17 @@ struct LVCF : BGModule {
configParam<ScaledSquaringParamQuantity<(int)maxFrequency>>(FREQUENCY_PARAM, 0.0f, 1.0f, 0.22361f, "Center/cutoff frequency", " HZ");
configParam(FREQUENCY_CV_PARAM, -1.0f, 1.0f, 0.0f, "Frequency CV attenuation", "%", 0.0f, 100.0f);
configParam(Q_PARAM, 0.0f, 1.0f, 0.0f, "Resonance / bandwidth", "%", 0.0f, 100.0f);
- configParam(MODE_PARAM, 0.0f, 3.0f, 0.0f, "Mode");
+ configSwitch(MODE_PARAM, 0.0f, 3.0f, 0.0f, "Mode", {"Lowpass", "Highpass", "Bandpass", "Band reject"});
+ configBypass(IN_INPUT, OUT_OUTPUT);
+
+ configInput(IN_INPUT, "Signal");
+ configInput(FREQUENCY_CV_INPUT, "Cutoff CV");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void sampleRateChange() override;
bool active() override;
int channels() override;
diff --git a/src/LVCO.cpp b/src/LVCO.cpp
@@ -5,16 +5,16 @@
#define LINEAR_MODE "linear_mode"
#define RESET_ON_WAVE_CHANGE "reset_on_wave_change"
-json_t* LVCO::toJson(json_t* root) {
- root = VCOBase::toJson(root);
+json_t* LVCO::saveToJson(json_t* root) {
+ root = VCOBase::saveToJson(root);
json_object_set_new(root, FM_MODE, json_boolean(_fmLinearMode));
json_object_set_new(root, LINEAR_MODE, json_boolean(_linearMode));
json_object_set_new(root, RESET_ON_WAVE_CHANGE, json_boolean(_resetOnWaveChange));
return root;
}
-void LVCO::fromJson(json_t* root) {
- VCOBase::fromJson(root);
+void LVCO::loadFromJson(json_t* root) {
+ VCOBase::loadFromJson(root);
json_t* fm = json_object_get(root, FM_MODE);
if (fm) {
@@ -139,12 +139,12 @@ struct LVCOWidget : VCOBaseModuleWidget {
addOutput(createOutput<Port24>(outOutputPosition, module, LVCO::OUT_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(sineLightPosition, module, LVCO::SINE_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(sawLightPosition, module, LVCO::SAW_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(pulse25LightPosition, module, LVCO::PULSE_25_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(triangleLightPosition, module, LVCO::TRIANGLE_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(squareLightPosition, module, LVCO::SQUARE_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(pulse10LightPosition, module, LVCO::PULSE_10_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(sineLightPosition, module, LVCO::SINE_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(sawLightPosition, module, LVCO::SAW_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(pulse25LightPosition, module, LVCO::PULSE_25_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(triangleLightPosition, module, LVCO::TRIANGLE_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(squareLightPosition, module, LVCO::SQUARE_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(pulse10LightPosition, module, LVCO::PULSE_10_LIGHT));
}
void contextMenu(Menu* menu) override {
diff --git a/src/LVCO.hpp b/src/LVCO.hpp
@@ -62,13 +62,19 @@ struct LVCO : VCOBase {
{
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
configParam<VCOFrequencyParamQuantity>(FREQUENCY_PARAM, -3.0f, 6.0f, 0.0f, "Frequency", " Hz");
- configParam(SLOW_PARAM, 0.0f, 1.0f, 0.0f, "Slow mode");
- configParam(WAVE_PARAM, 0.0f, 5.0f, 0.0f, "Waveform");
+ configButton(SLOW_PARAM, "Slow mode");
+ configSwitch(WAVE_PARAM, 0.0f, 5.0f, 0.0f, "Waveform", {"Sine", "Triangle", "Saw", "Square", "25% Pulse", "10% Pulse"});
configParam(FM_DEPTH_PARAM, 0.0f, 1.0f, 0.0f, "FM depth", "%", 0.0f, 100.0f);
+
+ configInput(PITCH_INPUT, "Pitch (1V/octave)");
+ configInput(FM_INPUT, "Frequency modulation");
+ configInput(SYNC_INPUT, "Sync");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
bool active() override;
void modulateAlways() override;
void modulate() override;
diff --git a/src/Lag.cpp b/src/Lag.cpp
@@ -67,7 +67,6 @@ struct LagWidget : BGModuleWidget {
{
auto w = createParam<Knob16>(timeScaleParamPosition, module, Lag::TIME_SCALE_PARAM);
auto k = dynamic_cast<SvgKnob*>(w);
- k->snap = true;
k->minAngle = -M_PI / 4.0f;
k->maxAngle = M_PI / 4.0f;
k->speed = 3.0;
diff --git a/src/Lag.hpp b/src/Lag.hpp
@@ -35,6 +35,7 @@ struct Lag : BGModule {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam(TIME_PARAM, 0.0f, 1.0f, 0.5f, "time");
configParam(TIME_SCALE_PARAM, 0.0f, 2.0f, 1.0f, "time_scale");
+ paramQuantities[TIME_SCALE_PARAM]->snapEnabled = true;
configParam(SHAPE_PARAM, -1.0f, 1.0f, 0.0f, "shape");
}
diff --git a/src/Lgsw.cpp b/src/Lgsw.cpp
@@ -35,7 +35,7 @@ void Lgsw::processAlways(const ProcessArgs& args) {
}
void Lgsw::processChannel(const ProcessArgs& args, int c) {
- bool buttonTriggered = _buttonTriggers[c].process(params[GATE_PARAM].getValue());
+ bool buttonTriggered = _buttonTriggers[c].process(10.0f*params[GATE_PARAM].getValue());
bool aTriggered = _aTriggers[c].process(inputs[GATE_A_INPUT].getVoltage(c));
bool bTriggered = _bTriggers[c].process(inputs[GATE_B_INPUT].getVoltage(c));
@@ -200,13 +200,13 @@ struct LgswWidget : SaveLatchToPatchModuleWidget {
addOutput(createOutput<Port24>(out1OutputPosition, module, Lgsw::OUT_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(logicOrLightPosition, module, Lgsw::LOGIC_OR_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(logicAndLightPosition, module, Lgsw::LOGIC_AND_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(logicXorLightPosition, module, Lgsw::LOGIC_XOR_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(logicNorLightPosition, module, Lgsw::LOGIC_NOR_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(logicNandLightPosition, module, Lgsw::LOGIC_NAND_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(high1LightPosition, module, Lgsw::HIGH_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(low1LightPosition, module, Lgsw::LOW_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(logicOrLightPosition, module, Lgsw::LOGIC_OR_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(logicAndLightPosition, module, Lgsw::LOGIC_AND_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(logicXorLightPosition, module, Lgsw::LOGIC_XOR_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(logicNorLightPosition, module, Lgsw::LOGIC_NOR_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(logicNandLightPosition, module, Lgsw::LOGIC_NAND_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(high1LightPosition, module, Lgsw::HIGH_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(low1LightPosition, module, Lgsw::LOW_LIGHT));
}
};
diff --git a/src/Lgsw.hpp b/src/Lgsw.hpp
@@ -58,9 +58,17 @@ struct Lgsw : SaveLatchToPatchModule {
Lgsw() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
- configParam(GATE_PARAM, 0.0f, 10.0f, 0.0f, "Gate");
- configParam(LATCH_PARAM, 0.0f, 1.0f, 0.0f, "Latch");
- configParam(LOGIC_MODE_PARAM, 0.0f, 4.0f, 0.0f, "Logic");
+ configButton(GATE_PARAM, "Gate");
+ configSwitch(LATCH_PARAM, 0.0f, 1.0f, 0.0f, "Latch", {"Disabled", "Enabled"});
+ configSwitch(LOGIC_MODE_PARAM, 0.0f, 4.0f, 0.0f, "Logic", {"OR", "AND", "XOR", "NOR", "NAND"});
+
+ configInput(GATE_A_INPUT, "Gate A");
+ configInput(GATE_B_INPUT, "Gate B");
+ configInput(LOGIC_MODE_INPUT, "Logic CV");
+ configInput(HIGH_INPUT, "High signal");
+ configInput(LOW_INPUT, "Low signal");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
void resetChannel(int c);
diff --git a/src/Lmtr.cpp b/src/Lmtr.cpp
@@ -39,14 +39,14 @@ void Lmtr::sampleRateChange() {
}
}
-json_t* Lmtr::toJson(json_t* root) {
+json_t* Lmtr::saveToJson(json_t* root) {
json_object_set_new(root, ATTACK_MS, json_real(_attackMs));
json_object_set_new(root, RELEASE_MS, json_real(_releaseMs));
json_object_set_new(root, THRESHOLD_RANGE, json_real(_thresholdRange));
return root;
}
-void Lmtr::fromJson(json_t* root) {
+void Lmtr::loadFromJson(json_t* root) {
json_t* a = json_object_get(root, ATTACK_MS);
if (a) {
_attackMs = std::max(0.0f, (float)json_real_value(a));
diff --git a/src/Lmtr.hpp b/src/Lmtr.hpp
@@ -68,12 +68,22 @@ struct Lmtr : BGModule {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam<ThresholdParamQuantity>(THRESHOLD_PARAM, 0.0f, 1.0f, 0.8f, "Threshold", " dB");
configParam(OUTPUT_GAIN_PARAM, 0.0f, 1.0f, 0.0f, "Output gain", " dB", 0.0f, 24.0f);
- configParam(KNEE_PARAM, 0.0f, 1.0f, 0.0f, "Knee");
+ configSwitch(KNEE_PARAM, 0.0f, 1.0f, 1.0f, "Knee", {"Hard", "Soft"});
+ configBypass(LEFT_INPUT, LEFT_OUTPUT);
+ configBypass(RIGHT_INPUT, RIGHT_OUTPUT);
+
+ configInput(LEFT_INPUT, "Left signal");
+ configInput(RIGHT_INPUT, "Right signal");
+ configInput(THRESHOLD_INPUT, "Threshold CV");
+ configInput(OUTPUT_GAIN_INPUT, "Output gain CV");
+
+ configOutput(LEFT_OUTPUT, "Left signal");
+ configOutput(RIGHT_OUTPUT, "Right signal");
}
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
bool active() override;
int channels() override;
void addChannel(int c) override;
diff --git a/src/Manual.cpp b/src/Manual.cpp
@@ -12,14 +12,14 @@ void Manual::sampleRateChange() {
_sampleTime = APP->engine->getSampleTime();
}
-json_t* Manual::toJson(json_t* root) {
- root = TriggerOnLoadModule::toJson(root);
+json_t* Manual::saveToJson(json_t* root) {
+ root = TriggerOnLoadModule::saveToJson(root);
json_object_set_new(root, OUTPUT_SCALE, json_real(_outputScale));
return root;
}
-void Manual::fromJson(json_t* root) {
- TriggerOnLoadModule::fromJson(root);
+void Manual::loadFromJson(json_t* root) {
+ TriggerOnLoadModule::loadFromJson(root);
json_t* os = json_object_get(root, OUTPUT_SCALE);
if (os) {
_outputScale = json_real_value(os);
diff --git a/src/Manual.hpp b/src/Manual.hpp
@@ -38,7 +38,17 @@ struct Manual : TriggerOnLoadModule {
Manual() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
- configParam(TRIGGER_PARAM, 0.0f, 1.0f, 0.0f, "Trigger");
+ configButton(TRIGGER_PARAM, "Trigger");
+
+ configOutput(OUT1_OUTPUT, "Trigger");
+ configOutput(OUT2_OUTPUT, "Trigger");
+ configOutput(OUT3_OUTPUT, "Trigger");
+ configOutput(OUT4_OUTPUT, "Trigger");
+ configOutput(OUT5_OUTPUT, "Trigger");
+ configOutput(OUT6_OUTPUT, "Trigger");
+ configOutput(OUT7_OUTPUT, "Trigger");
+ configOutput(OUT8_OUTPUT, "Trigger");
+
_triggerOnLoad = false;
_initialDelay = new bogaudio::dsp::Timer(APP->engine->getSampleRate(), 0.01f);
}
@@ -50,8 +60,8 @@ struct Manual : TriggerOnLoadModule {
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void processAll(const ProcessArgs& args) override;
bool shouldTriggerOnNextLoad() override {
return true;
diff --git a/src/Matrix18.hpp b/src/Matrix18.hpp
@@ -47,6 +47,17 @@ struct Matrix18 : KnobMatrixModule {
configParam(MIX6_PARAM, -1.0f, 1.0f, 0.0f, "Route 6", "%", 0.0f, 100.0f);
configParam(MIX7_PARAM, -1.0f, 1.0f, 0.0f, "Route 7", "%", 0.0f, 100.0f);
configParam(MIX8_PARAM, -1.0f, 1.0f, 0.0f, "Route 8", "%", 0.0f, 100.0f);
+
+ configInput(IN_INPUT, "Signal");
+
+ configOutput(OUT1_OUTPUT, "Signal 1");
+ configOutput(OUT2_OUTPUT, "Signal 2");
+ configOutput(OUT3_OUTPUT, "Signal 3");
+ configOutput(OUT4_OUTPUT, "Signal 4");
+ configOutput(OUT5_OUTPUT, "Signal 5");
+ configOutput(OUT6_OUTPUT, "Signal 6");
+ configOutput(OUT7_OUTPUT, "Signal 7");
+ configOutput(OUT8_OUTPUT, "Signal 8");
}
};
diff --git a/src/Matrix44.hpp b/src/Matrix44.hpp
@@ -63,6 +63,17 @@ struct Matrix44 : Matrix44Base {
configParam(MIX34_PARAM, -1.0f, 1.0f, 0.0f, "Mix 3D", "%", 0.0f, 100.0f);
configParam(MIX44_PARAM, -1.0f, 1.0f, 0.0f, "Mix 4D", "%", 0.0f, 100.0f);
+ configInput(IN1_INPUT, "Signal 1");
+ configInput(IN2_INPUT, "Signal 2");
+ configInput(IN3_INPUT, "Signal 3");
+ configInput(IN4_INPUT, "Signal 4");
+
+ configOutput(OUT1_OUTPUT, "Signal A");
+ configOutput(OUT2_OUTPUT, "Signal B");
+ configOutput(OUT3_OUTPUT, "Signal C");
+ configOutput(OUT4_OUTPUT, "Signal D");
+
+
setLocalElements({new Matrix44Element(NULL, NULL, NULL)});
registerBase();
setExpanderModelPredicate([](Model* m) { return m == modelMatrix44Cvm; });
diff --git a/src/Matrix44Cvm.hpp b/src/Matrix44Cvm.hpp
@@ -55,23 +55,41 @@ struct Matrix44Cvm : Matrix44CvmBase {
Input** _cvs = NULL;
Matrix44Cvm() {
+ const std::vector<std::string> muteLabels = {"Unmuted", "Muted", "Soloed", "Soloed"};
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
- configParam(MUTE11_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1A");
- configParam(MUTE21_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2A");
- configParam(MUTE31_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3A");
- configParam(MUTE41_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4A");
- configParam(MUTE12_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1B");
- configParam(MUTE22_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2B");
- configParam(MUTE32_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3B");
- configParam(MUTE42_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4B");
- configParam(MUTE13_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1C");
- configParam(MUTE23_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2C");
- configParam(MUTE33_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3C");
- configParam(MUTE43_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4C");
- configParam(MUTE14_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1D");
- configParam(MUTE24_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2D");
- configParam(MUTE34_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3D");
- configParam(MUTE44_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4D");
+ configSwitch(MUTE11_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1A", muteLabels);
+ configSwitch(MUTE21_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2A", muteLabels);
+ configSwitch(MUTE31_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3A", muteLabels);
+ configSwitch(MUTE41_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4A", muteLabels);
+ configSwitch(MUTE12_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1B", muteLabels);
+ configSwitch(MUTE22_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2B", muteLabels);
+ configSwitch(MUTE32_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3B", muteLabels);
+ configSwitch(MUTE42_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4B", muteLabels);
+ configSwitch(MUTE13_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1C", muteLabels);
+ configSwitch(MUTE23_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2C", muteLabels);
+ configSwitch(MUTE33_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3C", muteLabels);
+ configSwitch(MUTE43_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4C", muteLabels);
+ configSwitch(MUTE14_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1D", muteLabels);
+ configSwitch(MUTE24_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2D", muteLabels);
+ configSwitch(MUTE34_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3D", muteLabels);
+ configSwitch(MUTE44_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4D", muteLabels);
+
+ configInput(CV11_INPUT, "Level 1A CV");
+ configInput(CV21_INPUT, "Level 2A CV");
+ configInput(CV31_INPUT, "Level 3A CV");
+ configInput(CV41_INPUT, "Level 4A CV");
+ configInput(CV12_INPUT, "Level 1B CV");
+ configInput(CV22_INPUT, "Level 2B CV");
+ configInput(CV32_INPUT, "Level 3B CV");
+ configInput(CV42_INPUT, "Level 4B CV");
+ configInput(CV13_INPUT, "Level 1C CV");
+ configInput(CV23_INPUT, "Level 2C CV");
+ configInput(CV33_INPUT, "Level 3C CV");
+ configInput(CV43_INPUT, "Level 4C CV");
+ configInput(CV14_INPUT, "Level 1D CV");
+ configInput(CV24_INPUT, "Level 2D CV");
+ configInput(CV34_INPUT, "Level 3D CV");
+ configInput(CV44_INPUT, "Level 4D CV");
_mutes = new Param*[16];
_cvs = new Input*[16];
diff --git a/src/Matrix81.hpp b/src/Matrix81.hpp
@@ -47,6 +47,17 @@ struct Matrix81 : KnobMatrixModule {
configParam(MIX6_PARAM, -1.0f, 1.0f, 0.0f, "Mix 6", "%", 0.0f, 100.0f);
configParam(MIX7_PARAM, -1.0f, 1.0f, 0.0f, "Mix 7", "%", 0.0f, 100.0f);
configParam(MIX8_PARAM, -1.0f, 1.0f, 0.0f, "Mix 8", "%", 0.0f, 100.0f);
+
+ configInput(IN1_INPUT, "Signal A");
+ configInput(IN2_INPUT, "Signal B");
+ configInput(IN3_INPUT, "Signal C");
+ configInput(IN4_INPUT, "Signal D");
+ configInput(IN5_INPUT, "Signal E");
+ configInput(IN6_INPUT, "Signal F");
+ configInput(IN7_INPUT, "Signal G");
+ configInput(IN8_INPUT, "Signal H");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
};
diff --git a/src/Matrix88.hpp b/src/Matrix88.hpp
@@ -167,6 +167,24 @@ struct Matrix88 : Matrix88Base {
configParam(MIX78_PARAM, -1.0f, 1.0f, 0.0f, "Mix 7H", "%", 0.0f, 100.0f);
configParam(MIX88_PARAM, -1.0f, 1.0f, 0.0f, "Mix 8H", "%", 0.0f, 100.0f);
+ configInput(IN1_INPUT, "Signal 1");
+ configInput(IN2_INPUT, "Signal 2");
+ configInput(IN3_INPUT, "Signal 3");
+ configInput(IN4_INPUT, "Signal 4");
+ configInput(IN5_INPUT, "Signal 5");
+ configInput(IN6_INPUT, "Signal 6");
+ configInput(IN7_INPUT, "Signal 7");
+ configInput(IN8_INPUT, "Signal 8");
+
+ configOutput(OUT1_OUTPUT, "Signal A");
+ configOutput(OUT2_OUTPUT, "Signal B");
+ configOutput(OUT3_OUTPUT, "Signal C");
+ configOutput(OUT4_OUTPUT, "Signal D");
+ configOutput(OUT5_OUTPUT, "Signal E");
+ configOutput(OUT6_OUTPUT, "Signal F");
+ configOutput(OUT7_OUTPUT, "Signal G");
+ configOutput(OUT8_OUTPUT, "Signal H");
+
setLocalElements({new Matrix88Element(NULL, NULL, NULL)});
registerBase();
setExpanderModelPredicate([](Model* m) { return m == modelMatrix88Cv || m == modelMatrix88M; });
diff --git a/src/Matrix88Cv.hpp b/src/Matrix88Cv.hpp
@@ -87,6 +87,72 @@ struct Matrix88Cv : Matrix88CvBase {
Matrix88Cv() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
+
+ configInput(CV11_INPUT, "Level 1A CV");
+ configInput(CV21_INPUT, "Level 2A CV");
+ configInput(CV31_INPUT, "Level 3A CV");
+ configInput(CV41_INPUT, "Level 4A CV");
+ configInput(CV51_INPUT, "Level 5A CV");
+ configInput(CV61_INPUT, "Level 6A CV");
+ configInput(CV71_INPUT, "Level 7A CV");
+ configInput(CV81_INPUT, "Level 8A CV");
+ configInput(CV12_INPUT, "Level 1B CV");
+ configInput(CV22_INPUT, "Level 2B CV");
+ configInput(CV32_INPUT, "Level 3B CV");
+ configInput(CV42_INPUT, "Level 4B CV");
+ configInput(CV52_INPUT, "Level 5B CV");
+ configInput(CV62_INPUT, "Level 6B CV");
+ configInput(CV72_INPUT, "Level 7B CV");
+ configInput(CV82_INPUT, "Level 8B CV");
+ configInput(CV13_INPUT, "Level 1C CV");
+ configInput(CV23_INPUT, "Level 2C CV");
+ configInput(CV33_INPUT, "Level 3C CV");
+ configInput(CV43_INPUT, "Level 4C CV");
+ configInput(CV53_INPUT, "Level 5C CV");
+ configInput(CV63_INPUT, "Level 6C CV");
+ configInput(CV73_INPUT, "Level 7C CV");
+ configInput(CV83_INPUT, "Level 8C CV");
+ configInput(CV14_INPUT, "Level 1D CV");
+ configInput(CV24_INPUT, "Level 2D CV");
+ configInput(CV34_INPUT, "Level 3D CV");
+ configInput(CV44_INPUT, "Level 4D CV");
+ configInput(CV54_INPUT, "Level 5D CV");
+ configInput(CV64_INPUT, "Level 6D CV");
+ configInput(CV74_INPUT, "Level 7D CV");
+ configInput(CV84_INPUT, "Level 8D CV");
+ configInput(CV15_INPUT, "Level 1E CV");
+ configInput(CV25_INPUT, "Level 2E CV");
+ configInput(CV35_INPUT, "Level 3E CV");
+ configInput(CV45_INPUT, "Level 4E CV");
+ configInput(CV55_INPUT, "Level 5E CV");
+ configInput(CV65_INPUT, "Level 6E CV");
+ configInput(CV75_INPUT, "Level 7E CV");
+ configInput(CV85_INPUT, "Level 8E CV");
+ configInput(CV16_INPUT, "Level 1F CV");
+ configInput(CV26_INPUT, "Level 2F CV");
+ configInput(CV36_INPUT, "Level 3F CV");
+ configInput(CV46_INPUT, "Level 4F CV");
+ configInput(CV56_INPUT, "Level 5F CV");
+ configInput(CV66_INPUT, "Level 6F CV");
+ configInput(CV76_INPUT, "Level 7F CV");
+ configInput(CV86_INPUT, "Level 8F CV");
+ configInput(CV17_INPUT, "Level 1G CV");
+ configInput(CV27_INPUT, "Level 2G CV");
+ configInput(CV37_INPUT, "Level 3G CV");
+ configInput(CV47_INPUT, "Level 4G CV");
+ configInput(CV57_INPUT, "Level 5G CV");
+ configInput(CV67_INPUT, "Level 6G CV");
+ configInput(CV77_INPUT, "Level 7G CV");
+ configInput(CV87_INPUT, "Level 8G CV");
+ configInput(CV18_INPUT, "Level 1H CV");
+ configInput(CV28_INPUT, "Level 2H CV");
+ configInput(CV38_INPUT, "Level 3H CV");
+ configInput(CV48_INPUT, "Level 4H CV");
+ configInput(CV58_INPUT, "Level 5H CV");
+ configInput(CV68_INPUT, "Level 6H CV");
+ configInput(CV78_INPUT, "Level 7H CV");
+ configInput(CV88_INPUT, "Level 8H CV");
+
_cvs = new Input*[64];
for (int i = 0; i < 64; ++i) {
_cvs[i] = &inputs[CV11_INPUT + i];
diff --git a/src/Matrix88M.hpp b/src/Matrix88M.hpp
@@ -86,78 +86,79 @@ struct Matrix88M : Matrix88MBase {
Param** _mutes = NULL;
Matrix88M() {
+ const std::vector<std::string> muteLabels = {"Unmuted", "Muted", "Soloed", "Soloed"};
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
- configParam(MUTE11_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1A");
- configParam(MUTE21_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2A");
- configParam(MUTE31_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3A");
- configParam(MUTE41_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4A");
- configParam(MUTE51_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5A");
- configParam(MUTE61_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6A");
- configParam(MUTE71_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7A");
- configParam(MUTE81_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8A");
-
- configParam(MUTE12_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1B");
- configParam(MUTE22_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2B");
- configParam(MUTE32_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3B");
- configParam(MUTE42_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4B");
- configParam(MUTE52_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5B");
- configParam(MUTE62_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6B");
- configParam(MUTE72_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7B");
- configParam(MUTE82_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8B");
-
- configParam(MUTE13_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1C");
- configParam(MUTE23_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2C");
- configParam(MUTE33_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3C");
- configParam(MUTE43_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4C");
- configParam(MUTE53_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5C");
- configParam(MUTE63_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6C");
- configParam(MUTE73_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7C");
- configParam(MUTE83_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8C");
-
- configParam(MUTE14_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1D");
- configParam(MUTE24_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2D");
- configParam(MUTE34_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3D");
- configParam(MUTE44_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4D");
- configParam(MUTE54_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5D");
- configParam(MUTE64_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6D");
- configParam(MUTE74_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7D");
- configParam(MUTE84_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8D");
-
- configParam(MUTE15_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1E");
- configParam(MUTE25_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2E");
- configParam(MUTE35_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3E");
- configParam(MUTE45_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4E");
- configParam(MUTE55_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5E");
- configParam(MUTE65_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6E");
- configParam(MUTE75_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7E");
- configParam(MUTE85_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8E");
-
- configParam(MUTE16_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1F");
- configParam(MUTE26_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2F");
- configParam(MUTE36_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3F");
- configParam(MUTE46_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4F");
- configParam(MUTE56_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5F");
- configParam(MUTE66_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6F");
- configParam(MUTE76_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7F");
- configParam(MUTE86_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8F");
-
- configParam(MUTE17_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1G");
- configParam(MUTE27_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2G");
- configParam(MUTE37_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3G");
- configParam(MUTE47_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4G");
- configParam(MUTE57_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5G");
- configParam(MUTE67_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6G");
- configParam(MUTE77_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7G");
- configParam(MUTE87_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8G");
-
- configParam(MUTE18_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1H");
- configParam(MUTE28_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2H");
- configParam(MUTE38_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3H");
- configParam(MUTE48_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4H");
- configParam(MUTE58_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5H");
- configParam(MUTE68_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6H");
- configParam(MUTE78_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7H");
- configParam(MUTE88_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8H");
+ configSwitch(MUTE11_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1A", muteLabels);
+ configSwitch(MUTE21_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2A", muteLabels);
+ configSwitch(MUTE31_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3A", muteLabels);
+ configSwitch(MUTE41_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4A", muteLabels);
+ configSwitch(MUTE51_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5A", muteLabels);
+ configSwitch(MUTE61_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6A", muteLabels);
+ configSwitch(MUTE71_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7A", muteLabels);
+ configSwitch(MUTE81_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8A", muteLabels);
+
+ configSwitch(MUTE12_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1B", muteLabels);
+ configSwitch(MUTE22_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2B", muteLabels);
+ configSwitch(MUTE32_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3B", muteLabels);
+ configSwitch(MUTE42_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4B", muteLabels);
+ configSwitch(MUTE52_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5B", muteLabels);
+ configSwitch(MUTE62_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6B", muteLabels);
+ configSwitch(MUTE72_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7B", muteLabels);
+ configSwitch(MUTE82_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8B", muteLabels);
+
+ configSwitch(MUTE13_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1C", muteLabels);
+ configSwitch(MUTE23_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2C", muteLabels);
+ configSwitch(MUTE33_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3C", muteLabels);
+ configSwitch(MUTE43_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4C", muteLabels);
+ configSwitch(MUTE53_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5C", muteLabels);
+ configSwitch(MUTE63_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6C", muteLabels);
+ configSwitch(MUTE73_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7C", muteLabels);
+ configSwitch(MUTE83_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8C", muteLabels);
+
+ configSwitch(MUTE14_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1D", muteLabels);
+ configSwitch(MUTE24_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2D", muteLabels);
+ configSwitch(MUTE34_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3D", muteLabels);
+ configSwitch(MUTE44_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4D", muteLabels);
+ configSwitch(MUTE54_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5D", muteLabels);
+ configSwitch(MUTE64_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6D", muteLabels);
+ configSwitch(MUTE74_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7D", muteLabels);
+ configSwitch(MUTE84_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8D", muteLabels);
+
+ configSwitch(MUTE15_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1E", muteLabels);
+ configSwitch(MUTE25_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2E", muteLabels);
+ configSwitch(MUTE35_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3E", muteLabels);
+ configSwitch(MUTE45_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4E", muteLabels);
+ configSwitch(MUTE55_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5E", muteLabels);
+ configSwitch(MUTE65_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6E", muteLabels);
+ configSwitch(MUTE75_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7E", muteLabels);
+ configSwitch(MUTE85_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8E", muteLabels);
+
+ configSwitch(MUTE16_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1F", muteLabels);
+ configSwitch(MUTE26_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2F", muteLabels);
+ configSwitch(MUTE36_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3F", muteLabels);
+ configSwitch(MUTE46_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4F", muteLabels);
+ configSwitch(MUTE56_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5F", muteLabels);
+ configSwitch(MUTE66_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6F", muteLabels);
+ configSwitch(MUTE76_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7F", muteLabels);
+ configSwitch(MUTE86_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8F", muteLabels);
+
+ configSwitch(MUTE17_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1G", muteLabels);
+ configSwitch(MUTE27_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2G", muteLabels);
+ configSwitch(MUTE37_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3G", muteLabels);
+ configSwitch(MUTE47_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4G", muteLabels);
+ configSwitch(MUTE57_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5G", muteLabels);
+ configSwitch(MUTE67_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6G", muteLabels);
+ configSwitch(MUTE77_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7G", muteLabels);
+ configSwitch(MUTE87_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8G", muteLabels);
+
+ configSwitch(MUTE18_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1H", muteLabels);
+ configSwitch(MUTE28_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2H", muteLabels);
+ configSwitch(MUTE38_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3H", muteLabels);
+ configSwitch(MUTE48_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4H", muteLabels);
+ configSwitch(MUTE58_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5H", muteLabels);
+ configSwitch(MUTE68_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6H", muteLabels);
+ configSwitch(MUTE78_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7H", muteLabels);
+ configSwitch(MUTE88_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8H", muteLabels);
_mutes = new Param*[64];
for (int i = 0; i < 64; ++i) {
diff --git a/src/MegaGate.cpp b/src/MegaGate.cpp
@@ -32,14 +32,14 @@ void MegaGate::sampleRateChange() {
}
}
-json_t* MegaGate::toJson(json_t* root) {
- root = LPGEnvBaseModule::toJson(root);
+json_t* MegaGate::saveToJson(json_t* root) {
+ root = LPGEnvBaseModule::saveToJson(root);
json_object_set_new(root, VELOCITY_MINIMUM_DECIBELS, json_real(_minVelocityDb));
return root;
}
-void MegaGate::fromJson(json_t* root) {
- LPGEnvBaseModule::fromJson(root);
+void MegaGate::loadFromJson(json_t* root) {
+ LPGEnvBaseModule::loadFromJson(root);
json_t* mdb = json_object_get(root, VELOCITY_MINIMUM_DECIBELS);
if (mdb) {
_minVelocityDb = json_real_value(mdb);
@@ -420,14 +420,14 @@ struct MegaGateWidget : LPGEnvBaseWidget {
addOutput(createOutput<Port24>(leftOutputPosition, module, MegaGate::LEFT_OUTPUT));
addOutput(createOutput<Port24>(rightOutputPosition, module, MegaGate::RIGHT_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(lpfPoles1LightPosition, module, MegaGate::LPF_POLES_1_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(lpfPoles2LightPosition, module, MegaGate::LPF_POLES_2_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(lpfPoles3LightPosition, module, MegaGate::LPF_POLES_3_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(lpfPoles4LightPosition, module, MegaGate::LPF_POLES_4_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(hpfPoles1LightPosition, module, MegaGate::HPF_POLES_1_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(hpfPoles2LightPosition, module, MegaGate::HPF_POLES_2_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(hpfPoles3LightPosition, module, MegaGate::HPF_POLES_3_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(hpfPoles4LightPosition, module, MegaGate::HPF_POLES_4_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(lpfPoles1LightPosition, module, MegaGate::LPF_POLES_1_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(lpfPoles2LightPosition, module, MegaGate::LPF_POLES_2_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(lpfPoles3LightPosition, module, MegaGate::LPF_POLES_3_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(lpfPoles4LightPosition, module, MegaGate::LPF_POLES_4_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(hpfPoles1LightPosition, module, MegaGate::HPF_POLES_1_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(hpfPoles2LightPosition, module, MegaGate::HPF_POLES_2_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(hpfPoles3LightPosition, module, MegaGate::HPF_POLES_3_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(hpfPoles4LightPosition, module, MegaGate::HPF_POLES_4_LIGHT));
}
void contextMenu(Menu* menu) override {
diff --git a/src/MegaGate.hpp b/src/MegaGate.hpp
@@ -111,30 +111,50 @@ struct MegaGate : LPGEnvBaseModule {
configParam(FALL_SHAPE_PARAM, -1.0f, 1.0f, 0.0f, "Fall shape");
configParam<TimeParamQuantity<1>>(MINIMUM_GATE_PARAM, 0.0f, 1.0f, 0.3162278f, "Minimum gate", " s");
configParam(TILT_PARAM, -1.0f, 1.0f, 0.0f, "Tilt", "%", 0.0f, 100.0f);
- configParam(GATE_TO_TRIGGER_PARAM, 0.0f, 1.0f, 1.0f, "Gate to trigger mode");
- configParam(TIMES_10X_PARAM, 0.0f, 1.0f, 0.0f, "Timings 10X mode");
- configParam(FILTERS_SERIAL_PARAM, 0.0f, 1.0f, 0.0f, "Filters in series mode");
- configParam(LINEAR_VCA_PARAM, 0.0f, 1.0f, 0.0f, "Linear VCA mode");
+ configButton(GATE_TO_TRIGGER_PARAM, "Gate to trigger mode");
+ configButton(TIMES_10X_PARAM, "Timings 10X mode");
+ configButton(FILTERS_SERIAL_PARAM, "Filters in series mode");
+ configButton(LINEAR_VCA_PARAM, "Linear VCA mode");
configParam(LPF_ENV_PARAM, -1.0f, 1.0f, 0.8f, "LPF envelope amount", "%", 0.0f, 100.0f);
configParam(LPF_ENV_ATTENUATOR_PARAM, -1.0f, 1.0f, 0.0f, "LPF envelope amount CV", "%", 0.0f, 100.0f);
configParam<ScaledSquaringParamQuantity<(int)maxFilterCutoff>>(LPF_BIAS_PARAM, 0.0f, 1.0f, 0.0f, "LPF cutoff", " HZ");
configParam(LPF_BIAS_ATTENUATOR_PARAM, -1.0f, 1.0f, 0.0f, "LPF cutoff CV", "%", 0.0f, 100.0f);
- configParam(LPF_POLES_PARAM, 0.0f, 3.0f, 1.0f, "LPF poles");
+ configSwitch(LPF_POLES_PARAM, 0.0f, 3.0f, 1.0f, "LPF poles", {"1", "2", "3", "4"});
configParam(HPF_ENV_PARAM, -1.0f, 1.0f, 0.0f, "HPF envelope amount", "%", 0.0f, 100.0f);
configParam(HPF_ENV_ATTENUATOR_PARAM, -1.0f, 1.0f, 0.0f, "HPF envelope amount CV", "%", 0.0f, 100.0f);
configParam<ScaledSquaringParamQuantity<(int)maxFilterCutoff>>(HPF_BIAS_PARAM, 0.0f, 1.0f, 1.0f, "HPF cutoff", " HZ");
configParam(HPF_BIAS_ATTENUATOR_PARAM, -1.0f, 1.0f, 0.0f, "HPF cutoff CV", "%", 0.0f, 100.0f);
- configParam(HPF_POLES_PARAM, 0.0f, 3.0f, 1.0f, "HPF poles");
+ configSwitch(HPF_POLES_PARAM, 0.0f, 3.0f, 1.0f, "HPF poles", {"1", "2", "3", "4"});
configParam(VCA_ENV_PARAM, -1.0f, 1.0f, 1.0f, "VCA envelope amount", "%", 0.0f, 100.0f);
configParam(VCA_ENV_ATTENUATOR_PARAM, -1.0f, 1.0f, 0.0f, "VCA envelope amount CV", "%", 0.0f, 100.0f);
configParam(VCA_BIAS_PARAM, 0.0f, 1.0f, 0.0f, "VCA level", "%", 0.0f, 100.0f);
configParam(VCA_BIAS_ATTENUATOR_PARAM, -1.0f, 1.0f, 0.0f, "VCA level CV", "%", 0.0f, 100.0f);
+
+ configInput(RISE_INPUT, "Rise CV");
+ configInput(FALL_INPUT, "Fall CV");
+ configInput(MINIMUM_GATE_INPUT, "Minimum gate CV");
+ configInput(TILT_INPUT, "Tilt CV");
+ configInput(VELOCITY_INPUT, "Velocity CV");
+ configInput(SHAPE_INPUT, "Shape CV");
+ configInput(LEFT_INPUT, "Left signal");
+ configInput(RIGHT_INPUT, "Right signal");
+ configInput(GATE_INPUT, "Gate");
+ configInput(LPF_ENV_INPUT, "LPF envelope response CV");
+ configInput(LPF_BIAS_INPUT, "LPF bias CV");
+ configInput(HPF_ENV_INPUT, "HPF envelope response CV");
+ configInput(HPF_BIAS_INPUT, "HPF bias CV");
+ configInput(VCA_ENV_INPUT, "VCA envelope response CV");
+ configInput(VCA_BIAS_INPUT, "VCA bias CV");
+
+ configOutput(ENV_OUTPUT, "Envelope");
+ configOutput(LEFT_OUTPUT, "Left signal");
+ configOutput(RIGHT_OUTPUT, "Right signal");
}
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
bool active() override;
int channels() override;
void addChannel(int c) override;
diff --git a/src/Mix1.hpp b/src/Mix1.hpp
@@ -36,7 +36,14 @@ struct Mix1 : LinearCVMixerModule {
Mix1() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam(LEVEL_PARAM, 0.0f, 1.0f, fabsf(MixerChannel::minDecibels) / (MixerChannel::maxDecibels - MixerChannel::minDecibels), "Level", "dB", 0.0f, MixerChannel::maxDecibels - MixerChannel::minDecibels, MixerChannel::minDecibels);
- configParam(MUTE_PARAM, 0.0f, 1.0f, 0.0f, "Mute");
+ configSwitch(MUTE_PARAM, 0.0f, 1.0f, 0.0f, "Mute", {"Unmuted", "Muted"});
+ configBypass(IN_INPUT, OUT_OUTPUT);
+
+ configInput(MUTE_INPUT, "Mute CV");
+ configInput(LEVEL_INPUT, "Level CV");
+ configInput(IN_INPUT, "Signal");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
void sampleRateChange() override;
diff --git a/src/Mix2.cpp b/src/Mix2.cpp
@@ -60,6 +60,19 @@ void Mix2::postProcessAlways(const ProcessArgs& args) {
_rightRms = _rightRmsSum * _inverseChannels;
}
+void Mix2::processBypass(const ProcessArgs& args) {
+ outputs[L_OUTPUT].setChannels(inputs[L_INPUT].getChannels());
+ outputs[L_OUTPUT].writeVoltages(inputs[L_INPUT].getVoltages());
+ if (inputs[R_INPUT].isConnected()) {
+ outputs[R_OUTPUT].setChannels(inputs[R_INPUT].getChannels());
+ outputs[R_OUTPUT].writeVoltages(inputs[R_INPUT].getVoltages());
+ }
+ else {
+ outputs[R_OUTPUT].setChannels(inputs[L_INPUT].getChannels());
+ outputs[R_OUTPUT].writeVoltages(inputs[L_INPUT].getVoltages());
+ }
+}
+
struct Mix2Widget : LinearCVMixerWidget {
static constexpr int hp = 5;
diff --git a/src/Mix2.hpp b/src/Mix2.hpp
@@ -59,7 +59,15 @@ struct Mix2 : LinearCVMixerModule {
Mix2() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam(LEVEL_PARAM, 0.0f, 1.0f, fabsf(MixerChannel::minDecibels) / (MixerChannel::maxDecibels - MixerChannel::minDecibels), "Level", "dB", 0.0f, MixerChannel::maxDecibels - MixerChannel::minDecibels, MixerChannel::minDecibels);
- configParam(MUTE_PARAM, 0.0f, 1.0f, 0.0f, "Mute");
+ configSwitch(MUTE_PARAM, 0.0f, 1.0f, 0.0f, "Mute", {"Unmuted", "Muted"});
+
+ configInput(LEVEL_INPUT, "Level CV");
+ configInput(MUTE_INPUT, "Mute CV");
+ configInput(L_INPUT, "Left signal");
+ configInput(R_INPUT, "Right signal");
+
+ configOutput(L_OUTPUT, "Left signal");
+ configOutput(R_OUTPUT, "Right signal");
}
void sampleRateChange() override;
@@ -70,6 +78,7 @@ struct Mix2 : LinearCVMixerModule {
void processAlways(const ProcessArgs& args) override;
void processChannel(const ProcessArgs& args, int c) override;
void postProcessAlways(const ProcessArgs& args) override;
+ void processBypass(const ProcessArgs& args) override;
};
} // namespace bogaudio
diff --git a/src/Mix4.cpp b/src/Mix4.cpp
@@ -3,14 +3,21 @@
#define POLY_OFFSET "poly_channel_offset"
-json_t* Mix4::toJson(json_t* root) {
- root = DimmableMixerModule::toJson(root);
+void Mix4::onRandomize(const RandomizeEvent& e) {
+ Module::onRandomize(e);
+ for (int i = 0; i < 4; ++i) {
+ getParamQuantity(MUTE1_PARAM + 3*i)->setValue(random::uniform() > 0.5f);
+ }
+}
+
+json_t* Mix4::saveToJson(json_t* root) {
+ root = DimmableMixerModule::saveToJson(root);
json_object_set_new(root, POLY_OFFSET, json_integer(_polyChannelOffset));
return root;
}
-void Mix4::fromJson(json_t* root) {
- DimmableMixerModule::fromJson(root);
+void Mix4::loadFromJson(json_t* root) {
+ DimmableMixerModule::loadFromJson(root);
json_t* o = json_object_get(root, POLY_OFFSET);
if (o) {
_polyChannelOffset = json_integer_value(o);
@@ -228,16 +235,8 @@ struct Mix4Widget : DimmableMixerWidget {
addParam(createParam<Knob16>(pan4ParamPosition, module, Mix4::PAN4_PARAM));
addParam(createParam<SoloMuteButton>(mute4ParamPosition, module, Mix4::MUTE4_PARAM));
addSlider(mixParamPosition, module, Mix4::MIX_PARAM, module ? &module->_rmsLevel : NULL);
- {
- auto b = createParam<MuteButton>(mixMuteParamPosition, module, Mix4::MIX_MUTE_PARAM);
- b->setRandomize(false);
- addParam(b);
- }
- {
- auto b = createParam<MuteButton>(mixDimParamPosition, module, Mix4::MIX_DIM_PARAM);
- b->setRandomize(false);
- addParam(b);
- }
+ addParam(createParam<MuteButton>(mixMuteParamPosition, module, Mix4::MIX_MUTE_PARAM));
+ addParam(createParam<MuteButton>(mixDimParamPosition, module, Mix4::MIX_DIM_PARAM));
addInput(createInput<Port24>(cv1InputPosition, module, Mix4::CV1_INPUT));
addInput(createInput<Port24>(pan1InputPosition, module, Mix4::PAN1_INPUT));
diff --git a/src/Mix4.hpp b/src/Mix4.hpp
@@ -68,19 +68,42 @@ struct Mix4 : ExpandableModule<Mix4ExpanderMessage, DimmableMixerModule> {
float levelDefault = fabsf(MixerChannel::minDecibels) / (MixerChannel::maxDecibels - MixerChannel::minDecibels);
configParam(LEVEL1_PARAM, 0.0f, 1.0f, levelDefault, "Channel 1 level", " dB", 0.0f, MixerChannel::maxDecibels - MixerChannel::minDecibels, MixerChannel::minDecibels);
configParam(PAN1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1 panning", "%", 0.0f, 100.0f);
- configParam(MUTE1_PARAM, 0.0f, 3.0f, 0.0f, "Channel 1 mute");
+ configSwitch(MUTE1_PARAM, 0.0f, 3.0f, 0.0f, "Channel 1 mute", {"Unmuted", "Muted", "Soloed", "Soloed"});
configParam(LEVEL2_PARAM, 0.0f, 1.0f, levelDefault, "Channel 2 level", " dB", 0.0f, MixerChannel::maxDecibels - MixerChannel::minDecibels, MixerChannel::minDecibels);
configParam(PAN2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 panning", "%", 0.0f, 100.0f);
- configParam(MUTE2_PARAM, 0.0f, 3.0f, 0.0f, "Channel 2 mute");
+ configSwitch(MUTE2_PARAM, 0.0f, 3.0f, 0.0f, "Channel 2 mute", {"Unmuted", "Muted", "Soloed", "Soloed"});
configParam(LEVEL3_PARAM, 0.0f, 1.0f, levelDefault, "Channel 3 level", " dB", 0.0f, MixerChannel::maxDecibels - MixerChannel::minDecibels, MixerChannel::minDecibels);
configParam(PAN3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 panning", "%", 0.0f, 100.0f);
- configParam(MUTE3_PARAM, 0.0f, 3.0f, 0.0f, "Channel 3 mute");
+ configSwitch(MUTE3_PARAM, 0.0f, 3.0f, 0.0f, "Channel 3 mute", {"Unmuted", "Muted", "Soloed", "Soloed"});
configParam(LEVEL4_PARAM, 0.0f, 1.0f, levelDefault, "Channel 4 level", " dB", 0.0f, MixerChannel::maxDecibels - MixerChannel::minDecibels, MixerChannel::minDecibels);
configParam(PAN4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 panning", "%", 0.0f, 100.0f);
- configParam(MUTE4_PARAM, 0.0f, 3.0f, 0.0f, "Channel 4 mute");
+ configSwitch(MUTE4_PARAM, 0.0f, 3.0f, 0.0f, "Channel 4 mute", {"Unmuted", "Muted", "Soloed", "Soloed"});
configParam(MIX_PARAM, 0.0f, 1.0f, levelDefault, "Master level", " dB", 0.0f, MixerChannel::maxDecibels - MixerChannel::minDecibels, MixerChannel::minDecibels);
- configParam(MIX_MUTE_PARAM, 0.0f, 1.0f, 0.0f, "Master mute");
- configParam(MIX_DIM_PARAM, 0.0f, 1.0f, 0.0f, "Master dim");
+ configSwitch(MIX_MUTE_PARAM, 0.0f, 1.0f, 0.0f, "Master mute", {"Unmuted", "Muted"});
+ configSwitch<DimSwitchQuantity>(MIX_DIM_PARAM, 0.0f, 1.0f, 0.0f, "Master dim", {"Disabled", "Enabled"});
+ getParamQuantity(MUTE1_PARAM)->randomizeEnabled = false;
+ getParamQuantity(MUTE2_PARAM)->randomizeEnabled = false;
+ getParamQuantity(MUTE3_PARAM)->randomizeEnabled = false;
+ getParamQuantity(MUTE4_PARAM)->randomizeEnabled = false;
+ getParamQuantity(MIX_MUTE_PARAM)->randomizeEnabled = false;
+ getParamQuantity(MIX_DIM_PARAM)->randomizeEnabled = false;
+
+ configInput(CV1_INPUT, "Channel 1 level CV");
+ configInput(PAN1_INPUT, "Channel 1 pan CV");
+ configInput(IN1_INPUT, "Channel 1");
+ configInput(CV2_INPUT, "Channel 2 level CV");
+ configInput(PAN2_INPUT, "Channel 2 pan CV");
+ configInput(IN2_INPUT, "Channel 2");
+ configInput(CV3_INPUT, "Channel 3 level CV");
+ configInput(PAN3_INPUT, "Channel 3 pan CV");
+ configInput(IN3_INPUT, "Channel 3");
+ configInput(CV4_INPUT, "Channel 4 level CV");
+ configInput(PAN4_INPUT, "Channel 4 pan CV");
+ configInput(IN4_INPUT, "Channel 4");
+ configInput(MIX_CV_INPUT, "Mix level CV");
+
+ configOutput(L_OUTPUT, "Left signal");
+ configOutput(R_OUTPUT, "Right signal");
_channels[0] = new MixerChannel(params[LEVEL1_PARAM], params[MUTE1_PARAM], inputs[CV1_INPUT]);
_channels[1] = new MixerChannel(params[LEVEL2_PARAM], params[MUTE2_PARAM], inputs[CV2_INPUT]);
@@ -97,8 +120,9 @@ struct Mix4 : ExpandableModule<Mix4ExpanderMessage, DimmableMixerModule> {
}
}
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ void onRandomize(const RandomizeEvent& e) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void sampleRateChange() override;
void processAll(const ProcessArgs& args) override;
};
diff --git a/src/Mix4x.hpp b/src/Mix4x.hpp
@@ -76,33 +76,50 @@ struct Mix4x : ExpanderModule<Mix4ExpanderMessage, BGModule> {
configParam<EQParamQuantity>(MID1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1 mid", " dB");
configParam<EQParamQuantity>(HIGH1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1 high", " dB");
configParam<AmplifierParamQuantity>(A1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 A send");
- configParam(PRE_A1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 A send pre/post");
+ configSwitch(PRE_A1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 A send", {"Post-fader", "Pre-fader"});
configParam<AmplifierParamQuantity>(B1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 B send");
- configParam(PRE_B1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 B send pre/post");
+ configSwitch(PRE_B1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 B send", {"Post-fader", "Pre-fader"});
configParam<EQParamQuantity>(LOW2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 low", " dB");
configParam<EQParamQuantity>(MID2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 mid", " dB");
configParam<EQParamQuantity>(HIGH2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 high", " dB");
configParam<AmplifierParamQuantity>(A2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 A send");
- configParam(PRE_A2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 A send pre/post");
+ configSwitch(PRE_A2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 A send", {"Post-fader", "Pre-fader"});
configParam<AmplifierParamQuantity>(B2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 B send");
- configParam(PRE_B2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 B send pre/post");
+ configSwitch(PRE_B2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 B send", {"Post-fader", "Pre-fader"});
configParam<EQParamQuantity>(LOW3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 low", " dB");
configParam<EQParamQuantity>(MID3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 mid", " dB");
configParam<EQParamQuantity>(HIGH3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 high", " dB");
configParam<AmplifierParamQuantity>(A3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 A send");
- configParam(PRE_A3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 A send pre/post");
+ configSwitch(PRE_A3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 A send", {"Post-fader", "Pre-fader"});
configParam<AmplifierParamQuantity>(B3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 B send");
- configParam(PRE_B3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 B send pre/post");
+ configSwitch(PRE_B3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 B send", {"Post-fader", "Pre-fader"});
configParam<EQParamQuantity>(LOW4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 low", " dB");
configParam<EQParamQuantity>(MID4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 mid", " dB");
configParam<EQParamQuantity>(HIGH4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 high", " dB");
configParam<AmplifierParamQuantity>(A4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 A send");
- configParam(PRE_A4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 A send pre/post");
+ configSwitch(PRE_A4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 A send", {"Post-fader", "Pre-fader"});
configParam<AmplifierParamQuantity>(B4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 B send");
- configParam(PRE_B4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 B send pre/post");
+ configSwitch(PRE_B4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 B send", {"Post-fader", "Pre-fader"});
configParam<AmplifierParamQuantity>(LEVEL_A_PARAM, 0.0f, 1.0f, 0.8f, "A return level");
configParam<AmplifierParamQuantity>(LEVEL_B_PARAM, 0.0f, 1.0f, 0.8f, "B return level");
+ configInput(A1_INPUT, "Channel 1 send A CV");
+ configInput(B1_INPUT, "Channel 1 send B CV");
+ configInput(A2_INPUT, "Channel 2 send A CV");
+ configInput(B2_INPUT, "Channel 2 send B CV");
+ configInput(A3_INPUT, "Channel 3 send A CV");
+ configInput(B3_INPUT, "Channel 3 send B CV");
+ configInput(A4_INPUT, "Channel 4 send A CV");
+ configInput(B4_INPUT, "Channel 4 send B CV");
+ configInput(L_A_INPUT, "Return A left");
+ configInput(R_A_INPUT, "Return A right");
+ configInput(LEVEL_A_INPUT, "Return A level CV");
+ configInput(L_B_INPUT, "Return B left");
+ configInput(R_B_INPUT, "Return B right");
+
+ configOutput(SEND_A_OUTPUT, "Send A");
+ configOutput(SEND_B_OUTPUT, "Send B");
+
_channels[0] = new MixerExpanderChannel(params[LOW1_PARAM], params[MID1_PARAM], params[HIGH1_PARAM], params[A1_PARAM], params[B1_PARAM], params[PRE_A1_PARAM], params[PRE_B1_PARAM], inputs[A1_INPUT], inputs[B1_INPUT]);
_channels[1] = new MixerExpanderChannel(params[LOW2_PARAM], params[MID2_PARAM], params[HIGH2_PARAM], params[A2_PARAM], params[B2_PARAM], params[PRE_A2_PARAM], params[PRE_B2_PARAM], inputs[A2_INPUT], inputs[B2_INPUT]);
_channels[2] = new MixerExpanderChannel(params[LOW3_PARAM], params[MID3_PARAM], params[HIGH3_PARAM], params[A3_PARAM], params[B3_PARAM], params[PRE_A3_PARAM], params[PRE_B3_PARAM], inputs[A3_INPUT], inputs[B3_INPUT]);
diff --git a/src/Mix8.cpp b/src/Mix8.cpp
@@ -3,14 +3,21 @@
#define POLY_OFFSET "poly_channel_offset"
-json_t* Mix8::toJson(json_t* root) {
- root = DimmableMixerModule::toJson(root);
+void Mix8::onRandomize(const RandomizeEvent& e) {
+ Module::onRandomize(e);
+ for (int i = 0; i < 8; ++i) {
+ getParamQuantity(MUTE1_PARAM + 3*i)->setValue(random::uniform() > 0.5f);
+ }
+}
+
+json_t* Mix8::saveToJson(json_t* root) {
+ root = DimmableMixerModule::saveToJson(root);
json_object_set_new(root, POLY_OFFSET, json_integer(_polyChannelOffset));
return root;
}
-void Mix8::fromJson(json_t* root) {
- DimmableMixerModule::fromJson(root);
+void Mix8::loadFromJson(json_t* root) {
+ DimmableMixerModule::loadFromJson(root);
json_t* o = json_object_get(root, POLY_OFFSET);
if (o) {
_polyChannelOffset = json_integer_value(o);
@@ -272,16 +279,8 @@ struct Mix8Widget : DimmableMixerWidget {
addParam(createParam<SoloMuteButton>(mute8ParamPosition, module, Mix8::MUTE8_PARAM));
addParam(createParam<Knob16>(pan8ParamPosition, module, Mix8::PAN8_PARAM));
addSlider(mixParamPosition, module, Mix8::MIX_PARAM, module ? &module->_rmsLevel : NULL);
- {
- auto b = createParam<MuteButton>(mixMuteParamPosition, module, Mix8::MIX_MUTE_PARAM);
- b->setRandomize(false);
- addParam(b);
- }
- {
- auto b = createParam<MuteButton>(mixDimParamPosition, module, Mix8::MIX_DIM_PARAM);
- b->setRandomize(false);
- addParam(b);
- }
+ addParam(createParam<MuteButton>(mixMuteParamPosition, module, Mix8::MIX_MUTE_PARAM));
+ addParam(createParam<MuteButton>(mixDimParamPosition, module, Mix8::MIX_DIM_PARAM));
addInput(createInput<Port24>(cv1InputPosition, module, Mix8::CV1_INPUT));
addInput(createInput<Port24>(pan1InputPosition, module, Mix8::PAN1_INPUT));
diff --git a/src/Mix8.hpp b/src/Mix8.hpp
@@ -92,31 +92,70 @@ struct Mix8 : ExpandableModule<Mix8ExpanderMessage, DimmableMixerModule> {
float levelDefault = fabsf(MixerChannel::minDecibels) / (MixerChannel::maxDecibels - MixerChannel::minDecibels);
configParam(LEVEL1_PARAM, 0.0f, 1.0f, levelDefault, "Channel 1 level", " dB", 0.0f, MixerChannel::maxDecibels - MixerChannel::minDecibels, MixerChannel::minDecibels);
configParam(PAN1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1 panning", "%", 0.0f, 100.0f);
- configParam(MUTE1_PARAM, 0.0f, 3.0f, 0.0f, "Channel 1 mute");
+ configSwitch(MUTE1_PARAM, 0.0f, 3.0f, 0.0f, "Channel 1 mute", {"Unmuted", "Muted", "Soloed", "Soloed"});
configParam(LEVEL2_PARAM, 0.0f, 1.0f, levelDefault, "Channel 2 level", " dB", 0.0f, MixerChannel::maxDecibels - MixerChannel::minDecibels, MixerChannel::minDecibels);
configParam(PAN2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 panning", "%", 0.0f, 100.0f);
- configParam(MUTE2_PARAM, 0.0f, 3.0f, 0.0f, "Channel 2 mute");
+ configSwitch(MUTE2_PARAM, 0.0f, 3.0f, 0.0f, "Channel 2 mute", {"Unmuted", "Muted", "Soloed", "Soloed"});
configParam(LEVEL3_PARAM, 0.0f, 1.0f, levelDefault, "Channel 3 level", " dB", 0.0f, MixerChannel::maxDecibels - MixerChannel::minDecibels, MixerChannel::minDecibels);
configParam(PAN3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 panning", "%", 0.0f, 100.0f);
- configParam(MUTE3_PARAM, 0.0f, 3.0f, 0.0f, "Channel 3 mute");
+ configSwitch(MUTE3_PARAM, 0.0f, 3.0f, 0.0f, "Channel 3 mute", {"Unmuted", "Muted", "Soloed", "Soloed"});
configParam(LEVEL4_PARAM, 0.0f, 1.0f, levelDefault, "Channel 4 level", " dB", 0.0f, MixerChannel::maxDecibels - MixerChannel::minDecibels, MixerChannel::minDecibels);
configParam(PAN4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 panning", "%", 0.0f, 100.0f);
- configParam(MUTE4_PARAM, 0.0f, 3.0f, 0.0f, "Channel 4 mute");
+ configSwitch(MUTE4_PARAM, 0.0f, 3.0f, 0.0f, "Channel 4 mute", {"Unmuted", "Muted", "Soloed", "Soloed"});
configParam(LEVEL5_PARAM, 0.0f, 1.0f, levelDefault, "Channel 5 level", " dB", 0.0f, MixerChannel::maxDecibels - MixerChannel::minDecibels, MixerChannel::minDecibels);
configParam(PAN5_PARAM, -1.0f, 1.0f, 0.0f, "Channel 5 panning", "%", 0.0f, 100.0f);
- configParam(MUTE5_PARAM, 0.0f, 3.0f, 0.0f, "Channel 5 mute");
+ configSwitch(MUTE5_PARAM, 0.0f, 3.0f, 0.0f, "Channel 5 mute", {"Unmuted", "Muted", "Soloed", "Soloed"});
configParam(LEVEL6_PARAM, 0.0f, 1.0f, levelDefault, "Channel 6 level", " dB", 0.0f, MixerChannel::maxDecibels - MixerChannel::minDecibels, MixerChannel::minDecibels);
configParam(PAN6_PARAM, -1.0f, 1.0f, 0.0f, "Channel 6 panning", "%", 0.0f, 100.0f);
- configParam(MUTE6_PARAM, 0.0f, 3.0f, 0.0f, "Channel 6 mute");
+ configSwitch(MUTE6_PARAM, 0.0f, 3.0f, 0.0f, "Channel 6 mute", {"Unmuted", "Muted", "Soloed", "Soloed"});
configParam(LEVEL7_PARAM, 0.0f, 1.0f, levelDefault, "Channel 7 level", " dB", 0.0f, MixerChannel::maxDecibels - MixerChannel::minDecibels, MixerChannel::minDecibels);
configParam(PAN7_PARAM, -1.0f, 1.0f, 0.0f, "Channel 7 panning", "%", 0.0f, 100.0f);
- configParam(MUTE7_PARAM, 0.0f, 3.0f, 0.0f, "Channel 7 mute");
+ configSwitch(MUTE7_PARAM, 0.0f, 3.0f, 0.0f, "Channel 7 mute", {"Unmuted", "Muted", "Soloed", "Soloed"});
configParam(LEVEL8_PARAM, 0.0f, 1.0f, levelDefault, "Channel 8 level", " dB", 0.0f, MixerChannel::maxDecibels - MixerChannel::minDecibels, MixerChannel::minDecibels);
configParam(PAN8_PARAM, -1.0f, 1.0f, 0.0f, "Channel 8 panning", "%", 0.0f, 100.0f);
- configParam(MUTE8_PARAM, 0.0f, 3.0f, 0.0f, "Channel 8 mute");
+ configSwitch(MUTE8_PARAM, 0.0f, 3.0f, 0.0f, "Channel 8 mute", {"Unmuted", "Muted", "Soloed", "Soloed"});
configParam(MIX_PARAM, 0.0f, 1.0f, levelDefault, "Master level", " dB", 0.0f, MixerChannel::maxDecibels - MixerChannel::minDecibels, MixerChannel::minDecibels);
- configParam(MIX_MUTE_PARAM, 0.0f, 1.0f, 0.0f, "Master mute");
- configParam(MIX_DIM_PARAM, 0.0f, 1.0f, 0.0f, "Master dim");
+ configSwitch(MIX_MUTE_PARAM, 0.0f, 1.0f, 0.0f, "Master mute", {"Unmuted", "Muted"});
+ configSwitch<DimSwitchQuantity>(MIX_DIM_PARAM, 0.0f, 1.0f, 0.0f, "Master dim", {"Disabled", "Enabled"});
+ getParamQuantity(MUTE1_PARAM)->randomizeEnabled = false;
+ getParamQuantity(MUTE2_PARAM)->randomizeEnabled = false;
+ getParamQuantity(MUTE3_PARAM)->randomizeEnabled = false;
+ getParamQuantity(MUTE4_PARAM)->randomizeEnabled = false;
+ getParamQuantity(MUTE5_PARAM)->randomizeEnabled = false;
+ getParamQuantity(MUTE6_PARAM)->randomizeEnabled = false;
+ getParamQuantity(MUTE7_PARAM)->randomizeEnabled = false;
+ getParamQuantity(MUTE8_PARAM)->randomizeEnabled = false;
+ getParamQuantity(MIX_MUTE_PARAM)->randomizeEnabled = false;
+ getParamQuantity(MIX_DIM_PARAM)->randomizeEnabled = false;
+
+ configInput(CV1_INPUT, "Channel 1 level CV");
+ configInput(PAN1_INPUT, "Channel 1 pan CV");
+ configInput(IN1_INPUT, "Channel 1");
+ configInput(CV2_INPUT, "Channel 2 level CV");
+ configInput(PAN2_INPUT, "Channel 2 pan CV");
+ configInput(IN2_INPUT, "Channel 2");
+ configInput(CV3_INPUT, "Channel 3 level CV");
+ configInput(PAN3_INPUT, "Channel 3 pan CV");
+ configInput(IN3_INPUT, "Channel 3");
+ configInput(CV4_INPUT, "Channel 4 level CV");
+ configInput(PAN4_INPUT, "Channel 4 pan CV");
+ configInput(IN4_INPUT, "Channel 4");
+ configInput(CV5_INPUT, "Channel 5 level CV");
+ configInput(PAN5_INPUT, "Channel 5 pan CV");
+ configInput(IN5_INPUT, "Channel 5");
+ configInput(CV6_INPUT, "Channel 6 level CV");
+ configInput(PAN6_INPUT, "Channel 6 pan CV");
+ configInput(IN6_INPUT, "Channel 6");
+ configInput(CV7_INPUT, "Channel 7 level CV");
+ configInput(PAN7_INPUT, "Channel 7 pan CV");
+ configInput(IN7_INPUT, "Channel 7");
+ configInput(CV8_INPUT, "Channel 8 level CV");
+ configInput(PAN8_INPUT, "Channel 8 pan CV");
+ configInput(IN8_INPUT, "Channel 8");
+ configInput(MIX_CV_INPUT, "Mix level CV");
+
+ configOutput(L_OUTPUT, "Left signal");
+ configOutput(R_OUTPUT, "Right signal");
_channels[0] = new MixerChannel(params[LEVEL1_PARAM], params[MUTE1_PARAM], inputs[CV1_INPUT]);
_channels[1] = new MixerChannel(params[LEVEL2_PARAM], params[MUTE2_PARAM], inputs[CV2_INPUT]);
@@ -137,8 +176,9 @@ struct Mix8 : ExpandableModule<Mix8ExpanderMessage, DimmableMixerModule> {
}
}
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ void onRandomize(const RandomizeEvent& e) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void sampleRateChange() override;
void processAll(const ProcessArgs& args) override;
};
diff --git a/src/Mix8x.hpp b/src/Mix8x.hpp
@@ -111,61 +111,86 @@ struct Mix8x : ExpanderModule<Mix8ExpanderMessage, BGModule> {
configParam<EQParamQuantity>(MID1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1 mid", " dB");
configParam<EQParamQuantity>(HIGH1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1 high", " dB");
configParam<AmplifierParamQuantity>(A1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 A send");
- configParam(PRE_A1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 A send pre/post");
+ configSwitch(PRE_A1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 A send", {"Post-fader", "Pre-fader"});
configParam<AmplifierParamQuantity>(B1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 B send");
- configParam(PRE_B1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 B send pre/post");
+ configSwitch(PRE_B1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 B send", {"Post-fader", "Pre-fader"});
configParam<EQParamQuantity>(LOW2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 low", " dB");
configParam<EQParamQuantity>(MID2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 mid", " dB");
configParam<EQParamQuantity>(HIGH2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 high", " dB");
configParam<AmplifierParamQuantity>(A2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 A send");
- configParam(PRE_A2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 A send pre/post");
+ configSwitch(PRE_A2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 A send", {"Post-fader", "Pre-fader"});
configParam<AmplifierParamQuantity>(B2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 B send");
- configParam(PRE_B2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 B send pre/post");
+ configSwitch(PRE_B2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 B send", {"Post-fader", "Pre-fader"});
configParam<EQParamQuantity>(LOW3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 low", " dB");
configParam<EQParamQuantity>(MID3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 mid", " dB");
configParam<EQParamQuantity>(HIGH3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 high", " dB");
configParam<AmplifierParamQuantity>(A3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 A send");
- configParam(PRE_A3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 A send pre/post");
+ configSwitch(PRE_A3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 A send", {"Post-fader", "Pre-fader"});
configParam<AmplifierParamQuantity>(B3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 B send");
- configParam(PRE_B3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 B send pre/post");
+ configSwitch(PRE_B3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 B send", {"Post-fader", "Pre-fader"});
configParam<EQParamQuantity>(LOW4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 low", " dB");
configParam<EQParamQuantity>(MID4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 mid", " dB");
configParam<EQParamQuantity>(HIGH4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 high", " dB");
configParam<AmplifierParamQuantity>(A4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 A send");
- configParam(PRE_A4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 A send pre/post");
+ configSwitch(PRE_A4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 A send", {"Post-fader", "Pre-fader"});
configParam<AmplifierParamQuantity>(B4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 B send");
- configParam(PRE_B4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 B send pre/post");
+ configSwitch(PRE_B4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 B send", {"Post-fader", "Pre-fader"});
configParam<EQParamQuantity>(LOW5_PARAM, -1.0f, 1.0f, 0.0f, "Channel 5 low", " dB");
configParam<EQParamQuantity>(MID5_PARAM, -1.0f, 1.0f, 0.0f, "Channel 5 mid", " dB");
configParam<EQParamQuantity>(HIGH5_PARAM, -1.0f, 1.0f, 0.0f, "Channel 5 high", " dB");
configParam<AmplifierParamQuantity>(A5_PARAM, 0.0f, 1.0f, 0.0f, "Channel 5 A send");
- configParam(PRE_A5_PARAM, 0.0f, 1.0f, 0.0f, "Channel 5 A send pre/post");
+ configSwitch(PRE_A5_PARAM, 0.0f, 1.0f, 0.0f, "Channel 5 A send", {"Post-fader", "Pre-fader"});
configParam<AmplifierParamQuantity>(B5_PARAM, 0.0f, 1.0f, 0.0f, "Channel 5 B send");
- configParam(PRE_B5_PARAM, 0.0f, 1.0f, 0.0f, "Channel 5 B send pre/post");
+ configSwitch(PRE_B5_PARAM, 0.0f, 1.0f, 0.0f, "Channel 5 B send", {"Post-fader", "Pre-fader"});
configParam<EQParamQuantity>(LOW6_PARAM, -1.0f, 1.0f, 0.0f, "Channel 6 low", " dB");
configParam<EQParamQuantity>(MID6_PARAM, -1.0f, 1.0f, 0.0f, "Channel 6 mid", " dB");
configParam<EQParamQuantity>(HIGH6_PARAM, -1.0f, 1.0f, 0.0f, "Channel 6 high", " dB");
configParam<AmplifierParamQuantity>(A6_PARAM, 0.0f, 1.0f, 0.0f, "Channel 6 A send");
- configParam(PRE_A6_PARAM, 0.0f, 1.0f, 0.0f, "Channel 6 A send pre/post");
+ configSwitch(PRE_A6_PARAM, 0.0f, 1.0f, 0.0f, "Channel 6 A send", {"Post-fader", "Pre-fader"});
configParam<AmplifierParamQuantity>(B6_PARAM, 0.0f, 1.0f, 0.0f, "Channel 6 B send");
- configParam(PRE_B6_PARAM, 0.0f, 1.0f, 0.0f, "Channel 6 B send pre/post");
+ configSwitch(PRE_B6_PARAM, 0.0f, 1.0f, 0.0f, "Channel 6 B send", {"Post-fader", "Pre-fader"});
configParam<EQParamQuantity>(LOW7_PARAM, -1.0f, 1.0f, 0.0f, "Channel 7 low", " dB");
configParam<EQParamQuantity>(MID7_PARAM, -1.0f, 1.0f, 0.0f, "Channel 7 mid", " dB");
configParam<EQParamQuantity>(HIGH7_PARAM, -1.0f, 1.0f, 0.0f, "Channel 7 high", " dB");
configParam<AmplifierParamQuantity>(A7_PARAM, 0.0f, 1.0f, 0.0f, "Channel 7 A send");
- configParam(PRE_A7_PARAM, 0.0f, 1.0f, 0.0f, "Channel 7 A send pre/post");
+ configSwitch(PRE_A7_PARAM, 0.0f, 1.0f, 0.0f, "Channel 7 A send", {"Post-fader", "Pre-fader"});
configParam<AmplifierParamQuantity>(B7_PARAM, 0.0f, 1.0f, 0.0f, "Channel 7 B send");
- configParam(PRE_B7_PARAM, 0.0f, 1.0f, 0.0f, "Channel 7 B send pre/post");
+ configSwitch(PRE_B7_PARAM, 0.0f, 1.0f, 0.0f, "Channel 7 B send", {"Post-fader", "Pre-fader"});
configParam<EQParamQuantity>(LOW8_PARAM, -1.0f, 1.0f, 0.0f, "Channel 8 low", " dB");
configParam<EQParamQuantity>(MID8_PARAM, -1.0f, 1.0f, 0.0f, "Channel 8 mid", " dB");
configParam<EQParamQuantity>(HIGH8_PARAM, -1.0f, 1.0f, 0.0f, "Channel 8 high", " dB");
configParam<AmplifierParamQuantity>(A8_PARAM, 0.0f, 1.0f, 0.0f, "Channel 8 A send");
- configParam(PRE_A8_PARAM, 0.0f, 1.0f, 0.0f, "Channel 8 A send pre/post");
+ configSwitch(PRE_A8_PARAM, 0.0f, 1.0f, 0.0f, "Channel 8 A send", {"Post-fader", "Pre-fader"});
configParam<AmplifierParamQuantity>(B8_PARAM, 0.0f, 1.0f, 0.0f, "Channel 8 B send");
- configParam(PRE_B8_PARAM, 0.0f, 1.0f, 0.0f, "Channel 8 B send pre/post");
+ configSwitch(PRE_B8_PARAM, 0.0f, 1.0f, 0.0f, "Channel 8 B send", {"Post-fader", "Pre-fader"});
configParam<AmplifierParamQuantity>(LEVEL_A_PARAM, 0.0f, 1.0f, 0.8f, "A return level");
configParam<AmplifierParamQuantity>(LEVEL_B_PARAM, 0.0f, 1.0f, 0.8f, "B return level");
+ configInput(A1_INPUT, "Channel 1 send A CV");
+ configInput(B1_INPUT, "Channel 1 send B CV");
+ configInput(A2_INPUT, "Channel 2 send A CV");
+ configInput(B2_INPUT, "Channel 2 send B CV");
+ configInput(A3_INPUT, "Channel 3 send A CV");
+ configInput(B3_INPUT, "Channel 3 send B CV");
+ configInput(A4_INPUT, "Channel 4 send A CV");
+ configInput(B4_INPUT, "Channel 4 send B CV");
+ configInput(A5_INPUT, "Channel 5 send A CV");
+ configInput(B5_INPUT, "Channel 5 send B CV");
+ configInput(A6_INPUT, "Channel 6 send A CV");
+ configInput(B6_INPUT, "Channel 6 send B CV");
+ configInput(A7_INPUT, "Channel 7 send A CV");
+ configInput(B7_INPUT, "Channel 7 send B CV");
+ configInput(A8_INPUT, "Channel 8 send A CV");
+ configInput(B8_INPUT, "Channel 8 send B CV");
+ configInput(L_A_INPUT, "Return A left");
+ configInput(R_A_INPUT, "Return A right");
+ configInput(LEVEL_A_INPUT, "Return A level CV");
+ configInput(L_B_INPUT, "Return B left");
+ configInput(R_B_INPUT, "Return B right");
+
+ configOutput(SEND_A_OUTPUT, "Send A");
+ configOutput(SEND_B_OUTPUT, "Send B");
+
_channels[0] = new MixerExpanderChannel(params[LOW1_PARAM], params[MID1_PARAM], params[HIGH1_PARAM], params[A1_PARAM], params[B1_PARAM], params[PRE_A1_PARAM], params[PRE_B1_PARAM], inputs[A1_INPUT], inputs[B1_INPUT]);
_channels[1] = new MixerExpanderChannel(params[LOW2_PARAM], params[MID2_PARAM], params[HIGH2_PARAM], params[A2_PARAM], params[B2_PARAM], params[PRE_A2_PARAM], params[PRE_B2_PARAM], inputs[A2_INPUT], inputs[B2_INPUT]);
_channels[2] = new MixerExpanderChannel(params[LOW3_PARAM], params[MID3_PARAM], params[HIGH3_PARAM], params[A3_PARAM], params[B3_PARAM], params[PRE_A3_PARAM], params[PRE_B3_PARAM], inputs[A3_INPUT], inputs[B3_INPUT]);
diff --git a/src/Mono.cpp b/src/Mono.cpp
@@ -55,7 +55,7 @@ void Mono::processAll(const ProcessArgs& args) {
}
struct MonoWidget : BGModuleWidget {
- struct ChannelsDisplay : OpaqueWidget {
+ struct ChannelsDisplay : LightEmittingWidget<OpaqueWidget> {
const NVGcolor inactiveBgColor = nvgRGBA(0xaa, 0xaa, 0xaa, 0xff);
const NVGcolor activeBgColor = nvgRGBA(0x66, 0x66, 0x66, 0xff);
Mono* _module;
@@ -63,29 +63,48 @@ struct MonoWidget : BGModuleWidget {
ChannelsDisplay(Mono* module) : _module(module) {
}
+ bool isLit() override {
+ return _module && !_module->isBypassed();
+ }
+
void draw(const DrawArgs& args) override {
+ int active = 0;
+ if (_module) {
+ active = _module->_activeChannels;
+ }
+
nvgSave(args.vg);
- for (int i = 0; i < _module->maxChannels; ++i) {
+ for (int i = 0; i < Mono::maxChannels; ++i) {
nvgBeginPath(args.vg);
- if (!_module || i >= _module->_activeChannels) {
+ if (i >= active) {
+ nvgCircle(args.vg, (i % 4) * 10 + 5.0f, (i / 4) * 10 + 5.0f, 3.2f);
nvgFillColor(args.vg, inactiveBgColor);
+ nvgFill(args.vg);
}
- else {
- nvgFillColor(args.vg, activeBgColor);
- }
- nvgCircle(args.vg, (i % 4) * 10 + 5.0f, (i / 4) * 10 + 5.0f, 3.2f);
- nvgFill(args.vg);
+ }
+ nvgRestore(args.vg);
+ }
- if (_module && _module->_channelLevels[i] > 0.0f) {
- nvgFillColor(args.vg, decibelsToColor(amplitudeToDecibels(_module->_channelLevels[i])));
+ void drawLit(const DrawArgs& args) override {
+ assert(_module);
+ nvgSave(args.vg);
+ for (int i = 0; i < Mono::maxChannels; ++i) {
+ nvgBeginPath(args.vg);
+ if (i < _module->_activeChannels) {
+ nvgCircle(args.vg, (i % 4) * 10 + 5.0f, (i / 4) * 10 + 5.0f, 3.2f);
+ nvgFillColor(args.vg, activeBgColor);
nvgFill(args.vg);
+ if (_module->_channelLevels[i] > 0.0f) {
+ nvgFillColor(args.vg, decibelsToColor(amplitudeToDecibels(_module->_channelLevels[i])));
+ nvgFill(args.vg);
+ }
}
}
nvgRestore(args.vg);
}
};
- struct CompressionDisplay : OpaqueWidget {
+ struct CompressionDisplay : LightEmittingWidget<OpaqueWidget> {
struct Level {
float db;
NVGcolor color;
@@ -105,27 +124,42 @@ struct MonoWidget : BGModuleWidget {
}
}
+ bool isLit() override {
+ return _module && !_module->isBypassed();
+ }
+
void draw(const DrawArgs& args) override {
+ nvgSave(args.vg);
+ for (int i = 0; i < 35; i += 5) {
+ drawBox(args, i);
+ nvgFillColor(args.vg, bgColor);
+ nvgFill(args.vg);
+ }
+ nvgRestore(args.vg);
+ }
+
+ void drawLit(const DrawArgs& args) override {
float compressionDb = 0.0f;
- if (_module) {
+ if (_module && !_module->isBypassed()) {
compressionDb = _module->_compressionDb;
}
nvgSave(args.vg);
for (int i = 0; i < 35; i += 5) {
const Level& l = _levels.at(i / 5);
-
- nvgBeginPath(args.vg);
- nvgRect(args.vg, 3, i + 1, 5, 4);
- nvgFillColor(args.vg, bgColor);
- nvgFill(args.vg);
if (compressionDb > l.db) {
+ drawBox(args, i);
nvgFillColor(args.vg, l.color);
nvgFill(args.vg);
}
}
nvgRestore(args.vg);
}
+
+ void drawBox(const DrawArgs& args, int offset) {
+ nvgBeginPath(args.vg);
+ nvgRect(args.vg, 3, offset + 1, 5, 4);
+ }
};
static constexpr int hp = 3;
diff --git a/src/Mono.hpp b/src/Mono.hpp
@@ -44,6 +44,10 @@ struct Mono : BGModule {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam(COMPRESSION_PARAM, 0.0f, 1.0f, 0.2f, "Compression", "", 0.0f, 10.0f);
configParam<AmplifierParamQuantity>(LEVEL_PARAM, 0.0f, 1.0f, 1.0f, "Output level");
+
+ configInput(POLY_INPUT, "Polyphonic signal");
+
+ configOutput(MONO_OUTPUT, "Mono signal");
}
void sampleRateChange() override;
diff --git a/src/Mult.hpp b/src/Mult.hpp
@@ -29,6 +29,16 @@ struct Mult : BGModule {
Mult() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
+
+ configInput(INA_INPUT, "Signal A");
+ configInput(INB_INPUT, "Signal B");
+
+ configOutput(OUTA1_OUTPUT, "Signal A");
+ configOutput(OUTA2_OUTPUT, "Signal A");
+ configOutput(OUTA3_OUTPUT, "Signal A");
+ configOutput(OUTB1_OUTPUT, "Signal B");
+ configOutput(OUTB2_OUTPUT, "Signal B");
+ configOutput(OUTB3_OUTPUT, "Signal B");
}
void processAll(const ProcessArgs& args) override;
diff --git a/src/Mumix.hpp b/src/Mumix.hpp
@@ -52,14 +52,25 @@ struct Mumix : MatrixBaseModule {
Mumix() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
- configParam(MUTE1_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1");
- configParam(MUTE2_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2");
- configParam(MUTE3_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3");
- configParam(MUTE4_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4");
- configParam(MUTE5_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5");
- configParam(MUTE6_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6");
- configParam(MUTE7_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7");
- configParam(MUTE8_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8");
+ configSwitch(MUTE1_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1", {"Unmuted", "Muted", "Soloed", "Soloed"});
+ configSwitch(MUTE2_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2", {"Unmuted", "Muted", "Soloed", "Soloed"});
+ configSwitch(MUTE3_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3", {"Unmuted", "Muted", "Soloed", "Soloed"});
+ configSwitch(MUTE4_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4", {"Unmuted", "Muted", "Soloed", "Soloed"});
+ configSwitch(MUTE5_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5", {"Unmuted", "Muted", "Soloed", "Soloed"});
+ configSwitch(MUTE6_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6", {"Unmuted", "Muted", "Soloed", "Soloed"});
+ configSwitch(MUTE7_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7", {"Unmuted", "Muted", "Soloed", "Soloed"});
+ configSwitch(MUTE8_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8", {"Unmuted", "Muted", "Soloed", "Soloed"});
+
+ configInput(IN1_INPUT, "Signal 1");
+ configInput(IN2_INPUT, "Signal 2");
+ configInput(IN3_INPUT, "Signal 3");
+ configInput(IN4_INPUT, "Signal 4");
+ configInput(IN5_INPUT, "Signal 5");
+ configInput(IN6_INPUT, "Signal 6");
+ configInput(IN7_INPUT, "Signal 7");
+ configInput(IN8_INPUT, "Signal 8");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
void sampleRateChange() override;
diff --git a/src/Mute8.cpp b/src/Mute8.cpp
@@ -8,12 +8,12 @@ const float Mute8::maxDecibels = 0.0f;
const float Mute8::minDecibels = Amplifier::minDecibels;
const float Mute8::slewTimeMS = 5.0f;
-json_t* Mute8::toJson(json_t* root) {
+json_t* Mute8::saveToJson(json_t* root) {
json_object_set_new(root, LATCHING_CVS, json_boolean(_latchingCVs));
return root;
}
-void Mute8::fromJson(json_t* root) {
+void Mute8::loadFromJson(json_t* root) {
json_t* l = json_object_get(root, LATCHING_CVS);
if (l) {
_latchingCVs = json_is_true(l);
@@ -179,14 +179,14 @@ struct Mute8Widget : BGModuleWidget {
addOutput(createOutput<Port24>(output7OutputPosition, module, Mute8::OUTPUT7_OUTPUT));
addOutput(createOutput<Port24>(output8OutputPosition, module, Mute8::OUTPUT8_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(mute1LightPosition, module, Mute8::MUTE1_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(mute2LightPosition, module, Mute8::MUTE2_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(mute3LightPosition, module, Mute8::MUTE3_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(mute4LightPosition, module, Mute8::MUTE4_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(mute5LightPosition, module, Mute8::MUTE5_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(mute6LightPosition, module, Mute8::MUTE6_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(mute7LightPosition, module, Mute8::MUTE7_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(mute8LightPosition, module, Mute8::MUTE8_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(mute1LightPosition, module, Mute8::MUTE1_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(mute2LightPosition, module, Mute8::MUTE2_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(mute3LightPosition, module, Mute8::MUTE3_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(mute4LightPosition, module, Mute8::MUTE4_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(mute5LightPosition, module, Mute8::MUTE5_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(mute6LightPosition, module, Mute8::MUTE6_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(mute7LightPosition, module, Mute8::MUTE7_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(mute8LightPosition, module, Mute8::MUTE8_LIGHT));
}
void contextMenu(Menu* menu) override {
diff --git a/src/Mute8.hpp b/src/Mute8.hpp
@@ -78,18 +78,53 @@ struct Mute8 : BGModule {
Mute8() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
- configParam(MUTE1_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1");
- configParam(MUTE2_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2");
- configParam(MUTE3_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3");
- configParam(MUTE4_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4");
- configParam(MUTE5_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5");
- configParam(MUTE6_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6");
- configParam(MUTE7_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7");
- configParam(MUTE8_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8");
+ configSwitch(MUTE1_PARAM, 0.0f, 3.0f, 0.0f, "Mute 1", {"Unmuted", "Muted", "Soloed", "Soloed"});
+ configSwitch(MUTE2_PARAM, 0.0f, 3.0f, 0.0f, "Mute 2", {"Unmuted", "Muted", "Soloed", "Soloed"});
+ configSwitch(MUTE3_PARAM, 0.0f, 3.0f, 0.0f, "Mute 3", {"Unmuted", "Muted", "Soloed", "Soloed"});
+ configSwitch(MUTE4_PARAM, 0.0f, 3.0f, 0.0f, "Mute 4", {"Unmuted", "Muted", "Soloed", "Soloed"});
+ configSwitch(MUTE5_PARAM, 0.0f, 3.0f, 0.0f, "Mute 5", {"Unmuted", "Muted", "Soloed", "Soloed"});
+ configSwitch(MUTE6_PARAM, 0.0f, 3.0f, 0.0f, "Mute 6", {"Unmuted", "Muted", "Soloed", "Soloed"});
+ configSwitch(MUTE7_PARAM, 0.0f, 3.0f, 0.0f, "Mute 7", {"Unmuted", "Muted", "Soloed", "Soloed"});
+ configSwitch(MUTE8_PARAM, 0.0f, 3.0f, 0.0f, "Mute 8", {"Unmuted", "Muted", "Soloed", "Soloed"});
+
+ configBypass(INPUT1_INPUT, OUTPUT1_OUTPUT);
+ configBypass(INPUT2_INPUT, OUTPUT2_OUTPUT);
+ configBypass(INPUT3_INPUT, OUTPUT3_OUTPUT);
+ configBypass(INPUT4_INPUT, OUTPUT4_OUTPUT);
+ configBypass(INPUT5_INPUT, OUTPUT5_OUTPUT);
+ configBypass(INPUT6_INPUT, OUTPUT6_OUTPUT);
+ configBypass(INPUT7_INPUT, OUTPUT7_OUTPUT);
+ configBypass(INPUT8_INPUT, OUTPUT8_OUTPUT);
+
+ configInput(INPUT1_INPUT, "Signal 1");
+ configInput(INPUT2_INPUT, "Signal 2");
+ configInput(INPUT3_INPUT, "Signal 3");
+ configInput(INPUT4_INPUT, "Signal 4");
+ configInput(INPUT5_INPUT, "Signal 5");
+ configInput(INPUT6_INPUT, "Signal 6");
+ configInput(INPUT7_INPUT, "Signal 7");
+ configInput(INPUT8_INPUT, "Signal 8");
+ configInput(MUTE1_INPUT, "Mute 1 CV");
+ configInput(MUTE2_INPUT, "Mute 2 CV");
+ configInput(MUTE3_INPUT, "Mute 3 CV");
+ configInput(MUTE4_INPUT, "Mute 4 CV");
+ configInput(MUTE5_INPUT, "Mute 5 CV");
+ configInput(MUTE6_INPUT, "Mute 6 CV");
+ configInput(MUTE7_INPUT, "Mute 7 CV");
+ configInput(MUTE8_INPUT, "Mute 8 CV");
+
+ configOutput(OUTPUT1_OUTPUT, "Signal 1");
+ configOutput(OUTPUT2_OUTPUT, "Signal 2");
+ configOutput(OUTPUT3_OUTPUT, "Signal 3");
+ configOutput(OUTPUT4_OUTPUT, "Signal 4");
+ configOutput(OUTPUT5_OUTPUT, "Signal 5");
+ configOutput(OUTPUT6_OUTPUT, "Signal 6");
+ configOutput(OUTPUT7_OUTPUT, "Signal 7");
+ configOutput(OUTPUT8_OUTPUT, "Signal 8");
}
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void reset() override;
void sampleRateChange() override;
void processAll(const ProcessArgs& args) override;
diff --git a/src/Noise.hpp b/src/Noise.hpp
@@ -38,6 +38,15 @@ struct Noise : PolyChannelsModule {
Noise() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
+
+ configInput(ABS_INPUT, "Absolute value");
+
+ configOutput(WHITE_OUTPUT, "White noise");
+ configOutput(PINK_OUTPUT, "Pink noise");
+ configOutput(RED_OUTPUT, "Red noise");
+ configOutput(GAUSS_OUTPUT, "Gaussian noise");
+ configOutput(ABS_OUTPUT, "Absolute value");
+ configOutput(BLUE_OUTPUT, "Blue noise");
}
void processAll(const ProcessArgs& args) override;
diff --git a/src/Nsgt.cpp b/src/Nsgt.cpp
@@ -39,14 +39,14 @@ void Nsgt::sampleRateChange() {
}
}
-json_t* Nsgt::toJson(json_t* root) {
+json_t* Nsgt::saveToJson(json_t* root) {
json_object_set_new(root, ATTACK_MS, json_real(_attackMs));
json_object_set_new(root, RELEASE_MS, json_real(_releaseMs));
json_object_set_new(root, THRESHOLD_RANGE, json_real(_thresholdRange));
return root;
}
-void Nsgt::fromJson(json_t* root) {
+void Nsgt::loadFromJson(json_t* root) {
json_t* a = json_object_get(root, ATTACK_MS);
if (a) {
_attackMs = std::max(0.0f, (float)json_real_value(a));
diff --git a/src/Nsgt.hpp b/src/Nsgt.hpp
@@ -68,12 +68,22 @@ struct Nsgt : BGModule {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam<ThresholdParamQuantity>(THRESHOLD_PARAM, 0.0f, 1.0f, 0.8f, "Threshold", " dB");
configParam<DynamicsRatioParamQuantity>(RATIO_PARAM, 0.0f, 1.0f, 0.55159f, "Ratio");
- configParam(KNEE_PARAM, 0.0f, 1.0f, 1.0f, "Knee");
+ configSwitch(KNEE_PARAM, 0.0f, 1.0f, 1.0f, "Knee", {"Hard", "Soft"});
+ configBypass(LEFT_INPUT, LEFT_OUTPUT);
+ configBypass(RIGHT_INPUT, RIGHT_OUTPUT);
+
+ configInput(LEFT_INPUT, "Left signal");
+ configInput(RIGHT_INPUT, "Right signal");
+ configInput(THRESHOLD_INPUT, "Threshold CV");
+ configInput(RATIO_INPUT, "Ratio CV");
+
+ configOutput(LEFT_OUTPUT, "Left signal");
+ configOutput(RIGHT_OUTPUT, "Right signal");
}
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
bool active() override;
int channels() override;
void addChannel(int c) override;
diff --git a/src/Offset.cpp b/src/Offset.cpp
@@ -3,14 +3,14 @@
#define OFFSET_FIRST "offset_first"
-json_t* Offset::toJson(json_t* root) {
- root = DisableOutputLimitModule::toJson(root);
+json_t* Offset::saveToJson(json_t* root) {
+ root = DisableOutputLimitModule::saveToJson(root);
json_object_set_new(root, OFFSET_FIRST, json_boolean(_offsetFirst));
return root;
}
-void Offset::fromJson(json_t* root) {
- DisableOutputLimitModule::fromJson(root);
+void Offset::loadFromJson(json_t* root) {
+ DisableOutputLimitModule::loadFromJson(root);
json_t* of = json_object_get(root, OFFSET_FIRST);
if (of) {
_offsetFirst = json_boolean_value(of);
diff --git a/src/Offset.hpp b/src/Offset.hpp
@@ -8,20 +8,20 @@ extern Model* modelOffset;
namespace bogaudio {
struct Offset : DisableOutputLimitModule {
- enum ParamIds {
+ enum ParamsIds {
OFFSET_PARAM,
SCALE_PARAM,
NUM_PARAMS
};
- enum InputIds {
+ enum InputsIds {
OFFSET_INPUT,
SCALE_INPUT,
IN_INPUT,
NUM_INPUTS
};
- enum OutputIds {
+ enum OutputsIds {
OUT_OUTPUT,
NUM_OUTPUTS
};
@@ -32,10 +32,17 @@ struct Offset : DisableOutputLimitModule {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam(OFFSET_PARAM, -1.0f, 1.0f, 0.0f, "Offset", " V", 0.0f, 10.0f);
configParam<TenXSquaringParamQuantity>(SCALE_PARAM, -1.0f, 1.0f, 0.31623f, "Scale", "x");
+ configBypass(IN_INPUT, OUT_OUTPUT);
+
+ configInput(OFFSET_INPUT, "Offset CV");
+ configInput(SCALE_INPUT, "Scale CV");
+ configInput(IN_INPUT, "Signal");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
int channels() override;
void processChannel(const ProcessArgs& args, int c) override;
float knobValue(Param& knob, Input& cv, int c) const;
diff --git a/src/OneEight.cpp b/src/OneEight.cpp
@@ -86,17 +86,9 @@ struct OneEightWidget : AddressableSequenceModuleWidget {
auto out8LightPosition = Vec(66.5, 350.5);
// end generated by svg_widgets.rb
- {
- auto w = createParam<Knob16>(stepsParamPosition, module, OneEight::STEPS_PARAM);
- dynamic_cast<Knob*>(w)->snap = true;
- addParam(w);
- }
+ addParam(createParam<Knob16>(stepsParamPosition, module, OneEight::STEPS_PARAM));
addParam(createParam<SliderSwitch2State14>(directionParamPosition, module, OneEight::DIRECTION_PARAM));
- {
- auto w = createParam<Knob29>(selectParamPosition, module, OneEight::SELECT_PARAM);
- dynamic_cast<Knob*>(w)->snap = true;
- addParam(w);
- }
+ addParam(createParam<Knob29>(selectParamPosition, module, OneEight::SELECT_PARAM));
addInput(createInput<Port24>(clockInputPosition, module, OneEight::CLOCK_INPUT));
addInput(createInput<Port24>(resetInputPosition, module, OneEight::RESET_INPUT));
@@ -112,14 +104,14 @@ struct OneEightWidget : AddressableSequenceModuleWidget {
addOutput(createOutput<Port24>(out7OutputPosition, module, OneEight::OUT7_OUTPUT));
addOutput(createOutput<Port24>(out8OutputPosition, module, OneEight::OUT8_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(out1LightPosition, module, OneEight::OUT1_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out2LightPosition, module, OneEight::OUT2_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out3LightPosition, module, OneEight::OUT3_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out4LightPosition, module, OneEight::OUT4_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out5LightPosition, module, OneEight::OUT5_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out6LightPosition, module, OneEight::OUT6_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out7LightPosition, module, OneEight::OUT7_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(out8LightPosition, module, OneEight::OUT8_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out1LightPosition, module, OneEight::OUT1_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out2LightPosition, module, OneEight::OUT2_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out3LightPosition, module, OneEight::OUT3_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out4LightPosition, module, OneEight::OUT4_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out5LightPosition, module, OneEight::OUT5_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out6LightPosition, module, OneEight::OUT6_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out7LightPosition, module, OneEight::OUT7_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(out8LightPosition, module, OneEight::OUT8_LIGHT));
}
};
diff --git a/src/OneEight.hpp b/src/OneEight.hpp
@@ -55,9 +55,26 @@ struct OneEight : AddressableSequenceModule {
OneEight() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
configParam(STEPS_PARAM, 1.0f, 8.0f, 8.0f, "Steps");
- configParam(DIRECTION_PARAM, 0.0f, 1.0f, 1.0f, "Direction");
+ paramQuantities[STEPS_PARAM]->snapEnabled = true;
+ configSwitch(DIRECTION_PARAM, 0.0f, 1.0f, 1.0f, "Direction", {"Reverse", "Forward"});
configParam(SELECT_PARAM, 0.0f, 7.0f, 0.0f, "Select step");
+ paramQuantities[SELECT_PARAM]->snapEnabled = true;
setInputIDs(CLOCK_INPUT, SELECT_INPUT);
+ configBypass(IN_INPUT, OUT1_OUTPUT);
+
+ configInput(CLOCK_INPUT, "Clock");
+ configInput(RESET_INPUT, "Reset");
+ configInput(SELECT_INPUT, "Select CV");
+ configInput(IN_INPUT, "Signal");
+
+ configOutput(OUT1_OUTPUT, "Signal 1");
+ configOutput(OUT2_OUTPUT, "Signal 2");
+ configOutput(OUT3_OUTPUT, "Signal 3");
+ configOutput(OUT4_OUTPUT, "Signal 4");
+ configOutput(OUT5_OUTPUT, "Signal 5");
+ configOutput(OUT6_OUTPUT, "Signal 6");
+ configOutput(OUT7_OUTPUT, "Signal 7");
+ configOutput(OUT8_OUTPUT, "Signal 8");
}
void processAlways(const ProcessArgs& args) override;
diff --git a/src/PEQ.cpp b/src/PEQ.cpp
@@ -141,9 +141,9 @@ struct PEQWidget : BGModuleWidget {
addOutput(createOutput<Port24>(outOutputPosition, module, PEQ::OUT_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(aLightPosition, module, PEQ::A_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(bLightPosition, module, PEQ::B_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(cLightPosition, module, PEQ::C_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(aLightPosition, module, PEQ::A_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(bLightPosition, module, PEQ::B_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(cLightPosition, module, PEQ::C_LIGHT));
}
};
diff --git a/src/PEQ.hpp b/src/PEQ.hpp
@@ -63,7 +63,7 @@ struct PEQ : BGModule {
configParam<ScaledSquaringParamQuantity<(int)PEQChannel::maxFrequency>>(A_FREQUENCY_PARAM, 0.0f, 1.0f, 0.0707107f, "Channel A frequency", " HZ");
configParam(A_BANDWIDTH_PARAM, 0.0f, 1.0f, 0.5f, "Channel A bandwidth", "%", 0.0f, 100.0f);
configParam(A_CV_PARAM, -1.0f, 1.0f, 0.0f, "Channel A frequency CV attenuation", "%", 0.0f, 100.0f);
- configParam(A_MODE_PARAM, 0.0f, 1.0f, 1.0f, "Channel A LP/BP");
+ configSwitch(A_MODE_PARAM, 0.0f, 1.0f, 1.0f, "Channel A LP/BP", {"Bandpass", "Lowpass"});
configParam(B_LEVEL_PARAM, 0.0f, 1.0f, levelDefault, "Channel B level", " dB", 0.0f, PEQChannel::maxDecibels - PEQChannel::minDecibels, PEQChannel::minDecibels);
configParam<ScaledSquaringParamQuantity<(int)PEQChannel::maxFrequency>>(B_FREQUENCY_PARAM, 0.0f, 1.0f, 0.1322876f, "Channel B frequency", " HZ");
configParam(B_BANDWIDTH_PARAM, 0.0f, 1.0f, 0.66f, "Channel B bandwidth", "%", 0.0f, 100.0f);
@@ -72,7 +72,22 @@ struct PEQ : BGModule {
configParam<ScaledSquaringParamQuantity<(int)PEQChannel::maxFrequency>>(C_FREQUENCY_PARAM, 0.0f, 1.0f, 0.223607f, "Channel C frequency", " HZ");
configParam(C_BANDWIDTH_PARAM, 0.0f, 1.0f, 0.5f, "Channel C bandwidth", "%", 0.0f, 100.0f);
configParam(C_CV_PARAM, -1.0f, 1.0f, 0.0f, "Channel C frequency CV attenuation", "%", 0.0f, 100.0f);
- configParam(C_MODE_PARAM, 0.0f, 1.0f, 1.0f, "Channel C HP/BP");
+ configSwitch(C_MODE_PARAM, 0.0f, 1.0f, 1.0f, "Channel C HP/BP", {"Bandpass", "Highpass"});
+ configBypass(IN_INPUT, OUT_OUTPUT);
+
+ configInput(A_LEVEL_INPUT, "Channel A level CV");
+ configInput(B_LEVEL_INPUT, "Channel B level CV");
+ configInput(C_LEVEL_INPUT, "Channel C level CV");
+ configInput(A_FREQUENCY_INPUT, "Channel A frequency CV");
+ configInput(B_FREQUENCY_INPUT, "Channel B frequency CV");
+ configInput(C_FREQUENCY_INPUT, "Channel C frequency CV");
+ configInput(A_BANDWIDTH_INPUT, "Channel A bandwidth CV");
+ configInput(B_BANDWIDTH_INPUT, "Channel B bandwidth CV");
+ configInput(C_BANDWIDTH_INPUT, "Channel C bandwidth CV");
+ configInput(ALL_CV_INPUT, "All-channels frequency CV");
+ configInput(IN_INPUT, "Signal");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
void sampleRateChange() override;
diff --git a/src/PEQ14.cpp b/src/PEQ14.cpp
@@ -348,8 +348,8 @@ struct PEQ14Widget : BandExcludeModuleWidget {
addOutput(createOutput<Port24>(out13OutputPosition, module, PEQ14::OUT13_OUTPUT));
addOutput(createOutput<Port24>(out14OutputPosition, module, PEQ14::OUT14_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(fmodRelativeLightPosition, module, PEQ14::FMOD_RELATIVE_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(fmodFullLightPosition, module, PEQ14::FMOD_FULL_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(fmodRelativeLightPosition, module, PEQ14::FMOD_RELATIVE_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(fmodFullLightPosition, module, PEQ14::FMOD_FULL_LIGHT));
}
void addSlider(Vec position, PEQ14* module, int id, float* rms) {
diff --git a/src/PEQ14.hpp b/src/PEQ14.hpp
@@ -130,9 +130,9 @@ struct PEQ14 : ExpandableModule<PEQ14ExpanderMessage, BandExcludeModule> {
float levelDefault = fabsf(PEQChannel::minDecibels) / (PEQChannel::maxDecibels - PEQChannel::minDecibels);
configParam(FREQUENCY_CV_PARAM, -1.0f, 1.0f, 0.0f, "Global frequency CV attenuation", "%", 0.0f, 100.0f);
configParam(BANDWIDTH_PARAM, 0.0f, 1.0f, 0.11f, "Bandwidth", "%", 0.0f, 100.0f);
- configParam(LP_PARAM, 0.0f, 1.0f, 1.0f, "Channel 1 LP/BP");
- configParam(HP_PARAM, 0.0f, 1.0f, 1.0f, "Channel 14 HP/BP");
- configParam(FMOD_PARAM, 0.0f, 1.0f, 0.0f, "Frequency modulation range");
+ configSwitch(LP_PARAM, 0.0f, 1.0f, 1.0f, "Channel 1 LP/BP", {"Bandpass", "Lowpass"});
+ configSwitch(HP_PARAM, 0.0f, 1.0f, 1.0f, "Channel 6 HP/BP", {"Bandpass", "Highpass"});
+ configSwitch(FMOD_PARAM, 0.0f, 1.0f, 0.0f, "Frequency modulation range", {"Octave", "Full"});
configParam(LEVEL1_PARAM, 0.0f, 1.0f, levelDefault, "Channel 1 level", " dB", 0.0f, PEQChannel::maxDecibels - PEQChannel::minDecibels, PEQChannel::minDecibels);
configParam<ScaledSquaringParamQuantity<(int)PEQChannel::maxFrequency>>(FREQUENCY1_PARAM, 0.0f, 1.0f, 0.0689202f, "Channel 1 frequency", " HZ");
configParam(FREQUENCY_CV1_PARAM, -1.0f, 1.0f, 1.0f, "Channel 1 frequency CV attenuation", "%", 0.0f, 100.0f);
@@ -175,6 +175,59 @@ struct PEQ14 : ExpandableModule<PEQ14ExpanderMessage, BandExcludeModule> {
configParam(LEVEL14_PARAM, 0.0f, 1.0f, levelDefault, "Channel 14 level", " dB", 0.0f, PEQChannel::maxDecibels - PEQChannel::minDecibels, PEQChannel::minDecibels);
configParam<ScaledSquaringParamQuantity<(int)PEQChannel::maxFrequency>>(FREQUENCY14_PARAM, 0.0f, 1.0f, 0.5873670f, "Channel 14 frequency", " HZ");
configParam(FREQUENCY_CV14_PARAM, -1.0f, 1.0f, 1.0f, "Channel 14 frequency CV attenuation", "%", 0.0f, 100.0f);
+ configBypass(IN_INPUT, OUT_OUTPUT);
+ configBypass(IN_INPUT, ODDS_OUTPUT);
+ configBypass(IN_INPUT, EVENS_OUTPUT);
+
+ configInput(FREQUENCY_CV_INPUT, "Frequency CV");
+ configInput(BANDWIDTH_INPUT, "Bandwidth CV");
+ configInput(IN_INPUT, "Signal");
+ configInput(LEVEL1_INPUT, "Channel 1 level CV");
+ configInput(FREQUENCY_CV1_INPUT, "Channel 1 frequency CV");
+ configInput(LEVEL2_INPUT, "Channel 2 level CV");
+ configInput(FREQUENCY_CV2_INPUT, "Channel 2 frequency CV");
+ configInput(LEVEL3_INPUT, "Channel 3 level CV");
+ configInput(FREQUENCY_CV3_INPUT, "Channel 3 frequency CV");
+ configInput(LEVEL4_INPUT, "Channel 4 level CV");
+ configInput(FREQUENCY_CV4_INPUT, "Channel 4 frequency CV");
+ configInput(LEVEL5_INPUT, "Channel 5 level CV");
+ configInput(FREQUENCY_CV5_INPUT, "Channel 5 frequency CV");
+ configInput(LEVEL6_INPUT, "Channel 6 level CV");
+ configInput(FREQUENCY_CV6_INPUT, "Channel 6 frequency CV");
+ configInput(LEVEL7_INPUT, "Channel 7 level CV");
+ configInput(FREQUENCY_CV7_INPUT, "Channel 7 frequency CV");
+ configInput(LEVEL8_INPUT, "Channel 8 level CV");
+ configInput(FREQUENCY_CV8_INPUT, "Channel 8 frequency CV");
+ configInput(LEVEL9_INPUT, "Channel 9 level CV");
+ configInput(FREQUENCY_CV9_INPUT, "Channel 9 frequency CV");
+ configInput(LEVEL10_INPUT, "Channel 10 level CV");
+ configInput(FREQUENCY_CV10_INPUT, "Channel 10 frequency CV");
+ configInput(LEVEL11_INPUT, "Channel 11 level CV");
+ configInput(FREQUENCY_CV11_INPUT, "Channel 11 frequency CV");
+ configInput(LEVEL12_INPUT, "Channel 12 level CV");
+ configInput(FREQUENCY_CV12_INPUT, "Channel 12 frequency CV");
+ configInput(LEVEL13_INPUT, "Channel 13 level CV");
+ configInput(FREQUENCY_CV13_INPUT, "Channel 13 frequency CV");
+ configInput(LEVEL14_INPUT, "Channel 14 level CV");
+ configInput(FREQUENCY_CV14_INPUT, "Channel 14 frequency CV");
+
+ configOutput(ODDS_OUTPUT, "Odd channels mix");
+ configOutput(OUT_OUTPUT, "All channels mix");
+ configOutput(EVENS_OUTPUT, "Even channels mix");
+ configOutput(OUT1_OUTPUT, "Channel 1");
+ configOutput(OUT2_OUTPUT, "Channel 2");
+ configOutput(OUT3_OUTPUT, "Channel 3");
+ configOutput(OUT4_OUTPUT, "Channel 4");
+ configOutput(OUT5_OUTPUT, "Channel 5");
+ configOutput(OUT6_OUTPUT, "Channel 6");
+ configOutput(OUT7_OUTPUT, "Channel 7");
+ configOutput(OUT8_OUTPUT, "Channel 8");
+ configOutput(OUT9_OUTPUT, "Channel 9");
+ configOutput(OUT10_OUTPUT, "Channel 10");
+ configOutput(OUT11_OUTPUT, "Channel 11");
+ configOutput(OUT12_OUTPUT, "Channel 12");
+ configOutput(OUT13_OUTPUT, "Channel 13");
+ configOutput(OUT14_OUTPUT, "Channel 14");
setExpanderModelPredicate([](Model* m) { return m == modelPEQ14XF || m == modelPEQ14XR || m == modelPEQ14XV; });
}
diff --git a/src/PEQ14XF.hpp b/src/PEQ14XF.hpp
@@ -50,6 +50,24 @@ struct PEQ14XF : ExpanderModule<PEQ14ExpanderMessage, ExpandableModule<PEQ14Expa
configParam(DAMP_PARAM, 0.0f, 1.0f, 0.3f, "Envelope follower smoothing", "%", 0.0f, 100.0f);
configParam<EFGainParamQuantity>(GAIN_PARAM, -1.0f, 1.0f, 0.0f, "Envelope follower gain", " dB");
+ configInput(DAMP_INPUT, "Damp CV");
+ configInput(GAIN_INPUT, "Gain CV");
+
+ configOutput(EF1_OUTPUT, "Envelope 1");
+ configOutput(EF2_OUTPUT, "Envelope 2");
+ configOutput(EF3_OUTPUT, "Envelope 3");
+ configOutput(EF4_OUTPUT, "Envelope 4");
+ configOutput(EF5_OUTPUT, "Envelope 5");
+ configOutput(EF6_OUTPUT, "Envelope 6");
+ configOutput(EF7_OUTPUT, "Envelope 7");
+ configOutput(EF8_OUTPUT, "Envelope 8");
+ configOutput(EF9_OUTPUT, "Envelope 9");
+ configOutput(EF10_OUTPUT, "Envelope 10");
+ configOutput(EF11_OUTPUT, "Envelope 11");
+ configOutput(EF12_OUTPUT, "Envelope 12");
+ configOutput(EF13_OUTPUT, "Envelope 13");
+ configOutput(EF14_OUTPUT, "Envelope 14");
+
setBaseModelPredicate([](Model* m) { return m == modelPEQ14 || m == modelPEQ14XF || m == modelPEQ14XR || m == modelPEQ14XV; });
setExpanderModelPredicate([](Model* m) { return m == modelPEQ14XF || m == modelPEQ14XR || m == modelPEQ14XV; });
}
diff --git a/src/PEQ14XR.hpp b/src/PEQ14XR.hpp
@@ -56,6 +56,11 @@ struct PEQ14XR : ExpanderModule<PEQ14ExpanderMessage, ExpandableModule<PEQ14Expa
configParam(DAMP_PARAM, 0.0f, 1.0f, 0.3f, "Envelope follower smoothing", "%", 0.0f, 100.0f);
configParam<EFGainParamQuantity>(GAIN_PARAM, -1.0f, 1.0f, 0.0f, "Envelope follower gain", " dB");
+ configInput(DAMP_INPUT, "Damp CV");
+ configInput(GAIN_INPUT, "Gain CV");
+
+ configOutput(OUT_OUTPUT, "Signal");
+
setBaseModelPredicate([](Model* m) { return m == modelPEQ14 || m == modelPEQ14XF || m == modelPEQ14XR || m == modelPEQ14XV; });
setExpanderModelPredicate([](Model* m) { return m == modelPEQ14XF || m == modelPEQ14XR || m == modelPEQ14XV; });
}
diff --git a/src/PEQ14XV.hpp b/src/PEQ14XV.hpp
@@ -63,6 +63,15 @@ struct PEQ14XV : ExpanderModule<PEQ14ExpanderMessage, ExpandableModule<PEQ14Expa
configParam(BAND1_ENABLE_PARAM, 0.0f, 1.0f, 1.0f, "Band 1 enable");
configParam(BAND14_ENABLE_PARAM, 0.0f, 1.0f, 1.0f, "Band 14 enable");
+ configInput(EF_DAMP_INPUT, "Envelope follower damp CV");
+ configInput(EF_GAIN_INPUT, "Envelope follower gain CV");
+ configInput(TRANSPOSE_INPUT, "Transpose (1V/octave)");
+ configInput(IN_INPUT, "Signal");
+
+ configOutput(ODDS_OUTPUT, "Odd channels mix");
+ configOutput(OUT_OUTPUT, "All channels mix");
+ configOutput(EVENS_OUTPUT, "Even channels mix");
+
setBaseModelPredicate([](Model* m) { return m == modelPEQ14 || m == modelPEQ14XF || m == modelPEQ14XR || m == modelPEQ14XV; });
setExpanderModelPredicate([](Model* m) { return m == modelPEQ14XF || m == modelPEQ14XR || m == modelPEQ14XV; });
}
diff --git a/src/PEQ6.cpp b/src/PEQ6.cpp
@@ -108,8 +108,9 @@ void PEQ6::postProcessAlways(const ProcessArgs& args) {
_rms[i] = _rmsSums[i] * _inverseChannels;
}
- lights[FMOD_RELATIVE_LIGHT].value = !_fullFrequencyMode;
- lights[FMOD_FULL_LIGHT].value = _fullFrequencyMode;
+ bool ffm = params[FMOD_PARAM].getValue() > 0.5f;
+ lights[FMOD_RELATIVE_LIGHT].value = !ffm;
+ lights[FMOD_FULL_LIGHT].value = ffm;
}
struct PEQ6Widget : BandExcludeModuleWidget {
@@ -222,8 +223,8 @@ struct PEQ6Widget : BandExcludeModuleWidget {
addOutput(createOutput<Port24>(out5OutputPosition, module, PEQ6::OUT5_OUTPUT));
addOutput(createOutput<Port24>(out6OutputPosition, module, PEQ6::OUT6_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(fmodFullLightPosition, module, PEQ6::FMOD_FULL_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(fmodRelativeLightPosition, module, PEQ6::FMOD_RELATIVE_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(fmodFullLightPosition, module, PEQ6::FMOD_FULL_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(fmodRelativeLightPosition, module, PEQ6::FMOD_RELATIVE_LIGHT));
}
void addSlider(Vec position, PEQ6* module, int id, float* rms) {
diff --git a/src/PEQ6.hpp b/src/PEQ6.hpp
@@ -79,9 +79,9 @@ struct PEQ6 : ExpandableModule<PEQ6ExpanderMessage, BandExcludeModule> {
float levelDefault = fabsf(PEQChannel::minDecibels) / (PEQChannel::maxDecibels - PEQChannel::minDecibels);
configParam(FREQUENCY_CV_PARAM, -1.0f, 1.0f, 0.0f, "Global frequency CV attenuation", "%", 0.0f, 100.0f);
configParam(BANDWIDTH_PARAM, 0.0f, 1.0f, 0.33f, "Bandwidth", "%", 0.0f, 100.0f);
- configParam(LP_PARAM, 0.0f, 1.0f, 1.0f, "Channel 1 LP/BP");
- configParam(HP_PARAM, 0.0f, 1.0f, 1.0f, "Channel 6 HP/BP");
- configParam(FMOD_PARAM, 0.0f, 1.0f, 0.0f, "Frequency modulation range");
+ configSwitch(LP_PARAM, 0.0f, 1.0f, 1.0f, "Channel 1 LP/BP", {"Bandpass", "Lowpass"});
+ configSwitch(HP_PARAM, 0.0f, 1.0f, 1.0f, "Channel 6 HP/BP", {"Bandpass", "Highpass"});
+ configSwitch(FMOD_PARAM, 0.0f, 1.0f, 0.0f, "Frequency modulation range", {"Octave", "Full"});
configParam(LEVEL1_PARAM, 0.0f, 1.0f, levelDefault, "Channel 1 level", " dB", 0.0f, PEQChannel::maxDecibels - PEQChannel::minDecibels, PEQChannel::minDecibels);
configParam<ScaledSquaringParamQuantity<(int)PEQChannel::maxFrequency>>(FREQUENCY1_PARAM, 0.0f, 1.0f, 0.0707107f, "Channel 1 frequency", " HZ");
configParam(FREQUENCY_CV1_PARAM, -1.0f, 1.0f, 1.0f, "Channel 1 frequency CV attenuation", "%", 0.0f, 100.0f);
@@ -100,6 +100,31 @@ struct PEQ6 : ExpandableModule<PEQ6ExpanderMessage, BandExcludeModule> {
configParam(LEVEL6_PARAM, 0.0f, 1.0f, levelDefault, "Channel 6 level", " dB", 0.0f, PEQChannel::maxDecibels - PEQChannel::minDecibels, PEQChannel::minDecibels);
configParam<ScaledSquaringParamQuantity<(int)PEQChannel::maxFrequency>>(FREQUENCY6_PARAM, 0.0f, 1.0f, 0.3535534f, "Channel 6 frequency", " HZ");
configParam(FREQUENCY_CV6_PARAM, -1.0f, 1.0f, 1.0f, "Channel 6 frequency CV attenuation", "%", 0.0f, 100.0f);
+ configBypass(IN_INPUT, OUT_OUTPUT);
+
+ configInput(FREQUENCY_CV_INPUT, "Frequency CV");
+ configInput(BANDWIDTH_INPUT, "Bandwidth CV");
+ configInput(IN_INPUT, "Signal");
+ configInput(LEVEL1_INPUT, "Channel 1 level CV");
+ configInput(FREQUENCY_CV1_INPUT, "Channel 1 frequency CV");
+ configInput(LEVEL2_INPUT, "Channel 2 level CV");
+ configInput(FREQUENCY_CV2_INPUT, "Channel 2 frequency CV");
+ configInput(LEVEL3_INPUT, "Channel 3 level CV");
+ configInput(FREQUENCY_CV3_INPUT, "Channel 3 frequency CV");
+ configInput(LEVEL4_INPUT, "Channel 4 level CV");
+ configInput(FREQUENCY_CV4_INPUT, "Channel 4 frequency CV");
+ configInput(LEVEL5_INPUT, "Channel 5 level CV");
+ configInput(FREQUENCY_CV5_INPUT, "Channel 5 frequency CV");
+ configInput(LEVEL6_INPUT, "Channel 6 level CV");
+ configInput(FREQUENCY_CV6_INPUT, "Channel 6 frequency CV");
+
+ configOutput(OUT_OUTPUT, "All channels mix");
+ configOutput(OUT1_OUTPUT, "Channel 1");
+ configOutput(OUT2_OUTPUT, "Channel 2");
+ configOutput(OUT3_OUTPUT, "Channel 3");
+ configOutput(OUT4_OUTPUT, "Channel 4");
+ configOutput(OUT5_OUTPUT, "Channel 5");
+ configOutput(OUT6_OUTPUT, "Channel 6");
setExpanderModelPredicate([](Model* m) { return m == modelPEQ6XF; });
}
diff --git a/src/PEQ6XF.hpp b/src/PEQ6XF.hpp
@@ -40,6 +40,13 @@ struct PEQ6XF : ExpanderModule<PEQ6ExpanderMessage, PEQXFBase> {
configParam(DAMP_PARAM, 0.0f, 1.0f, 0.3f, "Envelope follower smoothing", "%", 0.0f, 100.0f);
configParam<EFGainParamQuantity>(GAIN_PARAM, -1.0f, 1.0f, 0.0f, "Envelope follower gain", " dB");
+ configOutput(EF1_OUTPUT, "Envelope 1");
+ configOutput(EF2_OUTPUT, "Envelope 2");
+ configOutput(EF3_OUTPUT, "Envelope 3");
+ configOutput(EF4_OUTPUT, "Envelope 4");
+ configOutput(EF5_OUTPUT, "Envelope 5");
+ configOutput(EF6_OUTPUT, "Envelope 6");
+
setBaseModelPredicate([](Model* m) { return m == modelPEQ6; });
}
diff --git a/src/Pan.hpp b/src/Pan.hpp
@@ -42,6 +42,14 @@ struct Pan : BGModule {
configParam(PAN1_PARAM, -1.0f, 1.0f, 0.0f, "Panning 1", "%", 0.0f, 100.0f);
configParam(PAN2_PARAM, -1.0f, 1.0f, 0.0f, "Panning 2", "%", 0.0f, 100.0f);
+ configInput(CV1_INPUT, "Pan 1 CV");
+ configInput(IN1_INPUT, "Signal 1");
+ configInput(CV2_INPUT, "Pan 2 CV");
+ configInput(IN2_INPUT, "Signal 2");
+
+ configOutput(L_OUTPUT, "Left signal");
+ configOutput(R_OUTPUT, "Right signal");
+
sampleRateChange();
}
diff --git a/src/Pgmr.cpp b/src/Pgmr.cpp
@@ -19,14 +19,14 @@ void Pgmr::sampleRateChange() {
_sampleTime = APP->engine->getSampleTime();
}
-json_t* Pgmr::toJson(json_t* root) {
- root = OutputRangeAddressableSequenceModule::toJson(root);
+json_t* Pgmr::saveToJson(json_t* root) {
+ root = OutputRangeAddressableSequenceModule::saveToJson(root);
json_object_set_new(root, SELECT_TRIGGERS, json_boolean(_selectTriggers));
return root;
}
-void Pgmr::fromJson(json_t* root) {
- OutputRangeAddressableSequenceModule::fromJson(root);
+void Pgmr::loadFromJson(json_t* root) {
+ OutputRangeAddressableSequenceModule::loadFromJson(root);
json_t* st = json_object_get(root, SELECT_TRIGGERS);
if (st) {
_selectTriggers = json_is_true(st);
@@ -222,10 +222,10 @@ struct PgmrWidget : AddressableSequenceBaseModuleWidget {
addOutput(createOutput<Port24>(select3OutputPosition, module, Pgmr::SELECT3_OUTPUT));
addOutput(createOutput<Port24>(select4OutputPosition, module, Pgmr::SELECT4_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(select1LightPosition, module, Pgmr::SELECT1_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(select2LightPosition, module, Pgmr::SELECT2_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(select3LightPosition, module, Pgmr::SELECT3_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(select4LightPosition, module, Pgmr::SELECT4_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(select1LightPosition, module, Pgmr::SELECT1_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(select2LightPosition, module, Pgmr::SELECT2_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(select3LightPosition, module, Pgmr::SELECT3_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(select4LightPosition, module, Pgmr::SELECT4_LIGHT));
}
void contextMenu(Menu* menu) override {
diff --git a/src/Pgmr.hpp b/src/Pgmr.hpp
@@ -71,30 +71,47 @@ struct Pgmr : PgmrBase {
Pgmr() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
- configParam(DIRECTION_PARAM, 0.0f, 1.0f, 1.0f, "Forward");
- configParam(SELECT_ON_CLOCK_PARAM, 0.0f, 1.0f, 0.0f, "Select on clock");
+ configSwitch(DIRECTION_PARAM, 0.0f, 1.0f, 1.0f, "Direction", {"Reverse", "Forward"});
+ configSwitch(SELECT_ON_CLOCK_PARAM, 0.0f, 1.0f, 0.0f, "Select on clock", {"Disabled", "Enabled"});
configParam<OutputRangeParamQuantity>(CVA1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1A", " V");
configParam<OutputRangeParamQuantity>(CVB1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1B", " V");
configParam<OutputRangeParamQuantity>(CVC1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1C", " V");
configParam<OutputRangeParamQuantity>(CVD1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1D", " V");
- configParam(SELECT1_PARAM, 0.0f, 1.0f, 0.0f, "Select 1");
+ configButton(SELECT1_PARAM, "Select 1");
configParam<OutputRangeParamQuantity>(CVA2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2A", " V");
configParam<OutputRangeParamQuantity>(CVB2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2B", " V");
configParam<OutputRangeParamQuantity>(CVC2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2C", " V");
configParam<OutputRangeParamQuantity>(CVD2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2D", " V");
- configParam(SELECT2_PARAM, 0.0f, 1.0f, 0.0f, "Select 2");
+ configButton(SELECT2_PARAM, "Select 2");
configParam<OutputRangeParamQuantity>(CVA3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3A", " V");
configParam<OutputRangeParamQuantity>(CVB3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3B", " V");
configParam<OutputRangeParamQuantity>(CVC3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3C", " V");
configParam<OutputRangeParamQuantity>(CVD3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3D", " V");
- configParam(SELECT3_PARAM, 0.0f, 1.0f, 0.0f, "Select 3");
+ configButton(SELECT3_PARAM, "Select 3");
configParam<OutputRangeParamQuantity>(CVA4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4A", " V");
configParam<OutputRangeParamQuantity>(CVB4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4B", " V");
configParam<OutputRangeParamQuantity>(CVC4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4C", " V");
configParam<OutputRangeParamQuantity>(CVD4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4D", " V");
- configParam(SELECT4_PARAM, 0.0f, 1.0f, 0.0f, "Select 4");
+ configButton(SELECT4_PARAM, "Select 4");
setInputIDs(CLOCK_INPUT, SELECT_INPUT);
+ configInput(CLOCK_INPUT, "Clock");
+ configInput(SELECT_INPUT, "Select CV");
+ configInput(SELECT1_INPUT, "Select 1 trigger");
+ configInput(SELECT2_INPUT, "Select 2 trigger");
+ configInput(SELECT3_INPUT, "Select 3 trigger");
+ configInput(SELECT4_INPUT, "Select 4 trigger");
+
+ configOutput(A_OUTPUT, "Sequence A");
+ configOutput(B_OUTPUT, "Sequence B");
+ configOutput(C_OUTPUT, "Sequence C");
+ configOutput(D_OUTPUT, "Sequence D");
+ configOutput(SELECT_ALL_OUTPUT, "Step change trigger");
+ configOutput(SELECT1_OUTPUT, "Select 1 trigger");
+ configOutput(SELECT2_OUTPUT, "Select 2 trigger");
+ configOutput(SELECT3_OUTPUT, "Select 3 trigger");
+ configOutput(SELECT4_OUTPUT, "Select 4 trigger");
+
setLocalElements({
new PgmrStep(params[CVA1_PARAM], params[CVB1_PARAM], params[CVC1_PARAM], params[CVD1_PARAM], lights[SELECT1_LIGHT], params[SELECT1_PARAM], inputs[SELECT1_INPUT], outputs[SELECT1_OUTPUT]),
new PgmrStep(params[CVA2_PARAM], params[CVB2_PARAM], params[CVC2_PARAM], params[CVD2_PARAM], lights[SELECT2_LIGHT], params[SELECT2_PARAM], inputs[SELECT2_INPUT], outputs[SELECT2_OUTPUT]),
@@ -107,8 +124,8 @@ struct Pgmr : PgmrBase {
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void modulate() override;
void processAlways(const ProcessArgs& args) override;
void processChannel(const ProcessArgs& args, int c) override;
diff --git a/src/PgmrX.cpp b/src/PgmrX.cpp
@@ -105,10 +105,10 @@ struct PgmrXWidget : BGModuleWidget {
addOutput(createOutput<Port24>(select3OutputPosition, module, PgmrX::SELECT3_OUTPUT));
addOutput(createOutput<Port24>(select4OutputPosition, module, PgmrX::SELECT4_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(select1LightPosition, module, PgmrX::SELECT1_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(select2LightPosition, module, PgmrX::SELECT2_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(select3LightPosition, module, PgmrX::SELECT3_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(select4LightPosition, module, PgmrX::SELECT4_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(select1LightPosition, module, PgmrX::SELECT1_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(select2LightPosition, module, PgmrX::SELECT2_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(select3LightPosition, module, PgmrX::SELECT3_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(select4LightPosition, module, PgmrX::SELECT4_LIGHT));
}
};
diff --git a/src/PgmrX.hpp b/src/PgmrX.hpp
@@ -61,22 +61,32 @@ struct PgmrX : PgmrXBase, OutputRange {
configParam<OutputRangeParamQuantity>(CVB1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1B", " V");
configParam<OutputRangeParamQuantity>(CVC1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1C", " V");
configParam<OutputRangeParamQuantity>(CVD1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1D", " V");
- configParam(SELECT1_PARAM, 0.0f, 1.0f, 0.0f, "Select 1");
+ configButton(SELECT1_PARAM, "Select 1");
configParam<OutputRangeParamQuantity>(CVA2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2A", " V");
configParam<OutputRangeParamQuantity>(CVB2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2B", " V");
configParam<OutputRangeParamQuantity>(CVC2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2C", " V");
configParam<OutputRangeParamQuantity>(CVD2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2D", " V");
- configParam(SELECT2_PARAM, 0.0f, 1.0f, 0.0f, "Select 2");
+ configButton(SELECT2_PARAM, "Select 2");
configParam<OutputRangeParamQuantity>(CVA3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3A", " V");
configParam<OutputRangeParamQuantity>(CVB3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3B", " V");
configParam<OutputRangeParamQuantity>(CVC3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3C", " V");
configParam<OutputRangeParamQuantity>(CVD3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3D", " V");
- configParam(SELECT3_PARAM, 0.0f, 1.0f, 0.0f, "Select 3");
+ configButton(SELECT3_PARAM, "Select 3");
configParam<OutputRangeParamQuantity>(CVA4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4A", " V");
configParam<OutputRangeParamQuantity>(CVB4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4B", " V");
configParam<OutputRangeParamQuantity>(CVC4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4C", " V");
configParam<OutputRangeParamQuantity>(CVD4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4D", " V");
- configParam<OutputRangeParamQuantity>(SELECT4_PARAM, 0.0f, 1.0f, 0.0f, "Select 4");
+ configButton(SELECT4_PARAM, "Select 4");
+
+ configInput(SELECT1_INPUT, "Select 1 trigger");
+ configInput(SELECT2_INPUT, "Select 2 trigger");
+ configInput(SELECT3_INPUT, "Select 3 trigger");
+ configInput(SELECT4_INPUT, "Select 4 trigger");
+
+ configOutput(SELECT1_OUTPUT, "Select 1 trigger");
+ configOutput(SELECT2_OUTPUT, "Select 2 trigger");
+ configOutput(SELECT3_OUTPUT, "Select 3 trigger");
+ configOutput(SELECT4_OUTPUT, "Select 4 trigger");
setLocalElements({
new PgmrStep(params[CVA1_PARAM], params[CVB1_PARAM], params[CVC1_PARAM], params[CVD1_PARAM], lights[SELECT1_LIGHT], params[SELECT1_PARAM], inputs[SELECT1_INPUT], outputs[SELECT1_OUTPUT]),
diff --git a/src/PolyCon16.cpp b/src/PolyCon16.cpp
@@ -70,11 +70,7 @@ struct PolyCon16Widget : BGModuleWidget {
auto channel16LightPosition = Vec(83.75, 311.0);
// end generated by svg_widgets.rb
- {
- auto w = createParam<Knob16>(channelsParamPosition, module, PolyCon16::CHANNELS_PARAM);
- dynamic_cast<Knob*>(w)->snap = true;
- addParam(w);
- }
+ addParam(createParam<Knob16>(channelsParamPosition, module, PolyCon16::CHANNELS_PARAM));
addParam(createParam<Knob19>(channel1ParamPosition, module, PolyCon16::CHANNEL1_PARAM));
addParam(createParam<Knob19>(channel2ParamPosition, module, PolyCon16::CHANNEL2_PARAM));
addParam(createParam<Knob19>(channel3ParamPosition, module, PolyCon16::CHANNEL3_PARAM));
@@ -96,22 +92,22 @@ struct PolyCon16Widget : BGModuleWidget {
addOutput(createOutput<Port24>(outOutputPosition, module, PolyCon16::OUT_OUTPUT));
- addChild(createLight<TinyLight<GreenLight>>(channel1LightPosition, module, PolyCon16::CHANNEL1_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel2LightPosition, module, PolyCon16::CHANNEL2_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel3LightPosition, module, PolyCon16::CHANNEL3_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel4LightPosition, module, PolyCon16::CHANNEL4_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel5LightPosition, module, PolyCon16::CHANNEL5_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel6LightPosition, module, PolyCon16::CHANNEL6_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel7LightPosition, module, PolyCon16::CHANNEL7_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel8LightPosition, module, PolyCon16::CHANNEL8_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel9LightPosition, module, PolyCon16::CHANNEL9_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel10LightPosition, module, PolyCon16::CHANNEL10_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel11LightPosition, module, PolyCon16::CHANNEL11_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel12LightPosition, module, PolyCon16::CHANNEL12_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel13LightPosition, module, PolyCon16::CHANNEL13_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel14LightPosition, module, PolyCon16::CHANNEL14_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel15LightPosition, module, PolyCon16::CHANNEL15_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel16LightPosition, module, PolyCon16::CHANNEL16_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel1LightPosition, module, PolyCon16::CHANNEL1_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel2LightPosition, module, PolyCon16::CHANNEL2_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel3LightPosition, module, PolyCon16::CHANNEL3_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel4LightPosition, module, PolyCon16::CHANNEL4_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel5LightPosition, module, PolyCon16::CHANNEL5_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel6LightPosition, module, PolyCon16::CHANNEL6_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel7LightPosition, module, PolyCon16::CHANNEL7_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel8LightPosition, module, PolyCon16::CHANNEL8_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel9LightPosition, module, PolyCon16::CHANNEL9_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel10LightPosition, module, PolyCon16::CHANNEL10_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel11LightPosition, module, PolyCon16::CHANNEL11_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel12LightPosition, module, PolyCon16::CHANNEL12_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel13LightPosition, module, PolyCon16::CHANNEL13_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel14LightPosition, module, PolyCon16::CHANNEL14_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel15LightPosition, module, PolyCon16::CHANNEL15_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel16LightPosition, module, PolyCon16::CHANNEL16_LIGHT));
}
void contextMenu(Menu* menu) override {
diff --git a/src/PolyCon16.hpp b/src/PolyCon16.hpp
@@ -62,6 +62,7 @@ struct PolyCon16 : OutputRangeModule<BGModule> {
PolyCon16() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
configParam(CHANNELS_PARAM, 1.0f, 16.0f, 1.0f, "Polyphony channels");
+ paramQuantities[CHANNELS_PARAM]->snapEnabled = true;
configParam<OutputRangeParamQuantity>(CHANNEL1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1", " V");
configParam<OutputRangeParamQuantity>(CHANNEL2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2", " V");
configParam<OutputRangeParamQuantity>(CHANNEL3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3", " V");
@@ -78,6 +79,10 @@ struct PolyCon16 : OutputRangeModule<BGModule> {
configParam<OutputRangeParamQuantity>(CHANNEL14_PARAM, -1.0f, 1.0f, 0.0f, "Channel 14", " V");
configParam<OutputRangeParamQuantity>(CHANNEL15_PARAM, -1.0f, 1.0f, 0.0f, "Channel 15", " V");
configParam<OutputRangeParamQuantity>(CHANNEL16_PARAM, -1.0f, 1.0f, 0.0f, "Channel 16", " V");
+
+ configInput(CHANNELS_INPUT, "Channels CV");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
void processAll(const ProcessArgs& args) override;
diff --git a/src/PolyCon8.cpp b/src/PolyCon8.cpp
@@ -59,14 +59,14 @@ struct PolyCon8Widget : BGModuleWidget {
addOutput(createOutput<Port24>(outOutputPosition, module, PolyCon8::OUT_OUTPUT));
- addChild(createLight<TinyLight<GreenLight>>(channel1LightPosition, module, PolyCon8::CHANNEL1_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel2LightPosition, module, PolyCon8::CHANNEL2_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel3LightPosition, module, PolyCon8::CHANNEL3_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel4LightPosition, module, PolyCon8::CHANNEL4_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel5LightPosition, module, PolyCon8::CHANNEL5_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel6LightPosition, module, PolyCon8::CHANNEL6_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel7LightPosition, module, PolyCon8::CHANNEL7_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel8LightPosition, module, PolyCon8::CHANNEL8_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel1LightPosition, module, PolyCon8::CHANNEL1_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel2LightPosition, module, PolyCon8::CHANNEL2_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel3LightPosition, module, PolyCon8::CHANNEL3_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel4LightPosition, module, PolyCon8::CHANNEL4_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel5LightPosition, module, PolyCon8::CHANNEL5_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel6LightPosition, module, PolyCon8::CHANNEL6_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel7LightPosition, module, PolyCon8::CHANNEL7_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel8LightPosition, module, PolyCon8::CHANNEL8_LIGHT));
}
void contextMenu(Menu* menu) override {
diff --git a/src/PolyCon8.hpp b/src/PolyCon8.hpp
@@ -52,6 +52,8 @@ struct PolyCon8 : OutputRangeModule<PolyChannelsModule> {
configParam<OutputRangeParamQuantity>(CHANNEL6_PARAM, -1.0f, 1.0f, 0.0f, "Channel 6", " V");
configParam<OutputRangeParamQuantity>(CHANNEL7_PARAM, -1.0f, 1.0f, 0.0f, "Channel 7", " V");
configParam<OutputRangeParamQuantity>(CHANNEL8_PARAM, -1.0f, 1.0f, 0.0f, "Channel 8", " V");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
void processAll(const ProcessArgs& args) override;
diff --git a/src/PolyMult.cpp b/src/PolyMult.cpp
@@ -41,11 +41,7 @@ struct PolyMultWidget : BGModuleWidget {
auto out4OutputPosition = Vec(10.5, 252.0);
// end generated by svg_widgets.rb
- {
- auto w = createParam<Knob16>(channelsParamPosition, module, PolyMult::CHANNELS_PARAM);
- dynamic_cast<Knob*>(w)->snap = true;
- addParam(w);
- }
+ addParam(createParam<Knob16>(channelsParamPosition, module, PolyMult::CHANNELS_PARAM));
addInput(createInput<Port24>(channelsInputPosition, module, PolyMult::CHANNELS_INPUT));
addInput(createInput<Port24>(inInputPosition, module, PolyMult::IN_INPUT));
diff --git a/src/PolyMult.hpp b/src/PolyMult.hpp
@@ -29,6 +29,15 @@ struct PolyMult : BGModule {
PolyMult() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam(CHANNELS_PARAM, 1.0f, 16.0f, 1.0f, "Polyphony channels");
+ paramQuantities[CHANNELS_PARAM]->snapEnabled = true;
+
+ configInput(CHANNELS_INPUT, "Channels CV");
+ configInput(IN_INPUT, "Signal");
+
+ configOutput(OUT1_OUTPUT, "Signal");
+ configOutput(OUT2_OUTPUT, "Signal");
+ configOutput(OUT3_OUTPUT, "Signal");
+ configOutput(OUT4_OUTPUT, "Signal");
}
void processAll(const ProcessArgs& args) override;
diff --git a/src/PolyOff16.cpp b/src/PolyOff16.cpp
@@ -3,14 +3,14 @@
#define OFFSET_FIRST "offset_first"
-json_t* PolyOff16::toJson(json_t* root) {
- root = OutputRangeModule<BGModule>::toJson(root);
+json_t* PolyOff16::saveToJson(json_t* root) {
+ root = OutputRangeModule<BGModule>::saveToJson(root);
json_object_set_new(root, OFFSET_FIRST, json_boolean(_offsetFirst));
return root;
}
-void PolyOff16::fromJson(json_t* root) {
- OutputRangeModule<BGModule>::fromJson(root);
+void PolyOff16::loadFromJson(json_t* root) {
+ OutputRangeModule<BGModule>::loadFromJson(root);
json_t* of = json_object_get(root, OFFSET_FIRST);
if (of) {
_offsetFirst = json_boolean_value(of);
@@ -188,11 +188,7 @@ struct PolyOff16Widget : BGModuleWidget {
addParam(createParam<Knob16>(scale15ParamPosition, module, PolyOff16::SCALE15_PARAM));
addParam(createParam<Knob16>(offset16ParamPosition, module, PolyOff16::OFFSET16_PARAM));
addParam(createParam<Knob16>(scale16ParamPosition, module, PolyOff16::SCALE16_PARAM));
- {
- auto w = createParam<Knob16>(channelsParamPosition, module, PolyOff16::CHANNELS_PARAM);
- dynamic_cast<Knob*>(w)->snap = true;
- addParam(w);
- }
+ addParam(createParam<Knob16>(channelsParamPosition, module, PolyOff16::CHANNELS_PARAM));
addInput(createInput<Port24>(cv1InputPosition, module, PolyOff16::CV1_INPUT));
addInput(createInput<Port24>(cv2InputPosition, module, PolyOff16::CV2_INPUT));
@@ -214,22 +210,22 @@ struct PolyOff16Widget : BGModuleWidget {
addOutput(createOutput<Port24>(outOutputPosition, module, PolyOff16::OUT_OUTPUT));
- addChild(createLight<TinyLight<GreenLight>>(channel1LightPosition, module, PolyOff16::CHANNEL1_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel2LightPosition, module, PolyOff16::CHANNEL2_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel3LightPosition, module, PolyOff16::CHANNEL3_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel4LightPosition, module, PolyOff16::CHANNEL4_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel5LightPosition, module, PolyOff16::CHANNEL5_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel6LightPosition, module, PolyOff16::CHANNEL6_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel7LightPosition, module, PolyOff16::CHANNEL7_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel8LightPosition, module, PolyOff16::CHANNEL8_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel9LightPosition, module, PolyOff16::CHANNEL9_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel10LightPosition, module, PolyOff16::CHANNEL10_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel11LightPosition, module, PolyOff16::CHANNEL11_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel12LightPosition, module, PolyOff16::CHANNEL12_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel13LightPosition, module, PolyOff16::CHANNEL13_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel14LightPosition, module, PolyOff16::CHANNEL14_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel15LightPosition, module, PolyOff16::CHANNEL15_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel16LightPosition, module, PolyOff16::CHANNEL16_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel1LightPosition, module, PolyOff16::CHANNEL1_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel2LightPosition, module, PolyOff16::CHANNEL2_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel3LightPosition, module, PolyOff16::CHANNEL3_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel4LightPosition, module, PolyOff16::CHANNEL4_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel5LightPosition, module, PolyOff16::CHANNEL5_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel6LightPosition, module, PolyOff16::CHANNEL6_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel7LightPosition, module, PolyOff16::CHANNEL7_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel8LightPosition, module, PolyOff16::CHANNEL8_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel9LightPosition, module, PolyOff16::CHANNEL9_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel10LightPosition, module, PolyOff16::CHANNEL10_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel11LightPosition, module, PolyOff16::CHANNEL11_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel12LightPosition, module, PolyOff16::CHANNEL12_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel13LightPosition, module, PolyOff16::CHANNEL13_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel14LightPosition, module, PolyOff16::CHANNEL14_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel15LightPosition, module, PolyOff16::CHANNEL15_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel16LightPosition, module, PolyOff16::CHANNEL16_LIGHT));
}
void contextMenu(Menu* menu) override {
diff --git a/src/PolyOff16.hpp b/src/PolyOff16.hpp
@@ -128,10 +128,31 @@ struct PolyOff16 : OutputRangeModule<BGModule> {
configParam<OutputRangeParamQuantity>(OFFSET16_PARAM, -1.0f, 1.0f, 0.0f, "Channel 16 offset", " V");
configParam(SCALE16_PARAM, -1.0f, 1.0f, 1.0f, "Channel 16 scale", "%", 0.0f, 100.0f);
configParam(CHANNELS_PARAM, 1.0f, 16.0f, 1.0f, "Polyphony channels");
+ paramQuantities[CHANNELS_PARAM]->snapEnabled = true;
+
+ configInput(CV1_INPUT, "Channel 1");
+ configInput(CV2_INPUT, "Channel 2");
+ configInput(CV3_INPUT, "Channel 3");
+ configInput(CV4_INPUT, "Channel 4");
+ configInput(CV5_INPUT, "Channel 5");
+ configInput(CV6_INPUT, "Channel 6");
+ configInput(CV7_INPUT, "Channel 7");
+ configInput(CV8_INPUT, "Channel 8");
+ configInput(CV9_INPUT, "Channel 9");
+ configInput(CV10_INPUT, "Channel 10");
+ configInput(CV11_INPUT, "Channel 11");
+ configInput(CV12_INPUT, "Channel 12");
+ configInput(CV13_INPUT, "Channel 13");
+ configInput(CV14_INPUT, "Channel 14");
+ configInput(CV15_INPUT, "Channel 15");
+ configInput(CV16_INPUT, "Channel 16");
+ configInput(IN_INPUT, "Signal");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void processAll(const ProcessArgs& args) override;
};
diff --git a/src/PolyOff8.cpp b/src/PolyOff8.cpp
@@ -3,14 +3,14 @@
#define OFFSET_FIRST "offset_first"
-json_t* PolyOff8::toJson(json_t* root) {
- root = OutputRangeModule<BGModule>::toJson(root);
+json_t* PolyOff8::saveToJson(json_t* root) {
+ root = OutputRangeModule<BGModule>::saveToJson(root);
json_object_set_new(root, OFFSET_FIRST, json_boolean(_offsetFirst));
return root;
}
-void PolyOff8::fromJson(json_t* root) {
- OutputRangeModule<BGModule>::fromJson(root);
+void PolyOff8::loadFromJson(json_t* root) {
+ OutputRangeModule<BGModule>::loadFromJson(root);
json_t* of = json_object_get(root, OFFSET_FIRST);
if (of) {
_offsetFirst = json_boolean_value(of);
@@ -140,11 +140,7 @@ struct PolyOff8Widget : BGModuleWidget {
addParam(createParam<Knob16>(scale7ParamPosition, module, PolyOff8::SCALE7_PARAM));
addParam(createParam<Knob16>(offset8ParamPosition, module, PolyOff8::OFFSET8_PARAM));
addParam(createParam<Knob16>(scale8ParamPosition, module, PolyOff8::SCALE8_PARAM));
- {
- auto w = createParam<Knob16>(channelsParamPosition, module, PolyOff8::CHANNELS_PARAM);
- dynamic_cast<Knob*>(w)->snap = true;
- addParam(w);
- }
+ addParam(createParam<Knob16>(channelsParamPosition, module, PolyOff8::CHANNELS_PARAM));
addInput(createInput<Port24>(cv1InputPosition, module, PolyOff8::CV1_INPUT));
addInput(createInput<Port24>(cv2InputPosition, module, PolyOff8::CV2_INPUT));
@@ -158,14 +154,14 @@ struct PolyOff8Widget : BGModuleWidget {
addOutput(createOutput<Port24>(outOutputPosition, module, PolyOff8::OUT_OUTPUT));
- addChild(createLight<TinyLight<GreenLight>>(channel1LightPosition, module, PolyOff8::CHANNEL1_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel2LightPosition, module, PolyOff8::CHANNEL2_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel3LightPosition, module, PolyOff8::CHANNEL3_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel4LightPosition, module, PolyOff8::CHANNEL4_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel5LightPosition, module, PolyOff8::CHANNEL5_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel6LightPosition, module, PolyOff8::CHANNEL6_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel7LightPosition, module, PolyOff8::CHANNEL7_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(channel8LightPosition, module, PolyOff8::CHANNEL8_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel1LightPosition, module, PolyOff8::CHANNEL1_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel2LightPosition, module, PolyOff8::CHANNEL2_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel3LightPosition, module, PolyOff8::CHANNEL3_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel4LightPosition, module, PolyOff8::CHANNEL4_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel5LightPosition, module, PolyOff8::CHANNEL5_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel6LightPosition, module, PolyOff8::CHANNEL6_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel7LightPosition, module, PolyOff8::CHANNEL7_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(channel8LightPosition, module, PolyOff8::CHANNEL8_LIGHT));
}
void contextMenu(Menu* menu) override {
diff --git a/src/PolyOff8.hpp b/src/PolyOff8.hpp
@@ -80,10 +80,23 @@ struct PolyOff8 : OutputRangeModule<BGModule> {
configParam<OutputRangeParamQuantity>(OFFSET8_PARAM, -1.0f, 1.0f, 0.0f, "Channel 8 offset", " V");
configParam(SCALE8_PARAM, -1.0f, 1.0f, 1.0f, "Channel 8 scale", "%", 0.0f, 100.0f);
configParam(CHANNELS_PARAM, 1.0f, 8.0f, 1.0f, "Polyphony channels");
+ paramQuantities[CHANNELS_PARAM]->snapEnabled = true;
+
+ configInput(CV1_INPUT, "Channel 1");
+ configInput(CV2_INPUT, "Channel 2");
+ configInput(CV3_INPUT, "Channel 3");
+ configInput(CV4_INPUT, "Channel 4");
+ configInput(CV5_INPUT, "Channel 5");
+ configInput(CV6_INPUT, "Channel 6");
+ configInput(CV7_INPUT, "Channel 7");
+ configInput(CV8_INPUT, "Channel 8");
+ configInput(IN_INPUT, "Signal");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void processAll(const ProcessArgs& args) override;
};
diff --git a/src/Pressor.cpp b/src/Pressor.cpp
@@ -37,12 +37,12 @@ void Pressor::sampleRateChange() {
}
}
-json_t* Pressor::toJson(json_t* root) {
+json_t* Pressor::saveToJson(json_t* root) {
json_object_set_new(root, THRESHOLD_RANGE, json_real(_thresholdRange));
return root;
}
-void Pressor::fromJson(json_t* root) {
+void Pressor::loadFromJson(json_t* root) {
json_t* tr = json_object_get(root, THRESHOLD_RANGE);
if (tr) {
_thresholdRange = std::max(0.0f, (float)json_real_value(tr));
@@ -192,7 +192,7 @@ void Pressor::processChannel(const ProcessArgs& args, int c) {
}
struct PressorWidget : BGModuleWidget {
- struct CompressionDisplay : OpaqueWidget {
+ struct CompressionDisplay : LightEmittingWidget<OpaqueWidget> {
struct Level {
float db;
NVGcolor color;
@@ -212,27 +212,42 @@ struct PressorWidget : BGModuleWidget {
}
}
+ bool isLit() override {
+ return _module && !_module->isBypassed();
+ }
+
void draw(const DrawArgs& args) override {
+ nvgSave(args.vg);
+ for (int i = 0; i < 80; i += 5) {
+ drawBox(args, i);
+ nvgFillColor(args.vg, bgColor);
+ nvgFill(args.vg);
+ }
+ nvgRestore(args.vg);
+ }
+
+ void drawLit(const DrawArgs& args) override {
float compressionDb = 0.0f;
- if (_module) {
+ if (_module && !_module->isBypassed()) {
compressionDb = _module->_compressionDb;
}
nvgSave(args.vg);
for (int i = 0; i < 80; i += 5) {
const Level& l = _levels.at(i / 5);
-
- nvgBeginPath(args.vg);
- nvgRect(args.vg, 3, i + 1, 5, 4);
- nvgFillColor(args.vg, bgColor);
- nvgFill(args.vg);
if (compressionDb > l.db) {
+ drawBox(args, i);
nvgFillColor(args.vg, l.color);
nvgFill(args.vg);
}
}
nvgRestore(args.vg);
}
+
+ void drawBox(const DrawArgs& args, int offset) {
+ nvgBeginPath(args.vg);
+ nvgRect(args.vg, 3, offset + 1, 5, 4);
+ }
};
static constexpr int hp = 15;
diff --git a/src/Pressor.hpp b/src/Pressor.hpp
@@ -90,14 +90,30 @@ struct Pressor : BGModule {
configParam(OUTPUT_GAIN_PARAM, 0.0f, 1.0f, 0.0f, "Output gain", " dB", 0.0f, 24.0f);
configParam(INPUT_GAIN_PARAM, -1.0f, 1.0f, 0.0f, "Input gain", " dB", 0.0f, 12.0f);
configParam(DETECTOR_MIX_PARAM, -1.0f, 1.0f, 0.0f, "Detector mix", "%", 0.0f, 100.0f);
- configParam(MODE_PARAM, 0.0f, 1.0f, 1.0f, "Mode");
- configParam(DECTECTOR_MODE_PARAM, 0.0f, 1.0f, 1.0f, "Dectector mode");
- configParam(KNEE_PARAM, 0.0f, 1.0f, 1.0f, "Knee");
+ configSwitch(MODE_PARAM, 0.0f, 1.0f, 1.0f, "Mode", {"Noise gate", "Compressor"});
+ configSwitch(DECTECTOR_MODE_PARAM, 0.0f, 1.0f, 1.0f, "Dectector mode", {"Peak", "RMS"});
+ configSwitch(KNEE_PARAM, 0.0f, 1.0f, 1.0f, "Knee", {"Hard", "Soft"});
+ configBypass(LEFT_INPUT, LEFT_OUTPUT);
+ configBypass(RIGHT_INPUT, RIGHT_OUTPUT);
+
+ configInput(LEFT_INPUT, "Left signal");
+ configInput(SIDECHAIN_INPUT, "Sidechain");
+ configInput(THRESHOLD_INPUT, "Threshold CV");
+ configInput(RATIO_INPUT, "Ratio CV");
+ configInput(RIGHT_INPUT, "Right signal");
+ configInput(ATTACK_INPUT, "Attack CV");
+ configInput(RELEASE_INPUT, "Release CV");
+ configInput(INPUT_GAIN_INPUT, "Input gain CV");
+ configInput(OUTPUT_GAIN_INPUT, "Output gain CV");
+
+ configOutput(ENVELOPE_OUTPUT, "Envelope");
+ configOutput(LEFT_OUTPUT, "Left signal");
+ configOutput(RIGHT_OUTPUT, "Right signal");
}
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
bool active() override;
int channels() override;
void addChannel(int c) override;
diff --git a/src/Pulse.cpp b/src/Pulse.cpp
@@ -3,14 +3,14 @@
#define LINEAR_MODE "linear_mode"
-json_t* Pulse::toJson(json_t* root) {
- root = VCOBase::toJson(root);
+json_t* Pulse::saveToJson(json_t* root) {
+ root = VCOBase::saveToJson(root);
json_object_set_new(root, LINEAR_MODE, json_boolean(_linearMode));
return root;
}
-void Pulse::fromJson(json_t* root) {
- VCOBase::fromJson(root);
+void Pulse::loadFromJson(json_t* root) {
+ VCOBase::loadFromJson(root);
json_t* l = json_object_get(root, LINEAR_MODE);
if (l) {
_linearMode = json_is_true(l);
diff --git a/src/Pulse.hpp b/src/Pulse.hpp
@@ -39,13 +39,19 @@ struct Pulse : VCOBase {
{
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam<VCOFrequencyParamQuantity>(FREQUENCY_PARAM, -3.0f, 6.0f, 0.0f, "Frequency", " Hz");
- configParam(SLOW_PARAM, 0.0f, 1.0f, 0.0f, "Slow mode");
+ configButton(SLOW_PARAM, "Slow mode");
configParam(PW_PARAM, -1.0f, 1.0f, 0.0f, "Pulse width", "%", 0.0f, 100.0f*0.5f*(1.0f - 2.0f * SquareOscillator::minPulseWidth), 50.0f);
configParam(PWM_PARAM, -1.0f, 1.0f, 0.0f, "Pulse width CV amount");
+
+ configInput(PITCH_INPUT, "Pitch (1V/octave)");
+ configInput(PWM_INPUT, "Pulse width CV");
+ configInput(SYNC_INPUT, "Sync");
+
+ configOutput(OUT_OUTPUT, "Pulse");
}
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
bool active() override;
void addChannel(int c) override;
void modulate() override;
diff --git a/src/RGate.cpp b/src/RGate.cpp
@@ -32,16 +32,16 @@ void RGate::sampleRateChange() {
_sampleTime = APP->engine->getSampleTime();
}
-json_t* RGate::toJson(json_t* root) {
- root = OutputRangeModule<BGModule>::toJson(root);
+json_t* RGate::saveToJson(json_t* root) {
+ root = OutputRangeModule<BGModule>::saveToJson(root);
json_object_set_new(root, RESET_MODE, json_integer(_resetMode));
json_object_set_new(root, INITIAL_CLOCK_SECONDS, json_real(_initialClockPeriod));
json_object_set_new(root, POLY_INPUT, json_integer(_polyInputID));
return root;
}
-void RGate::fromJson(json_t* root) {
- OutputRangeModule<BGModule>::fromJson(root);
+void RGate::loadFromJson(json_t* root) {
+ OutputRangeModule<BGModule>::loadFromJson(root);
json_t* rm = json_object_get(root, RESET_MODE);
if (rm) {
diff --git a/src/RGate.hpp b/src/RGate.hpp
@@ -67,14 +67,22 @@ struct RGate : OutputRangeModule<BGModule> {
configParam<RoundingParamQuantity<ScaledSquaringParamQuantity<63>>>(CLOCK_DIVIDE_PARAM, 0.0f, 1.0f, 0.0f, "Clock division", "", 0.0f, 1.0f, 1.0f);
configParam<RoundingParamQuantity<ScaledSquaringParamQuantity<63>>>(CLOCK_MULTIPLY_PARAM, 0.0f, 1.0f, 0.0f, "Clock multiplication", "", 0.0f, 1.0f, 1.0f);
+ configInput(LENGTH_INPUT, "Length CV");
+ configInput(CLOCK_DIVIDE_INPUT, "Clock divider CV");
+ configInput(RESET_INPUT, "Reset");
+ configInput(CLOCK_MULTIPLE_INPUT, "Clock multiplier CV");
+ configInput(CLOCK_INPUT, "Clock");
+
+ configOutput(GATE_OUTPUT, "Gate");
+
_rangeOffset = 1.0f;
_rangeScale = 5.0f;
}
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
bool active() override;
int channels() override;
void addChannel(int c) override;
diff --git a/src/Ranalyzer.cpp b/src/Ranalyzer.cpp
@@ -43,7 +43,7 @@ void Ranalyzer::sampleRateChange() {
}
}
-json_t* Ranalyzer::toJson(json_t* root) {
+json_t* Ranalyzer::saveToJson(json_t* root) {
frequencyPlotToJson(root);
frequencyRangeToJson(root);
amplitudePlotToJson(root);
@@ -86,7 +86,7 @@ json_t* Ranalyzer::toJson(json_t* root) {
return root;
}
-void Ranalyzer::fromJson(json_t* root) {
+void Ranalyzer::loadFromJson(json_t* root) {
frequencyPlotFromJson(root);
frequencyRangeFromJson(root);
amplitudePlotFromJson(root);
@@ -389,12 +389,7 @@ struct RanalyzerWidget : AnalyzerBaseWidget {
addParam(createParam<Button18>(triggerParamPosition, module, Ranalyzer::TRIGGER_PARAM));
addParam(createParam<IndicatorButtonGreen9>(exponentialParamPosition, module, Ranalyzer::EXPONENTIAL_PARAM));
addParam(createParam<IndicatorButtonGreen9>(loopParamPosition, module, Ranalyzer::LOOP_PARAM));
- {
- auto w = createParam<Knob16>(delayParamPosition, module, Ranalyzer::DELAY_PARAM);
- auto k = dynamic_cast<SvgKnob*>(w);
- k->snap = true;
- addParam(w);
- }
+ addParam(createParam<Knob16>(delayParamPosition, module, Ranalyzer::DELAY_PARAM));
addInput(createInput<Port24>(triggerInputPosition, module, Ranalyzer::TRIGGER_INPUT));
addInput(createInput<Port24>(testInputPosition, module, Ranalyzer::TEST_INPUT));
diff --git a/src/Ranalyzer.hpp b/src/Ranalyzer.hpp
@@ -117,10 +117,19 @@ struct Ranalyzer : AnalyzerBase {
{
configParam<FrequencyParamQuantity>(FREQUENCY1_PARAM, 0.0f, 1.0f, 0.0f, "Frequency 1", " Hz");
configParam<FrequencyParamQuantity>(FREQUENCY2_PARAM, 0.0f, 1.0f, 1.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, 0.0f, "Loop");
+ configButton(TRIGGER_PARAM, "Trigger");
+ configSwitch(EXPONENTIAL_PARAM, 0.0f, 1.0f, 1.0f, "Sweep", {"Linear", "Exponential"});
+ configSwitch(LOOP_PARAM, 0.0f, 1.0f, 0.0f, "Loop", {"Disabled", "Enabled"});
configParam(DELAY_PARAM, 2.0f, (float)maxResponseDelay, 2.0f, "Return sample delay");
+ paramQuantities[DELAY_PARAM]->snapEnabled = true;
+
+ configInput(TRIGGER_INPUT, "Trigger");
+ configInput(RETURN_INPUT, "Return signal");
+ configInput(TEST_INPUT, "Test signal");
+
+ configOutput(TRIGGER_OUTPUT, "Trigger");
+ configOutput(EOC_OUTPUT, "End-of-cycle trigger");
+ configOutput(SEND_OUTPUT, "Send signal");
_skinnable = false;
}
@@ -135,8 +144,8 @@ struct Ranalyzer : AnalyzerBase {
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void modulate() override;
void processAll(const ProcessArgs& args) override;
void setDisplayTraces(Traces traces);
diff --git a/src/Reftone.cpp b/src/Reftone.cpp
@@ -34,24 +34,27 @@ void Reftone::processAll(const ProcessArgs& args) {
}
}
-struct ReftoneDisplay : TransparentWidget {
+struct ReftoneDisplay : DisplayWidget {
const NVGcolor _textColor = nvgRGBA(0x00, 0xff, 0x00, 0xee);
Reftone* _module;
const Vec _size;
- std::shared_ptr<Font> _font;
+ std::string _fontPath;
ReftoneDisplay(
Reftone* module,
Vec size
)
- : _module(module)
+ : DisplayWidget(module)
+ , _module(module)
, _size(size)
- , _font(APP->window->loadFont(asset::plugin(pluginInstance, "res/fonts/inconsolata-bold.ttf")))
+ , _fontPath(asset::plugin(pluginInstance, "res/fonts/inconsolata-bold.ttf"))
{
}
void draw(const DrawArgs& args) override;
+ void drawLit(const DrawArgs& args) override;
+ void drawOnce(const DrawArgs& args, bool screenshot, bool lit) override;
void drawBackground(const DrawArgs& args);
void drawText(const DrawArgs& args, const char* s, float x, float y, int size);
void drawCenteredText(const DrawArgs& args, const char* s, float y, int size);
@@ -59,11 +62,23 @@ struct ReftoneDisplay : TransparentWidget {
};
void ReftoneDisplay::draw(const DrawArgs& args) {
+ if (!isLit()) {
+ drawOnce(args, isScreenshot(), false);
+ }
+}
+
+void ReftoneDisplay::drawLit(const DrawArgs& args) {
+ if (isLit()) {
+ drawOnce(args, false, true);
+ }
+}
+
+void ReftoneDisplay::drawOnce(const DrawArgs& args, bool screenshot, bool lit) {
int mPitch = 9;
int mOctave = 4;
float mFine = 0.0f;
float mFrequency = 440.0f;
- if (_module) {
+ if (!screenshot) {
mPitch = _module->_pitch;
mOctave = _module->_octave;
mFine = _module->_fine;
@@ -131,17 +146,24 @@ void ReftoneDisplay::draw(const DrawArgs& args) {
}
}
- drawBackground(args);
- if (sharpFlat) {
- drawText(args, pitch, 3, 20, 28);
- drawText(args, sharpFlat, 16, 12, 16);
- drawText(args, octave.c_str(), 22, 20, 28);
+ nvgSave(args.vg);
+ if (!screenshot && !lit) {
+ drawBackground(args);
}
else {
- drawCenteredText(args, (pitch + octave).c_str(), 20, 28);
+ drawBackground(args);
+ if (sharpFlat) {
+ drawText(args, pitch, 3, 20, 28);
+ drawText(args, sharpFlat, 16, 12, 16);
+ drawText(args, octave.c_str(), 22, 20, 28);
+ }
+ else {
+ drawCenteredText(args, (pitch + octave).c_str(), 20, 28);
+ }
+ drawCenteredText(args, fine.c_str(), 32.5, 14);
+ drawCenteredText(args, frequency.c_str(), 45, 14);
}
- drawCenteredText(args, fine.c_str(), 32.5, 14);
- drawCenteredText(args, frequency.c_str(), 45, 14);
+ nvgRestore(args.vg);
}
void ReftoneDisplay::drawBackground(const DrawArgs& args) {
@@ -156,10 +178,11 @@ void ReftoneDisplay::drawBackground(const DrawArgs& args) {
}
void ReftoneDisplay::drawText(const DrawArgs& args, const char* s, float x, float y, int size) {
+ std::shared_ptr<Font> font = APP->window->loadFont(_fontPath);
nvgSave(args.vg);
nvgTranslate(args.vg, x, y);
nvgFontSize(args.vg, size);
- nvgFontFaceId(args.vg, _font->handle);
+ nvgFontFaceId(args.vg, font->handle);
nvgFillColor(args.vg, _textColor);
nvgText(args.vg, 0, 0, s, NULL);
nvgRestore(args.vg);
@@ -208,16 +231,8 @@ struct ReftoneWidget : BGModuleWidget {
auto outOutputPosition = Vec(10.5, 274.0);
// end generated by svg_widgets.rb
- {
- auto w = createParam<Knob26>(pitchParamPosition, module, Reftone::PITCH_PARAM);
- dynamic_cast<Knob*>(w)->snap = true;
- addParam(w);
- }
- {
- auto w = createParam<Knob26>(octaveParamPosition, module, Reftone::OCTAVE_PARAM);
- dynamic_cast<Knob*>(w)->snap = true;
- addParam(w);
- }
+ addParam(createParam<Knob26>(pitchParamPosition, module, Reftone::PITCH_PARAM));
+ addParam(createParam<Knob26>(octaveParamPosition, module, Reftone::OCTAVE_PARAM));
addParam(createParam<Knob26>(fineParamPosition, module, Reftone::FINE_PARAM));
addOutput(createOutput<Port24>(cvOutputPosition, module, Reftone::CV_OUTPUT));
diff --git a/src/Reftone.hpp b/src/Reftone.hpp
@@ -38,9 +38,14 @@ struct Reftone : BGModule {
Reftone() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam(PITCH_PARAM, 0.0f, 11.0f, 9.0f, "Pitch");
+ paramQuantities[PITCH_PARAM]->snapEnabled = true;
configParam(OCTAVE_PARAM, 1.0f, 8.0f, 4.0f, "Octave");
+ paramQuantities[OCTAVE_PARAM]->snapEnabled = true;
configParam(FINE_PARAM, -0.99f, 0.99f, 0.0f, "Fine tune", " cents", 0.0f, 100.0f);
+ configOutput(CV_OUTPUT, "Pitch (1V/octave)");
+ configOutput(OUT_OUTPUT, "Sine signal");
+
sampleRateChange();
}
diff --git a/src/SampleHold.cpp b/src/SampleHold.cpp
@@ -16,7 +16,7 @@ void SampleHold::reset() {
}
}
-json_t* SampleHold::toJson(json_t* root) {
+json_t* SampleHold::saveToJson(json_t* root) {
json_object_set_new(root, POLY_INPUT, json_integer(_polyInputID));
json_object_set_new(root, NOISE_TYPE, json_integer((int)_noiseType));
json_object_set_new(root, RANGE_OFFSET, json_real(_rangeOffset));
@@ -25,7 +25,7 @@ json_t* SampleHold::toJson(json_t* root) {
return root;
}
-void SampleHold::fromJson(json_t* root) {
+void SampleHold::loadFromJson(json_t* root) {
json_t* p = json_object_get(root, POLY_INPUT);
if (p) {
_polyInputID = json_integer_value(p);
diff --git a/src/SampleHold.hpp b/src/SampleHold.hpp
@@ -61,17 +61,22 @@ struct SampleHold : BGModule {
SampleHold() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
- configParam(TRIGGER1_PARAM, 0.0f, 10.0f, 0.0f, "Trigger 1");
- configParam(TRIGGER2_PARAM, 0.0f, 10.0f, 0.0f, "Trigger 2");
- configParam(TRACK1_PARAM, 0.0f, 1.0f, 0.0f, "Track 1");
- configParam(TRACK2_PARAM, 0.0f, 1.0f, 0.0f, "Track 2");
- configParam(INVERT1_PARAM, 0.0f, 1.0f, 0.0f, "Invert 1");
- configParam(INVERT2_PARAM, 0.0f, 1.0f, 0.0f, "Invert 2");
+ configButton(TRIGGER1_PARAM, "Trigger 1");
+ configButton(TRIGGER2_PARAM, "Trigger 2");
+ configSwitch(TRACK1_PARAM, 0.0f, 1.0f, 0.0f, "Track 1", {"Disabled", "Enabled"});
+ configSwitch(TRACK2_PARAM, 0.0f, 1.0f, 0.0f, "Track 2", {"Disabled", "Enabled"});
+ configSwitch(INVERT1_PARAM, 0.0f, 1.0f, 0.0f, "Invert 1", {"Disabled", "Enabled"});
+ configSwitch(INVERT2_PARAM, 0.0f, 1.0f, 0.0f, "Invert 2", {"Disabled", "Enabled"});
+
+ configInput(TRIGGER1_INPUT, "Trigger 1");
+ configInput(IN1_INPUT, "Signal 1");
+ configInput(TRIGGER2_INPUT, "Trigger 2");
+ configInput(IN2_INPUT, "Signal 2");
}
void reset() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void modulateChannel(int c) override;
void processAll(const ProcessArgs& args) override;
void handleChannel(
diff --git a/src/Shaper.cpp b/src/Shaper.cpp
@@ -140,10 +140,10 @@ struct ShaperWidget : TriggerOnLoadModuleWidget {
addInput(createInput<Port24>(signalInputPosition, module, Shaper::SIGNAL_INPUT));
addOutput(createOutput<Port24>(signalOutputPosition, module, Shaper::SIGNAL_OUTPUT));
- addChild(createLight<TinyLight<GreenLight>>(attackLightPosition, module, Shaper::ATTACK_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(onLightPosition, module, Shaper::ON_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(decayLightPosition, module, Shaper::DECAY_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(offLightPosition, module, Shaper::OFF_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(attackLightPosition, module, Shaper::ATTACK_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(onLightPosition, module, Shaper::ON_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(decayLightPosition, module, Shaper::DECAY_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(offLightPosition, module, Shaper::OFF_LIGHT));
}
};
diff --git a/src/Shaper.hpp b/src/Shaper.hpp
@@ -9,7 +9,7 @@ extern Model* modelShaper;
namespace bogaudio {
struct Shaper : TriggerOnLoadModule {
- enum ParamIds {
+ enum ParamsIds {
ATTACK_PARAM,
ON_PARAM,
DECAY_PARAM,
@@ -22,13 +22,13 @@ struct Shaper : TriggerOnLoadModule {
NUM_PARAMS
};
- enum InputIds {
+ enum InputsIds {
SIGNAL_INPUT,
TRIGGER_INPUT,
NUM_INPUTS
};
- enum OutputIds {
+ enum OutputsIds {
SIGNAL_OUTPUT,
ENV_OUTPUT,
INV_OUTPUT,
@@ -36,7 +36,7 @@ struct Shaper : TriggerOnLoadModule {
NUM_OUTPUTS
};
- enum LightIds {
+ enum LightsIds {
ATTACK_LIGHT,
ON_LIGHT,
DECAY_LIGHT,
@@ -58,9 +58,17 @@ struct Shaper : TriggerOnLoadModule {
configParam<EnvelopeSegmentParamQuantity>(OFF_PARAM, 0.0f, 1.0f, 0.07071f, "Off", " s");
configParam(ENV_PARAM, 0.0f, 1.0f, 1.0f, "Env", "%", 0.0f, 100.0f);
configParam(SIGNAL_PARAM, 0.0f, 1.0f, 0.1f, "Signal", "x", 10.0f);
- configParam(TRIGGER_PARAM, 0.0f, 1.0f, 0.0f, "Trigger");
- configParam(SPEED_PARAM, 0.0f, 1.0f, 1.0f, "Speed");
- configParam(LOOP_PARAM, 0.0f, 1.0f, 1.0f, "Loop");
+ configButton(TRIGGER_PARAM, "Trigger");
+ configSwitch(SPEED_PARAM, 0.0f, 1.0f, 1.0f, "Speed", {"Slow", "Normal"});
+ configSwitch(LOOP_PARAM, 0.0f, 1.0f, 1.0f, "Loop", {"Loop", "Stop"});
+
+ configInput(SIGNAL_INPUT, "Signal");
+ configInput(TRIGGER_INPUT, "Trigger");
+
+ configOutput(SIGNAL_OUTPUT, "Signal");
+ configOutput(ENV_OUTPUT, "Envelope");
+ configOutput(INV_OUTPUT, "Inverted envelope");
+ configOutput(TRIGGER_OUTPUT, "Trigger");
}
void reset() override;
diff --git a/src/ShaperPlus.cpp b/src/ShaperPlus.cpp
@@ -162,10 +162,10 @@ struct ShaperPlusWidget : TriggerOnLoadModuleWidget {
addOutput(createOutput<Port24>(decayOutputPosition, module, ShaperPlus::DECAY_OUTPUT));
addOutput(createOutput<Port24>(offOutputPosition, module, ShaperPlus::OFF_OUTPUT));
- addChild(createLight<TinyLight<GreenLight>>(attackLightPosition, module, ShaperPlus::ATTACK_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(onLightPosition, module, ShaperPlus::ON_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(decayLightPosition, module, ShaperPlus::DECAY_LIGHT));
- addChild(createLight<TinyLight<GreenLight>>(offLightPosition, module, ShaperPlus::OFF_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(attackLightPosition, module, ShaperPlus::ATTACK_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(onLightPosition, module, ShaperPlus::ON_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(decayLightPosition, module, ShaperPlus::DECAY_LIGHT));
+ addChild(createLight<BGTinyLight<GreenLight>>(offLightPosition, module, ShaperPlus::OFF_LIGHT));
}
};
diff --git a/src/ShaperPlus.hpp b/src/ShaperPlus.hpp
@@ -9,7 +9,7 @@ extern Model* modelShaperPlus;
namespace bogaudio {
struct ShaperPlus : TriggerOnLoadModule {
- enum ParamIds {
+ enum ParamsIds {
ATTACK_PARAM,
ON_PARAM,
DECAY_PARAM,
@@ -22,7 +22,7 @@ struct ShaperPlus : TriggerOnLoadModule {
NUM_PARAMS
};
- enum InputIds {
+ enum InputsIds {
SIGNAL_INPUT,
TRIGGER_INPUT,
ATTACK_INPUT,
@@ -34,7 +34,7 @@ struct ShaperPlus : TriggerOnLoadModule {
NUM_INPUTS
};
- enum OutputIds {
+ enum OutputsIds {
SIGNAL_OUTPUT,
ENV_OUTPUT,
INV_OUTPUT,
@@ -46,7 +46,7 @@ struct ShaperPlus : TriggerOnLoadModule {
NUM_OUTPUTS
};
- enum LightIds {
+ enum LightsIds {
ATTACK_LIGHT,
ON_LIGHT,
DECAY_LIGHT,
@@ -68,9 +68,27 @@ struct ShaperPlus : TriggerOnLoadModule {
configParam<EnvelopeSegmentParamQuantity>(OFF_PARAM, 0.0f, 1.0f, 0.07071f, "Off", " s");
configParam(ENV_PARAM, 0.0f, 1.0f, 1.0f, "Env", "%", 0.0f, 100.0f);
configParam(SIGNAL_PARAM, 0.0f, 1.0f, 0.1f, "Signal", "x", 10.0f);
- configParam(TRIGGER_PARAM, 0.0f, 1.0f, 0.0f, "Trigger");
- configParam(SPEED_PARAM, 0.0f, 1.0f, 1.0f, "Speed");
- configParam(LOOP_PARAM, 0.0f, 1.0f, 1.0f, "Loop");
+ configButton(TRIGGER_PARAM, "Trigger");
+ configSwitch(SPEED_PARAM, 0.0f, 1.0f, 1.0f, "Speed", {"Slow", "Normal"});
+ configSwitch(LOOP_PARAM, 0.0f, 1.0f, 1.0f, "Loop", {"Loop", "Stop"});
+
+ configInput(SIGNAL_INPUT, "Signal");
+ configInput(TRIGGER_INPUT, "Trigger");
+ configInput(ATTACK_INPUT, "Attack CV");
+ configInput(ON_INPUT, "On CV");
+ configInput(DECAY_INPUT, "Decay CV");
+ configInput(OFF_INPUT, "Off CV");
+ configInput(ENV_INPUT, "Envelope level CV");
+ configInput(SIGNALCV_INPUT, "Output signal level CV");
+
+ configOutput(SIGNAL_OUTPUT, "Signal");
+ configOutput(ENV_OUTPUT, "Envelope");
+ configOutput(INV_OUTPUT, "Inverted envelope");
+ configOutput(TRIGGER_OUTPUT, "Trigger");
+ configOutput(ATTACK_OUTPUT, "Attack stage gate");
+ configOutput(ON_OUTPUT, "On stage gate");
+ configOutput(DECAY_OUTPUT, "Decay stage gate");
+ configOutput(OFF_OUTPUT, "Off stage gate");
}
void reset() override;
diff --git a/src/Sine.cpp b/src/Sine.cpp
@@ -5,16 +5,16 @@
#define FM_MODE "fm_mode"
#define LINEAR_MODE "linear_mode"
-json_t* Sine::toJson(json_t* root) {
- root = VCOBase::toJson(root);
+json_t* Sine::saveToJson(json_t* root) {
+ root = VCOBase::saveToJson(root);
json_object_set_new(root, WAVE, json_integer((int)_wave));
json_object_set_new(root, FM_MODE, json_boolean(_fmLinearMode));
json_object_set_new(root, LINEAR_MODE, json_boolean(_linearMode));
return root;
}
-void Sine::fromJson(json_t* root) {
- VCOBase::fromJson(root);
+void Sine::loadFromJson(json_t* root) {
+ VCOBase::loadFromJson(root);
json_t* w = json_object_get(root, WAVE);
if (w) {
diff --git a/src/Sine.hpp b/src/Sine.hpp
@@ -53,13 +53,20 @@ struct Sine : VCOBase {
{
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam<VCOFrequencyParamQuantity>(FREQUENCY_PARAM, -3.0f, 6.0f, 0.0f, "Frequency", " Hz");
- configParam(SLOW_PARAM, 0.0f, 1.0f, 0.0f, "Slow mode");
+ configButton(SLOW_PARAM, "Slow mode");
configParam(FM_DEPTH_PARAM, 0.0f, 1.0f, 0.0f, "FM depth", "%", 0.0f, 100.0f);
configParam(PHASE_PARAM, -1.0f, 1.0f, 0.0f, "Phase offset", "º", 0.0f, 180.0f);
+
+ configInput(PITCH_INPUT, "Pitch (1V/octave)");
+ configInput(FM_INPUT, "Frequency modulation");
+ configInput(PHASE_INPUT, "Phase CV");
+ configInput(SYNC_INPUT, "Sync");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
bool active() override;
void modulate() override;
void modulateChannel(int c) override;
diff --git a/src/Slew.hpp b/src/Slew.hpp
@@ -37,7 +37,14 @@ struct Slew : BGModule {
configParam(RISE_SHAPE_PARAM, -1.0f, 1.0f, 0.0f, "Rise shape");
configParam<EnvelopeSegmentParamQuantity>(FALL_PARAM, 0.0f, 1.0f, 0.31623f, "Fall", " s");
configParam(FALL_SHAPE_PARAM, -1.0f, 1.0f, 0.0f, "Fall shape");
- configParam(SLOW_PARAM, 0.0f, 1.0f, 0.0f, "Slow mode");
+ configSwitch(SLOW_PARAM, 0.0f, 1.0f, 0.0f, "Slow mode", {"Disabled", "Enabled"});
+ configBypass(IN_INPUT, OUT_OUTPUT);
+
+ configInput(RISE_INPUT, "Rise CV");
+ configInput(FALL_INPUT, "Fall CV");
+ configInput(IN_INPUT, "Signal");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
bool active() override;
diff --git a/src/Stack.cpp b/src/Stack.cpp
@@ -42,6 +42,17 @@ void Stack::processChannel(const ProcessArgs& args, int c) {
outputs[OUT_OUTPUT].setVoltage(_outCV[c], c);
}
+void Stack::processBypass(const ProcessArgs& args) {
+ int cn = channels();
+ outputs[THRU_OUTPUT].setChannels(cn);
+ outputs[OUT_OUTPUT].setChannels(cn);
+ for (int c = 0; c < cn; ++c) {
+ float out = inputs[IN_INPUT].getVoltage(c);
+ outputs[THRU_OUTPUT].setVoltage(out, c);
+ outputs[OUT_OUTPUT].setVoltage(out, c);
+ }
+}
+
struct StackWidget : BGModuleWidget {
static constexpr int hp = 3;
@@ -64,15 +75,10 @@ struct StackWidget : BGModuleWidget {
auto outOutputPosition = Vec(10.5, 289.0);
// end generated by svg_widgets.rb
- {
- auto w = createParam<Knob26>(semisParamPosition, module, Stack::SEMIS_PARAM);
- dynamic_cast<Knob*>(w)->snap = true;
- addParam(w);
- }
+ addParam(createParam<Knob26>(semisParamPosition, module, Stack::SEMIS_PARAM));
{
auto w = createParam<Knob16>(octaveParamPosition, module, Stack::OCTAVE_PARAM);
auto k = dynamic_cast<SvgKnob*>(w);
- k->snap = true;
k->minAngle = -0.5 * M_PI;
k->maxAngle = 0.5 * M_PI;
addParam(w);
diff --git a/src/Stack.hpp b/src/Stack.hpp
@@ -42,9 +42,17 @@ struct Stack : BGModule {
Stack() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam(SEMIS_PARAM, 0.0f, 11.0f, 0.0f, "Semitones");
+ paramQuantities[SEMIS_PARAM]->snapEnabled = true;
configParam(OCTAVE_PARAM, -3.0f, 3.0f, 0.0f, "Octaves");
+ paramQuantities[OCTAVE_PARAM]->snapEnabled = true;
configParam(FINE_PARAM, -0.99f, 0.99f, 0.0f, "Fine tune", " cents", 0.0f, 100.0f);
- configParam(QUANTIZE_PARAM, 0.0f, 1.0f, 1.0f, "Quantize");
+ configSwitch(QUANTIZE_PARAM, 0.0f, 1.0f, 1.0f, "Quantize", {"Disabled", "Enabled"});
+
+ configInput(CV_INPUT, "Interval CV");
+ configInput(IN_INPUT, "Pitch (1V/octave)");
+
+ configOutput(THRU_OUTPUT, "Pitch through (1V/octave)");
+ configOutput(OUT_OUTPUT, "Pitch transposed (1V/octave)");
for (int i = 0; i < maxChannels; ++i) {
_lastSemitones[i] = -1000.0f;
@@ -57,6 +65,7 @@ struct Stack : BGModule {
int channels() override;
void modulateChannel(int c) override;
void processChannel(const ProcessArgs& args, int c) override;
+ void processBypass(const ProcessArgs& args) override;
};
} // namespace bogaudio
diff --git a/src/Sums.hpp b/src/Sums.hpp
@@ -30,6 +30,16 @@ struct Sums : DisableOutputLimitModule {
Sums() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
+
+ configInput(A_INPUT, "Signal A");
+ configInput(B_INPUT, "Signal B");
+ configInput(NEGATE_INPUT, "Negative signal");
+
+ configOutput(SUM_OUTPUT, "Sum");
+ configOutput(DIFFERENCE_OUTPUT, "Difference");
+ configOutput(MAX_OUTPUT, "Max");
+ configOutput(MIN_OUTPUT, "Min");
+ configOutput(NEGATE_OUTPUT, "Negative signal");
}
void processAll(const ProcessArgs& args) override;
diff --git a/src/Switch.cpp b/src/Switch.cpp
@@ -30,7 +30,7 @@ void bogaudio::Switch::processAlways(const ProcessArgs& args) {
}
void bogaudio::Switch::processChannel(const ProcessArgs& args, int c) {
- bool triggered = _trigger[c].process(params[GATE_PARAM].getValue() + inputs[GATE_INPUT].getVoltage(c));
+ bool triggered = _trigger[c].process(10.0f*params[GATE_PARAM].getValue() + inputs[GATE_INPUT].getVoltage(c));
if (_latch) {
if (triggered) {
_latchedHigh[c] = !_latchedHigh[c];
@@ -127,10 +127,10 @@ struct SwitchWidget : SaveLatchToPatchModuleWidget {
addOutput(createOutput<Port24>(out1OutputPosition, module, bogaudio::Switch::OUT1_OUTPUT));
addOutput(createOutput<Port24>(out2OutputPosition, module, bogaudio::Switch::OUT2_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(high1LightPosition, module, bogaudio::Switch::HIGH1_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(low1LightPosition, module, bogaudio::Switch::LOW1_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(high2LightPosition, module, bogaudio::Switch::HIGH2_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(low2LightPosition, module, bogaudio::Switch::LOW2_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(high1LightPosition, module, bogaudio::Switch::HIGH1_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(low1LightPosition, module, bogaudio::Switch::LOW1_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(high2LightPosition, module, bogaudio::Switch::HIGH2_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(low2LightPosition, module, bogaudio::Switch::LOW2_LIGHT));
}
};
diff --git a/src/Switch.hpp b/src/Switch.hpp
@@ -45,8 +45,19 @@ struct Switch : SaveLatchToPatchModule {
Switch() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
- configParam(GATE_PARAM, 0.0f, 10.0f, 0.0f, "Gate");
- configParam(LATCH_PARAM, 0.0f, 1.0f, 0.0f, "Latch");
+ configButton(GATE_PARAM, "Gate");
+ configSwitch(LATCH_PARAM, 0.0f, 1.0f, 0.0f, "Latch", {"Disabled", "Enabled"});
+ configBypass(LOW1_INPUT, OUT1_OUTPUT);
+ configBypass(LOW2_INPUT, OUT2_OUTPUT);
+
+ configInput(GATE_INPUT, "Gate");
+ configInput(HIGH1_INPUT, "High 1 signal");
+ configInput(LOW1_INPUT, "Low 1 signal");
+ configInput(HIGH2_INPUT, "Hight 2 signal");
+ configInput(LOW2_INPUT, "Low 2 signal");
+
+ configOutput(OUT1_OUTPUT, "Signal 1");
+ configOutput(OUT2_OUTPUT, "Signal 2");
}
void reset() override;
diff --git a/src/Switch1616.hpp b/src/Switch1616.hpp
@@ -582,6 +582,40 @@ struct Switch1616 : SwitchMatrixModule {
configSwitchParam(MIX_16_14_PARAM, "Mix 14P");
configSwitchParam(MIX_16_15_PARAM, "Mix 15P");
configSwitchParam(MIX_16_16_PARAM, "Mix 16P");
+
+ configInput(IN1_INPUT, "Signal 1");
+ configInput(IN2_INPUT, "Signal 2");
+ configInput(IN3_INPUT, "Signal 3");
+ configInput(IN4_INPUT, "Signal 4");
+ configInput(IN5_INPUT, "Signal 5");
+ configInput(IN6_INPUT, "Signal 6");
+ configInput(IN7_INPUT, "Signal 7");
+ configInput(IN8_INPUT, "Signal 8");
+ configInput(IN9_INPUT, "Signal 9");
+ configInput(IN10_INPUT, "Signal 10");
+ configInput(IN11_INPUT, "Signal 11");
+ configInput(IN12_INPUT, "Signal 12");
+ configInput(IN13_INPUT, "Signal 13");
+ configInput(IN14_INPUT, "Signal 14");
+ configInput(IN15_INPUT, "Signal 15");
+ configInput(IN16_INPUT, "Signal 16");
+
+ configOutput(OUT1_OUTPUT, "Signal A");
+ configOutput(OUT2_OUTPUT, "Signal B");
+ configOutput(OUT3_OUTPUT, "Signal C");
+ configOutput(OUT4_OUTPUT, "Signal D");
+ configOutput(OUT5_OUTPUT, "Signal E");
+ configOutput(OUT6_OUTPUT, "Signal F");
+ configOutput(OUT7_OUTPUT, "Signal G");
+ configOutput(OUT8_OUTPUT, "Signal H");
+ configOutput(OUT9_OUTPUT, "Signal I");
+ configOutput(OUT10_OUTPUT, "Signal J");
+ configOutput(OUT11_OUTPUT, "Signal K");
+ configOutput(OUT12_OUTPUT, "Signal L");
+ configOutput(OUT13_OUTPUT, "Signal M");
+ configOutput(OUT14_OUTPUT, "Signal N");
+ configOutput(OUT15_OUTPUT, "Signal O");
+ configOutput(OUT16_OUTPUT, "Signal P");
}
};
diff --git a/src/Switch18.hpp b/src/Switch18.hpp
@@ -47,6 +47,17 @@ struct Switch18 : SwitchMatrixModule {
configSwitchParam(MIX6_PARAM, "Route 6");
configSwitchParam(MIX7_PARAM, "Route 7");
configSwitchParam(MIX8_PARAM, "Route 8");
+
+ configInput(IN_INPUT, "Signal");
+
+ configOutput(OUT1_OUTPUT, "Signal 1");
+ configOutput(OUT2_OUTPUT, "Signal 2");
+ configOutput(OUT3_OUTPUT, "Signal 3");
+ configOutput(OUT4_OUTPUT, "Signal 4");
+ configOutput(OUT5_OUTPUT, "Signal 5");
+ configOutput(OUT6_OUTPUT, "Signal 6");
+ configOutput(OUT7_OUTPUT, "Signal 7");
+ configOutput(OUT8_OUTPUT, "Signal 8");
}
};
diff --git a/src/Switch44.hpp b/src/Switch44.hpp
@@ -62,6 +62,16 @@ struct Switch44 : SwitchMatrixModule {
configSwitchParam(MIX24_PARAM, "Mix 2D");
configSwitchParam(MIX34_PARAM, "Mix 3D");
configSwitchParam(MIX44_PARAM, "Mix 4D");
+
+ configInput(IN1_INPUT, "Signal 1");
+ configInput(IN2_INPUT, "Signal 2");
+ configInput(IN3_INPUT, "Signal 3");
+ configInput(IN4_INPUT, "Signal 4");
+
+ configOutput(OUT1_OUTPUT, "Signal A");
+ configOutput(OUT2_OUTPUT, "Signal B");
+ configOutput(OUT3_OUTPUT, "Signal C");
+ configOutput(OUT4_OUTPUT, "Signal D");
}
};
diff --git a/src/Switch81.hpp b/src/Switch81.hpp
@@ -47,6 +47,17 @@ struct Switch81 : SwitchMatrixModule {
configSwitchParam(MIX6_PARAM, "Mix 6");
configSwitchParam(MIX7_PARAM, "Mix 7");
configSwitchParam(MIX8_PARAM, "Mix 8");
+
+ configInput(IN1_INPUT, "Signal 1");
+ configInput(IN2_INPUT, "Signal 2");
+ configInput(IN3_INPUT, "Signal 3");
+ configInput(IN4_INPUT, "Signal 4");
+ configInput(IN5_INPUT, "Signal 5");
+ configInput(IN6_INPUT, "Signal 6");
+ configInput(IN7_INPUT, "Signal 7");
+ configInput(IN8_INPUT, "Signal 8");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
};
diff --git a/src/Switch88.hpp b/src/Switch88.hpp
@@ -166,6 +166,24 @@ struct Switch88 : SwitchMatrixModule {
configSwitchParam(MIX68_PARAM, "Mix 6H");
configSwitchParam(MIX78_PARAM, "Mix 7H");
configSwitchParam(MIX88_PARAM, "Mix 8H");
+
+ configInput(IN1_INPUT, "Signal 1");
+ configInput(IN2_INPUT, "Signal 2");
+ configInput(IN3_INPUT, "Signal 3");
+ configInput(IN4_INPUT, "Signal 4");
+ configInput(IN5_INPUT, "Signal 5");
+ configInput(IN6_INPUT, "Signal 6");
+ configInput(IN7_INPUT, "Signal 7");
+ configInput(IN8_INPUT, "Signal 8");
+
+ configOutput(OUT1_OUTPUT, "Signal A");
+ configOutput(OUT2_OUTPUT, "Signal B");
+ configOutput(OUT3_OUTPUT, "Signal C");
+ configOutput(OUT4_OUTPUT, "Signal D");
+ configOutput(OUT5_OUTPUT, "Signal E");
+ configOutput(OUT6_OUTPUT, "Signal F");
+ configOutput(OUT7_OUTPUT, "Signal G");
+ configOutput(OUT8_OUTPUT, "Signal H");
}
};
diff --git a/src/TestExpander.cpp b/src/TestExpander.cpp
@@ -41,7 +41,7 @@ struct TestExpanderBaseWidget : BGModuleWidget {
addOutput(createOutput<Port24>(outOutputPosition, module, TestExpanderBase::OUT_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(comLightPosition, module, TestExpanderBase::COM_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(comLightPosition, module, TestExpanderBase::COM_LIGHT));
}
};
@@ -81,7 +81,7 @@ struct TestExpanderExtensionWidget : BGModuleWidget {
addOutput(createOutput<Port24>(outOutputPosition, module, TestExpanderExtension::OUT_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(comLightPosition, module, TestExpanderExtension::COM_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(comLightPosition, module, TestExpanderExtension::COM_LIGHT));
}
};
diff --git a/src/TestVCF.cpp b/src/TestVCF.cpp
@@ -872,16 +872,16 @@ struct TestVCFWidget : BGModuleWidget {
addOutput(createOutput<Port24>(outOutputPosition, module, TestVCF::OUT_OUTPUT));
addOutput(createOutput<Port24>(outBOutputPosition, module, TestVCF::OUT_B_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(lowpassLightPosition, module, TestVCF::LOWPASS_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(highpassLightPosition, module, TestVCF::HIGHPASS_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(bandpassLightPosition, module, TestVCF::BANDPASS_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(bandRejectLightPosition, module, TestVCF::BAND_REJECT_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(poles2LightPosition, module, TestVCF::POLES_2_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(poles4LightPosition, module, TestVCF::POLES_4_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(poles6LightPosition, module, TestVCF::POLES_6_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(poles8LightPosition, module, TestVCF::POLES_8_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(poles10LightPosition, module, TestVCF::POLES_10_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(poles12LightPosition, module, TestVCF::POLES_12_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(lowpassLightPosition, module, TestVCF::LOWPASS_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(highpassLightPosition, module, TestVCF::HIGHPASS_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(bandpassLightPosition, module, TestVCF::BANDPASS_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(bandRejectLightPosition, module, TestVCF::BAND_REJECT_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(poles2LightPosition, module, TestVCF::POLES_2_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(poles4LightPosition, module, TestVCF::POLES_4_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(poles6LightPosition, module, TestVCF::POLES_6_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(poles8LightPosition, module, TestVCF::POLES_8_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(poles10LightPosition, module, TestVCF::POLES_10_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(poles12LightPosition, module, TestVCF::POLES_12_LIGHT));
}
};
diff --git a/src/UMix.hpp b/src/UMix.hpp
@@ -36,6 +36,17 @@ struct UMix : MatrixBaseModule {
UMix() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
+
+ configInput(IN1_INPUT, "Signal 1");
+ configInput(IN2_INPUT, "Signal 2");
+ configInput(IN3_INPUT, "Signal 3");
+ configInput(IN4_INPUT, "Signal 4");
+ configInput(IN5_INPUT, "Signal 5");
+ configInput(IN6_INPUT, "Signal 6");
+ configInput(IN7_INPUT, "Signal 7");
+ configInput(IN8_INPUT, "Signal 8");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
bool active() override;
diff --git a/src/Unison.cpp b/src/Unison.cpp
@@ -61,11 +61,7 @@ struct UnisonWidget : BGModuleWidget {
auto gateOutputPosition = Vec(10.5, 282.0);
// end generated by svg_widgets.rb
- {
- auto w = createParam<Knob26>(channelsParamPosition, module, Unison::CHANNELS_PARAM);
- dynamic_cast<Knob*>(w)->snap = true;
- addParam(w);
- }
+ addParam(createParam<Knob26>(channelsParamPosition, module, Unison::CHANNELS_PARAM));
addParam(createParam<Knob26>(detuneParamPosition, module, Unison::DETUNE_PARAM));
addInput(createInput<Port24>(detuneInputPosition, module, Unison::DETUNE_INPUT));
diff --git a/src/Unison.hpp b/src/Unison.hpp
@@ -33,7 +33,15 @@ struct Unison : BGModule {
Unison() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam(CHANNELS_PARAM, 1.0f, 16.0f, 1.0f, "Channels");
+ paramQuantities[CHANNELS_PARAM]->snapEnabled = true;
configParam(DETUNE_PARAM, 0.0f, maxDetuneCents, 0.0f, "Detune");
+
+ configInput(DETUNE_INPUT, "Detune CV");
+ configInput(PITCH_INPUT, "Pitch (1V/octave)");
+ configInput(GATE_INPUT, "Gate");
+
+ configOutput(PITCH_OUTPUT, "Pitch (1V/octave)");
+ configOutput(GATE_OUTPUT, "Gate");
}
void modulate() override;
diff --git a/src/VCA.hpp b/src/VCA.hpp
@@ -44,7 +44,17 @@ struct VCA : BGModule {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam<LevelParamQuantity>(LEVEL1_PARAM, 0.0f, 1.0f, 0.8f, "Level 1");
configParam<LevelParamQuantity>(LEVEL2_PARAM, 0.0f, 1.0f, 0.8f, "Level 2");
- configParam(LINEAR_PARAM, 0.0f, 1.0f, 0.0f, "Linear");
+ configSwitch(LINEAR_PARAM, 0.0f, 1.0f, 0.0f, "Linear", {"Disabled", "Enabled"});
+ configBypass(IN1_INPUT, OUT1_OUTPUT);
+ configBypass(IN2_INPUT, OUT2_OUTPUT);
+
+ configInput(CV1_INPUT, "Level 1 CV");
+ configInput(IN1_INPUT, "Signal 1");
+ configInput(CV2_INPUT, "Level 2 CV");
+ configInput(IN2_INPUT, "Signal 2");
+
+ configOutput(OUT1_OUTPUT, "Signal 1");
+ configOutput(OUT2_OUTPUT, "Signal 2");
sampleRateChange();
}
diff --git a/src/VCAmp.hpp b/src/VCAmp.hpp
@@ -38,6 +38,12 @@ struct VCAmp : BGModule {
VCAmp() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam(LEVEL_PARAM, 0.0f, 1.0f, fabs(minDecibels) / (maxDecibels - minDecibels), "Level", " dB", 0.0f, maxDecibels - minDecibels, minDecibels);
+ configBypass(IN_INPUT, OUT_OUTPUT);
+
+ configInput(CV_INPUT, "Level CV");
+ configInput(IN_INPUT, "Signal");
+
+ configOutput(OUT_OUTPUT, "Signal");
sampleRateChange();
for (int c = 0; c < maxChannels; ++c) {
diff --git a/src/VCF.cpp b/src/VCF.cpp
@@ -75,7 +75,7 @@ float VCF::Engine::next(float sample) {
return _finalHP.next(out);
}
-json_t* VCF::toJson(json_t* root) {
+json_t* VCF::saveToJson(json_t* root) {
switch (_bandwidthMode) {
case MultimodeFilter::LINEAR_BANDWIDTH_MODE: {
json_object_set_new(root, BANDWIDTH_MODE_KEY, json_string(LINEAR_BANDWIDTH_MODE_KEY));
@@ -90,7 +90,7 @@ json_t* VCF::toJson(json_t* root) {
return root;
}
-void VCF::fromJson(json_t* root) {
+void VCF::loadFromJson(json_t* root) {
json_t* bwm = json_object_get(root, BANDWIDTH_MODE_KEY);
if (bwm) {
if (strcmp(json_string_value(bwm), LINEAR_BANDWIDTH_MODE_KEY) == 0) {
@@ -217,7 +217,6 @@ struct VCFWidget : BGModuleWidget {
{
auto w = createParam<Knob16>(modeParamPosition, module, VCF::MODE_PARAM);
auto k = dynamic_cast<SvgKnob*>(w);
- k->snap = true;
float a = (22.5 / 180.0) * M_PI;
k->minAngle = a;
k->maxAngle = M_PI - a;
diff --git a/src/VCF.hpp b/src/VCF.hpp
@@ -75,12 +75,23 @@ struct VCF : BGModule {
configParam(FREQUENCY_CV_PARAM, -1.0f, 1.0f, 0.0f, "Frequency CV attenuation", "%", 0.0f, 100.0f);
configParam(FM_PARAM, 0.0f, 1.0f, 0.0f, "FM", "%", 0.0f, 100.0f);
configParam(Q_PARAM, 0.0f, 1.0f, 0.0f, "Resonance / bandwidth", "%", 0.0f, 100.0f);
- configParam(MODE_PARAM, 0.0f, 3.0f, 0.0f, "Mode");
+ configSwitch(MODE_PARAM, 0.0f, 3.0f, 0.0f, "Mode", {"Lowpass", "Highpass", "Bandpass", "Band reject"});
+ paramQuantities[MODE_PARAM]->snapEnabled = true;
configParam<ScaledSquaringParamQuantity<Engine::maxPoles - Engine::minPoles>>(SLOPE_PARAM, 0.0f, 1.0f, 0.522233f, "Slope", " poles", 0.0f, 1.0f, Engine::minPoles);
+ configBypass(IN_INPUT, OUT_OUTPUT);
+
+ configInput(FREQUENCY_CV_INPUT, "Cutoff CV");
+ configInput(FM_INPUT, "Cutoff FM");
+ configInput(PITCH_INPUT, "Cutoff pitch (1V/octave)");
+ configInput(IN_INPUT, "Signal");
+ configInput(Q_INPUT, "Resonance CV");
+ configInput(SLOPE_INPUT, "Slope CV");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void sampleRateChange() override;
bool active() override;
int channels() override;
diff --git a/src/VCM.hpp b/src/VCM.hpp
@@ -56,6 +56,18 @@ struct VCM : DisableOutputLimitModule {
configParam<LevelParamQuantity>(LEVEL4_PARAM, 0.0f, 1.0f, 0.8f, "Level 4");
configParam<LevelParamQuantity>(MIX_PARAM, 0.0f, 1.0f, 0.8f, "Mix level");
configParam(LINEAR_PARAM, 0.0f, 1.0f, 0.0f, "Linear");
+
+ configInput(IN1_INPUT, "Signal 1");
+ configInput(CV1_INPUT, "Level 1 CV");
+ configInput(IN2_INPUT, "Signal 2");
+ configInput(CV2_INPUT, "Level 2 CV");
+ configInput(IN3_INPUT, "Signal 3");
+ configInput(CV3_INPUT, "Level 3 CV");
+ configInput(IN4_INPUT, "Signal 4");
+ configInput(CV4_INPUT, "Level 4 CV");
+ configInput(MIX_CV_INPUT, "Mix level CV");
+
+ configOutput(MIX_OUTPUT, "Signal");
}
inline bool isLinear() { return params[LINEAR_PARAM].getValue() > 0.5f; }
diff --git a/src/VCO.hpp b/src/VCO.hpp
@@ -47,11 +47,21 @@ struct VCO : VCOBase {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam<VCOFrequencyParamQuantity>(FREQUENCY_PARAM, -3.0f, 6.0f, 0.0f, "Frequency", " Hz");
configParam(FINE_PARAM, -1.0f, 1.0f, 0.0f, "Fine tune", " cents", 0.0f, 100.0f);
- configParam(SLOW_PARAM, 0.0f, 1.0f, 0.0f, "Slow mode");
+ configButton(SLOW_PARAM, "Slow mode");
configParam(PW_PARAM, -1.0f, 1.0f, 0.0f, "Pulse width", "%", 0.0f, 100.0f*0.5f*(1.0f - 2.0f * SquareOscillator::minPulseWidth), 50.0f);
configParam(FM_PARAM, 0.0f, 1.0f, 0.0f, "FM depth", "%", 0.0f, 100.0f);
- configParam(FM_TYPE_PARAM, 0.0f, 1.0f, 1.0f, "FM mode");
- configParam(LINEAR_PARAM, 0.0f, 1.0f, 0.0f, "Linear Freq");
+ configSwitch(FM_TYPE_PARAM, 0.0f, 1.0f, 1.0f, "FM mode", {"Linear FM", "Exponential FM"});
+ configButton(LINEAR_PARAM, "Linear frequency");
+
+ configInput(PITCH_INPUT, "Pitch (1V/octave)");
+ configInput(SYNC_INPUT, "Sync");
+ configInput(PW_INPUT, "Pulse width CV");
+ configInput(FM_INPUT, "Frequency modulation");
+
+ configOutput(SQUARE_OUTPUT, "Square signal");
+ configOutput(SAW_OUTPUT, "Saw signal");
+ configOutput(TRIANGLE_OUTPUT, "Triangle signal");
+ configOutput(SINE_OUTPUT, "Sine signal");
}
bool active() override;
diff --git a/src/VU.cpp b/src/VU.cpp
@@ -58,7 +58,7 @@ void VU::processAll(const ProcessArgs& args) {
_rPeakLevel = rPeak;
}
-struct VUDisplay : OpaqueWidget {
+struct VUDisplay : LightEmittingWidget<OpaqueWidget> {
struct Level {
float db;
NVGcolor color;
@@ -76,50 +76,64 @@ struct VUDisplay : OpaqueWidget {
}
}
+ bool isLit() override {
+ return _module && !_module->isBypassed();
+ }
+
void draw(const DrawArgs& args) override {
- float lDb = -100.0f;
- float rDb = -100.0f;
- float lPeakDb = -100.0f;
- float rPeakDb = -100.0f;
- if (_module) {
- lDb = amplitudeToDecibels(_module->_lLevel);
- rDb = amplitudeToDecibels(_module->_rLevel);
- lPeakDb = amplitudeToDecibels(_module->_lPeakLevel);
- rPeakDb = amplitudeToDecibels(_module->_rPeakLevel);
+ nvgSave(args.vg);
+ for (int i = 0; i < 180; i += 5) {
+ drawBox(args, i, true);
+ nvgFillColor(args.vg, bgColor);
+ nvgFill(args.vg);
+
+ drawBox(args, i, false);
+ nvgFillColor(args.vg, bgColor);
+ nvgFill(args.vg);
}
+ nvgRestore(args.vg);
+ }
+
+ void drawLit(const DrawArgs& args) override {
+ assert(_module);
+ float lDb = amplitudeToDecibels(_module->_lLevel);
+ float rDb = amplitudeToDecibels(_module->_rLevel);
+ float lPeakDb = amplitudeToDecibels(_module->_lPeakLevel);
+ float rPeakDb = amplitudeToDecibels(_module->_rPeakLevel);
nvgSave(args.vg);
for (int i = 0; i < 180; i += 5) {
const Level& l = _levels.at(i / 5);
- nvgBeginPath(args.vg);
- nvgRect(args.vg, 3, i + 1, 5, 4);
- nvgFillColor(args.vg, bgColor);
- nvgFill(args.vg);
if (lPeakDb > l.db && lPeakDb < l.db + 2.0f) {
+ drawBox(args, i, true);
nvgFillColor(args.vg, nvgRGBA(0x00, 0xdd, 0xff, 0xff));
nvgFill(args.vg);
}
if (lDb > l.db) {
+ drawBox(args, i, true);
nvgFillColor(args.vg, l.color);
nvgFill(args.vg);
}
- nvgBeginPath(args.vg);
- nvgRect(args.vg, 10, i + 1, 5, 4);
- nvgFillColor(args.vg, bgColor);
- nvgFill(args.vg);
if (rPeakDb > l.db && rPeakDb < l.db + 2.0f) {
+ drawBox(args, i, false);
nvgFillColor(args.vg, nvgRGBA(0x00, 0xdd, 0xff, 0xff));
nvgFill(args.vg);
}
if (rDb > l.db) {
+ drawBox(args, i, false);
nvgFillColor(args.vg, l.color);
nvgFill(args.vg);
}
}
nvgRestore(args.vg);
}
+
+ void drawBox(const DrawArgs& args, int offset, bool left) {
+ nvgBeginPath(args.vg);
+ nvgRect(args.vg, left ? 3 : 10, offset + 1, 5, 4);
+ }
};
struct VUWidget : BGModuleWidget {
diff --git a/src/VU.hpp b/src/VU.hpp
@@ -43,6 +43,15 @@ struct VU : BGModule {
VU() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
+ configBypass(L_INPUT, L_OUTPUT);
+ configBypass(R_INPUT, R_OUTPUT);
+
+ configInput(L_INPUT, "Left signal");
+ configInput(R_INPUT, "Right signal");
+
+ configOutput(L_OUTPUT, "Left signal");
+ configOutput(R_OUTPUT, "Right signal");
+
sampleRateChange();
_lRms.setSensitivity(1.0f);
_rRms.setSensitivity(1.0f);
diff --git a/src/Velo.cpp b/src/Velo.cpp
@@ -15,12 +15,12 @@ void Velo::sampleRateChange() {
}
}
-json_t* Velo::toJson(json_t* root) {
+json_t* Velo::saveToJson(json_t* root) {
json_object_set_new(root, LEVEL_SCALES_CV, json_boolean(_levelScalesCV));
return root;
}
-void Velo::fromJson(json_t* root) {
+void Velo::loadFromJson(json_t* root) {
json_t* s = json_object_get(root, LEVEL_SCALES_CV);
if (s) {
_levelScalesCV = json_boolean_value(s);
diff --git a/src/Velo.hpp b/src/Velo.hpp
@@ -48,13 +48,21 @@ struct Velo : BGModule {
configParam<LevelParamQuantity>(LEVEL_PARAM, 0.0f, 1.0f, 0.8f, "level");
configParam(LEVEL_ATTENUATOR_PARAM, -1.0f, 1.0f, 0.0f, "Level CV");
configParam<ScaledSquaringParamQuantity<-60>>(VELOCITY_PARAM, 0.0f, 1.0f, 0.3162278f, "Velocity range", " dB");
- configParam(LINEAR_PARAM, 0.0f, 1.0f, 0.0f, "Linear");
+ configSwitch(LINEAR_PARAM, 0.0f, 1.0f, 0.0f, "Linear", {"Disabled", "Enabled"});
+ configBypass(IN_INPUT, OUT_OUTPUT);
+
+ configInput(LEVEL_INPUT, "Level unipolar CV");
+ configInput(CV_INPUT, "Level bipolar CV");
+ configInput(VELOCITY_INPUT, "Velocity CV");
+ configInput(IN_INPUT, "Signal");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
inline bool isLinear() { return params[LINEAR_PARAM].getValue() > 0.5f; }
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
bool active() override;
void modulate() override;
void processAll(const ProcessArgs& args) override;
diff --git a/src/Vish.hpp b/src/Vish.hpp
@@ -55,8 +55,16 @@ struct Vish : LPGEnvBaseModule {
configParam<TimeParamQuantity<1>>(FALL_PARAM, 0.0f, 1.0f, 0.5477226f, "Fall time", " s");
configParam(FALL_SHAPE_PARAM, -1.0f, 1.0f, 0.0f, "Fall shape");
configParam<TimeParamQuantity<1>>(MINIMUM_GATE_PARAM, 0.0f, 1.0f, 0.3162278f, "Minimum gate", " s");
- configParam(GATE_TO_TRIGGER_PARAM, 0.0f, 1.0f, 1.0f, "Gate to trigger mode");
- configParam(TIMES_10X_PARAM, 0.0f, 1.0f, 0.0f, "Timings 10X mode");
+ configSwitch(GATE_TO_TRIGGER_PARAM, 0.0f, 1.0f, 1.0f, "Gate to trigger mode", {"Disabled (input pass-through)", "Enabled"});
+ configSwitch(TIMES_10X_PARAM, 0.0f, 1.0f, 0.0f, "Timings 10X mode", {"Disabled (normal)", "Enabled"});
+
+ configInput(RISE_INPUT, "Rise CV");
+ configInput(MINIMUM_GATE_INPUT, "Minimum gate CV");
+ configInput(FALL_INPUT, "Fall CV");
+ configInput(SHAPE_INPUT, "Shape CV");
+ configInput(GATE_INPUT, "Gate");
+
+ configOutput(OUT_OUTPUT, "Envelope");
}
void reset() override;
diff --git a/src/Walk.cpp b/src/Walk.cpp
@@ -19,7 +19,7 @@ void Walk::sampleRateChange() {
}
}
-json_t* Walk::toJson(json_t* root) {
+json_t* Walk::saveToJson(json_t* root) {
json_object_set_new(root, POLY_INPUT, json_integer(_polyInputID));
switch (_jumpMode) {
case JUMP_JUMPMODE: {
@@ -38,7 +38,7 @@ json_t* Walk::toJson(json_t* root) {
return root;
}
-void Walk::fromJson(json_t* root) {
+void Walk::loadFromJson(json_t* root) {
json_t* p = json_object_get(root, POLY_INPUT);
if (p) {
_polyInputID = json_integer_value(p);
diff --git a/src/Walk.hpp b/src/Walk.hpp
@@ -51,12 +51,19 @@ struct Walk : BGModule {
configParam(RATE_PARAM, 0.0f, 1.0f, 0.1f, "Rate", "%", 0.0f, 100.0f);
configParam(OFFSET_PARAM, -1.0f, 1.0f, 0.0f, "Offset", " V", 0.0f, 5.0f);
configParam(SCALE_PARAM, 0.0f, 1.0f, 1.0f, "Scale", "%", 0.0f, 100.0f);
+
+ configInput(RATE_INPUT, "Rate CV");
+ configInput(OFFSET_INPUT, "Offset CV");
+ configInput(SCALE_INPUT, "Scale CV");
+ configInput(JUMP_INPUT, "Trigger");
+
+ configOutput(OUT_OUTPUT, "Signal");
}
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
int channels() override;
void modulateChannel(int c) override;
void processChannel(const ProcessArgs& args, int c) override;
diff --git a/src/Walk2.cpp b/src/Walk2.cpp
@@ -15,14 +15,14 @@ void Walk2::sampleRateChange() {
_historySteps = (historySeconds * APP->engine->getSampleRate()) / historyPoints;
}
-json_t* Walk2::toJson(json_t* root) {
+json_t* Walk2::saveToJson(json_t* root) {
json_object_set_new(root, ZOOM_OUT_KEY, json_boolean(_zoomOut));
json_object_set_new(root, GRID_KEY, json_boolean(_drawGrid));
json_object_set_new(root, COLOR_KEY, json_integer(_traceColor));
return root;
}
-void Walk2::fromJson(json_t* root) {
+void Walk2::loadFromJson(json_t* root) {
json_t* zo = json_object_get(root, ZOOM_OUT_KEY);
if (zo) {
_zoomOut = json_is_true(zo);
@@ -169,7 +169,7 @@ void Walk2::processAll(const ProcessArgs& args) {
_historyStep %= _historySteps;
}
-struct Walk2Display : TransparentWidget {
+struct Walk2Display : DisplayWidget {
const int _insetAround = 4;
const NVGcolor _axisColor = nvgRGBA(0xff, 0xff, 0xff, 0x70);
@@ -179,7 +179,6 @@ struct Walk2Display : TransparentWidget {
const Vec _size;
const Vec _drawSize;
int _midX, _midY;
- std::shared_ptr<Font> _font;
NVGcolor _traceColor = _defaultTraceColor;
Vec _dragLast;
@@ -187,12 +186,12 @@ struct Walk2Display : TransparentWidget {
Walk2* module,
Vec size
)
- : _module(module)
+ : DisplayWidget(module)
+ , _module(module)
, _size(size)
, _drawSize(2 * (_size.x - 2 * _insetAround), 2 * (_size.y - 2 * _insetAround))
, _midX(_insetAround + _drawSize.x/2)
, _midY(_insetAround + _drawSize.y/2)
- , _font(APP->window->loadFont(asset::plugin(pluginInstance, "res/fonts/inconsolata.ttf")))
{
}
@@ -227,11 +226,11 @@ struct Walk2Display : TransparentWidget {
}
}
- void draw(const DrawArgs& args) override {
+ void drawOnce(const DrawArgs& args, bool screenshot, bool lit) override {
float strokeWidth = std::max(1.0f, 3.0f - getZoom());
- drawBackground(args);
nvgSave(args.vg);
+ drawBackground(args);
nvgScissor(args.vg, _insetAround, _insetAround, _drawSize.x / 2, _drawSize.y / 2);
if (_module && _module->_zoomOut) {
nvgScale(args.vg, 0.5f, 0.5f);
@@ -248,7 +247,7 @@ struct Walk2Display : TransparentWidget {
}
drawAxes(args, strokeWidth);
- if (_module) {
+ if (lit) {
switch (_module->_traceColor) {
case Walk2::ORANGE_TRACE_COLOR: {
_traceColor = nvgRGBA(0xff, 0x80, 0x00, 0xee);
@@ -545,9 +544,9 @@ struct Walk2Widget : BGModuleWidget {
addOutput(createOutput<Port24>(outYOutputPosition, module, Walk2::OUT_Y_OUTPUT));
addOutput(createOutput<Port24>(distanceOutputPosition, module, Walk2::DISTANCE_OUTPUT));
- addChild(createLight<SmallLight<GreenLight>>(jumpLightPosition, module, Walk2::JUMP_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(sampleholdLightPosition, module, Walk2::SAMPLEHOLD_LIGHT));
- addChild(createLight<SmallLight<GreenLight>>(trackholdLightPosition, module, Walk2::TRACKHOLD_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(jumpLightPosition, module, Walk2::JUMP_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(sampleholdLightPosition, module, Walk2::SAMPLEHOLD_LIGHT));
+ addChild(createLight<BGSmallLight<GreenLight>>(trackholdLightPosition, module, Walk2::TRACKHOLD_LIGHT));
}
void contextMenu(Menu* menu) override {
diff --git a/src/Walk2.hpp b/src/Walk2.hpp
@@ -88,13 +88,25 @@ struct Walk2 : BGModule {
configParam(OFFSET_Y_PARAM, -1.0f, 1.0f, 0.0f, "Offset Y", " V", 0.0f, 5.0f);
configParam(SCALE_X_PARAM, 0.0f, 1.0f, 1.0f, "Scale X", "%", 0.0f, 100.0f);
configParam(SCALE_Y_PARAM, 0.0f, 1.0f, 1.0f, "Scale Y", "%", 0.0f, 100.0f);
- configParam(JUMP_MODE_PARAM, 0.0f, 2.0f, 0.0f, "TRIG action");
+ configSwitch(JUMP_MODE_PARAM, 0.0f, 2.0f, 0.0f, "TRIG action", {"Jump", "Sample & hold", "Track & hold"});
+
+ configInput(OFFSET_X_INPUT, "Offset X CV");
+ configInput(SCALE_X_INPUT, "Scale X CV");
+ configInput(RATE_X_INPUT, "Rate X CV");
+ configInput(OFFSET_Y_INPUT, "Offset Y CV");
+ configInput(SCALE_Y_INPUT, "Scale Y CV");
+ configInput(RATE_Y_INPUT, "Rate Y CV");
+ configInput(JUMP_INPUT, "Trigger");
+
+ configOutput(OUT_X_OUTPUT, "X signal");
+ configOutput(OUT_Y_OUTPUT, "Y signal");
+ configOutput(DISTANCE_OUTPUT, "X/Y distance signal");
}
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void modulate() override;
void processAlways(const ProcessArgs& args) override;
void processAll(const ProcessArgs& args) override;
diff --git a/src/XCO.cpp b/src/XCO.cpp
@@ -58,12 +58,12 @@ void XCO::sampleRateChange() {
}
}
-json_t* XCO::toJson(json_t* root) {
+json_t* XCO::saveToJson(json_t* root) {
json_object_set_new(root, DC_CORRECTION, json_boolean(_dcCorrection));
return root;
}
-void XCO::fromJson(json_t* root) {
+void XCO::loadFromJson(json_t* root) {
json_t* dc = json_object_get(root, DC_CORRECTION);
if (dc) {
_dcCorrection = json_boolean_value(dc);
diff --git a/src/XCO.hpp b/src/XCO.hpp
@@ -134,9 +134,9 @@ struct XCO : BGModule {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam<XCOFrequencyParamQuantity>(FREQUENCY_PARAM, -3.0f, 6.0f, 0.0f, "Frequency", " Hz");
configParam(FINE_PARAM, -1.0f, 1.0f, 0.0f, "Fine tune", " cents", 0.0f, 100.0f);
- configParam(SLOW_PARAM, 0.0f, 1.0f, 0.0f, "Slow mode");
+ configButton(SLOW_PARAM, "Slow mode");
configParam(FM_DEPTH_PARAM, 0.0f, 1.0f, 0.0f, "FM depth", "%", 0.0f, 100.0f);
- configParam(FM_TYPE_PARAM, 0.0f, 1.0f, 1.0f, "FM mode");
+ configSwitch(FM_TYPE_PARAM, 0.0f, 1.0f, 1.0f, "FM mode", {"Linear FM", "Exponential FM"});
configParam(SQUARE_PW_PARAM, -0.97f, 0.97f, 0.0f, "Square wave pulse width", "%", 0.0f, 100.0f);
configParam(SQUARE_PHASE_PARAM, -1.0f, 1.0f, 0.0f, "Square wave phase", "º", 0.0f, 180.0f);
configParam(SQUARE_MIX_PARAM, 0.0f, 1.0f, 1.0f, "Square wave mix", "%", 0.0f, 100.0f);
@@ -149,12 +149,35 @@ struct XCO : BGModule {
configParam(SINE_FEEDBACK_PARAM, 0.0f, 1.0f, 0.0f, "Sine wave feedback", "%", 0.0f, 100.0f);
configParam(SINE_PHASE_PARAM, -1.0f, 1.0f, 0.0f, "Sine wave phase", "º", 0.0f, 180.0f);
configParam(SINE_MIX_PARAM, 0.0f, 1.0f, 1.0f, "Sine wave mix", "%", 0.0f, 100.0f);
+
+ configInput(FM_INPUT, "Frequency modulation");
+ configInput(FM_DEPTH_INPUT, "FM depth CV");
+ configInput(SQUARE_PW_INPUT, "Square pulse width CV");
+ configInput(SQUARE_PHASE_INPUT, "Square phase CV");
+ configInput(SQUARE_MIX_INPUT, "Square mix CV");
+ configInput(SAW_SATURATION_INPUT, "Saw saturation CV");
+ configInput(SAW_PHASE_INPUT, "Saw phase CV");
+ configInput(SAW_MIX_INPUT, "Saw mix CV");
+ configInput(TRIANGLE_SAMPLE_INPUT, "Triangle sample CV");
+ configInput(TRIANGLE_PHASE_INPUT, "Triangle phase CV");
+ configInput(TRIANGLE_MIX_INPUT, "Triangle mix CV");
+ configInput(SINE_FEEDBACK_INPUT, "Sine feedback CV");
+ configInput(SINE_PHASE_INPUT, "Sine phase CV");
+ configInput(SINE_MIX_INPUT, "Sine mix CV");
+ configInput(PITCH_INPUT, "Pitch (1V/octave)");
+ configInput(SYNC_INPUT, "Sync");
+
+ configOutput(SQUARE_OUTPUT, "Square signal");
+ configOutput(SAW_OUTPUT, "Saw signal");
+ configOutput(TRIANGLE_OUTPUT, "Triangle signal");
+ configOutput(SINE_OUTPUT, "Sine signal");
+ configOutput(MIX_OUTPUT, "Mixed signal");
}
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
bool active() override;
int channels() override;
void addChannel(int c) override;
diff --git a/src/XFade.hpp b/src/XFade.hpp
@@ -39,7 +39,13 @@ struct XFade : BGModule {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
configParam(MIX_PARAM, -1.0f, 1.0f, 0.0f, "Mix", "%", 0.0f, 100.0f);
configParam(CURVE_PARAM, 0.0f, 1.0f, 0.5f, "Curve");
- configParam(LINEAR_PARAM, 0.0f, 1.0f, 0.0f, "Linear");
+ configSwitch(LINEAR_PARAM, 0.0f, 1.0f, 0.0f, "Linear", {"Decibels", "Amplitude"});
+
+ configInput(MIX_INPUT, "Mix CV");
+ configInput(A_INPUT, "Signal A");
+ configInput(B_INPUT, "Signal B");
+
+ configOutput(OUT_OUTPUT, "Signal");
sampleRateChange();
for (int c = 0; c < maxChannels; ++c) {
diff --git a/src/addressable_sequence.cpp b/src/addressable_sequence.cpp
@@ -31,7 +31,7 @@ void AddressableSequenceModule::sampleRateChange() {
}
}
-json_t* AddressableSequenceModule::toJson(json_t* root) {
+json_t* AddressableSequenceModule::saveToJson(json_t* root) {
json_object_set_new(root, POLY_INPUT, json_integer(_polyInputID));
json_object_set_new(root, SELECT_ON_CLOCK, json_boolean(_selectOnClock));
json_object_set_new(root, TRIGGERED_SELECT, json_boolean(_triggeredSelect));
@@ -40,7 +40,7 @@ json_t* AddressableSequenceModule::toJson(json_t* root) {
return root;
}
-void AddressableSequenceModule::fromJson(json_t* root) {
+void AddressableSequenceModule::loadFromJson(json_t* root) {
json_t* p = json_object_get(root, POLY_INPUT);
if (p) {
_polyInputID = json_integer_value(p);
diff --git a/src/addressable_sequence.hpp b/src/addressable_sequence.hpp
@@ -27,8 +27,8 @@ struct AddressableSequenceModule : BGModule {
void setInputIDs(int clockInputID, int selectInputID);
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
int channels() override;
int nextStep(
int c,
diff --git a/src/analyzer_base.cpp b/src/analyzer_base.cpp
@@ -453,8 +453,9 @@ void AnalyzerDisplay::channelLabel(int channel, std::string label) {
_channelLabels[channel] = label;
}
-void AnalyzerDisplay::draw(const DrawArgs& args) {
- if (_module) {
+void AnalyzerDisplay::drawOnce(const DrawArgs& args, bool screenshot, bool lit) {
+ if (!screenshot) {
+ assert(_module);
_module->_core._channelsMutex.lock();
}
@@ -462,7 +463,7 @@ void AnalyzerDisplay::draw(const DrawArgs& args) {
AmplitudePlot amplitudePlot = DECIBELS_80_AP;
float rangeMinHz = 0.0f;
float rangeMaxHz = 0.0f;
- if (_module) {
+ if (!screenshot) {
frequencyPlot = _module->_frequencyPlot;
amplitudePlot = _module->_amplitudePlot;
rangeMinHz = _module->_rangeMinHz;
@@ -474,8 +475,6 @@ void AnalyzerDisplay::draw(const DrawArgs& args) {
rangeMaxHz = 0.5f * APP->engine->getSampleRate();
}
- drawBackground(args);
-
float strokeWidth = std::max(1.0f, 3.0f - getZoom());
if (frequencyPlot == LINEAR_FP) {
_xAxisLogFactor = 1.0f;
@@ -487,13 +486,16 @@ void AnalyzerDisplay::draw(const DrawArgs& args) {
}
nvgSave(args.vg);
+ drawBackground(args);
nvgScissor(args.vg, _insetAround, _insetAround, _size.x - _insetAround, _size.y - _insetAround);
- if (_module) {
- drawHeader(args, rangeMinHz, rangeMaxHz);
+ if (isScreenshot() || !lit) {
+ drawYAxis(args, strokeWidth, amplitudePlot);
+ drawXAxis(args, strokeWidth, frequencyPlot, rangeMinHz, rangeMaxHz);
}
- drawYAxis(args, strokeWidth, amplitudePlot);
- drawXAxis(args, strokeWidth, frequencyPlot, rangeMinHz, rangeMaxHz);
- if (_module) {
+ else {
+ drawHeader(args, rangeMinHz, rangeMaxHz);
+ drawYAxis(args, strokeWidth, amplitudePlot);
+ drawXAxis(args, strokeWidth, frequencyPlot, rangeMinHz, rangeMaxHz);
int freezeBinI = 0;
float freezeLowHz = 0.0f;
float freezeHighHz = 0.0f;
@@ -522,7 +524,7 @@ void AnalyzerDisplay::draw(const DrawArgs& args) {
}
nvgRestore(args.vg);
- if (_module) {
+ if (!screenshot) {
_module->_core._channelsMutex.unlock();
}
}
@@ -981,11 +983,12 @@ void AnalyzerDisplay::drawFreezeOver(const DrawArgs& args, int binI, int binsN,
}
void AnalyzerDisplay::drawText(const DrawArgs& args, const char* s, float x, float y, float rotation, const NVGcolor* color, int fontSize) {
+ std::shared_ptr<Font> font = APP->window->loadFont(_fontPath);
nvgSave(args.vg);
nvgTranslate(args.vg, x, y);
nvgRotate(args.vg, rotation);
nvgFontSize(args.vg, fontSize);
- nvgFontFaceId(args.vg, _font->handle);
+ nvgFontFaceId(args.vg, font->handle);
nvgFillColor(args.vg, color ? *color : _textColor);
nvgText(args.vg, 0, 0, s, NULL);
nvgRestore(args.vg);
diff --git a/src/analyzer_base.hpp b/src/analyzer_base.hpp
@@ -178,7 +178,7 @@ struct AnalyzerBaseWidget : BGModuleWidget {
void addAmplitudePlotContextMenu(Menu* menu, bool linearOption = true);
};
-struct AnalyzerDisplay : TransparentWidget, AnalyzerTypes {
+struct AnalyzerDisplay : DisplayWidget, AnalyzerTypes {
struct BinsReader {
BinsReader() {}
virtual ~BinsReader() {}
@@ -224,7 +224,7 @@ struct AnalyzerDisplay : TransparentWidget, AnalyzerTypes {
const Vec _size;
const Vec _graphSize;
bool _drawInset;
- std::shared_ptr<Font> _font;
+ std::string _fontPath;
float _xAxisLogFactor = baseXAxisLogFactor;
BinsReaderFactory* _channelBinsReaderFactories = NULL;
bool* _displayChannel = NULL;
@@ -240,11 +240,12 @@ struct AnalyzerDisplay : TransparentWidget, AnalyzerTypes {
Vec size,
bool drawInset
)
- : _module(module)
+ : DisplayWidget(module)
+ , _module(module)
, _size(size)
, _graphSize(_size.x - _insetLeft - _insetRight, _size.y - _insetTop - _insetBottom)
, _drawInset(drawInset)
- , _font(APP->window->loadFont(asset::plugin(pluginInstance, "res/fonts/inconsolata.ttf")))
+ , _fontPath(asset::plugin(pluginInstance, "res/fonts/inconsolata.ttf"))
{
if (_module) {
_channelBinsReaderFactories = new BinsReaderFactory[_module->_core._nChannels] {};
@@ -268,7 +269,7 @@ struct AnalyzerDisplay : TransparentWidget, AnalyzerTypes {
void setChannelBinsReaderFactory(int channel, BinsReaderFactory brf);
void displayChannel(int channel, bool display);
void channelLabel(int channel, std::string label);
- void draw(const DrawArgs& args) override;
+ void drawOnce(const DrawArgs& args, bool screenshot, bool lit) override;
void drawBackground(const DrawArgs& args);
virtual void drawHeader(const DrawArgs& args, float rangeMinHz, float rangeMaxHz);
void drawYAxis(const DrawArgs& args, float strokeWidth, AmplitudePlot plot);
diff --git a/src/disable_output_limit.cpp b/src/disable_output_limit.cpp
@@ -3,12 +3,12 @@
#define DISABLE_OUTPUT_LIMIT "disableOutputLimit"
-json_t* DisableOutputLimitModule::toJson(json_t* root) {
+json_t* DisableOutputLimitModule::saveToJson(json_t* root) {
json_object_set_new(root, DISABLE_OUTPUT_LIMIT, json_boolean(_disableOutputLimit));
return root;
}
-void DisableOutputLimitModule::fromJson(json_t* root) {
+void DisableOutputLimitModule::loadFromJson(json_t* root) {
json_t* dol = json_object_get(root, DISABLE_OUTPUT_LIMIT);
if (dol) {
_disableOutputLimit = json_is_true(dol);
diff --git a/src/disable_output_limit.hpp b/src/disable_output_limit.hpp
@@ -7,8 +7,8 @@ namespace bogaudio {
struct DisableOutputLimitModule : BGModule {
bool _disableOutputLimit = false;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
};
struct DisableOutputLimitModuleWidget : BGModuleWidget {
diff --git a/src/dsp/filters/multimode.hpp b/src/dsp/filters/multimode.hpp
@@ -5,7 +5,7 @@
#include "filters/filter.hpp"
#ifdef RACK_SIMD
-#include "simd/vector.hpp"
+#include "simd/Vector.hpp"
using rack::simd::float_4;
#endif
diff --git a/src/lpg_common.cpp b/src/lpg_common.cpp
@@ -7,7 +7,7 @@
#define SHAPE_MODE_ON "on"
#define SHAPE_MODE_INVERTED "inverted"
-json_t* LPGEnvBaseModule::toJson(json_t* root) {
+json_t* LPGEnvBaseModule::saveToJson(json_t* root) {
switch (_riseShapeMode) {
case RiseFallShapedSlewLimiter::OFF_SCVM: {
json_object_set_new(root, RISE_SHAPE_MODE, json_string(SHAPE_MODE_OFF));
@@ -41,7 +41,7 @@ json_t* LPGEnvBaseModule::toJson(json_t* root) {
return root;
}
-void LPGEnvBaseModule::fromJson(json_t* root) {
+void LPGEnvBaseModule::loadFromJson(json_t* root) {
json_t* rsm = json_object_get(root, RISE_SHAPE_MODE);
if (rsm) {
std::string s = json_string_value(rsm);
diff --git a/src/lpg_common.hpp b/src/lpg_common.hpp
@@ -17,8 +17,8 @@ struct LPGEnvBaseModule : BGModule {
, _longTimeScale(longTimeScale)
{}
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void modulate() override;
};
diff --git a/src/matrix_base.cpp b/src/matrix_base.cpp
@@ -9,14 +9,14 @@ using namespace bogaudio::dsp;
#define INPUT_GAIN_DB "input_gain_db"
#define SUM "sum"
-json_t* MatrixBaseModule::toJson(json_t* root) {
+json_t* MatrixBaseModule::saveToJson(json_t* root) {
json_object_set_new(root, CLIPPING_MODE, json_integer(_clippingMode));
json_object_set_new(root, INPUT_GAIN_DB, json_real(_inputGainDb));
json_object_set_new(root, SUM, json_boolean(_sum));
return root;
}
-void MatrixBaseModule::fromJson(json_t* root) {
+void MatrixBaseModule::loadFromJson(json_t* root) {
json_t* c = json_object_get(root, CLIPPING_MODE);
if (c) {
_clippingMode = (Clipping)json_integer_value(c);
@@ -179,15 +179,15 @@ void MatrixModuleWidget::contextMenu(Menu* menu) {
#define INDICATOR_KNOBS "indicator_knobs"
#define UNIPOLAR "unipolar"
-json_t* KnobMatrixModule::toJson(json_t* root) {
- root = MatrixBaseModule::toJson(root);
+json_t* KnobMatrixModule::saveToJson(json_t* root) {
+ root = MatrixBaseModule::saveToJson(root);
json_object_set_new(root, INDICATOR_KNOBS, json_boolean(_indicatorKnobs));
json_object_set_new(root, UNIPOLAR, json_boolean(_unipolar));
return root;
}
-void KnobMatrixModule::fromJson(json_t* root) {
- MatrixBaseModule::fromJson(root);
+void KnobMatrixModule::loadFromJson(json_t* root) {
+ MatrixBaseModule::loadFromJson(root);
json_t* k = json_object_get(root, INDICATOR_KNOBS);
if (k) {
@@ -256,8 +256,8 @@ void KnobMatrixModuleWidget::contextMenu(Menu* menu) {
#define ROW_EXCLUSIVE "row_exclusive"
#define COLUMN_EXCLUSIVE "column_exclusive"
-json_t* SwitchMatrixModule::toJson(json_t* root) {
- root = MatrixBaseModule::toJson(root);
+json_t* SwitchMatrixModule::saveToJson(json_t* root) {
+ root = MatrixBaseModule::saveToJson(root);
switch (_inverting) {
case CLICK_INVERTING: {
@@ -280,8 +280,8 @@ json_t* SwitchMatrixModule::toJson(json_t* root) {
return root;
}
-void SwitchMatrixModule::fromJson(json_t* root) {
- MatrixBaseModule::fromJson(root);
+void SwitchMatrixModule::loadFromJson(json_t* root) {
+ MatrixBaseModule::loadFromJson(root);
json_t* i = json_object_get(root, INVERTING);
if (i) {
@@ -428,12 +428,12 @@ void SwitchMatrixModuleWidget::contextMenu(Menu* menu) {
#define SOLO_BY_COLUMNS "solo_by_columns"
-json_t* MutesMatrixExpanderModule::toJson(json_t* root) {
+json_t* MutesMatrixExpanderModule::saveToJson(json_t* root) {
json_object_set_new(root, SOLO_BY_COLUMNS, json_boolean(_soloByColumns));
return root;
}
-void MutesMatrixExpanderModule::fromJson(json_t* root) {
+void MutesMatrixExpanderModule::loadFromJson(json_t* root) {
json_t* sbc = json_object_get(root, SOLO_BY_COLUMNS);
if (sbc) {
_soloByColumns = json_is_true(sbc);
diff --git a/src/matrix_base.hpp b/src/matrix_base.hpp
@@ -20,8 +20,8 @@ struct MatrixBaseModule : BGModule {
float _inputGainLevel = 1.0f;
bool _sum = true;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void modulate() override;
};
@@ -80,8 +80,8 @@ struct KnobMatrixModule : MatrixModule {
: MatrixModule(ins, outs, firstParamID, firstInputID, firstOutputID)
{}
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void updateParamMinimumValues();
};
@@ -109,8 +109,8 @@ struct SwitchMatrixModule : MatrixModule {
: MatrixModule(ins, outs, firstParamID, firstInputID, firstOutputID)
{}
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
void setInverting(Inverting inverting);
void configSwitchParam(int id, const char* label);
void switchChanged(int id, float value);
@@ -134,8 +134,8 @@ struct SwitchMatrixModuleWidget : MatrixModuleWidget {
struct MutesMatrixExpanderModule : BGModule {
bool _soloByColumns = false;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
};
struct MutesMatrixExpanderModuleWidget : BGModuleWidget {
diff --git a/src/mixer.cpp b/src/mixer.cpp
@@ -49,12 +49,12 @@ void MixerChannel::next(float sample, bool solo, int c, bool linearCV) {
#define LINEAR_CV "linear_cv"
-json_t* LinearCVMixerModule::toJson(json_t* root) {
+json_t* LinearCVMixerModule::saveToJson(json_t* root) {
json_object_set_new(root, LINEAR_CV, json_boolean(_linearCV));
return root;
}
-void LinearCVMixerModule::fromJson(json_t* root) {
+void LinearCVMixerModule::loadFromJson(json_t* root) {
json_t* l = json_object_get(root, LINEAR_CV);
if (l) {
_linearCV = json_boolean_value(l);
@@ -71,14 +71,14 @@ void LinearCVMixerWidget::contextMenu(Menu* menu) {
#define DIM_DB "dim_decibels"
-json_t* DimmableMixerModule::toJson(json_t* root) {
- root = LinearCVMixerModule::toJson(root);
+json_t* DimmableMixerModule::saveToJson(json_t* root) {
+ root = LinearCVMixerModule::saveToJson(root);
json_object_set_new(root, DIM_DB, json_real(_dimDb));
return root;
}
-void DimmableMixerModule::fromJson(json_t* root) {
- LinearCVMixerModule::fromJson(root);
+void DimmableMixerModule::loadFromJson(json_t* root) {
+ LinearCVMixerModule::loadFromJson(root);
json_t* o = json_object_get(root, DIM_DB);
if (o) {
_dimDb = json_real_value(o);
@@ -99,12 +99,6 @@ void DimmableMixerWidget::contextMenu(Menu* menu) {
}
-void MuteButton::randomize() {
- if (_randomize) {
- ToggleButton::randomize();
- }
-}
-
void MuteButton::onButton(const event::Button& e) {
if (!(e.action == GLFW_PRESS && (e.mods & RACK_MOD_MASK) == 0)) {
return;
@@ -118,6 +112,20 @@ void MuteButton::onButton(const event::Button& e) {
}
}
+bool MuteButton::isLit() {
+ return module && !module->isBypassed() && getParamQuantity() && getParamQuantity()->getValue() > 0.0f;
+}
+
+void MuteButton::draw(const DrawArgs& args) {
+ if (!isLit()) {
+ ToggleButton::draw(args);
+ }
+}
+
+void MuteButton::drawLit(const DrawArgs& args) {
+ ToggleButton::draw(args);
+}
+
SoloMuteButton::SoloMuteButton() {
shadow = new CircularShadow();
@@ -139,33 +147,21 @@ SoloMuteButton::SoloMuteButton() {
shadow->box.pos = Vec(0.0, 1.0);
}
-void SoloMuteButton::reset() {
- if (paramQuantity) {
- paramQuantity->setValue(0.0f);
- }
-}
-
-void SoloMuteButton::randomize() {
- if (paramQuantity) {
- paramQuantity->setValue(random::uniform() > 0.5f ? 1.0f : 0.0f);
- }
-}
-
void SoloMuteButton::onButton(const event::Button& e) {
- if (!paramQuantity || !(e.action == GLFW_PRESS && (e.mods & RACK_MOD_MASK) == 0)) {
+ if (!getParamQuantity() || !(e.action == GLFW_PRESS && (e.mods & RACK_MOD_MASK) == 0)) {
ParamWidget::onButton(e);
return;
}
- float value = paramQuantity->getValue();
+ float value = getParamQuantity()->getValue();
if (value >= 2.0f) {
- paramQuantity->setValue(value - 2.0f);
+ getParamQuantity()->setValue(value - 2.0f);
}
else if (e.button == GLFW_MOUSE_BUTTON_RIGHT) {
- paramQuantity->setValue(value + 2.0f);
+ getParamQuantity()->setValue(value + 2.0f);
}
else {
- paramQuantity->setValue(value > 0.5f ? 0.0f : 1.0f);
+ getParamQuantity()->setValue(value > 0.5f ? 0.0f : 1.0f);
}
if (e.button == GLFW_MOUSE_BUTTON_RIGHT) {
@@ -177,10 +173,36 @@ void SoloMuteButton::onButton(const event::Button& e) {
void SoloMuteButton::onChange(const event::Change& e) {
assert(_frames.size() == 4);
- if (paramQuantity) {
- float value = paramQuantity->getValue();
+ if (getParamQuantity()) {
+ float value = getParamQuantity()->getValue();
assert(value >= 0.0f && value <= 3.0f);
_svgWidget->setSvg(_frames[(int)value]);
}
ParamWidget::onChange(e);
}
+
+bool SoloMuteButton::isLit() {
+ return module && !module->isBypassed() && getParamQuantity() && getParamQuantity()->getValue() > 0.0f;
+}
+
+void SoloMuteButton::draw(const DrawArgs& args) {
+ if (!isLit() || !getParamQuantity() || getParamQuantity()->getValue() < 1.0f) {
+ ParamWidget::draw(args);
+ }
+}
+
+void SoloMuteButton::drawLit(const DrawArgs& args) {
+ if (getParamQuantity() && getParamQuantity()->getValue() >= 1.0f) {
+ ParamWidget::draw(args);
+ }
+}
+
+
+std::string DimSwitchQuantity::getDisplayValueString() {
+ if (!module || getValue() < 1.0f) {
+ return SwitchQuantity::getDisplayValueString();
+ }
+ auto* m = static_cast<DimmableMixerModule*>(module);
+ assert(labels.size() == 2);
+ return format("%s (-%ddB)", labels[1].c_str(), (int)m->_dimDb);
+}
diff --git a/src/mixer.hpp b/src/mixer.hpp
@@ -52,8 +52,8 @@ struct MixerChannel {
struct LinearCVMixerModule : BGModule {
bool _linearCV = false;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
};
struct LinearCVMixerWidget : BGModuleWidget {
@@ -63,37 +63,41 @@ struct LinearCVMixerWidget : BGModuleWidget {
struct DimmableMixerModule : LinearCVMixerModule {
float _dimDb = 12.0f;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
};
struct DimmableMixerWidget : LinearCVMixerWidget {
void contextMenu(Menu* menu) override;
};
-struct MuteButton : ToggleButton {
- bool _randomize = true;
-
+struct MuteButton : LightEmittingWidget<ToggleButton> {
MuteButton() {
addFrame(APP->window->loadSvg(asset::plugin(pluginInstance, "res/button_18px_0.svg")));
addFrame(APP->window->loadSvg(asset::plugin(pluginInstance, "res/button_18px_1_orange.svg")));
}
- inline void setRandomize(bool randomize) { _randomize = randomize; }
- void randomize() override;
void onButton(const event::Button& e) override;
+ bool isLit() override;
+ void draw(const DrawArgs& args) override;
+ void drawLit(const DrawArgs& args) override;
};
-struct SoloMuteButton : ParamWidget {
+struct SoloMuteButton : LightEmittingWidget<ParamWidget> {
std::vector<std::shared_ptr<Svg>> _frames;
SvgWidget* _svgWidget; // deleted elsewhere.
CircularShadow* shadow = NULL;
SoloMuteButton();
- void reset() override;
- void randomize() override;
void onButton(const event::Button& e) override;
void onChange(const event::Change& e) override;
+ bool isLit() override;
+ void draw(const DrawArgs& args) override;
+ void drawLit(const DrawArgs& args) override;
+};
+
+struct DimSwitchQuantity : SwitchQuantity {
+ std::string getDisplayValueString() override;
};
} // namespace bogaudio
diff --git a/src/module.cpp b/src/module.cpp
@@ -22,7 +22,7 @@ json_t* BGModule::dataToJson() {
if (_skinnable && _skin != "default") {
json_object_set_new(root, SKIN, json_string(_skin.c_str()));
}
- return toJson(root);
+ return saveToJson(root);
}
void BGModule::dataFromJson(json_t* root) {
@@ -36,7 +36,7 @@ void BGModule::dataFromJson(json_t* root) {
}
}
- fromJson(root);
+ loadFromJson(root);
}
void BGModule::process(const ProcessArgs& args) {
diff --git a/src/module.hpp b/src/module.hpp
@@ -43,8 +43,8 @@ struct BGModule : Module {
virtual void reset() {}
virtual void sampleRateChange() {}
- virtual json_t* toJson(json_t* root) { return root; }
- virtual void fromJson(json_t* root) {}
+ virtual json_t* saveToJson(json_t* root) { return root; }
+ virtual void loadFromJson(json_t* root) {}
virtual bool active() { return true; }
virtual int channels() { return 1; }
virtual void channelsChanged(int before, int after) {}
diff --git a/src/output_range.hpp b/src/output_range.hpp
@@ -18,15 +18,15 @@ struct OutputRange {
template<class BASE>
struct OutputRangeModule : BASE, OutputRange {
- json_t* toJson(json_t* root) override {
- root = BASE::toJson(root);
+ json_t* saveToJson(json_t* root) override {
+ root = BASE::saveToJson(root);
json_object_set_new(root, "range_offset", json_real(_rangeOffset));
json_object_set_new(root, "range_scale", json_real(_rangeScale));
return root;
}
- void fromJson(json_t* root) override {
- BASE::fromJson(root);
+ void loadFromJson(json_t* root) override {
+ BASE::loadFromJson(root);
json_t* ro = json_object_get(root, "range_offset");
if (ro) {
diff --git a/src/parametric_eq.cpp b/src/parametric_eq.cpp
@@ -130,12 +130,12 @@ float PEQXFBase::scaleEF(float ef, float frequency, float bandwidth) {
#define BAND_EXCLUDE "band_exclude"
-json_t* BandExcludeModule::toJson(json_t* root) {
+json_t* BandExcludeModule::saveToJson(json_t* root) {
json_object_set_new(root, BAND_EXCLUDE, json_boolean(_bandExclude));
return root;
}
-void BandExcludeModule::fromJson(json_t* root) {
+void BandExcludeModule::loadFromJson(json_t* root) {
json_t* be = json_object_get(root, BAND_EXCLUDE);
if (be) {
_bandExclude = json_is_true(be);
diff --git a/src/parametric_eq.hpp b/src/parametric_eq.hpp
@@ -152,8 +152,8 @@ struct PEQXFBase : FollowerBase {
struct BandExcludeModule : BGModule {
bool _bandExclude = false;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
};
struct BandExcludeModuleWidget : BGModuleWidget {
diff --git a/src/poly_channels.cpp b/src/poly_channels.cpp
@@ -5,12 +5,12 @@ using namespace bogaudio;
#define POLY_CHANNELS "poly_channels"
-json_t* PolyChannelsModule::toJson(json_t* root) {
+json_t* PolyChannelsModule::saveToJson(json_t* root) {
json_object_set_new(root, POLY_CHANNELS, json_integer(_polyChannels));
return root;
}
-void PolyChannelsModule::fromJson(json_t* root) {
+void PolyChannelsModule::loadFromJson(json_t* root) {
json_t* pc = json_object_get(root, POLY_CHANNELS);
if (!pc) {
pc = json_object_get(root, "noise_channels"); // backward compatibility hack.
diff --git a/src/poly_channels.hpp b/src/poly_channels.hpp
@@ -9,8 +9,8 @@ namespace bogaudio {
struct PolyChannelsModule : BGModule {
int _polyChannels = 1;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
};
struct PolyChannelsMenuItem : MenuItem {
diff --git a/src/save_latch_to_patch.cpp b/src/save_latch_to_patch.cpp
@@ -3,7 +3,7 @@
#define SAVE_LATCHED_TO_PATCH "save_latched_to_patch"
#define LATCHED_STATE "latched_state"
-json_t* SaveLatchToPatchModule::toJson(json_t* root) {
+json_t* SaveLatchToPatchModule::saveToJson(json_t* root) {
json_object_set_new(root, SAVE_LATCHED_TO_PATCH, json_boolean(_saveLatchedToPatch));
if (_saveLatchedToPatch && _latch) {
json_t* a = json_array();
@@ -15,7 +15,7 @@ json_t* SaveLatchToPatchModule::toJson(json_t* root) {
return root;
}
-void SaveLatchToPatchModule::fromJson(json_t* root) {
+void SaveLatchToPatchModule::loadFromJson(json_t* root) {
json_t* sl = json_object_get(root, SAVE_LATCHED_TO_PATCH);
if (sl) {
_saveLatchedToPatch = json_is_true(sl);
diff --git a/src/save_latch_to_patch.hpp b/src/save_latch_to_patch.hpp
@@ -11,8 +11,8 @@ struct SaveLatchToPatchModule : BGModule {
bool _latchedHigh[maxChannels] {};
bool _latch = false;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
};
struct SaveLatchToPatchModuleWidget : BGModuleWidget {
diff --git a/src/trigger_on_load.cpp b/src/trigger_on_load.cpp
@@ -6,13 +6,13 @@ using namespace bogaudio;
#define TRIGGER_ON_LOAD "triggerOnLoad"
#define SHOULD_TRIGGER_ON_LOAD "shouldTriggerOnLoad"
-json_t* TriggerOnLoadModule::toJson(json_t* root) {
+json_t* TriggerOnLoadModule::saveToJson(json_t* root) {
json_object_set_new(root, TRIGGER_ON_LOAD, json_boolean(_triggerOnLoad));
json_object_set_new(root, SHOULD_TRIGGER_ON_LOAD, json_boolean(shouldTriggerOnNextLoad()));
return root;
}
-void TriggerOnLoadModule::fromJson(json_t* root) {
+void TriggerOnLoadModule::loadFromJson(json_t* root) {
json_t* tol = json_object_get(root, TRIGGER_ON_LOAD);
if (tol) {
_triggerOnLoad = json_is_true(tol);
diff --git a/src/trigger_on_load.hpp b/src/trigger_on_load.hpp
@@ -10,8 +10,8 @@ struct TriggerOnLoadModule : BGModule {
bool _triggerOnLoad = true;
bool _shouldTriggerOnLoad = true;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
virtual bool shouldTriggerOnNextLoad() = 0;
};
diff --git a/src/vco_base.cpp b/src/vco_base.cpp
@@ -76,13 +76,13 @@ void VCOBase::sampleRateChange() {
}
}
-json_t* VCOBase::toJson(json_t* root) {
+json_t* VCOBase::saveToJson(json_t* root) {
json_object_set_new(root, POLY_INPUT, json_integer(_polyInputID));
json_object_set_new(root, DC_CORRECTION, json_boolean(_dcCorrection));
return root;
}
-void VCOBase::fromJson(json_t* root) {
+void VCOBase::loadFromJson(json_t* root) {
json_t* p = json_object_get(root, POLY_INPUT);
if (p) {
_polyInputID = json_integer_value(p);
diff --git a/src/vco_base.hpp b/src/vco_base.hpp
@@ -84,8 +84,8 @@ struct VCOBase : BGModule {
inline float linearModeVoltsToHertz(float v) { return _slowMode ? v : 1000.0f * v; }
void reset() override;
void sampleRateChange() override;
- json_t* toJson(json_t* root) override;
- void fromJson(json_t* root) override;
+ json_t* saveToJson(json_t* root) override;
+ void loadFromJson(json_t* root) override;
int channels() override;
void addChannel(int c) override;
void removeChannel(int c) override;
diff --git a/src/widgets.cpp b/src/widgets.cpp
@@ -6,6 +6,30 @@
using namespace bogaudio;
using namespace bogaudio::dsp;
+DisplayWidget::DisplayWidget(Module* module) : _module(module) {
+}
+
+bool DisplayWidget::isLit() {
+ return _module && !_module->isBypassed();
+}
+
+bool DisplayWidget::isScreenshot() {
+ return !_module;
+}
+
+void DisplayWidget::draw(const DrawArgs& args) {
+ if (!isLit()) {
+ drawOnce(args, isScreenshot(), false);
+ }
+}
+
+void DisplayWidget::drawLit(const DrawArgs& args) {
+ if (isLit()) {
+ drawOnce(args, false, true);
+ }
+}
+
+
std::string SkinnableWidget::skinSVG(const std::string& base, const std::string& skin) {
std::string s = skin;
if (s == "default") {
@@ -20,6 +44,7 @@ std::string SkinnableWidget::skinSVG(const std::string& base, const std::string&
return svg;
}
+
Screw::Screw() {
skinChanged("default");
}
@@ -216,8 +241,8 @@ void IndicatorKnob::onHover(const event::Hover& e) {
void IndicatorKnob::onChange(const event::Change& e) {
fb->dirty = true;
- if (paramQuantity) {
- w->setAngle(paramQuantity->getValue());
+ if (getParamQuantity()) {
+ w->setAngle(getParamQuantity()->getValue());
}
Knob::onChange(e);
}
@@ -227,6 +252,22 @@ void IndicatorKnob::redraw() {
onChange(c);
}
+bool IndicatorKnob::isLit() {
+ return module && !module->isBypassed() && getParamQuantity() &&
+ (getParamQuantity()->getValue() < -0.01f || getParamQuantity()->getValue() > 0.01f) &&
+ (!w->_drawColorsCB || w->_drawColorsCB());
+}
+
+void IndicatorKnob::draw(const DrawArgs& args) {
+ if (!isLit()) {
+ Knob::draw(args);
+ }
+}
+
+void IndicatorKnob::drawLit(const DrawArgs& args) {
+ Knob::draw(args);
+}
+
void IndicatorKnob::skinChanged(const std::string& skin) {
const Skins& skins = Skins::skins();
const char* knobRim = skins.skinCssValue(skin, "knob-rim");
@@ -240,6 +281,7 @@ void IndicatorKnob::skinChanged(const std::string& skin) {
fb->dirty = true;
}
+
Port24::Port24() {
setSvg(APP->window->loadSvg(asset::plugin(pluginInstance, skinSVG("port").c_str())));
box.size = Vec(24, 24);
@@ -301,29 +343,14 @@ StatefulButton::StatefulButton(const char* offSvgPath, const char* onSvgPath) {
shadow->box.pos = Vec(0.0, 1.0);
}
-void StatefulButton::reset() {
- if (paramQuantity) {
- paramQuantity->reset();
- }
-}
-
-void StatefulButton::randomize() {
- if (paramQuantity) {
- float min = paramQuantity->getMinValue();
- float max = paramQuantity->getMaxValue();
- float value = roundf(min + (max - min) * random::uniform());
- paramQuantity->setValue(value);
- }
-}
-
void StatefulButton::onDragStart(const event::DragStart& e) {
- if (paramQuantity) {
+ if (getParamQuantity()) {
_svgWidget->setSvg(_frames[1]);
- if (paramQuantity->getValue() >= paramQuantity->getMaxValue()) {
- paramQuantity->setValue(paramQuantity->getMinValue());
+ if (getParamQuantity()->getValue() >= getParamQuantity()->getMaxValue()) {
+ getParamQuantity()->setValue(getParamQuantity()->getMinValue());
}
else {
- paramQuantity->setValue(paramQuantity->getValue() + 1.0);
+ getParamQuantity()->setValue(getParamQuantity()->getValue() + 1.0);
}
}
}
@@ -352,6 +379,20 @@ IndicatorButtonGreen9::IndicatorButtonGreen9() {
addFrame(APP->window->loadSvg(asset::plugin(pluginInstance, "res/button_9px_1_green.svg")));
}
+bool IndicatorButtonGreen9::isLit() {
+ return module && !module->isBypassed() && getParamQuantity() && getParamQuantity()->getValue() > 0.0f;
+}
+
+void IndicatorButtonGreen9::draw(const DrawArgs& args) {
+ if (!isLit()) {
+ SvgSwitch::draw(args);
+ }
+}
+
+void IndicatorButtonGreen9::drawLit(const DrawArgs& args) {
+ SvgSwitch::draw(args);
+}
+
void InvertingIndicatorButton::IIBWidget::setValue(float v) {
assert(v >= -1.0f && v <= 1.0f);
@@ -448,18 +489,6 @@ InvertingIndicatorButton::InvertingIndicatorButton(int dim) {
fb->addChild(w);
}
-void InvertingIndicatorButton::reset() {
- if (paramQuantity) {
- paramQuantity->reset();
- }
-}
-
-void InvertingIndicatorButton::randomize() {
- if (paramQuantity) {
- paramQuantity->setValue(roundf(2.0f * random::uniform()) - 1.0f);
- }
-}
-
void InvertingIndicatorButton::onHover(const event::Hover& e) {
math::Vec c = box.size.div(2);
float dist = e.pos.minus(c).norm();
@@ -470,37 +499,52 @@ void InvertingIndicatorButton::onHover(const event::Hover& e) {
void InvertingIndicatorButton::onButton(const event::Button& e) {
ParamWidget::onButton(e);
- if (!paramQuantity || !(e.action == GLFW_PRESS && (e.mods & RACK_MOD_MASK) == 0) || e.button == GLFW_MOUSE_BUTTON_RIGHT) {
+ if (!getParamQuantity() || !(e.action == GLFW_PRESS && (e.mods & RACK_MOD_MASK) == 0) || e.button == GLFW_MOUSE_BUTTON_RIGHT) {
return;
}
- float value = paramQuantity->getValue();
+ float value = getParamQuantity()->getValue();
if (value <= -1.0f) {
- paramQuantity->setValue(0.0f);
+ getParamQuantity()->setValue(0.0f);
}
else if (value < 1.0f) {
- paramQuantity->setValue(1.0f);
+ getParamQuantity()->setValue(1.0f);
}
- else if (paramQuantity->minValue < 0.0f && (!clickToInvertCB || clickToInvertCB())) {
- paramQuantity->setValue(-1.0f);
+ else if (getParamQuantity()->minValue < 0.0f && (!clickToInvertCB || clickToInvertCB())) {
+ getParamQuantity()->setValue(-1.0f);
}
else {
- paramQuantity->setValue(0.0f);
+ getParamQuantity()->setValue(0.0f);
}
}
void InvertingIndicatorButton::onChange(const event::Change& e) {
fb->dirty = true;
- if (paramQuantity) {
- float v = paramQuantity->getValue();
+ if (getParamQuantity()) {
+ float v = getParamQuantity()->getValue();
w->setValue(v);
if (onChangeCB) {
- onChangeCB(paramQuantity->paramId, v);
+ onChangeCB(getParamQuantity()->paramId, v);
}
}
ParamWidget::onChange(e);
}
+bool InvertingIndicatorButton::isLit() {
+ return module && !module->isBypassed() && getParamQuantity() &&
+ (getParamQuantity()->getValue() < -0.01f || getParamQuantity()->getValue() > 0.01f);
+}
+
+void InvertingIndicatorButton::draw(const DrawArgs& args) {
+ if (!isLit()) {
+ ParamWidget::draw(args);
+ }
+}
+
+void InvertingIndicatorButton::drawLit(const DrawArgs& args) {
+ ParamWidget::draw(args);
+}
+
NVGcolor bogaudio::decibelsToColor(float db) {
if (db < -80.0f) {
@@ -516,16 +560,18 @@ NVGcolor bogaudio::decibelsToColor(float db) {
}
-void VUSlider::draw(const DrawArgs& args) {
- float level = 0.0f;
- if (paramQuantity) {
- level = paramQuantity->getValue();
- }
- else {
- float minDb = -60.0f;
- float maxDb = 6.0f;
- level = fabsf(minDb) / (maxDb - minDb);
+bool VUSlider::isLit() {
+ float db = _vuLevel ? *_vuLevel : 0.0f;
+ bool stereo = false;
+ float stereoDb = 0.0f;
+ if (_stereoVuLevel) {
+ stereo = true;
+ stereoDb = *_stereoVuLevel;
}
+ return module && !module->isBypassed() && (db > 0.0f || (stereo && stereoDb > 0.0f));
+}
+
+void VUSlider::draw(const DrawArgs& args) {
nvgSave(args.vg);
{
@@ -540,7 +586,7 @@ void VUSlider::draw(const DrawArgs& args) {
nvgSave(args.vg);
{
- nvgTranslate(args.vg, 0, (box.size.y - 13.0f) * (1.0f - level));
+ drawTranslate(args);
nvgBeginPath(args.vg);
nvgRoundedRect(args.vg, 0, 0, 18, 13, 1.5);
nvgFillColor(args.vg, nvgRGBA(0x77, 0x77, 0x77, 0xff));
@@ -560,31 +606,54 @@ void VUSlider::draw(const DrawArgs& args) {
nvgRoundedRect(args.vg, 2, 4, 14, 5, 1.0);
nvgFillColor(args.vg, nvgRGBA(0xaa, 0xaa, 0xaa, 0xff));
nvgFill(args.vg);
+ }
+ nvgRestore(args.vg);
+}
- float db = _vuLevel ? *_vuLevel : 0.0f;
- bool stereo = false;
- float stereoDb = 0.0f;
- if (_stereoVuLevel) {
- stereo = true;
- stereoDb = *_stereoVuLevel;
- }
- if (db > 0.0f) {
- nvgBeginPath(args.vg);
- if (stereo) {
- nvgRoundedRect(args.vg, 2, 4, stereo ? 7 : 14, 5, 1.0);
- }
- else {
- nvgRoundedRect(args.vg, 2, 4, 14, 5, 1.0);
- }
- nvgFillColor(args.vg, decibelsToColor(amplitudeToDecibels(db)));
- nvgFill(args.vg);
+void VUSlider::drawLit(const DrawArgs& args) {
+ float db = _vuLevel ? *_vuLevel : 0.0f;
+ bool stereo = false;
+ float stereoDb = 0.0f;
+ if (_stereoVuLevel) {
+ stereo = true;
+ stereoDb = *_stereoVuLevel;
+ }
+
+ nvgSave(args.vg);
+ drawTranslate(args);
+ if (db > 0.0f) {
+ nvgSave(args.vg);
+ nvgBeginPath(args.vg);
+ if (stereo) {
+ nvgRoundedRect(args.vg, 2, 4, stereo ? 7 : 14, 5, 1.0);
}
- if (stereo && stereoDb > 0.0f) {
- nvgBeginPath(args.vg);
- nvgRoundedRect(args.vg, 9, 4, 7, 5, 1.0);
- nvgFillColor(args.vg, decibelsToColor(amplitudeToDecibels(stereoDb)));
- nvgFill(args.vg);
+ else {
+ nvgRoundedRect(args.vg, 2, 4, 14, 5, 1.0);
}
+ nvgFillColor(args.vg, decibelsToColor(amplitudeToDecibels(db)));
+ nvgFill(args.vg);
+ nvgRestore(args.vg);
+ }
+ if (stereo && stereoDb > 0.0f) {
+ nvgSave(args.vg);
+ nvgBeginPath(args.vg);
+ nvgRoundedRect(args.vg, 9, 4, 7, 5, 1.0);
+ nvgFillColor(args.vg, decibelsToColor(amplitudeToDecibels(stereoDb)));
+ nvgFill(args.vg);
+ nvgRestore(args.vg);
}
nvgRestore(args.vg);
}
+
+void VUSlider::drawTranslate(const DrawArgs& args) {
+ float level = 0.0f;
+ if (getParamQuantity()) {
+ level = getParamQuantity()->getValue();
+ }
+ else {
+ float minDb = -60.0f;
+ float maxDb = 6.0f;
+ level = fabsf(minDb) / (maxDb - minDb);
+ }
+ nvgTranslate(args.vg, 0, (box.size.y - 13.0f) * (1.0f - level));
+}
diff --git a/src/widgets.hpp b/src/widgets.hpp
@@ -11,6 +11,32 @@ extern Plugin *pluginInstance;
namespace bogaudio {
+template <class BASE>
+struct LightEmittingWidget : BASE {
+ virtual bool isLit() = 0;
+
+ void drawLayer(const typename BASE::DrawArgs& args, int layer) override {
+ if (layer == 1 && isLit()) {
+ drawLit(args);
+ }
+ BASE::drawLayer(args, layer);
+ }
+
+ virtual void drawLit(const typename BASE::DrawArgs& args) {}
+};
+
+struct DisplayWidget : LightEmittingWidget<OpaqueWidget> {
+ Module* _module = NULL;
+
+ DisplayWidget(Module* module);
+
+ bool isLit() override;
+ virtual bool isScreenshot();
+ void draw(const DrawArgs& args) override;
+ void drawLit(const DrawArgs& args) override;
+ virtual void drawOnce(const DrawArgs& args, bool screenshot, bool lit) = 0;
+};
+
struct SkinnableWidget : SkinChangeListener {
void skinChanged(const std::string& skin) override {}
std::string skinSVG(const std::string& base, const std::string& skin = "default");
@@ -59,7 +85,7 @@ struct Knob68 : BGKnob {
Knob68();
};
-struct IndicatorKnob : Knob, SkinnableWidget {
+struct IndicatorKnob : LightEmittingWidget<Knob>, SkinnableWidget {
struct IKWidget : widget::Widget {
float _angle = 0.0f;
NVGcolor _color = nvgRGBA(0x00, 0x00, 0x00, 0x00);
@@ -82,6 +108,9 @@ struct IndicatorKnob : Knob, SkinnableWidget {
inline void setDrawColorsCallback(std::function<bool()> fn) { w->_drawColorsCB = fn; }
inline void setUnipolarCallback(std::function<bool()> fn) { w->_unipolarCB = fn; }
void redraw();
+ bool isLit() override;
+ void draw(const DrawArgs& args) override;
+ void drawLit(const DrawArgs& args) override;
void skinChanged(const std::string& skin) override;
};
@@ -118,8 +147,6 @@ struct StatefulButton : ParamWidget {
CircularShadow* shadow = NULL;
StatefulButton(const char* offSvgPath, const char* onSvgPath);
- void reset() override;
- void randomize() override;
void onDragStart(const event::DragStart& e) override;
void onDragEnd(const event::DragEnd& e) override;
void onDoubleClick(const event::DoubleClick& e) override {}
@@ -140,11 +167,15 @@ struct ToggleButton18 : ToggleButton {
ToggleButton18();
};
-struct IndicatorButtonGreen9 : SvgSwitch {
+struct IndicatorButtonGreen9 : LightEmittingWidget<SvgSwitch> {
IndicatorButtonGreen9();
+
+ bool isLit() override;
+ void draw(const DrawArgs& args) override;
+ void drawLit(const DrawArgs& args) override;
};
-struct InvertingIndicatorButton : ParamWidget {
+struct InvertingIndicatorButton : LightEmittingWidget<ParamWidget> {
struct IIBWidget : widget::Widget {
int _dim;
NVGcolor _color = nvgRGBA(0x00, 0x00, 0x00, 0x00);
@@ -165,12 +196,13 @@ struct InvertingIndicatorButton : ParamWidget {
inline void setClickToInvertCallback(std::function<bool()> fn) { clickToInvertCB = fn; }
inline void setOnChangeCallback(std::function<void(int, float)> fn) { onChangeCB = fn; }
- void reset() override;
- void randomize() override;
void onHover(const event::Hover& e) override;
void onDoubleClick(const event::DoubleClick& e) override {}
void onButton(const event::Button& e) override;
void onChange(const event::Change& e) override;
+ bool isLit() override;
+ void draw(const DrawArgs& args) override;
+ void drawLit(const DrawArgs& args) override;
};
struct InvertingIndicatorButton9 : InvertingIndicatorButton {
@@ -183,7 +215,7 @@ struct InvertingIndicatorButton18 : InvertingIndicatorButton {
NVGcolor decibelsToColor(float db);
-struct VUSlider : SliderKnob {
+struct VUSlider : LightEmittingWidget<SliderKnob> {
const float slideHeight = 13.0f;
float* _vuLevel = NULL;
float* _stereoVuLevel = NULL;
@@ -198,11 +230,44 @@ struct VUSlider : SliderKnob {
inline void setStereoVULevel(float* level) {
_stereoVuLevel = level;
}
+ bool isLit() override;
void draw(const DrawArgs& args) override;
+ void drawLit(const DrawArgs& args) override;
+ void drawTranslate(const DrawArgs& args);
};
struct VUSlider151 : VUSlider {
VUSlider151() : VUSlider(151.0f) {}
};
+template <typename TBase>
+struct BGTinyLight : TinyLight<TBase> {
+ void drawLight(const typename TinyLight<TBase>::DrawArgs& args) override {
+ if (!TinyLight<TBase>::module || !TinyLight<TBase>::module->isBypassed()) {
+ TinyLight<TBase>::drawLight(args);
+ }
+ }
+
+ void drawHalo(const typename TinyLight<TBase>::DrawArgs& args) override {
+ if (!TinyLight<TBase>::module || !TinyLight<TBase>::module->isBypassed()) {
+ TinyLight<TBase>::drawHalo(args);
+ }
+ }
+};
+
+template <typename TBase>
+struct BGSmallLight : SmallLight<TBase> {
+ void drawLight(const typename SmallLight<TBase>::DrawArgs& args) override {
+ if (!SmallLight<TBase>::module || !SmallLight<TBase>::module->isBypassed()) {
+ SmallLight<TBase>::drawLight(args);
+ }
+ }
+
+ void drawHalo(const typename SmallLight<TBase>::DrawArgs& args) override {
+ if (!SmallLight<TBase>::module || !SmallLight<TBase>::module->isBypassed()) {
+ SmallLight<TBase>::drawHalo(args);
+ }
+ }
+};
+
} // namespace bogaudio