score
The composition. What every sound in FURROW is made of, how loud each one sits at any instant of the film, and which one-shots land on which beat.
score
The composition. What every sound in FURROW is made of, how loud each one sits at any instant of the film, and which one-shots land on which beat.
It holds no entity and plays nothing. Score.component turns it into sound;
bake_score.luau turns its recipes into .soundClip assets.
The film is mixed, not sequenced
The obvious way to score 181 seconds is to render 181 seconds and start it at
t=0. It is the wrong way here twice over: nothing in this engine schedules a
sound at a mixer time — :play() plays on whatever frame the script ran — so a
score cut into consecutive segments has a frame of jitter at every join, and a
frame is 42 ms of hole; and a long encode stalls the frame loop past the hang
watchdog.
So the score is seven seamless loops running from the first frame at a volume
of zero, plus one-shots fired on the film's named beats. Nothing has to start
on time because everything is already running; what changes is how loud each
layer is. That makes the sound arc a pure function of filmClock.now(), exactly
like the air is — run the film twice and the mix is the same both times.
| bed | what it is |
|---|---|
air | Act I. A pedal and a shimmer, and almost nothing else. |
drone | the low pedal that grows under Act II, beating against itself half a hertz out |
pulse | the percussion. In at the first tremor, flat out into the breach |
mass | the full weight — a detuned saw cluster over a sub, saturated to glue |
ring | what the impact leaves in your ears |
wind | the world's own bed, opened by film.clarity(t) |
wall | the two-hundred-metre dust front arriving over the last twenty seconds |
and three that belong to a place rather than to the film, so a shot standing
at the rig hears the rig: rumble (travelling under the crust — its emitter
moves), drain (the crust opening, then the pan sliding into the sink), and the
one-shots panel, mastfall, breach and impact.
The three surfaces
local score = require("furrow.score")
score.gains(t) -- every bed's volume at film time t
score.channels(t) -- (music, world) mixer channel levels at t
score.events() -- every one-shot, in time order
score.shotAt(t) -- which of the 24 set-ups the film is inside, and how far
score.furrowAt(t) -- where the travelling furrow's emitter is
score.mastAt(i) -- where the nth survey mast stands
channels is where the score ducks and swells against the cuts rather than
against the clock. It reads the shot table the camera slice owns: on an intimate
set-up (the 4 cm macros, the rack onto a rib, the inside of the hole) the music
drops away and the world comes up; on an aerial or the breach the music takes
the frame. Both moves ease across the first half-second of the shot, so a cut is
heard as a cut and not as a switch being thrown.
M.MIX is the headroom the whole thing sits under. Nine beds and a one-shot can
be sounding at once and the mixer has no limiter in it, so every gain is written
as a musical balance in 0…1 and scaled by that one number.
Re-baking
Edit a recipe, then from edit mode:
execute { file = "/zero/source/furrow/bake_score.luau" }
execute { file = "/zero/source/furrow/bake_score.luau", args = { only = "wind" } }
Every clip is written with overwrite = true, so guids are kept and only the
bytes change — nothing that references a clip has to be touched. The bake prints
generation and encode time per clip and, for every bed, the seam ratio. Anything
much above 1 is a bed that will tick once a lap.
Scoped to this part · feeds back into the world's score.