Game Audio Engineer (Web Audio API)
You are an expert game audio engineer. You use the Web Audio API for both background music (looping sequencer) and one-shot sound effects. Zero dependencies β everything is built into the browser.
Performance Notes
- Take your time with each step. Quality is more important than speed.
- Do not skip validation steps β they catch issues early.
- Read the full context of each file before making changes.
- Test every sound in the browser. Web Audio timing is different from what you expect.
Reference Files
For detailed reference, see companion files in this directory:
sequencer-pattern.md β BGM sequencer function, parsePattern(), example patterns, anti-repetition techniques
sfx-engine.md β playTone(), playNotes(), playNoise(), all SFX presets
mute-button.md β Mute state management, drawMuteIcon(), UIScene button, localStorage persistence
bgm-patterns.md β Strudel BGM pattern examples
strudel-reference.md β Strudel.cc API reference
mixing-guide.md β Volume levels table and style guidelines per genre
Tech Stack
| Purpose |
Engine |
Package |
| Background music |
Web Audio API sequencer |
Built into browsers |
| Sound effects |
Web Audio API one-shot |
Built into browsers |
| Synths |
OscillatorNode (square, triangle, sawtooth, sine) |
β |
| Effects |
GainNode, BiquadFilterNode, ConvolverNode, DelayNode |
β |
No external audio files or npm packages needed β all sounds are procedural.
File Structure
src/
βββ audio/
β βββ AudioManager.js # AudioContext init, BGM sequencer, play/stop
β βββ AudioBridge.js # Wires EventBus β audio playback
β βββ music.js # BGM patterns (sequencer note arrays)
β βββ sfx.js # SFX (one-shot oscillator + gain + filter)
AudioManager (BGM Sequencer + AudioContext)
The AudioManager owns the AudioContext (created on first user interaction for autoplay policy) and runs a simple step sequencer for BGM loops.
class AudioManager {
constructor() {
this.ctx = null;
this.currentBgm = null;
this.masterGain = null;
}
init() {
if (this.ctx) return;
this.ctx = new (window.AudioContext || window.webkitAudioContext)();
this.masterGain = this.ctx.createGain();
this.masterGain.connect(this.ctx.destination);
}
getCtx() {
if (!this.ctx) this.init();
return this.ctx;
}
getMaster() {
if (!this.masterGain) this.init();
return this.masterGain;
}
playMusic(patternFn) {
this.stopMusic();
try {
this.currentBgm = patternFn(this.getCtx(), this.getMaster());
} catch (e) {
console.warn('[Audio] BGM error:', e);
}
}
stopMusic() {
if (this.currentBgm) {
try { this.currentBgm.stop(); } catch (_) {}
this.currentBgm = null;
}
}
setMuted(muted) {
if (this.masterGain) {
this.masterGain.gain.value = muted ? 0 : 1;
}
}
}
export const audioManager = new AudioManager();
BGM Sequencer Pattern
See sequencer-pattern.md for the full sequencer function, parsePattern(), example BGM patterns, and anti-repetition techniques.
SFX Engine (Web Audio API -- one-shot)
See sfx-engine.md for playTone(), playNotes(), playNoise(), and all common game SFX presets (score, jump, death, click, powerUp, hit, whoosh, select).
AudioBridge (wiring EventBus -> audio)
import { eventBus, Events } from '../core/EventBus.js';
import { audioManager } from './AudioManager.js';
import { gameplayBGM, gameOverTheme } from './music.js';
import { scoreSfx, deathSfx, clickSfx } from './sfx.js';
export function initAudioBridge() {
eventBus.on(Events.AUDIO_INIT, () => audioManager.init());
eventBus.on(Events.MUSIC_GAMEPLAY, () => audioManager.playMusic(gameplayBGM));
eventBus.on(Events.MUSIC_GAMEOVER, () => audioManager.playMusic(gameOverTheme));
eventBus.on(Events.MUSIC_STOP, () => audioManager.stopMusic());
eventBus.on(Events.SCORE_CHANGED, () => scoreSfx());
eventBus.on(Events.PLAYER_DIED, () => deathSfx());
}
Mute State Management
See mute-button.md for mute toggle event handling, drawMuteIcon() Phaser Graphics implementation, UIScene button creation, and localStorage persistence.
Integration Checklist
- Create
src/audio/AudioManager.js β AudioContext + sequencer + master gain
- Create
src/audio/music.js β BGM patterns as note arrays + sequencer calls
- Create
src/audio/sfx.js β SFX using Web Audio API (oscillator + gain + filter)
- Create
src/audio/AudioBridge.js β wire EventBus events to audio
- Wire
initAudioBridge() in main.js
- Emit
AUDIO_INIT on first user click (browser autoplay policy)
- Emit
MUSIC_GAMEPLAY, MUSIC_GAMEOVER, MUSIC_STOP at scene transitions
- Add mute toggle β
AUDIO_TOGGLE_MUTE event, UI button, M key shortcut
- Test: BGM loops seamlessly, SFX fire once and stop, mute silences everything
Important Notes
- Zero dependencies: Everything uses the built-in Web Audio API. No npm pac