r/webaudio • u/rhslvkf • 22h ago
Karplus-Strong gayageum in Web Audio: allpass tuning, silk excitation, playbackRate bends (write-up + playable demo)
I built the soundtrack of my mobile game entirely in Web Audio, with no audio files: a Korean gayageum (silk-string zither) using Karplus-Strong. Write-up plus a playable demo (same code as the game):
https://boreumdal.app/devlog/gayageum/
Web Audio details that might be useful to others:
- Strings are rendered once into an AudioBuffer (a couple of dozen distinct strings at most) and played with AudioBufferSourceNode, which is cheap on phones.
- Bends and vibrato are playbackRate automation: linearRampToValueAtTime for the bend, setValueCurveAtTime with a 48-point sine curve for a 5.2 Hz vibrato that deepens after the attack.
- A shared "body" chain on every string: peaking EQ at 260 Hz (+4 dB, Q 0.9) into a 4.2 kHz low-pass.
- Scheduling only uses AudioContext.currentTime with a 0.4 s lookahead per frame, so the game's hit-stop never affects the beat.
- Ducking on each hit: cancelScheduledValues, ramp to 45% in 20 ms, then setTargetAtTime back. Low health slides the music low-pass from 4.2 kHz to 700 Hz.
- For checking levels I render the title, a full run and each boss through an OfflineAudioContext into WAV files and log peak and RMS.
Questions and critique welcome.





