Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Envelopes & Modulators

Modulation sources shape how parameters change over time, creating movement and expression.

ADSR Envelope

The classic Attack-Decay-Sustain-Release envelope generator.

let env = patch.add("env", Adsr::new(44100.0));

Inputs

PortSignalRangeDescription
gateGate0/5VTrigger/sustain signal
attackUnipolar CV0-10VAttack time (ms-s)
decayUnipolar CV0-10VDecay time (ms-s)
sustainUnipolar CV0-10VSustain level (0-100%)
releaseUnipolar CV0-10VRelease time (ms-s)

Output

PortSignalDescription
envUnipolar CVEnvelope output (0-5V)

Envelope Stages

Level
  5V ┤    ╱╲
     │   ╱  ╲____
     │  ╱        ╲
     │ ╱          ╲
  0V ┼╱────────────╲────
     A    D   S    R

Timing Curves

All stages use exponential curves:

Attack: $$v(t) = 5 \cdot (1 - e^{-t/\tau_a})$$

Decay/Release: $$v(t) = (v_{start} - v_{end}) \cdot e^{-t/\tau} + v_{end}$$

Typical Settings

SoundAttackDecaySustainRelease
Pluck5ms200ms0%100ms
Pad1s500ms80%2s
Brass50ms100ms70%200ms
Perc1ms50ms0%50ms

LFO (Low-Frequency Oscillator)

See Oscillators for full documentation.

Quick reference:

let lfo = patch.add("lfo", Lfo::new(44100.0));
patch.connect(lfo.out("sin"), vcf.in_("fm"))?;

Sample and Hold

Captures input value on trigger pulse.

let sh = patch.add("sh", SampleAndHold::new());

Inputs

PortSignalDescription
inCV/AudioSignal to sample
triggerTriggerWhen to sample

Output

PortSignalDescription
outCVHeld value

Classic Use: Random CV

// Random stepped modulation
patch.connect(noise.out("white_left"), sh.in_("in"))?;
patch.connect(clock.out("div_8"), sh.in_("trigger"))?;
patch.connect(sh.out("out"), vcf.in_("cutoff"))?;

Slew Limiter

Limits rate of change—creates portamento and smoothing.

let slew = patch.add("slew", SlewLimiter::new(44100.0));

Inputs

PortSignalDescription
inCVInput signal
riseUnipolar CVRise time (upward slew)
fallUnipolar CVFall time (downward slew)

Output

PortSignalDescription
outCVSlewed output

Applications

flowchart LR
    subgraph "Portamento"
        P1[Pitch CV] --> SLEW1[Slew] --> VCO1[VCO]
    end

    subgraph "Envelope Follower"
        P2[Audio] --> RECT[Rectify] --> SLEW2[Slew]
    end

    subgraph "Smooth Random"
        P3[S&H] --> SLEW3[Slew] --> MOD[Smooth CV]
    end

Quantizer

Snaps continuous CV to scale degrees.

let quant = patch.add("quant", Quantizer::new());

Inputs

PortSignalDescription
inV/OctUnquantized pitch
scaleCVScale selection

Output

PortSignalDescription
outV/OctQuantized pitch

Available Scales

ScaleNotes
ChromaticAll 12 semitones
Major1 2 3 4 5 6 7
Minor1 2 ♭3 4 5 ♭6 ♭7
Pentatonic1 2 3 5 6
Blues1 ♭3 4 ♭5 5 ♭7

Clock

Master timing generator.

let clock = patch.add("clock", Clock::new(44100.0));

Inputs

PortSignalDescription
tempoUnipolar CVBPM (0-10V = 20-300 BPM)
resetTriggerReset to beat 1

Outputs

PortSignalDescription
div_1TriggerWhole notes
div_2TriggerHalf notes
div_4TriggerQuarter notes
div_8TriggerEighth notes
div_16TriggerSixteenth notes
div_32Trigger32nd notes

Step Sequencer

8-step CV/gate sequencer.

let seq = patch.add("seq", StepSequencer::new());

Inputs

PortSignalDescription
clockTriggerAdvance to next step
resetTriggerReturn to step 1

Outputs

PortSignalDescription
cvV/OctStep CV value
gateGateStep gate state

Programming Steps

The sequencer holds 8 CV/gate pairs. In a full application, you’d set these via UI or MIDI.