Field notes

Chapter 20 · Mechanism

Sound you can license: every recording CC0, measured and ledgered

The prototypes beeped. The games needed recorded sound: every file public domain, hashed, measured for loudness and pitch, looped without a click, and heard by a person before it shipped. Where no recording fit, a generated take now plays beside it, labeled as one.

The Margin6 min read

When a child at the Table for Six isn't sure about their seat, they make a small "hm?". When the cue was first built, three of its four takes were a young woman's "hmm", cut from a Freesound set and pitched up three or four semitones, and the fourth came from a recording of a toddler waking up. Our own note on it said it read as "a sped-up woman, not a child", which was fair.

That cue heads a list we keep of every sound in the break room where no library recording matched what we asked for. There are 38 on it. Volley has the most, twelve. Seven more are background sounds shared by the scenery, and The Week has none.

From five beeps#

The prototype page had five sounds, and they were all one oscillator: a sine or triangle wave with a quick envelope, at five pitches, named tick, place, chord, thud and brush. The brief for the real games asked for actual assets from the internet, so that was the first thing to go.

The license rule was CC0 or public domain first, CC-BY only with a visible credit, and nothing unclear or non-commercial at all. Every recording we use came from Freesound or Kenney's audio packs, and all of it is CC0. We checked at fetch time, on the source. Every Freesound item's page and API record named the CC0 deed, and every Kenney pack's page and bundled license file said Creative Commons Zero. With no CC-BY in the set, no game needs a credit line. The authors are listed in the ledger anyway, because they made the sounds.

That ledger, Docs/games/AUDIO-LICENSES.md, has a row for every shipped file with the cue, the source link, the author, the license, the fetch date, a SHA-256 of what was downloaded, and a note on what was done to it. When the four new games launched, it looked like this:

GameFilesSize
The Week35544 KB
Table for Six72913 KB
Paper Plane42873 KB
Loose Ends36756 KB

We allowed ourselves about 1.5 MB a game. Table for Six is the heaviest at 913 KB, and 34 of its 72 files are guest voices.

Four rooms#

Each game's sound manifest starts with a paragraph saying what the room is, and those paragraphs were written before any searching. The Week sits on a desk. A card comes off the pile, a pencil taps the grid as a piece crosses it, a rubber stamp lands, a finished day gets a pencil line through it, and a single wooden pluck climbs a pentatonic scale as your flow builds. Table for Six is a dining room with chairs scraping on floorboards and cutlery touching glass, and each guest has a closed-mouth "mm" repitched per person from one recorded set, so the dog comes out as a small "wuf". Paper Plane has no engine, which leaves the air. A wind loop follows airspeed in volume and filter, and a thin whistle only opens up when you are going fast.

Loose Ends was the fussiest. Every thread is a string, and moving a pin plucks the threads it holds at a pitch set by the thread's length. One good string recording carries a root frequency in the manifest and gets repitched to whatever note each thread needs. That only works if the root frequency is true, so the marimba and kalimba notes were measured with a small FFT script and tuned by resampling. A note the manifest calls C5 plays as C5.

Measured on the encoded file#

Everything went through one chain. Trim the silence, fade in over 5 ms and out over at least 10, high-pass, normalize loudness with the true peak under -1.5 dBTP, encode to AAC. Loudness is measured in LUFS, where a lower number is quieter. Short cues land at -18 LUFS. The continuous sounds a game leans on, like the plane's wind and the drone under a tangled Loose Ends board, land at -22, and so does the music. Room tone sits lower, at -28. All of it plays by default, and every game has a switch for anyone who wants quiet.

We measured after encoding, because the encoder is where surprises come from. The QA table for each game has duration, loudness, true peak, the level of the first and last millisecond, DC offset and a count of clipped samples. We decoded every shipped file again on Oct 7, 513 of them by then. Of the 455 that aren't music, not one has a clipped sample.

Loops got a test of their own. Each bed was crossfaded into a loop, and the jump across the seam was set against the largest sample-to-sample step anywhere else in the same file. On the Oct 7 decode, The Week's room tone jumps 0.0019 at the seam, while the biggest step inside it is 0.0177. No bed or ambience loop has a seam larger than a step the recording already makes on its own.

The reels#

A table of loudness figures can't tell you whether a chair scrape sounds like a chair. So every game got an audition reel before anything was wired in: each cue in order a third of a second apart, loops played straight across their seams so a click would be heard, a timestamped list of what plays when, and a spectrogram. The founder listened to the first four reels and signed them off before any of it went in.

The list sits beside the ledger in the games docs, with an entry for each of those 38 giving what shipped, what was wrong with it, and a prompt for a pass with generated sound. Some of the entries are small confessions. The dinner table's dining-room bed is a restaurant low-passed until the talk blurs, and a few words still come through if you listen. The pushpin in Loose Ends is partly Kenney's light wood knocks, which are wood on wood where the brief wanted steel going into cork. Paper Plane's loop-the-loop is meant to be somebody whistling a swoop, and one of its two takes is a slide whistle that sounds like a toy.

That pass ran on Sep 30, and every cue on the list now has generated takes. They play beside the recordings they were meant to replace, so nothing recorded was removed: the unsure child is now three generated takes and the original four, picked in turn. Each generated file went through the same chain, the same QA table and the same kind of reel, and its ledger row says "generated" and gives the prompt. Four came back weak and play only rarely, and each of those four also got a new CC0 recording at full weight. The break room's music arrived the same way: 46 generated pieces under a commercial license, beside 12 CC0 recordings, all in the same ledger.

The method got reused almost at once. Brief every cue, source CC0, process the same way, measure the encoded file, write the ledger row, make one reel, let a person listen, keep the list of misses. It is written up now as a reusable skill with its own scripts and a spec file per project, and Stack and Catch the Tasks got their sound from it afterwards: 27 recordings for Stack and 37 for Catch, in the same ledger.

The hash column has a wrinkle too. For Freesound items it is the hash of the high-quality preview, because downloading the original file needs a login. For a CC0 recording the preview carries the same license, and the ledger says which one we hashed.