clips
The fen's clip library, and the bake that makes it. Every sound the game plays that is not a spoken line is declared here and baked into a `.soundClip` under `/source/audio/`.
sound.clips
The fen's clip library, and the bake that makes it. Every sound the game plays
that is not a spoken line is declared here and baked into a .soundClip under
/source/audio/.
Clips.ref(name) is how the rest of the game reaches one. It answers nil
for a clip that was never baked, which is a real answer — a slice that plays a
sound the library does not carry should be quiet, not broken.
The library
The score — bed_fen (the fen at rest), bed_press (the same drone with
the tide in it), bed_lament (one reed pipe, for the title and both endings),
bed_crest (played once, when the water goes over the deck).
The place — amb_air (wind through the reed beds with the far birds under
it), amb_water (brackish water against the posts, which comes up with the
tide).
What the world does — sfx_gate, sfx_splash, sfx_creak, sfx_swell.
What the score does — answer_right, answer_wrong, tide_notch,
yowe_toll, hail_lean, gate_give, phase_won, phase_lost.
The interface — ui_click, ui_hover, ui_back, ui_page.
How each kind is encoded, and why
| kind | codec | because |
|---|---|---|
| bed — the score and the ambience | pcm | these loop, and an Opus clip loses its first few milliseconds on decode ([#8873]) — a step in the waveform, which is a click, every cycle |
| one-shot — a gate, a splash, a toll | opus | no seam to keep, and the file is a twentieth of the size |
| transient — a click, a page turn | pcm | the whole sound is its attack; losing five milliseconds off the front is losing the sound |
Compression goes in asset.create's settings. Creating a clip and calling
setSettings afterwards re-encodes the PCM through Opus and undoes the
choice ([#8872]), so it is never done that way here. Loop points are stored
and never read ([#8874]), so the beds are authored seamless end to end and
looped with the Audio component's own looping field.
The bake
Clips.bake { only, force } is idempotent — a clip already on disk is skipped,
so a re-run costs no credit and re-encodes nothing. A bed decodes and resamples
tens of megabytes of samples, so pass only and work through the library in
batches.
Beds are cut with Synth.bestLoop and refused above a seam ratio of 3, so
a clicking loop cannot be written by accident. A bed is levelled by its RMS
rather than its peak: a generated water take is a handful of splashes over
near-silence, and peak-normalising it leaves a bed nobody can hear.
Clips.SOURCES records what audio_gen was asked for, so a bake on a machine
that never had /source/generated can regenerate the source rather than
failing — and a source already on disk is never re-bought.
Clips.verify() reads every baked payload's header back off disk. A duration
of zero, one frame, or the wrong channel count is exactly the failure that
otherwise ships silently, so this is the proof, not the bake's own return.
[#8872]: an asset's compression settings must be set at creation [#8873]: an Opus clip loses its head on decode [#8874]: a clip's loop points are stored and never read
Scoped to this part · feeds back into the world's score.