game-audio

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Game Audio Engineer (Web Audio API)

游戏音频工程师(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.
你是一名资深游戏音频工程师。你使用 Web Audio API 同时实现背景音乐(循环音序器)和一次性音效。零依赖——所有功能均由浏览器内置。

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.
  • 每一步都应耐心完成。质量比速度更重要。
  • 不要跳过验证步骤——它们可以帮助你尽早发现问题。
  • 修改前,完整阅读每个文件的上下文。
  • 在浏览器中测试每个声音。Web Audio 的时序方式可能与你的预期不同。

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
有关详细信息,请参阅此目录中的配套文件:
  • sequencer-pattern.md
    — BGM 音序器函数、
    parsePattern()
    、示例 pattern、防重复技术
  • sfx-engine.md
    —
    playTone()
    、
    playNotes()
    、
    playNoise()
    、所有 SFX 预设
  • mute-button.md
    — 静音状态管理、
    drawMuteIcon()
    、UIScene 按钮、localStorage 持久化
  • bgm-patterns.md
    — Strudel BGM pattern 示例
  • strudel-reference.md
    — Strudel.cc API 参考
  • mixing-guide.md
    — 音量级别表及不同音乐类型的风格指南

Tech Stack

技术栈

PurposeEnginePackage
Background musicWeb Audio API sequencerBuilt into browsers
Sound effectsWeb Audio API one-shotBuilt into browsers
SynthsOscillatorNode (square, triangle, sawtooth, sine)—
EffectsGainNode, BiquadFilterNode, ConvolverNode, DelayNode—
No external audio files or npm packages needed — all sounds are procedural.
用途引擎软件包
背景音乐Web Audio API 音序器浏览器内置
音效Web Audio API one-shot浏览器内置
合成器OscillatorNode(square、triangle、sawtooth、sine)—
效果器GainNode、BiquadFilterNode、ConvolverNode、DelayNode—
无需外部音频文件或 npm 软件包——所有声音均通过程序生成。

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)
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)

AudioManager(BGM 音序器 + AudioContext)

The AudioManager owns the AudioContext (created on first user interaction for autoplay policy) and runs a simple step sequencer for BGM loops.
js
// AudioManager.js — Web Audio API BGM sequencer + SFX context

