Skip to content

Give the commissioned pieces the treatment nocturne got - #42

Merged
rossry merged 1 commit into
mainfrom
art/audio-matched-scenes
Aug 28, 2026
Merged

rossry merged 1 commit into
mainfrom
art/audio-matched-scenes

Conversation

@rossry

@rossry rossry commented Aug 28, 2026

Copy link
Copy Markdown
Owner

Nocturne knows how to do this already — arc_s set to the movement's own duration, from/to on every parameter that has one, one dramaturgy per act. The other four audio-matched shows were cue sheets with a still image behind each cue. This is nocturne's lesson, applied to them.

Köln was the worst of it — 56 of its 66 minutes were four scenes that never changed, including a Layered(banks, theme) held flat for sixteen minutes and a RingWave whose arc completed in its first minute and then sat there for the next fourteen.

show longest single scene, before after
koln 18:13 7:30
apollo 8:02 (and every track static) 8:02, and every track travels
promises 9:30 8:52 (one deliberate crest)

No cue sheet moved. Every pinned track boundary, part length and Part I cue time is untouched; the shape went inside the movements.

Two rules, now in patterns/README.md

Set arc_s to the movement's duration — that is what it is for. And past six or seven minutes one arc stops being enough, because a monotone ramp across a quarter of an hour reads as flat too: there, nest a Conductor inside the movement. That keeps the outer cue sheet where the record put it while the inside gets a shape.

What each piece does now

koln — "revisited" (16:21) becomes settling / the long climb / coming to rest. Part IIa becomes the figure / the ecstasy: rings launch faster than they descend so two or three always share the sphere, and each is coloured by when it launched — fifteen minutes of unbroken pulse that is also one continuous walk from deep amber through white-gold and back down. Part IIb is the congregation gathering, warming (pools widen and cores climb, rather than just more candles), and thinning. Part IIc plays the tune and then brings the house lights up under the stars, which is what the live record actually does.

apollo — every track's arc_s is its own length. The vigil sky fills before the launch. Signals walks 223° cold blue to 93° gold as it is acquired. Always Returning's meander ends on the stop it starts from, so the last wave arrives in the first wave's colour. Silver Morning finally does the pewter-then-pearl its liner note always promised. "An Ending (Ascent)" is a nested pair — both words of the title, in order. Tracks 1, 6 and 12 share a salt: the record closes under the sky it opened under, and it is the same sky.

promises — the three sax movements are three crests that arrive earlier and burn hotter in turn (crest_at 0.62 → 0.50 → 0.42): a shape spread across movements rather than inside one. Movement 7 splits into the sky filling and the voice walking in it. The lattice is the piece and is untouched — but the obvious way to write that split (one Layered around the sub-conductor) hides the children from chapters() and makes it easy for a later edit to hand one scene its own lattice, so each sub-movement carries the lattice itself and a new test walks the tree asserting object identity across all ten scenes.

spiegel — the biggest gap between what the piece does and what the code did. Pärt's melodic voice leaves the tonic, reaches one step further than last time, and comes home; the code played the same 22-second climb 32 times. Now the line goes out and back on a half-sine, alternating direction, the reach widening and the breath lengthening every phrase — 30 phrases filling the recording, the first a short lean either side of the middle, the last a 29-second sweep nearly apex to rim. The dynamics still never change, because his don't. Phrase boundaries are a precomputed array searchsorted per frame: pure, so statelessness holds, as does the mirror.

Measured, not asserted

Mean L and lit-figure fraction sampled at five points inside every scene of every show — no movement is flat now — and the hue journeys checked directly. Cost is unchanged at the median (koln 14.6 ms, apollo 10.6, promises 15.2, on 6,660 lights), and koln's worst crossfade improves 46.8 → 36.1 ms.

439 passed, black --check clean.

The sharp edge, and it is pre-existing

A Conductor renders two children mid-fade, so every conducted show on main already blows a 33 ms frame at its seams — promises 50 ms, nocturne 43 ms. That is not from this branch (koln gets better here), but nothing measured it, so plan/todo/conducted-show-frame-cost.md now does: the numbers, four options ranked, and the honest note that none of it has been run on the deployment box under load. Worth a look before this goes in front of an audience.

