helm

helm · sources · schema v1

Polyphonic subtractive synth — algorithm port of Matt Tytel's Helm (helm_engine.cpp / helm_voice_handler.cpp / helm_oscillators.cpp / helm_lfo.cpp / state_variable_filter.cpp / envelope.cpp / step_generator.cpp, originally GPL-3.0, ported to AGPL-3.0-or-later per the project's license relicense). v1 ships: 4-8 voice polyphony (Voices knob); 2 morphing oscillators (saw/square/triangle/sine continuous morph) with per-osc transpose (±24 st), tune (±100 ¢), unison (1..7 voices, detune ±50 ¢ spread), and volume; 1 sub oscillator (-2 oct, selectable wave); white-noise source; state-variable filter (Andy Simper TPT topology, Cytomic formulation) with 12dB / 24dB pole select, LP↔BP↔HP continuous blend, drive, resonance, key-track; three ADSR envelopes (amplitude, filter, mod) with depth knobs for filter-env → cutoff and mod-env → osc1 pitch; two mono LFOs pre-wired (LFO1 → filter cutoff, LFO2 → osc2 pitch); 16-step step sequencer with smoothing + frequency division pre-wired to osc2 transpose; stereo output with adjustable voice-pan spread. Polyphonic MIDI input via the gear-icon settings panel — pick a connected Web MIDI device + select which of channels 1-16 to receive on (multi-select; ALL is the default). Multiple held notes simultaneously trigger multiple voices via a free-slot / steal-oldest allocator. Optional pitch_cv (V/oct) + gate fallback inputs let the module be driven by SCORE / sequencer cables when no MIDI is connected. DEFERRED to follow-up PRs: effects bus (distortion / delay / reverb / stutter / formant / feedback), arpeggiator, poly LFO, mod sources panel (aftertouch / mod wheel / pitch wheel / random), BPM-locked LFO frequencies, and a freeform modulation matrix (v1 hard-wires mod sources to musically sensible defaults — see the helm.ts worklet header for the routing table).

A full polyphonic subtractive (analog-style) synth voice — a port of Matt Tytel's Helm. The signal chain per voice is: two morphing oscillators (each saw/square/triangle/sine, with their own tune, transpose, unison stack and detune) plus a sub-oscillator and a noise source are mixed, run through one state-variable multimode resonant filter (low-pass / band-pass / high-pass, 12 or 24 dB/oct), and shaped by an amplitude VCA. Three dedicated ADSR envelopes drive it: the AMP envelope shapes loudness, the FILTER envelope sweeps the filter cutoff by an amount you set, and the MOD envelope is a spare modulation source. Two LFOs and a built-in 16-step sequencer add motion. Mental model: hold notes (via MIDI or a patched gate) and each note grabs one of up to 8 voices; voiceCount sets how many notes can sound at once, and voices are stolen oldest-first when you run out. v1 pre-wires the modulators to musical destinations (LFO1→cutoff, LFO2→osc2 pitch, MOD env→osc1 pitch, step sequencer→osc2 transpose) rather than exposing Helm's full mod matrix.

the faceplate

helmpitch_cvcvgategatemidi_incvseq_resetgateout_laudioout_raudioaudiocvgatepitch
4 inputs · 2 outputs · 48 params

inputs

idcablewhat it does
pitch_cvcvMonophonic V/oct pitch for the fallback CV/gate path used when no MIDI device is connected: while the GATE input is high it plays a single voice at midi note 60 + (pitch_cv × 12 semitones). MIDI note input (via the gear-icon device picker) takes priority and drives true polyphony; this CV path is a single-note fallback for patching from a sequencer or keyboard CV.
control voltage (CV)
gategateNote on/off gate for the fallback CV/gate path (level-sensitive): a rising edge starts a note at the current pitch_cv and a falling edge releases it. It is ALSO the sequencer's clock — every rising edge here advances the built-in step sequencer one step (and re-attacks the envelopes), so the same gate that plays notes also walks the pattern.
gate / trigger
midi_incvA presentation-only port that exists so MIDI shows up as a first-class cable on the panel; it carries no audio or CV and nothing is read from it. Actual MIDI flows through the Web MIDI API (open the gear icon to pick a device and receive channels), not through this cable.
control voltage (CV)
seq_resetgateReset gate for the built-in step sequencer (trigger): a rising edge snaps the step pointer back so the next gate advance lands on step 0. Honored whether or not the sequencer is switched on, so you can sync the pattern's start to a clock or another sequencer.
gate / trigger

outputs

idcablewhat it does
out_laudioLeft channel of the stereo mix of all sounding voices. The stereo image comes from spreading each oscillator's unison voices across the field by the SPR (spread) amount; with no unison and spread at 0 the output is effectively centered/mono.
audio signal
out_raudioRight channel of the stereo mix of all sounding voices (the spread partner of out_l). Patch both out_l and out_r to keep the unison/pan stereo image.
audio signal

params

idlabelrangedefaultcurve
voiceCountVoices1..86discrete
volumeVol0..20.7linear
osc1WaveO1 Wav0..30discrete
osc1TransO1 Tr-24..24st0linear
osc1TuneO1 Tu-100..100c0linear
osc1UnisonO1 Uni1..71discrete
osc1DetuneO1 Det0..50c10linear
osc1VolO1 Vol0..10.8linear
osc2WaveO2 Wav0..31discrete
osc2TransO2 Tr-24..24st0linear
osc2TuneO2 Tu-100..100c7linear
osc2UnisonO2 Uni1..71discrete
osc2DetuneO2 Det0..50c10linear
osc2VolO2 Vol0..10.6linear
subWaveSub W0..33discrete
subVolSub V0..10.4linear
noiseVolNoise0..10linear
filterCutoffCut20..20000Hz4000log
filterResRes0.5..161linear
filterBlendMode0..20linear
filterStylePole0..10discrete
filterDriveDrv0.5..61linear
filterKeyTrackKey-1..10linear
ampAttackA A0..8s0.005linear
ampDecayA D0..8s0.2linear
ampSustainA S0..10.6linear
ampReleaseA R0..8s0.3linear
filAttackF A0..8s0.005linear
filDecayF D0..8s0.5linear
filSustainF S0..10linear
filReleaseF R0..8s0.3linear
filEnvDepthF Dpth-1..10linear
modAttackM A0..8s0.005linear
modDecayM D0..8s0.5linear
modSustainM S0..10linear
modReleaseM R0..8s0.3linear
modEnvDepthM Dpth-1..10linear
lfo1WaveL1 W0..33discrete
lfo1FreqL1 Hz0.01..30Hz1log
lfo1AmpL1 Amt0..10linear
lfo2WaveL2 W0..33discrete
lfo2FreqL2 Hz0.01..30Hz4log
lfo2AmpL2 Amt0..10linear
stepNumStepsSteps1..168discrete
stepRateSt Hz0.1..30Hz4log
stepSmoothSt Smth0..10linear
stepDepthSt Dpth-1..10linear
spreadSpr0..10.3linear

controls

controlwhat it does
A AAmplitude envelope attack time in seconds (0–8): how quickly each note fades in on note-on.
A DAmplitude envelope decay time in seconds (0–8): how quickly the level falls from peak to the sustain level after the attack.
A RAmplitude envelope release time in seconds (0–8): how long the note takes to fade out after note-off.
A SAmplitude envelope sustain level (0–1): the steady loudness held while the note is on, after the decay.
F AFilter envelope attack time in seconds (0–8): how fast the filter-env contour rises on note-on (its effect on cutoff is scaled by F Dpth).
F DFilter envelope decay time in seconds (0–8): fall from the envelope's peak to its sustain.
F DpthHow much (and which direction) the filter envelope modulates the cutoff (−1 to +1, labeled F Dpth): positive sweeps the cutoff up with the envelope, negative sweeps it down, 0 disables the filter envelope's effect.
F RFilter envelope release time in seconds (0–8) after note-off.
F SFilter envelope sustain level (0–1) held while the note is on (default 0, so by default the filter sweep decays away).
ModeContinuously crossfades the filter response across 0 = low-pass, 1 = band-pass, 2 = high-pass, so in-between values are blends of two modes (labeled MODE on the panel).
CutFilter cutoff frequency (20 Hz–20 kHz, log) — the corner where the filter starts acting. The filter envelope and LFO 1 add to this around the knob value.
DrvPre-filter drive/gain (0.5–6) pushing harder into the filter for added saturation and bite.
KeyHow much the cutoff follows the played pitch (−1 to +1): positive opens the filter as you play higher (keeping brightness consistent up the keyboard), negative inverts it, 0 is no tracking.
ResFilter resonance / emphasis at the cutoff (0.5–16); higher values peak harder and can self-oscillate-like ring.
PoleFilter slope / pole count: 0 = 12 dB/oct (2-pole, gentler) and 1 = 24 dB/oct (4-pole, steeper, more aggressive). Labeled POLE.
Helm gear btn {n}Gear icon (header) — opens the MIDI settings panel: pick the input device and which MIDI channels to receive on, and view the last note / active-voice count.
Helm seq onoff {n}SEQ ON/OFF — switches the built-in step sequencer on or off. When off the pattern contributes no modulation and doesn't advance; default off.
Helm seq reset {n}RST — resets the step pointer so the next gate advance starts the pattern at step 0 (same effect as a rising edge on the SEQ RESET input).
Helm step {n}Step {n} value slider — sets this step's modulation amount (−1..+1). With the sequencer on, the step values are walked one-per-gate and sent to the sequencer's destination (osc-2 transpose, scaled by St Dpth/Amt).
L1 AmtLFO 1 depth (0–1): how much LFO 1 modulates its destination — the filter cutoff in v1 (0 = off).
L1 HzLFO 1 rate in Hz (0.01–30, log).
L1 WLFO 1 waveform (0 = saw, 1 = square, 2 = triangle, 3 = sine, default sine).
L2 AmtLFO 2 depth (0–1): how much LFO 2 modulates its destination — oscillator-2 pitch (±1 semitone) in v1 (0 = off).
L2 HzLFO 2 rate in Hz (0.01–30, log, default 4 Hz).
L2 WLFO 2 waveform (0 = saw, 1 = square, 2 = triangle, 3 = sine, default sine).
M AMod envelope attack time in seconds (0–8). The mod envelope is a spare ADSR; in v1 it is pre-wired to oscillator-1 pitch (depth set by M Dpth).
M DMod envelope decay time in seconds (0–8).
M DpthHow much the mod envelope modulates its destination — oscillator-1 pitch in v1 — over ±12 semitones (−1 to +1, labeled M Dpth); 0 disables it.
M RMod envelope release time in seconds (0–8) after note-off.
M SMod envelope sustain level (0–1, default 0).
NoiseWhite-noise level in the mix (0–1, default 0) — adds breath/hiss or, through a resonant filter, percussive/wind textures.
O1 DetHow far apart the oscillator 1 unison copies are spread in cents (0–50); 0 stacks them in tune, higher values fatten and detune the stack. No effect when unison is 1.
O1 TrOscillator 1 coarse transpose in semitones (−24 to +24), shifting it by whole steps relative to the played note.
O1 TuOscillator 1 fine tune in cents (−100 to +100) for slight detuning or beating against osc 2.
O1 UniNumber of stacked unison copies of oscillator 1 (1–7); higher counts thicken the tone and, with detune, widen it.
O1 VolOscillator 1 level in the pre-filter mix (0–1).
O1 WavOscillator 1 waveform, morphing across 0 = saw, 1 = square, 2 = triangle, 3 = sine (the knob crossfades between adjacent shapes at in-between values).
O2 DetCents spread between oscillator 2's unison copies (0–50); no effect when unison is 1.
O2 TrOscillator 2 coarse transpose in semitones (−24 to +24) — e.g. +12 for an octave-up layer.
O2 TuOscillator 2 fine tune in cents (−100 to +100); defaults to +7 c so the two oscillators beat slightly out of the box.
O2 UniNumber of stacked unison copies of oscillator 2 (1–7).
O2 VolOscillator 2 level in the pre-filter mix (0–1).
O2 WavOscillator 2 waveform, morphing across 0 = saw, 1 = square, 2 = triangle, 3 = sine, just like osc 1 (defaults to square).
SprStereo width (0–1): how far each oscillator's unison voices are panned across the stereo field. 0 collapses toward center/mono; higher values widen the image.
St DpthHow much the step sequencer modulates its destination — oscillator-2 transpose over ±12 semitones (−1 to +1, labeled Amt); 0 disables it.
StepsNumber of active steps in the built-in step sequencer (1–16) before the pattern loops.
St HzStep sequencer rate knob (0.1–30 Hz). Retained from v1's free-running mode; in the current gate-clocked mode the sequencer advances on GATE rising edges, so this is effectively inactive.
St SmthGlide/smoothing between step values (0–1): 0 jumps instantly between steps, higher values slew the modulation for portamento-like motion.
Sub VSub-oscillator level in the mix (0–1).
Sub WSub-oscillator waveform (0 = saw, 1 = square, 2 = triangle, 3 = sine; defaults to sine). The sub plays two octaves below the note for low-end weight.
VoicesPolyphony cap (1–8): the maximum number of notes that can sound simultaneously. When more notes are held than voices available, the synth steals a voice (a releasing voice first, otherwise the oldest-held note). Set it to 1 for a strictly monophonic patch.
VolMaster output level for the whole synth (0–2, default 0.7); above 1 it boosts past unity.

source

helm.ts on GitHub.

Generated from packages/web/src/lib/{audio,video}/module-registry.ts · repo