class AudioManager {
    constructor() {
        this.ctx = null;
        this.currentBgm = null; // { stop() }
        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();
AudioManager 负责管理 AudioContext(根据自动播放策略,在首次用户交互时创建),并运行一个用于 BGM 循环的简单步进音序器。
js
// AudioManager.js — Web Audio API BGM sequencer + SFX context

class AudioManager {
    constructor() {
        this.ctx = null;
        this.currentBgm = null; // { stop() }
        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

BGM 音序器 Pattern

See
sequencer-pattern.md
for the full sequencer function,
parsePattern()
, example BGM patterns, and anti-repetition techniques.
有关完整的音序器函数、
parsePattern()
、示例 BGM pattern 和防重复技术,请参阅
sequencer-pattern.md
。

SFX Engine (Web Audio API -- one-shot)

SFX 引擎(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).
有关
playTone()
、
playNotes()
、
playNoise()
以及所有常见游戏 SFX 预设(score、jump、death、click、powerUp、hit、whoosh、select),请参阅
sfx-engine.md
。

AudioBridge (wiring EventBus -> audio)

AudioBridge(连接 EventBus -> 音频)

js
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() {
    // Init AudioContext on first user interaction (browser autoplay policy)
    eventBus.on(Events.AUDIO_INIT, () => audioManager.init());

    // BGM transitions
    eventBus.on(Events.MUSIC_GAMEPLAY, () => audioManager.playMusic(gameplayBGM));
    eventBus.on(Events.MUSIC_GAMEOVER, () => audioManager.playMusic(gameOverTheme));
    eventBus.on(Events.MUSIC_STOP, () => audioManager.stopMusic());

    // SFX (one-shot)
    eventBus.on(Events.SCORE_CHANGED, () => scoreSfx());
    eventBus.on(Events.PLAYER_DIED, () => deathSfx());
}
js
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() {
    // Init AudioContext on first user interaction (browser autoplay policy)
    eventBus.on(Events.AUDIO_INIT, () => audioManager.init());

    // BGM transitions
    eventBus.on(Events.MUSIC_GAMEPLAY, () => audioManager.playMusic(gameplayBGM));
    eventBus.on(Events.MUSIC_GAMEOVER, () => audioManager.playMusic(gameOverTheme));
    eventBus.on(Events.MUSIC_STOP, () => audioManager.stopMusic());

    // SFX (one-shot)
    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.
有关静音切换事件处理、
drawMuteIcon()
的 Phaser Graphics 实现、UIScene 按钮创建和 localStorage 持久化,请参阅
mute-button.md
。

Integration Checklist

集成检查清单

  1. Create
    src/audio/AudioManager.js
    — AudioContext + sequencer + master gain
  2. Create
    src/audio/music.js
    — BGM patterns as note arrays + sequencer calls
  3. Create
    src/audio/sfx.js
    — SFX using Web Audio API (oscillator + gain + filter)
  4. Create
    src/audio/AudioBridge.js
    — wire EventBus events to audio
  5. Wire
    initAudioBridge()
    in
    main.js
  6. Emit
    AUDIO_INIT
    on first user click (browser autoplay policy)
  7. Emit
    MUSIC_GAMEPLAY
    ,
    MUSIC_GAMEOVER
    ,
    MUSIC_STOP
    at scene transitions
  8. Add mute toggle —
    AUDIO_TOGGLE_MUTE
    event, UI button, M key shortcut
  9. Test: BGM loops seamlessly, SFX fire once and stop, mute silences everything
  1. 创建
    src/audio/AudioManager.js
    ——包含 AudioContext、音序器和主增益
  2. 创建
    src/audio/music.js
    ——将 BGM pattern 存储为音符数组,并通过音序器调用
  3. 创建
    src/audio/sfx.js
    ——使用 Web Audio API 实现 SFX(oscillator + gain + filter)
  4. 创建
    src/audio/AudioBridge.js
    ——将 EventBus 事件连接到音频
  5. 在
    main.js
    中连接
    initAudioBridge()
  6. 在首次用户点击时触发
    AUDIO_INIT
    (浏览器自动播放策略)
  7. 在场景切换时触发
    MUSIC_GAMEPLAY
    、
    MUSIC_GAMEOVER
    、
    MUSIC_STOP
  8. 添加静音切换——
    AUDIO_TOGGLE_MUTE
    事件、UI 按钮和 M 键快捷键
  9. 测试:确保 BGM 无缝循环、SFX 只触发一次并停止、静音后所有声音均被静音

Important Notes

重要说明

  • Zero dependencies: Everything uses the built-in Web Audio API. No npm packages needed for audio.
  • Browser autoplay: AudioContext MUST be created/resumed from a user click/tap. The
    AUDIO_INIT
    event handles this.
  • Master gain for mute: Route everything through a single GainNode. Setting
    gain.value = 0
    mutes all audio instantly.
  • Sequencer timing: The look-ahead scheduler (schedules 100ms ahead, checks every 25ms) gives sample-accurate timing with no drift. This is the standard Web Audio scheduling pattern.
  • No external audio files needed: Everything is synthesized with oscillators.
  • SFX are instant: Web Audio API fires immediately with zero scheduler latency.
  • 零依赖:所有功能均使用浏览器内置的 Web Audio API,音频处理不需要任何 npm 软件包。
  • 浏览器自动播放:AudioContext 必须在用户点击或触摸时创建或恢复。
    AUDIO_INIT
    事件负责处理此操作。
  • 使用主增益实现静音:将所有音频路由到同一个 GainNode。设置
    gain.value = 0
    可立即静音所有音频。
  • 音序器时序:前瞻调度器(提前调度 100ms,每 25ms 检查一次)可实现无漂移的采样级精确时序。这是标准的 Web Audio 调度模式。
  • 无需外部音频文件:所有声音均通过 oscillator 合成。
  • SFX 即时触发:Web Audio API 会立即触发音效,不会产生音序器延迟。

Optional: Strudel.cc Upgrade

可选:升级至 Strudel.cc

For richer procedural BGM with pattern language support, you can optionally install
@strudel/web
:
bash
npm install @strudel/web
Note: Strudel is AGPL-3.0 — projects using it must be open source. See
strudel-reference.md
and
bgm-patterns.md
in this directory for Strudel-specific patterns.
The Strudel upgrade replaces the Web Audio sequencer for BGM only. SFX always use Web Audio API directly.
如果需要更丰富的程序化 BGM 和 pattern 语言支持,可以选择安装
@strudel/web
:
bash
npm install @strudel/web
注意:Strudel 采用 AGPL-3.0 许可证——使用它的项目必须开源。有关 Strudel 专用 pattern,请参阅此目录中的
strudel-reference.md
和
bgm-patterns.md
。
升级至 Strudel 后,仅 BGM 会改用 Strudel,替代 Web Audio 音序器。SFX 始终直接使用 Web Audio API。