Not covered: none of this has been seen on the sphere, only measured.

Every audio-matched show was a cue sheet with a still image behind each
cue. Köln was the worst of it: 56 of its 66 minutes were four scenes
that never changed, including one Layered(banks, theme) held flat for
sixteen minutes and a RingWave whose arc completed in its first minute
and then sat there for the next fourteen. Nocturne already knows how to
do this — arc_s set to the movement's own duration, from/to on every
parameter that has one, and one dramaturgy per act — so this is that,
applied to the other four.

Two rules came out of doing it, and they are now in patterns/README:
set arc_s to the movement's duration, and past six or seven minutes one
arc stops being enough — nest a Conductor inside the movement instead.
Nesting keeps the outer cue sheet exactly where the record put it (every
pinned track boundary is untouched) while the inside gets a shape.

koln: revisited (16:21) becomes settling / the long climb / coming to
  rest; Part IIa becomes the figure / the ecstasy, rings launching
  faster than they descend so two or three always share the sphere and
  each coloured by WHEN it launched — fifteen minutes of unbroken pulse
  that is also one continuous walk from deep amber through white-gold
  and back; Part IIb becomes the congregation gathering, warming, and
  thinning (pools widen and cores climb rather than just more candles);
  Part IIc plays the tune and then brings the house lights up under the
  stars, which is what the live record actually does. Longest single
  scene: 18:13 -> 7:30.

apollo: every track's arc_s is now its own length. The vigil sky fills
  before the launch; Signals walks 223 deg cold blue to 93 deg gold as
  it is acquired; Always Returning's meander ends on the stop it starts
  from, so the last wave arrives in the first wave's colour; Silver
  Morning finally does the pewter-then-pearl its liner note has always
  promised. "An Ending (Ascent)" is a nested pair, both words of the
  title in order. Tracks 1, 6 and 12 now share a salt: the record closes
  under the sky it opened under, and it is the same sky.

promises: the three sax movements are three crests that arrive earlier
  and burn hotter in turn (crest_at 0.62 -> 0.50 -> 0.42) — a shape
  spread across movements rather than inside one. The opening near-dark
  gathers for its whole six minutes; the quiet gives up a third of its
  light over seven. Movement 7 splits into the sky filling and the voice
  walking in it.
  The lattice is the piece and it is untouched — but the obvious way to
  write that split (one Layered around the sub-conductor) both hides the
  children from chapters() and makes it easy for a later edit to hand
  one scene a lattice of its own, so each sub-movement carries the
  lattice itself and a test now walks the tree asserting object
  identity across all ten scenes.

spiegel: the biggest gap between what the piece does and what the code
  did. Pärt's melodic voice leaves the tonic, reaches one step further
  than last time, and comes home; the code played the same 22-second
  climb 32 times. Now the line goes out and back on a half-sine,
  alternating direction, with the reach widening and the breath
  lengthening every phrase — 30 phrases filling the recording, the first
  a short lean either side of the middle, the last a 29-second sweep
  nearly apex to rim. The dynamics still never change, because his
  don't. Phrase boundaries are a precomputed array searchsorted per
  frame: pure, so the stateless contract holds, as does the mirror.

Measured, not asserted: mean L and lit-figure fraction sampled at five
points inside every scene of every show (no movement is flat now), and
the hue journeys checked directly. Cost is unchanged at the median
(koln 14.6ms, apollo 10.6, promises 15.2 on 6,660 lights) and koln's
worst crossfade improves 46.8ms -> 36.1ms.

That last number is the sharp edge, and it is pre-existing: a Conductor
renders two children mid-fade, so every conducted show on main already
blows a 33ms frame at its seams (promises 50ms, nocturne 43ms). Nothing
measures this, so plan/todo/conducted-show-frame-cost.md now does, with
the numbers, four options, and the honest note that none of it has been
run on the deployment box under load.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FbzmvdzTNSUxDUjVraRZMx
@rossry
rossry merged commit 64ea9b0 into main Aug 28, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant