On this page

Lessons Learned from a Decade of Audio Programming

What the talk teaches

  1. Playing sounds is cheap; the mix is the hard part. Mixing is adding signals sample by sample. The work is deciding what the player hears: lowering less important sounds, and above all not playing some sounds at all (maximum playbacks, stream limits, virtual voices).
  2. Max within radius. On Hellgate: London, and again on BioShock 2, each sound got a maximum number of playbacks within a radius, set by the sound designers. Inside each cluster only that many play, so sound still comes from every direction but the mix does not turn into noise. The idea comes from Murch's "rule of two and a half": past two sources, an audience hears "the sound of footsteps" rather than each step.
  3. Speak the sound designers' language. The one number to know: 6 dB is half or double. His first four lines in any new engine convert decibels to linear volume and back.
  4. Give designers the tool for the real problem, not the one they asked for (an ambience system, not "play these randomly on a timer").
  5. A small engine on top of middleware (FMOD here), with three details: start a sound paused, set its 3D position and volume, then unpause, or the mixer thread may play a few samples with the old settings and pop; hand out integer channel IDs, not objects pointing into the sound system (an object outlives the voice it points to; switching to IDs fixed many odd crashes for him); and return a valid ID even when the load fails, so code that replays whenever its ID is invalid does not retry every frame.
  6. Sound loses memory and schedule at the end. Ask for more than you need, use all you get. Thread the audio interface so audio hitches never reach the game. Listen to your games on as many speakers as you can.

What the kit took

Measured: the "start paused" pop in Godot 4.7.2

A pooled player first played a 60 ms 1 kHz tone with the old setting (position 5000 px or 10 m to the left, 0 dB, or pitch 1). It was then given the new setting (to the right, -40 dB, or pitch 2) just before or just after Play() in the same frame. AudioEffectCapture on Master recorded the first 5 ms. In the position and volume cases the new playback ran at pitch 1.5, so it could be told apart from the old one. Each case ran 40 times under Xvfb with Godot 4.7.2 standard; the first PulseAudio case lost 3 tries to the driver warming up (no sound at all), so it counts 37.

So the skill says the order does not matter in Godot. The FMOD workaround is not carried over.

Not taken, and why