One LFO
One oscillator, one filter, one LFO, and the whole wobble-bass sound falls out.
What it is
A sawtooth at 55 Hz through a resonant lowpass, with a sine LFO wired into the filter’s cutoff. Move the pointer: X sets the LFO rate, Y sets how far it swings.
That’s the entire patch, and it’s most of what people mean by wobble bass.
How it works
The interesting part is what you can’t see. The LFO isn’t modulating a number in JavaScript,
it’s an OscillatorNode connected to filter.frequency, which is an AudioParam. Connecting
an audio node to a param sums the signal into it at audio rate, so the wobble is
sample-accurate and costs no main-thread work at all.
That also means you can’t read the modulated value back. filter.frequency.value returns only
the intrinsic value, ignoring anything connected to it. The curve on screen is drawn from the
same rate and depth being sent to the audio graph, not measured from it.
The other detail is smoothing. Assigning straight to .value on every pointer move produces a
click per event, because the parameter jumps discontinuously. setTargetAtTime glides it over a
short constant instead.
What I would do next
A second LFO at a slightly detuned rate, so the wobble never repeats exactly.