How do you add sound to an AI-generated game?
Ask the AI to wire up the Web Audio API: create one AudioContext, decode your sound files into AudioBuffers once at load, then play copies on each event. The critical catch — browsers block audio until the user clicks or taps, so your AudioContext must start or resume inside a click handler, or nothing will play.
Why — the first-principles explanation
AI tools generate game code well and game sound badly, because sound isn't in the code — it's a separate asset plus a timing system. When an AI writes you a browser game, it usually emits HTML, CSS, and JavaScript with no audio at all, or it drops in an `<audio>` tag that half-works. Understanding why fixes it permanently.
The browser gives you two audio systems. The `<audio>` element is a media player: fine for one background track, terrible for games, because it has noticeable latency and you can't easily play the same sound twice at once — fire a laser twice quickly and the second shot cuts off the first. The Web Audio API is the real tool. It's a routing graph: you make an `AudioContext`, create source nodes, connect them through effect nodes like `GainNode` (volume) or `PannerNode` (3D position), and end at the destination (the speakers). Because it's built for precise, low-latency timing, it's what actual games use.
The performance trick is decode once, play many. Loading an MP3 gives you compressed bytes; `decodeAudioData()` turns those into an `AudioBuffer` sitting in memory as raw samples. That decode is expensive, so you do it at load time. Then every time the player jumps, you create a cheap throwaway `AudioBufferSourceNode`, point it at that same buffer, and start it. Source nodes are single-use by design — you can't restart one — so making a fresh one per shot is correct, not wasteful. That's the design that lets ten overlapping explosions cost almost nothing.
The last piece is the one that breaks 90% of AI-generated games: the autoplay restriction. Browsers refuse to let pages make noise on load, so a newly created AudioContext starts in a suspended state. Your code runs, no errors appear, and no sound comes out. The fix is to call `audioContext.resume()` from inside a real user gesture — a click, tap, or keypress. A "Click to Start" button isn't a design choice; it's a technical requirement.
An example that makes it click
Think of your sound files as sheet music and the AudioContext as an orchestra pit. Decoding a file is copying the sheet music out of the sealed envelope — slow, and you only want to do it once. An `AudioBufferSourceNode` is one musician who reads that sheet, plays it exactly one time, and then goes home forever. Need the sound again? Hire another musician. They're free and they read from the same sheet.
And the autoplay rule is the theater's front door: the orchestra isn't allowed to make a sound until someone in the audience actually walks in and takes a seat. That's why your game needs a start button. The musicians were ready the whole time — nobody had opened the door.
How to do it
- Get your sounds first: record them, use royalty-free packs, or generate them with an audio model. Save as MP3 or WAV. Keep effects under about 1 second and mono to save memory.
- Tell the AI exactly what to build, not just 'add sound.' Say: 'Use the Web Audio API. Create one AudioContext, preload and decodeAudioData all sounds into a buffer map at startup, and play each effect with a new AudioBufferSourceNode.'
- Add the unlock gesture: 'Add a Start button that calls audioContext.resume() on click, because the AudioContext starts suspended under the browser autoplay policy.'
- Route volume through a GainNode: 'Connect all sound effects through one GainNode so I can add a master volume slider, and give music its own GainNode separate from effects.'
- Hook sounds to events by naming them: 'Play jump.mp3 on the jump function, hit.mp3 on collision, and loop music.mp3 with loop = true.' Be specific about function names — AI wires audio to the wrong event when you're vague.
- Test overlap: trigger the same sound five times fast. If it cuts itself off, the AI reused one source node instead of creating a new one per play. Tell it to create a fresh AudioBufferSourceNode on every trigger.
- Add spatial audio last if you want it: 'Route each enemy sound through a PannerNode positioned at the enemy's x coordinate' — this is the polish step, not the foundation.
Key facts
- The Web Audio API works as a modular routing graph: sources connect through effect nodes to a destination, giving high-precision, low-latency timing suited to game sound effects.
- AudioBuffer holds a decoded short audio asset in memory, produced by decodeAudioData() from a file or createBuffer() from raw data.
- AudioBufferSourceNode is single-use: each playback needs a new node, which is why decode-once/play-many is the standard game pattern.
- GainNode multiplies input samples to control volume; PannerNode positions sound in 3D space and simulates distance attenuation.
- Browser autoplay policy requires a user gesture (click or tap) before audio can play, so an AudioContext created on page load is suspended until resumed from a real interaction.
- The <audio> element is unsuitable for rapid game effects because it cannot cleanly play overlapping copies of the same sound.
▶ The 60-second explainer (script)
Your AI built you a game and it's completely silent. Here's the fix. Don't ask for 'sound.' Ask for the Web Audio API by name. Tell it: create one AudioContext, load every sound file, run decodeAudioData on each one at startup, and store the results in a buffer map. Then, on every jump or hit, create a brand new AudioBufferSourceNode pointing at that buffer and start it. That sounds wasteful, but source nodes are single-use by design and cost almost nothing — it's why ten explosions can overlap without lag. Now the part that breaks most AI-generated games. Browsers will not let a page make noise on load. Your AudioContext gets created in a suspended state, your code runs, no errors appear, and you hear nothing. The fix is a Start button that calls audioContext dot resume inside the click handler. That button isn't decoration — it's required. Two more upgrades: route everything through a GainNode so you get a volume slider, and use a separate GainNode for music so players can mute the soundtrack without killing the effects. Want positional audio? Add a PannerNode per enemy. Do that last.
What authoritative sources say
People also ask
Why is my AI-generated game silent even though the code looks right?
Almost always the autoplay policy. The AudioContext is created suspended and never resumed, so playback calls succeed silently. Add a Start button that calls audioContext.resume() inside the click handler.
Can I just use an <audio> tag instead?
For one looping background track, yes. For game effects, no — it has higher latency and can't cleanly overlap copies of the same sound, so rapid repeats cut each other off.
Why does my sound effect cut itself off when triggered twice quickly?
The code is reusing a single source node. AudioBufferSourceNode is single-use; create a new one on every trigger, all pointing at the same cached AudioBuffer.
Can AI generate the sound files themselves?
Yes — audio generation models can produce effects and music, and the resulting MP3 or WAV files drop into the same Web Audio pipeline. The code side and the asset side are separate problems; solve the pipeline first so any asset works.
How do I add a volume slider?
Connect all your sound sources through a single GainNode before the destination, then set gainNode.gain.value from the slider. Use a separate GainNode for music so players can mute it independently.