tidy vco
tidyVco · sourcesTIDY VCO — flagship virtual-analog SUBTRACTIVE SYNTH VOICE: two polyBLEP oscillators with a continuous saw↔pulse SHAPE morph per osc, shared PW + audio-rate PWM CV, OSC2 octave switch + cents detune, and a −1-octave sub square, into an ALL-NEW nonlinear zero-delay-feedback DIODE LADDER filter (EMS VCS3 / TB-303 lineage — bidirectionally-coupled stages, soft warm knee into 24 dB/oct, feedback squelch limiter for a bounded near-sine self-oscillation, CUTOFF calibrated to the resonant pitch within 3 cents so keytracked self-osc plays in tune, DRIVE tanh saturation at 2× oversampling, part-compensated squelch bass dip). Two RC-curve "punch" ADSRs (CEM3310-style exponential segments, overshoot-target convex attack, analog resume-from-level retrigger): a filter EG with bipolar ±4-octave ENV amount + keytracking, and an amp EG into an OTA-flavored soft-knee VCA whose tanh bias blooms gentle even harmonics with level. 5-voice POLY on the polyPitchGate chord bus (lane i → voice i, release tails hold their pitch) AND a mono pitch/gate pair driving a REAL 2-voice unison (±7¢·WIDTH drift panned to opposite sides — true stereo beating); WIDTH also fans the poly voices across the stereo field (root anchored center). Stereo out_l/out_r pair (auto-wires R when L is patched), HOLD pad for droning the voice from the card, and a CV jack for EVERY control (27 inputs): the six original CVs — cutoff (4 oct/V, audio-rate), res, pwm (audio-rate), drive, fold (audio-rate), sym (audio-rate) — PLUS a GLOBAL block-rate per-knob CV for each remaining control: shape1/shape2/mix/sub/fsus/sus/track/width (0..1 full-swing), detune (±50¢), oct2 (discrete ±1 step/V), env (±4-oct bipolar), the six EG times (4 oct/V), and level (±18 dB/V). Every law is scaled in the shared core (lib/tidy-vco-dsp.ts) so cv = 0 is a byte-exact no-op. The rear patch panel groups its jacks into OSC·WAVEFOLD·DIODE FILTER·FILTER EG·AMP EG·OUT·POLY/OUT sections mirroring the card headers.
the faceplate
inputs
| id | cable | what it does |
|---|---|---|
poly | polyPitchGate | The 5-lane poly pitch/gate chord bus: lane i drives voice i (fixed mapping, no allocator). Patch a real poly source — MIDI LANE, POLYSEQZ, or a SEQUENCER with chords — and each gated lane opens that voice’s own filter + amp envelopes; a releasing voice keeps sounding at its held pitch. While ANY lane is gated this bus wins over the mono pitch/gate pair. poly pitch+gate bus; 10-channel poly bus (5 pitch + 5 gate lanes) |
pitch | cv | Mono pitch CV, 1 V/oct with 0 V = C4. When no poly lane is gated, this drives the 2-voice unison pair (both voices track it, split by WIDTH’s detune drift). control voltage (CV) |
gate | gate | Mono gate (level-sensitive, not edge-only): high opens the unison pair’s envelopes, low releases them — note-off matters, an ADSR sustain lives while this is held. The panel HOLD pad ORs into this gate, and poly lanes take precedence the moment any lane goes high. gate / trigger; gate — acts while the level is high (reacts to both edges) |
cutoff_cv | cv | Filter cutoff CV at 4 octaves per volt — a ±1 V full swing covers ±4 octaves around the CUTOFF knob. Audio-rate (per-sample) for filter FM growl. control voltage (CV) |
res_cv | cv | Resonance CV: ±1 V spans the whole RES range on top of the knob — sequence the squelch, or push a moderate knob setting over the self-osc threshold. control voltage (CV) |
pwm_cv | cv | Pulse-width modulation CV: ±0.45 duty per volt on the shared PW, audio-rate. The effective width is clamped 0.05–0.95, so CV reaches wide duties past the knob’s 0.5 (square) ceiling. Classic PWM strings come from an LFO here with SHAPE at pulse. control voltage (CV) |
drive_cv | cv | Drive CV: ±1 V spans the whole DRIVE range on top of the knob — automate the filter’s input saturation for building intensity. control voltage (CV) |
fold_cv | cv | Wavefolder FOLD CV: ±1 V spans the whole FOLD range on top of the knob, audio-rate. The folder is very modulation-hungry — an envelope or LFO here sweeps timbre from clean to fully folded (classic West-Coast dynamic-fold gestures). control voltage (CV) |
sym_cv | cv | Wavefolder SYMMETRY CV: ±1 V spans the whole asymmetry range each way, audio-rate. Modulate the fold’s bias to make the even-harmonic content breathe (only audible while FOLD is up). control voltage (CV) |
shape1_cv | cv | OSC1 SHAPE CV: ±1 V sweeps the full saw↔pulse morph (0..1) on top of the knob. GLOBAL (all 5 voices), block-rate; cv = 0 is a no-op. control voltage (CV) |
shape2_cv | cv | OSC2 SHAPE CV: ±1 V sweeps the full saw↔pulse morph (0..1) on top of the knob. GLOBAL (all voices), block-rate. control voltage (CV) |
detune_cv | cv | OSC2 DETUNE CV (cents, linear): ±1 V sweeps ±50 ¢ — the full detune range centered on the knob. GLOBAL (all voices), block-rate; feed a slow LFO for a drifting chorus. control voltage (CV) |
oct2_cv | cv | OSC2 OCTAVE CV (discrete): 1 octave step per volt, summed with the knob, rounded and clamped to −1 / 0 / +1. GLOBAL (all voices), block-rate. control voltage (CV) |
mix_cv | cv | OSC1↔OSC2 MIX CV: ±1 V sweeps the full equal-power balance (0..1) on top of the knob. GLOBAL (all voices), block-rate. control voltage (CV) |
sub_cv | cv | SUB-oscillator level CV: ±1 V sweeps the full sub-square level (0..1) on top of the knob. GLOBAL (all voices), block-rate. control voltage (CV) |
env_cv | cv | Filter-EG AMOUNT CV (bipolar): ±1 V sweeps the full ±1 ENV depth (±4 octaves of cutoff sweep) centered on the knob. GLOBAL (all voices), block-rate. control voltage (CV) |
track_cv | cv | Cutoff KEYTRACKING CV: ±1 V sweeps the full 0–100 % TRACK amount on top of the knob. GLOBAL (all voices), block-rate. control voltage (CV) |
fatk_cv | cv | Filter-EG ATTACK-time CV: 4 octaves of time per volt (+1 V = ×16, −1 V = ×1⁄16) multiplying the knob time. GLOBAL (all voices), block-rate; cv = 0 = ×1, a no-op. control voltage (CV) |
fdec_cv | cv | Filter-EG DECAY-time CV: 4 octaves of time per volt on top of the knob. GLOBAL (all voices), block-rate. control voltage (CV) |
fsus_cv | cv | Filter-EG SUSTAIN CV: ±1 V sweeps the full 0–1 sustain level on top of the knob. GLOBAL (all voices), block-rate. control voltage (CV) |
frel_cv | cv | Filter-EG RELEASE-time CV: 4 octaves of time per volt on top of the knob. GLOBAL (all voices), block-rate. control voltage (CV) |
atk_cv | cv | Amp-EG ATTACK-time CV: 4 octaves of time per volt (+1 V = ×16) multiplying the knob time. GLOBAL (all voices), block-rate. control voltage (CV) |
dec_cv | cv | Amp-EG DECAY-time CV: 4 octaves of time per volt on top of the knob. GLOBAL (all voices), block-rate. control voltage (CV) |
sus_cv | cv | Amp-EG SUSTAIN CV: ±1 V sweeps the full 0–1 sustain level on top of the knob. GLOBAL (all voices), block-rate. control voltage (CV) |
rel_cv | cv | Amp-EG RELEASE-time CV: 4 octaves of time per volt on top of the knob. GLOBAL (all voices), block-rate. control voltage (CV) |
width_cv | cv | Stereo WIDTH CV: ±1 V sweeps the full 0–1 width — the poly pan fan / mono unison spread AND the wavefolder’s stereo decorrelation. GLOBAL, block-rate. control voltage (CV) |
level_cv | cv | Output LEVEL CV (dB): ±1 V sweeps ±18 dB — the full 36 dB level range centered on the knob (clamped −24..+12 dB into the true-peak bound). GLOBAL, block-rate; cv = 0 is a no-op. control voltage (CV) |
outputs
| id | cable | what it does |
|---|---|---|
out_l | audio | Left output of the stereo voice bus (equal-power voice pans, 1/√n normalization, dB LEVEL, DC-blocked, true-peak bounded). Pairs with out_r — patching L into a stereo target auto-wires R. audio signal; L/R stereo pair with out_r |
out_r | audio | Right output — the partner of out_l, carrying the WIDTH pan fan (poly) or the opposite unison voice (mono). audio signal; L/R stereo pair with out_l |
params
| id | label | range | default | curve |
|---|---|---|---|---|
shape1 | Shape 1 | 0..1 | 0 | linear |
shape2 | Shape 2 | 0..1 | 0 | linear |
pw | PW | 0.05..0.5 | 0.5 | linear |
detune | Detune | -50..50¢ | 6 | linear |
oct2 | Oct 2 | -1..1 | 0 | discrete |
mix | Mix | 0..1 | 0.5 | linear |
sub | Sub | 0..1 | 0.15 | linear |
fold | Fold | 0..1 | 0 | linear |
sym | Sym | -1..1 | 0 | linear |
cutoff | Cutoff | 40..14000Hz | 900 | log |
res | Res | 0..1 | 0.35 | linear |
drive | Drive | 0..1 | 0.25 | linear |
env | Env | -1..1 | 0.45 | linear |
track | Track | 0..1 | 0.4 | linear |
fatk | F.A | 0.0005..5s | 0.005 | log |
fdec | F.D | 0.001..5s | 0.35 | log |
fsus | F.S | 0..1 | 0.2 | linear |
frel | F.R | 0.001..5s | 0.3 | log |
atk | A | 0.0005..5s | 0.003 | log |
dec | D | 0.001..5s | 0.25 | log |
sus | S | 0..1 | 0.75 | linear |
rel | R | 0.001..5s | 0.25 | log |
width | Width | 0..1 | 0.4 | linear |
level | Level | -24..12dB | 0 | linear |
hold | Hold | 0..1 | 0 | discrete |
controls
| control | what it does |
|---|---|
| A | Amp attack time — the same convex RC punch: a re-struck note resumes from its current level (analog retrigger, no reset click). |
| Cutoff | Filter cutoff, 40 Hz–14 kHz — calibrated to the RESONANT pitch: at full RES the filter whistles AT this frequency (and tracks it to under 3 cents). The zero-res brightness knee sits a few octaves below the knob — the diode ladder’s soft spread knee, part of its warmth. |
| D | Amp decay time to SUSTAIN while the note is held. |
| Detune | OSC2 detune in cents (±50): a few cents gives the classic two-osc VA shimmer — the pair beats at a rate proportional to the note’s frequency, so high notes shimmer faster — while large values approach quarter-tone clash. |
| Drive | Input saturation into the ladder (2× oversampled tanh with loudness makeup): grows odd harmonics by tens of dB across the travel without acting as a volume knob. |
| Env | Filter-EG amount, bipolar: up to ±4 octaves of cutoff sweep from the filter ADSR. Negative values pull the attack DARK and open into the sustain. |
| F.A | Filter EG attack time (RC-curve: exponential charge toward an overshoot target — front-loaded, punchy). |
| F.D | Filter EG decay time to the filter sustain level (−60 dB RC convention). |
| Fold | Stereo WAVEFOLDER amount, placed BEFORE the filter (the West-Coast timbre-into-lowpass voice): 0 is a true bypass (the voice sounds exactly as it did without the folder), and turning it up drives the osc bus into a reflecting triangle folder that reflects more times as you climb — a rising thicket of harmonics the diode ladder then shapes. The fold is antialiased (ADAA + 2× oversampling) and GENUINELY stereo: L and R fold at antiphase points (scaled by WIDTH) so the folder itself widens the image, more as FOLD rises. Very modulation-hungry — patch an envelope or LFO into the FOLD CV. |
| F.R | Filter EG release time after note-off (the brightness falls at its own rate, independent of the amp tail). |
| F.S | Filter EG sustain level — the settled brightness while a note is held. |
| Hold | Momentary drone pad: pressed = the mono gate held high, released = note-off (no latch). OR-ed with the GATE jack — an external gate keeps working — and poly lanes still win while any lane is gated. The fastest way to audition the voice as you shape it. |
| Level | Output level in dB (−24…+12) into the true-peak bound. |
| Mix | Equal-power OSC1↔OSC2 balance: 0 = OSC1 only, 1 = OSC2 only. |
| Oct 2 | OSC2 octave switch — three states, not a sweep: −1 (an octave below OSC1), 0 (OSC1’s own octave, where DETUNE alone separates the pair into the classic two-osc shimmer) and +1 (an octave above). At ±1 the DETUNE beat rides on top of the interval rather than replacing it. |
| PW | Shared pulse width for both oscillators’ pulse legs: 0.5 = square (even harmonics nulled) down to 0.05 = a thin reedy sliver. The PWM CV jack modulates around this — and can push the effective width past the knob’s square ceiling, up to 0.95. |
| R | Amp release time after note-off. |
| Res | Resonance: squelchy diode-ladder emphasis that compresses through the feedback limiter as it rises; self-oscillation starts near 0.89 and the whistle stays bounded and near-sinusoidal. High RES also drops the passband by design — up to ~10 dB near full resonance, part-compensated from the raw diode ladder’s −25 dB collapse: the 303 body-drop squelch dip. |
| Shape 1 | OSC1 waveform morph: 0 = sawtooth, 1 = pulse, continuous crossfade between (both legs band-limited; the even harmonics drain out as it approaches the square). |
| Shape 2 | OSC2 waveform morph, same law as SHAPE 1 (0 = saw, 1 = pulse). |
| Sub | Sub-oscillator level: a band-limited square one octave below OSC1, mixed under the pair for floor weight. |
| S | Amp sustain level (read live — sweeping it during a held note tracks). |
| Sym | Wavefolder SYMMETRY: a bipolar DC bias on the fold input (only active while FOLD is up). At center the fold is symmetric (odd harmonics only); pushed either way it folds asymmetrically, blooming EVEN harmonics for a hollow, brassy, or reedy character. Modulate it with the SYM CV. |
| Track | Cutoff keytracking, 0–100 %: at 100 % the filter (and its self-osc whistle) follows the keyboard exactly — play the resonance as a voice. |
| Width | Stereo width: in poly it fans the five voices across the field (root anchored center); in mono it engages the 2-voice unison — ±(7 ¢ × WIDTH) drift panned to opposite sides. It also scales the wavefolder’s L/R decorrelation, so the folder widens with it. 0 = center mono, 1 = full field. |
source
tidy-vco.ts on GitHub.