Browser-based Eurorack modular synthesizer emulator. Patch virtual modules together with cables to create sounds.
The factory patch menu includes a numbered Demo - Synth Voice series for reusable patching principles. See Voice Demos for expected sounds, listening exercises, source material, and deliberate software adaptations.
Built-in modules are loaded in the order listed by src/js/rack/module-manifest.js and grouped by each module definition's sidebar category.
| ID | Module | Description |
|---|---|---|
midi-cv |
MIDI-CV | Mono MIDI-to-CV interface with pitch, gate, velocity, and mod outputs |
midi-4 |
MIDI-4 | Four-voice polyphonic MIDI-to-CV interface |
midi-cc |
MIDI-CC | Four assignable MIDI CC to CV outputs |
midi-clk |
M-CLK | MIDI clock, reset, and run outputs |
midi-drum |
MIDI-DRUM | MIDI drum pads to trigger outputs plus velocity CV |
| ID | Module | Description |
|---|---|---|
clk |
CLK | Master clock with adjustable rate, pause control, and rate CV |
div |
DIV | Dual clock divider/multiplier with CV rate control |
swing |
SWING | Clock swing processor with straight and swung/humanized trigger outputs |
burst |
BURST | Pingable burst generator for ratchets, probability, and trigger clusters |
gate-delay |
GATE DELAY | Dual retriggerable trigger delay and gate-length generator |
cascade |
CASCADE | Four rank-nested trigger lanes with live Fill and phrase-latched rotation |
| ID | Module | Description |
|---|---|---|
nse |
NSE | White and pink noise generator |
vco |
VCO | Voltage-controlled oscillator with triangle, saw, and pulse outputs |
wavetable |
WAVE | Procedural wavetable oscillator with morphing, bank CV, FM, and sync |
complex-vco |
CPLX VCO | Through-zero FM/phase oscillator with fundamental, even, odd, and full outputs |
ensemble-vco |
ENSEMBLE | Sixteen-voice scale oscillator with cross-FM, shaping, freeze, learning, and stereo modes |
| ID | Module | Description |
|---|---|---|
pluck |
PLUCK | Four-voice Karplus-Strong plucked string voice |
kick |
KICK | Analog-style kick drum synthesizer |
snare |
SNARE | Analog-style snare drum synthesizer |
hat |
HAT | Hi-hat synthesizer with separate open and closed triggers |
| ID | Module | Description |
|---|---|---|
lfo |
LFO | Low frequency oscillator with multiple waveforms |
quad-lfo |
Quad LFO | Quadrature sine LFO with 0, 90, 180, and 270 degree CV outputs |
rnd |
RND | Seeded random voltage generator with stepped, smooth, and gate outputs |
func |
FUNC | Function generator for envelopes, cycling LFOs, and slew behavior |
adsr |
ADSR | ADSR envelope generator with CV timing inputs |
ochd |
OCHD | Eight free-running triangle LFOs based on Instruo ochd |
chaos |
Chaos | Three correlated Lorenz chaotic CV axes with rate, character, reset, and lobe gate |
cv-rec |
CV REC | Dual arbitrary-CV/gate recorder with free-time and clocked looping |
| ID | Module | Description |
|---|---|---|
arp |
ARP | Triggered chord arpeggiator with root and chord CV |
changes |
CHANGES | Scale-aware 16-note harmonic sequencer with cyclic voice-leading plans |
refrain |
REFRAIN | Seed-CV-addressable phrase-form sequencer with selective exact mutation, triggerable Recall, Hold, and four macro CV lanes |
seq |
SEQ | 8-step CV/gate sequencer with direction and range controls |
prob-seq |
PROB SEQ | 8-step probability trigger sequencer with ratchets, skips, conditional gates, and deterministic seeds |
seq-switch |
SEQ-SW | Clocked sequential switch for 4-to-1 and 1-to-4 signal routing |
euclid |
EUCLID | Euclidean rhythm generator with length, hits, and rotation controls |
turing |
TURING | Random looping sequencer based on Music Thing Turing Machine |
Refrain holds each four-lane tuple for 16 accepted clocks. When patching
HARM as an absolute selector into Changes or Arp, set the destination's
corresponding selector knob to 0. Bipolar SEED CV addresses 121 nearby
deterministic forms at 12 seeds per volt; ACTIVE shows the committed seed and
NEXT previews the current target. Seed, Mutate, and Recall changes land on
the next 16-clock cell boundary, while Length and automatic evolution wait for
a natural loop boundary. The four lane buttons scope future mutations.
Panel or gate Hold captures the current Anchor and blocks unattended Seed-CV activation and automatic mutation without stopping transport or deliberate Seed, Mutate, Recall, and Length gestures. Live mutations and the captured Anchor are volatile: reloading a patch or recreating audio reconstructs the base pattern from panel Seed plus the first routed Seed-CV sample rather than restoring the previous performance state; a restored Hold captures that reconstructed base.
| ID | Module | Description |
|---|---|---|
quant |
QUANT | Pitch quantizer with selectable scales and trigger output |
| ID | Module | Description |
|---|---|---|
vcf |
VCF | State-variable filter with low-pass, band-pass, and high-pass outputs |
lpg |
LPG | Vactrol-style low pass gate with VCA, combo, and low-pass modes |
formant |
FORMANT | Morphable vowel/formant filter with drive, shift, resonance, and CV control |
resbank |
RESBANK | Modal, sympathetic-string, and dispersive-string resonator bank |
| ID | Module | Description |
|---|---|---|
fold |
FOLD | Wavefolder for adding harmonic complexity |
ring |
RING | Ring modulator for signal multiplication |
vocoder |
VOCODER | 12-band channel vocoder with envelope shifting and direct sibilance |
dly |
DLY | Mono digital delay with time, feedback, mix, and CV control |
tape |
TAPE | Tape-style delay with saturation, multi-head modes, wow/flutter, crinkle, tap, and freeze |
verb |
VERB | Stereo reverb with time, damping, mix, and mix CV |
shimmer |
SHIMMER | Stereo Hadamard-FDN reverb with pitch-shifted input or regenerative feedback |
chorus |
CHORUS | Stereo chorus effect |
phaser |
PHASER | Stereo phaser effect |
flanger |
FLANGER | Stereo flanger effect |
crush |
CRUSH | Bit crusher and sample-rate reducer |
loop |
LOOP | Minimal looper with record, reverse, half-speed, and clear controls |
granulita |
GRANULITA | Stereo granular chord processor based on Noise Engineering Granulita Versio |
| ID | Module | Description |
|---|---|---|
sh |
S+H | Dual sample and hold |
logic |
LOGIC | Boolean gate operator with AND and OR outputs |
mult |
MULT | Two-input, six-output signal splitter |
matrix |
MATRIX | 4x4 DC-coupled matrix mixer with unipolar and bipolar output modes |
joystick |
JOY | X/Y performance CV controller with gate, trigger, CV modes, and runtime gesture recording |
envf |
ENVF | Envelope follower with normal and inverted CV outputs |
pitch-track |
PITCH TRACK | Monophonic audio-to-continuous-1 V/oct tracker with held pitch and validity gate |
vca |
VCA | Dual voltage-controlled amplifier |
atten |
ATTN | Dual attenuverter with offset controls |
slew |
SLEW | Dual slew limiter for portamento and CV smoothing |
db |
DB | Stereo VU/peak meter with audio passthrough |
pwm |
PWM | Pulse-width modulator with complementary outputs |
cmp2 |
CMP2 | Dual window comparator with logic outputs based on Joranalogue Compare 2 |
comp |
COMP | Stereo-linked compressor/limiter with sidechain filtering and gain-reduction CV |
mix |
MIX | Four-channel mixer with level controls |
scope |
SCOPE | Dual-channel oscilloscope with scope, X-Y, and tuning modes |
spectrum |
SPECTRUM | Real-time FFT spectrum analyzer with audio passthrough |
plot |
PLOT | Waveform plotter and signal monitor with trigger input |
spectrogram |
SPECTRO | Scrolling spectrogram analyzer with audio passthrough |
rec |
REC | WAV recorder with stereo passthrough |
| ID | Module | Description |
|---|---|---|
out |
OUT | Stereo output to speakers |
Open Code in the app toolbar to build and debug racks with client-side JavaScript. The workbench provides syntax highlighting; themed surrounding controls; module, parameter, control-state, MIDI, and direction-aware socket completion; non-mutating validation; atomic Apply; AudioWorklet profiling; named local scripts; and graphical-rack snapshots.
Use .module('type') for canonical auto-incremented names such as vco_1 and vco_2, or .module('type', 'name', params) when a stable name is useful. add('type') uses the same naming rules and returns the resolved name for reusable systems. Ordinary JavaScript functions can package voices, drum kits, modulation buses, and effect chains.
patch()
.module('vco', 'osc', { coarse: 0.3 })
.module('out', 'main', { volume: 0.65 })
.connect('osc.triangle', 'main.L')
.connect('osc.triangle', 'main.R')Start with the Patch Workbench Guide, then use the Patch Workbench Reference for the complete builder API, shortcuts, completion behavior, commands, safety model, and troubleshooting.
Self-contained module system where each module is a folder containing DSP + UI. RackHost owns the rack and synchronizes stable main-thread UI mirrors with production DSP instances in a required AudioWorklet.
See Codebase Architecture and Schemas for the operational mental model, repository map, thread ownership, plugin loading, telemetry, routing rules, and complete schemas.
src/js/
├── index.js # Public exports
├── app/ # Browser app state/controllers
│ ├── app.js # App bootstrap and event orchestration
│ ├── rack-host.js # Authoritative rack/plugin/audio host
│ ├── rack-state.js # Modules, rows, params, cables, patch state
│ └── patch-format.js # Strict v3 patch validation
├── audio/
│ ├── graph.js # Compiled routing graph and feedback delays
│ ├── worklet-engine.js # Main-thread AudioWorklet controller
│ └── worklet/ # Audio-thread processor and plugin registry
├── cables/
│ └── cable-manager.js # Cable rendering & connections
├── config/
│ ├── constants.js # System constants
│ ├── factory-patches.js # Aggregate factory patch export
│ └── patches/ # Factory patch definitions
├── modules/ # Module definitions
│ └── {moduleId}/
│ └── index.js # DSP + UI
├── patches/ # Patch serialization
├── rack/ # Rack infrastructure
│ ├── module-manifest.js # Module order, category taxonomy, dynamic imports
│ ├── core-definitions.js # Static core imports for the audio worklet
│ ├── module-contract.js # Port and DSP contract validation
│ └── registry.js # Atomic trusted-plugin registry
├── ui/
│ ├── renderer.js # Module UI generation
│ └── toolkit/ # UI components
└── utils/ # Utility functions
├── fft.js # Preallocated, calibrated real FFT
├── interpolation.js # Linear and circular-buffer interpolation
├── math.js
├── nested-access.js
├── oscillator.js # Phase wrapping and PolyBLEP
├── slew.js
├── color.js
└── voltage.js # Shared voltage rail limiting
Runtime invariants:
- Production DSP runs only in the audio worklet; UI mirrors never produce sound.
- Module input and output buffers keep stable identities for their DSP lifetime.
- Inputs accept one cable. Patching an occupied input replaces its cable; outputs support fan-out.
- Feedback edges have an explicit one-block delay.
- Patch activation is revision-acknowledged and atomic.
- Trusted plugins register matching main-thread and worklet contracts.
See the Module Creation Guide for detailed documentation.
This basic sine LFO is a complete, useful source module:
// src/js/modules/basic-lfo/index.js
import { wrapPhase } from '../../utils/oscillator.js';
export default {
id: 'basic-lfo',
name: 'Basic LFO',
hp: 4,
color: 'module-color-six',
category: 'modulation',
createDSP({ sampleRate = 44100, bufferSize = 512 } = {}) {
const sine = new Float32Array(bufferSize);
let phase = 0;
return {
params: { rate: 1 },
inputs: {},
outputs: { sine },
leds: { phase: 0.5 },
process() {
const rate = Math.max(0.05, Math.min(20, this.params.rate));
for (let i = 0; i < bufferSize; i++) {
sine[i] = Math.sin(phase * Math.PI * 2) * 5;
phase = wrapPhase(phase + rate / sampleRate);
}
this.leds.phase = sine[bufferSize - 1] / 10 + 0.5;
},
reset() {
phase = 0;
sine.fill(0);
this.leds.phase = 0.5;
}
};
},
ui: {
leds: ['phase'],
knobs: [{ id: 'rate', label: 'Rate', param: 'rate', min: 0.05, max: 20, default: 1 }],
outputs: [{
id: 'sine', label: 'Sine', port: 'sine', signal: 'cv',
voltage: { min: -5, max: 5 }
}]
}
};The ui declaration is the public parameter and port schema. The DSP keeps its phase private, fills the same output buffer every block, and scales the waveform to the declared ±5V range. reset() restores both internal state and observable outputs deterministically.
Built-in modules are registered in src/js/rack/module-manifest.js. External trusted modules are installed as plugins with registerPlugin(manifest) and must provide both their main-thread definitions and a worklet entry point. See the module creation guide for the manifest contract.
Built-ins must also be statically imported by src/js/rack/core-definitions.js; contract tests keep its order aligned with the manifest.
Patch state is canonicalized to version 3 and declares the exact plugin patch contracts it needs:
{
version: 3,
plugins: { core: 1 },
modules: [{ id: 'vco_1', type: 'vco', row: 1, index: 0 }],
params: { vco_1: { coarse: 0.35 } },
cables: [{ fromModule: 'vco_1', fromPort: 'triangle', toModule: 'out_1', toPort: 'L' }],
midiMappings: {}
}Only version 3 patches are accepted. Parameters must belong to the referenced module and be declared by its UI contract; unknown modules, parameters, plugin versions, ports, and duplicate input destinations reject the patch atomically.
Every module type must belong to a declared plugin. Missing plugins, unknown ports, missing endpoints, and duplicate input destinations reject the patch atomically.
- Audio: ±5V bipolar
- Gates: 0V (off) / 10V (on)
- Triggers: 5-10ms pulse at 5-10V
- Pitch CV: 1V/octave
npm test # Run tests
npm run test:e2e # Run Chromium AudioWorklet smoke tests
npm run audit:dsp # Run deterministic DSP audit scenarios
npm run audit:dsp -- --matrix --strict-voltage # Enforce every declared voltage contract
python3 -m http.server 8000 --directory srcOpen http://localhost:8000. AudioWorklet requires a supported browser and secure context; localhost qualifies for local development.
Use npm run audit:dsp -- --matrix --strict-voltage to cover 44.1, 48, and 96 kHz at 128- and 512-sample block sizes and fail on contract violations. See the sound engineering audit for scope, limitations, and current priorities.
MIT
