engines/kick.js — SynthKick
The kick drum synthesiser. Defined as a SynthEngine object with 7 modules.
Modules
The modules array defines both the UI panels (order, labels, params) and the signal chain (processor order).
1. Pitch (source)
| Param | Range | Default | Description |
|---|---|---|---|
pitchStart |
80–400 Hz | 220 | Initial oscillator frequency |
pitchEnd |
25–100 Hz | 50 | Final frequency after decay |
pitchDecay |
0.03–0.5 s | 0.06055 | Sweep duration |
sineLevel |
0–1 | 1 | Sine oscillator level |
triangleLevel |
0–1 | 0 | Triangle oscillator level |
sawtoothLevel |
0–1 | 0 | Sawtooth oscillator level |
pitchCurve |
exponential/linear | exponential | Contour of the frequency sweep |
subMix |
0–1 | 0.5 | Sub oscillator (sine, octave down) blend |
Creates the main oscillator with a frequency ramp (exponential or linear), a gain envelope, and an optional sub oscillator at half frequency.
2. Transient (source)
| Param | Range | Default | Description |
|---|---|---|---|
noiseAmount |
0–0.5 | 0.12 | White noise burst volume |
noiseDecay |
0.003–0.08 s | 0.015 | Noise fade time |
clickTone |
200–2000 Hz | 800 | Pitched click frequency |
clickMix |
0–0.3 | 0.1 | Click blend level |
Generates a white noise buffer source and a sine oscillator click, both with exponential decay envelopes.
3. Distortion
Dynamic stage pipeline (see distortion.js).
4. Filter (processor)
| Param | Range | Default | Description |
|---|---|---|---|
filterCut |
200–20000 Hz | 20000 | Low-pass cutoff (bypassed at 20000) |
BiquadFilter node with type: 'lowpass'. When cutoff is at maximum (20000 Hz),
the filter bypasses (returns input unchanged).
5. Compressor (processor)
| Param | Range | Default | Description |
|---|---|---|---|
compThreshold |
–60–0 dB | –21.3 | Compression threshold |
compRatio |
1–20 | 4 | Compression ratio |
compAttack |
0.001–0.1 s | 0.003 | Attack time |
compRelease |
0.01–1.0 s | 0.1 | Release time |
Wraps DynamicsCompressorNode with clamped parameter ranges. Wrapped in
try/catch for browser compatibility — falls back to pass-through.
6. Volume (master)
| Param | Range | Default | Description |
|---|---|---|---|
volAttack |
0.001–0.1 s | 0.002 | Time to peak |
volDecay |
0.05–0.8 s | 0.3 | Time to sustain |
volSustain |
0–0.5 | 0.05 | Post-decay level |
volRelease |
0.005–0.5 s | 0.05 | Fade to silence |
Schedules linearRampToValueAtTime on the master gain node. Total duration:
max(0.5, attack + decay + release + 0.1).
7. Normalize (builtin)
| Param | Default | Description |
|---|---|---|
normalize |
true | Peak normalise to –0.5 dBFS after render |
Signal Chain
osc + sub + noise + click
→ [distortion stages]
→ filter (lowpass)
→ compressor
→ master gain (ADSR volume)
→ destination
After rendering, normalize is applied to the PCM samples if enabled.
Canvas Visualisations
Three envelope canvases are rendered in a dedicated Envelopes card below the waveform:
| Canvas ID | Module | Curve |
|---|---|---|
env-pitch |
Pitch | Exponential decay of frequency from start to end |
env-volume |
Volume | ADSR amplitude envelope |
env-transient |
Transient | Exponential decay of transient amplitude |
Rendering
The render function creates source nodes (oscillator, sub, noise, click)
and connects them to chainInput (the first distortion stage or master gain):
render(ctx, params, stages, chainInput, dur) {
// Pitch oscillator + gain
osc = ctx.createOscillator()
schedulePitch(osc, params, dur)
osc.connect(oscGain).connect(chainInput)
// Sub oscillator (if subMix > 0)
sub.connect(subGain).connect(chainInput)
// Noise burst (if noiseAmount > 0)
noiseBufferSource.connect(noiseGain).connect(chainInput)
// Click tone (if clickMix > 0)
click.connect(clickGain).connect(chainInput)
}
Defaults
Loaded from static/js/synth/presets/kick.json at startup, falling back to
engine.defaults:
{
"params": {
"pitchStart": 220, "pitchEnd": 50, "pitchDecay": 0.06055,
"sineLevel": 1, "triangleLevel": 0, "sawtoothLevel": 0,
"pitchCurve": "linear", "subMix": 0.5,
"noiseAmount": 0.12, "noiseDecay": 0.015,
"clickTone": 800, "clickMix": 0.1,
"filterCut": 20000,
"volAttack": 0.002, "volDecay": 0.3, "volSustain": 0.05, "volRelease": 0.05,
"compThreshold": -21.3, "compRatio": 4,
"compAttack": 0.003, "compRelease": 0.1,
"normalize": true
},
"stages": [{ "type": "softClip", "amount": 0.01 }]
}
Built-in Templates
Defined in static/js/synth/presets/templates/kick.json:
| Template | Description |
|---|---|
| None | No constraints, params set to defaults |
| Sine Kick | Sine wave, no compression, linear pitch, locked distortion |
| Hard Punch | Sawtooth wave, subMix: 0.3, hardClip distortion |
| Sub Heavy | Deep sub focus (subMix: 0.85), gentle saturation |
Randomisation Ranges
Each module's randomise(param) function sets curated ranges. Locked params
are skipped.
| Section | Param | Range |
|---|---|---|
| Pitch | Start | 120–350 Hz |
| End | 30–80 Hz | |
| Decay | 0.05–0.35 s | |
| Sine/Triangle/Sawtooth | each 0.3–1 (at least one non-zero) | |
| Curve | random: exponential / linear | |
| Sub mix | 0.2–0.8 | |
| Volume | Attack | 0.001–0.06 s |
| Decay | 0.08–0.5 s | |
| Sustain | 0–0.25 | |
| Release | 0.01–0.2 s | |
| Transient | Noise | 0.03–0.4 |
| Decay | 0.004–0.06 s | |
| Click tone | 300–1500 Hz | |
| Click mix | 0.02–0.25 | |
| Filter | Cutoff | 300–18000 Hz (log) |
| Compressor | Threshold | –40 to –10 dB |
| Ratio | 2–12 | |
| Attack | 0.001–0.05 s | |
| Release | 0.02–0.5 s |