Follow the Signal
A patch is not a program that runs once — it is a circuit where every cable carries a living voltage, all the time. The diagram below is the classic subtractive voice from Your First Patch: a gate triggers an envelope, while the oscillator’s audio runs through a filter and an amplifier. Click any module to put a scope on its output and watch the same note from six different points in the circuit. The strip of mini-scopes under the main scope shows all six stations at once — tap one to jump the big scope there — and while the note plays, a playhead sweeps the full-note view so you can match what you hear to where you are.
The voice plays a note at -1 V (1 V/octave, so −1 V is C3), with the gate held for 0.6 s. The filter sits at a base cutoff of 0.15 (knob CV, 0–1) with resonance 0.25, and the envelope pushes the cutoff up by 0.55 before falling back — the brightness of the note is a shape in time, not a setting.
Things to try
- Read the mini-scope strip left to right: rectangle → contour → tone → sculpted tone → note. That row is the patch — every station of the transformation in one glance. Tap any mini-scope to inspect it up close.
- Scope the VCO, then the SVF, then the VCA — the same 30 ms of waveform at three stations. The saw’s sharp corners melt at the filter, and the VCA finally gives the sound a beginning and an end.
- Turn zoom to waveform off while scoping the VCA, then press ▶ hear this point: the playhead sweeps the note’s whole amplitude contour — the ADSR curve, worn by the audio like a glove — while you listen.
- Scope the GATE and then the ADSR: a rectangle goes in, a contour comes out. Every knob on an envelope module is a statement about how to round off a rectangle.
- Drag the envelope→cutoff depth to
0: the note becomes static and dull — subtractive synthesis with nobody moving the tone control. Now drag it to1and listen to the attack spit. - Raise resonance toward
1with a low base cutoff: the filter starts to sing its own note on top of the saw (the SVF self-oscillates; its integrator states are soft-clipped in the Rust so this stays bounded). - Shorten the gate to
0.1s: the envelope never reaches sustain — you can see it turn around mid-decay when the gate falls.
What you just saw
Each cable color is a signal type, and each type is a voltage convention:
- audio — the sound itself, ±5 V
- CV — control voltage, here the envelope’s 0–10 V
- gate — 0 V or +5 V, “the key is down”
- V/Oct — pitch, one volt per octave, 0 V = C4
The VCA is nothing but a multiplication,
\[ \text{out}(t) = \text{in}(t) \cdot \frac{\text{cv}(t)}{10~\text{V}}, \]
and the filter’s cutoff knob follows an exponential law so that equal knob motion covers equal musical distance,
\[ f_c(\text{cv}) = 20 \cdot 1000^{\text{cv}}~\text{Hz}, \qquad \text{cv} \in [0, 1]. \]
The envelope output is 10 V at full level, while the cutoff CV wants 0–1 — in
hardware you would patch through an attenuverter, and Quiver’s cutoff port
carries one for exactly this reason. The scrub for depth above is that
attenuverter.
The Quiver code
This is the real example the diagram mirrors — module for module, cable for
cable (examples/first_patch.rs):
//! First Patch Example
//!
//! A complete subtractive synthesizer voice demonstrating the core
//! Quiver workflow: VCO → VCF → VCA with ADSR envelope shaping.
//!
//! How this differs from `simple_patch.rs`: that example is the bare-minimum
//! patch (just a VCO wired to the output, no envelope or gate at all). This
//! one is the fuller voice you'd actually use in a synth — a gate signal
//! triggers an ADSR envelope, which shapes both the filter's cutoff and the
//! VCA's amplitude, so a "note" has a distinct attack and release instead of
//! playing as a static, unchanging tone.
//!
//! Run with: cargo run --example first_patch
use quiver::prelude::*;
use std::sync::Arc;
fn main() {
// CD-quality sample rate
let sample_rate = 44100.0;
// Create our patch (virtual modular case)
let mut patch = Patch::new(sample_rate);
// External control: gate signal for envelope triggering
let gate_cv = Arc::new(AtomicF64::new(0.0));
// Add modules to the patch
let gate = patch.add("gate", ExternalInput::gate(Arc::clone(&gate_cv)));
let vco = patch.add("vco", Vco::new(sample_rate));
let vcf = patch.add("vcf", Svf::new(sample_rate));
let vca = patch.add("vca", Vca::new());
let env = patch.add("env", Adsr::new(sample_rate));
let output = patch.add("output", StereoOutput::new());
// Patch cables: signal flow
// Gate triggers the envelope
patch.connect(gate.out("out"), env.in_("gate")).unwrap();
// VCO → VCF → VCA → Output (main audio path)
patch.connect(vco.out("saw"), vcf.in_("in")).unwrap();
patch.connect(vcf.out("lp"), vca.in_("in")).unwrap();
patch.connect(vca.out("out"), output.in_("left")).unwrap();
patch.connect(vca.out("out"), output.in_("right")).unwrap();
// Envelope modulates both filter and amplitude
patch.connect(env.out("env"), vcf.in_("cutoff")).unwrap();
patch.connect(env.out("env"), vca.in_("cv")).unwrap();
// Compile the patch for processing
patch.set_output(output.id());
patch.compile().unwrap();
println!(
"Patch compiled: {} modules, {} cables",
patch.node_count(),
patch.cable_count()
);
println!();
// Play a note: gate on
println!("Note ON - Gate rises to +5V");
gate_cv.set(5.0);
// Process attack phase (0.5 seconds)
let attack_samples = (sample_rate * 0.5) as usize;
let mut peak = 0.0_f64;
for _ in 0..attack_samples {
let (left, _) = patch.tick();
peak = peak.max(left.abs());
}
println!(" Attack complete, peak level: {:.2}V", peak);
// Release the note: gate off
println!("Note OFF - Gate falls to 0V");
gate_cv.set(0.0);
// Process release phase
let release_samples = (sample_rate * 1.0) as usize;
let mut release_peak = 0.0_f64;
for _ in 0..release_samples {
let (left, _) = patch.tick();
release_peak = release_peak.max(left.abs());
}
println!(" Release complete, final level: {:.4}V", release_peak);
println!();
println!("Subtractive synthesis voice complete!");
}
Run it with cargo run --example first_patch.
Go deeper
- Tutorial: Basic Subtractive Synthesis builds this voice step by step.
- Concepts: Understanding Signal Flow and Signal Conventions for the voltage rules the colors encode.
- Other explorables: each module in this circuit has its own page — the oscillator, the filter, the envelope, pitch.