engines/neuro.js — SynthNeuro
Sub and neurofunk bass synthesiser. Defined as a SynthEngine object with
13 modules. Dual detuned oscillators with FM routing, reese detune spread
(1–8 voices), sub oscillator, noise injection, multi-mode filter with per-note
ADSR envelope and LFO modulation, tempo-synced LFO, ADSR volume envelope,
multi-stage distortion, OTT multiband compressor, dynamics compressor,
and clarity processor.
Available standalone at /synth/neuro and as an engine in the sequencer.
Signal Flow
osc1 ──┐
osc2 ──┼── FM mix (osc2 → osc1.frequency) ──→ reese detune spread (1–8 voices)
│ ↓
sub ───┘ filter (multi-mode)
noise ─┘ ↓
lfo → filter cutoff / volume / pitch / fm distortion → OTT → clarity
↓
compressor → masterGain (ADSR envelope)
Each note creates a per-trigger filter node and a per-trigger gain node to avoid scheduling conflicts between overlapping notes.
Modules
The modules array defines both the UI panels (order, labels, params) and the signal chain (processor order for the backward loop).
1. Osc (source)
| Param | Range | Default | Description |
|---|---|---|---|
osc1Wave |
sawtooth/square/triangle/sine | saw | Oscillator 1 waveform |
osc2Wave |
sawtooth/square/triangle/sine | saw | Oscillator 2 waveform |
osc1Cents |
–100–100 ct | 0 | Osc 1 fine detune |
osc2Cents |
–100–100 ct | 0 | Osc 2 fine detune |
osc1Level |
0–1 | 0.7 | Osc 1 level |
osc2Level |
0–1 | 0.7 | Osc 2 level |
fmAmount |
0–1 | 0 | FM depth (osc2 → osc1 frequency, sqrt-scaled × 400) |
Osc 2 modulates Osc 1's frequency at fmAmount^0.5 × 400 depth, creating
classic neurofunk FM tones. Both oscillators run for the full note duration.
2. Reese (source)
| Param | Range | Default | Description |
|---|---|---|---|
voiceCount |
1–8 | 3 | Number of detuned saw voices |
detuneCents |
0–50 ct | 12 | Max detune spread (half above, half below) |
reeseMix |
0–1 | 0.6 | Reese voice mix level |
Creates a thick "wall of sound" via multiple detuned sawtooth oscillators.
Each voice is offset by (v / (voices-1) - 0.5) × 2 × detuneCents cents
from the base frequency, producing the classic reese chord effect.
3. Sub (source)
| Param | Range | Default | Description |
|---|---|---|---|
subWave |
sine/triangle | sine | Sub oscillator waveform |
subLevel |
0–1 | 0.5 | Sub level |
subOctave |
1, 2 | 1 | Octave divider (×1 = same, ×2 = octave below) |
Clean sub oscillator at freq / subOctave. Pure sine or triangle for deep
sub-bass foundations.
4. Noise (source)
| Param | Range | Default | Description |
|---|---|---|---|
noiseLevel |
0–1 | 0.03 | White noise level |
Per-note noise buffer for texture and transient grit.
5. Filter (source — handled manually in trigger)
| Param | Range | Default | Description |
|---|---|---|---|
filterType |
lowpass/highpass/bandpass | lowpass | Filter mode |
filterCut |
20–20000 Hz | 18000 | Cutoff frequency |
filterRes |
0–1 | 0.3 | Resonance (Q: 0.5–20) |
envAmount |
0–36 st | 12 | Envelope → cutoff modulation depth |
lfoAmount |
0–36 st | 6 | LFO → cutoff modulation depth |
A per-trigger BiquadFilterNode is created for each note so overlapping
notes don't conflict on the filter frequency AudioParam. The filter envelope
opens on attack (peak = baseCut × 2^(envAmount/12)) and closes over
attack + decay time.
LFO modulation adds baseCut × (2^(lfoAmt×lfoDepth/12) - 1) Hz (in semitones)
to the cutoff frequency via AudioNode.connect(AudioParam).
6. LFO (source)
| Param | Range | Default | Description |
|---|---|---|---|
lfoRate |
0.1–20 Hz | 2 | Free-running LFO rate |
lfoSync |
off/1/2/4/8/16 | 4 | Tempo-synced division |
lfoWave |
sine/triangle/sawtooth/square/sAndH | sine | LFO waveform |
lfoTarget |
cutoff/volume/pitch/fm | cutoff | Modulation target |
lfoDepth |
0–1 | 0.5 | LFO depth |
When lfoSync is not 'off', the LFO rate is calculated as
(tempo / 60) / division where tempo comes from params.tempo.
Default tempo is 174 BPM standalone; sequencer passes this.bpm.
The LFO is per-trigger with start(time) and is stopped early by noteOff
to prevent long tails (stopped at time + release + 0.5s).
7. Env (master)
| Param | Range | Default | Description |
|---|---|---|---|
volAttack |
0.001–1 s | 0.005 | Attack time |
volDecay |
0.01–0.5 s | 0.08 | Decay time |
volSustain |
0–1 | 0.6 | Sustain level |
volRelease |
0.001–3 s | 0.2 | Release time |
ADSR volume envelope applied to the per-trigger noteGain. In trigger()
(sequencer mode) the full A→D→S→R is scheduled with auto-release. In
noteOn() (keyboard mode) the envelope holds at sustain until noteOff()
triggers the release ramp.
8. EQ (processor)
Standard 3-band EQ (same as other engines): lowshelf (250 Hz), peaking (1 kHz), highshelf (8 kHz), ±12 dB range.
9. Distortion
Standard multi-stage distortion card (same pattern as all other engines). 9 drive types, per-stage amount and drive controls.
10. OTT (processor)
| Param | Range | Default | Description |
|---|---|---|---|
ottMode |
basic/adv | basic | Basic mode (depth only) vs advanced |
ottDepth |
0–1 | 0.4 | Wet/dry mix |
ottDown |
0–1 | 0.7 | Downward compression amount (adv) |
ottUp |
0–1 | 0.8 | Upward compression amount (adv) |
ottAttack |
0.001–0.05 s | 0.003 | Compressor attack (adv) |
ottRelease |
0.01–0.5 s | 0.08 | Compressor release (adv) |
Three-band multiband compressor (low ≤250 Hz, mid 250–4000 Hz, high ≥4000 Hz) with parallel upward + downward compression per band. Essential for the aggressive neurofunk sound.
11. Compressor (processor)
| Param | Range | Default | Description |
|---|---|---|---|
compThreshold |
–60–0 dB | –24 | Threshold |
compRatio |
1–20 | 4 | Ratio |
compAttack |
0.001–0.1 s | 0.003 | Attack |
compRelease |
0.01–1 s | 0.1 | Release |
Standard dynamics compressor for final signal shaping.
12. Clarity (processor)
Dynamic mud (~350 Hz) + air (~4 kHz) reduction. Same module as used by kick, snare, hihat, and BIA Clone.
13. Normalize (builtin)
| Param | Type | Default | Description |
|---|---|---|---|
normalize |
checkbox | true | Peak normalisation (target 0.944) |
Dual Trigger Modes
The engine supports two distinct trigger patterns:
trigger(ctx, chain, params, time, velocity)
Used by the sequencer. Schedules the full ADSR envelope with auto-release:
t=0: setValueAtTime(0)
t+attack: linearRampToValueAtTime(1)
t+attack+decay: linearRampToValueAtTime(sustain)
t+dur-release: setValueAtTime(sustain)
t+dur: linearRampToValueAtTime(0.001)
getDuration returns attack + decay + 0.5 + release + 0.1s.
noteOn(ctx, chain, params, time, velocity)
noteOff(ctx, chain, params, time)
Used by the standalone keyboard page. noteOn schedules A→D→S only and
holds at sustain. noteOff schedules release:
cancelScheduledValues(now)
setValueAtTime(currentGain, now)
linearRampToValueAtTime(0.001, now + release)
setValueAtTime(0, now + release + 5ms)
LFO sources are also stopped at now + release + 0.5s to prevent long tails
from still-running oscillators.
LFO Tempo Sync
When lfoSync is not 'off', the LFO rate is derived from params.tempo:
rate = (tempo / 60) / division
| Sync | Rate at 174 BPM | Rate at 140 BPM |
|---|---|---|
| 1 | 2.9 Hz | 2.33 Hz |
| 2 | 1.45 Hz | 1.17 Hz |
| 4 | 0.725 Hz | 0.583 Hz |
| 8 | 0.363 Hz | 0.292 Hz |
| 16 | 0.181 Hz | 0.146 Hz |
Standalone key press sets p.tempo = lfoBpm (default 174, adjustable via
BPM input). The sequencer passes p.tempo = this.bpm.
Stereo and Mono
All processing is mono. The reese voices sum to mono. Stereo effects (reverb/delay in the sequencer) are applied post-engine on the strip bus.
Default Preset
The default preset produces a mid-range neuro bass with: - Dual sawtooth oscillators, slight detune (5ct on osc2) - FM modulation (30%) - 3-voice reese spread (12ct detune) - Sine sub at same octave (50% level) - Low-pass filter at 18 kHz with envelope (12 st) and LFO (6 st) modulation - OTT at 40% depth - Volume envelope: 5ms attack, 80ms decay, 60% sustain, 200ms release - SoftClip distortion at 30%
Dependencies
core.js—SAMPLE_RATE,randInRange,randInt,logRandregistry.js—register()modules/eq.js— EQ processormodules/compressor.js— dynamics compressormodules/ott.js— multiband OTT compressormodules/clarity.js— mud/air reductiondistortion.js—buildDistortionChain
Files
| File | Purpose |
|---|---|
engines/neuro.js |
Engine definition (673 lines) |
init-neuro.js |
Bootstrap with keyboard, noteOn/noteOff, BPM control, VU meter |
templates/synth_neuro.html |
Standalone page with preset sidebar + piano keyboard |
presets/neuro/default.json |
Factory default params |
presets/neuro/manifest.json |
Built-in presets (empty) |
See Also
docs/synth/overview.md— framework architecturedocs/synth/sequencer.md— sequencer integrationdocs/synth/engine.md—initSynthandrenderToBufferdocs/synth/modules/ott.md— OTT moduledocs/synth/modules/clarity.md— clarity module