Take the climb to a real branch point, and find the cadence has a third column

FINDINGS 70, and it closes ROADMAP P6.  65.6 recorded that "the slack table is
here, but 51.3's refill climb with a second consumer through a real branch point
is not", and 67.6 repeated it verbatim two sessions later.
tools/analysis/36_branch_audio.py is that run: 51.3's surplus model, 56.3's 612
real branch points, 32's cadence arithmetic, both containers' headers and the
buffer constants of the player 68 measured, in one place.  No machine -- all
five were already numbers.

AUDIO IS 1.7% OF THE CODEC WIRE AND UP TO 3.30x OF THE CLIMB.  Slack accrues out
of pipe - wire, which is a small difference of two large numbers, so a second
consumer is not priced by its share of the wire -- which is how every budget in
this tree since FINDINGS 8 has quoted it.  At 451.4 KB/s (the container's own
zero-prefill pipe, 49.5) in a 256 KB ring the climb goes 6.70 s -> 22.11 s and
the branch points arriving under it go 482/612 (79%) -> 603/612 (99%).  At 488
it is 1.19x, at 600 it is 1.05x.  Correction to 56.4: it charged audio at
ratectl.AUDIO_KBPS = 7.8, which is 7,812.5 B/s in decimal kB; in binary KB the
figure is 7.6294, so the placeholder was 2.24% high and every column moved in
the flattering direction by less than one part in six hundred of the wire.

AND ON THE PACKED BRANCH THERE IS NO CLIMB AT ALL.  A record goes straight into
GVRAM, so the video lookahead is zero records and 56.4's alarming column is
vacuous when every frame arrives with less lookahead than the one before it.
Acceptance there is a per-frame deadline, not an average, which is why B1 has to
name a burst rate.  The only consumer on that branch with any lookahead is the
audio one: 1.833 s of sound held against 0.000 s of picture.  And at 589.6 KB/s
-- the acceptance figure this project quotes -- the sounded container's surplus
is exactly zero: it plays and never banks a byte, while the silent one climbs
its record in 6.38 s.

THE COST NOBODY HAD COUNTED.  A DLXP2 group is `lump k, then F records`, so lump
k is at a LOWER address than every record of its group but the first, and a seek
to record i finds its audio behind it.  Measured on the 409 within-container
seek targets of the arcade's own graph at the shipped F=11: mean 416.5 ms of
silence entering a branch, median 416.7, p90 750.0, worst 833.3, and only 36 of
409 land on a group boundary.  The other 203 -- the scene changes -- are free by
construction, because lump 0 sits between the header and record 0.  The
container's own start is the one branch point the cadence costs nothing at, and
it was the only one anybody had looked at.

SO THE CADENCE PICK IS REOPENED, on a third column.  32_audio_wire chose F=11 on
padding and RAM; F=1, the cadence it called the worst one, has no group to enter
off-boundary at all, and gives back 12,288 B of RAM for +4.36 KB/s of wire
(0.74% of the acceptance figure).  The alternative is a second read: lump k is
up to 503,808 B behind, so it is a separate command of 7,168 B -- 11.7 ms
against 416, 36x cheaper in time -- and src/player/packed.s starts PG_AK/PG_AKF
at lump 0 and has no audio seek path at all.  Nothing here decides it; the
deciding number is what one more SCSI command costs, and that is B1's.  The
content is not uniform mod F either: the measured mean runs 0.67x..1.23x of a
uniform assumption across the sweep, and the 1.00x at F=11 is a coincidence.

New check.sh stage, ~10 s, and it gates the STRUCTURE and deliberately not the
milliseconds: audio never shortens a climb, the shipped cadence strands most
within-container branches, F=1 strands none, and the lump read is an order of
magnitude cheaper than the silence it removes.

The one thing 70.3 and 70.4 rest on is a DESIGN ASSUMPTION and is printed in the
tool's own output: one container per SCENE (53, 55.1, 56.3).  One container per
sequence makes every seek land on frame 0 and empties both sections.

No encoder, player or container byte moved.

Claude-Session: https://claude.ai/code/session_01194oWYW8DQXK1SZ2DnChW6
This commit is contained in:
prosolis
2026-08-25 14:21:32 -07:00
parent ab15c0749a
commit 8b5f51704c
6 changed files with 817 additions and 5 deletions
+103
View File
@@ -1,3 +1,106 @@
# Status & next-session handoff — end of session 38 (2026-08-25)
## Session 38: the climb meets a branch point with sound on it, and the cadence has a third column
**FINDINGS 70.** ROADMAP P6's last and oldest item, named by 65.6 and repeated
verbatim by 67.6: 51.3's refill climb with a second consumer, through a real
branch point. `tools/analysis/36_branch_audio.py` puts five things that had
never been in the same room together — 51.3's surplus model, 56.3's 612 real
branch points, 32's cadence arithmetic, both containers, and the buffer
constants of the player 68 measured. It needs no machine: all five were already
numbers.
**THE HEADLINE. Audio is 1.7% of the codec wire and up to 3.30x of the climb.**
Slack accrues out of `pipe wire`, which is a small difference of two large
numbers, so a second consumer is *not* priced by its share of the wire — which
is how every budget in this tree since FINDINGS 8 has quoted it. At 451.4 KB/s
(the container's own zero-prefill pipe, 49.5) in a 256 KB ring the climb goes
**6.70 s → 22.11 s** and the branch points arriving under it go **482/612 (79%)
→ 603/612 (99%)**. At 488 it is 1.19x, at 600 it is 1.05x.
**AND ON THE PACKED BRANCH THERE IS NO CLIMB AT ALL.** The packed player puts a
record straight into GVRAM, so its **video lookahead is zero records** and
51.3's question has no answer there: 56.4's alarming column is vacuous when
every frame arrives with less lookahead than the one before it. Its acceptance
is a per-frame deadline, not an average, which is why B1 has to name a burst
rate. **The only consumer on that branch with any lookahead is the audio one**
1.833 s of sound held against 0.000 s of picture. And on the CPU-painted variant
the acceptance figure itself reads differently: **at 589.6 KB/s the sounded
container's surplus is exactly zero**, so it plays and never accumulates a byte,
while the silent one climbs its record in 6.38 s.
**THE COST NOBODY HAD COUNTED.** A DLXP2 group is `lump k, then F records`, so
lump *k* is at a LOWER address than every record of its group but the first. A
seek to record *i* finds its audio behind it and the next lump ahead carries
frame *(k+1)F*. Measured on the **409 within-container seek targets of the
arcade's own graph** at the shipped F=11: **mean 416.5 ms of silence entering a
branch, worst 833.3 ms, and only 36 of 409 land on a group boundary.** The other
203 — the scene changes — are free by construction, because lump 0 sits between
the header and record 0. **The container's own start is the one branch point the
cadence costs nothing at, and it is the only one anybody had looked at.**
**SO THE CADENCE PICK IS REOPENED**, on a third column. F=1 — the cadence
32_audio_wire called the worst one — has no group to enter off-boundary, and it
gives back **12,288 B of RAM** for **+4.36 KB/s of wire (0.74%)**. The
alternative is a second read: lump *k* is up to 503,808 B behind, so it is a
separate command of 7,168 B — **11.7 ms against 416 ms, 36x cheaper in time**
and `src/player/packed.s` has no audio seek path at all. **Nothing here decides
it; the deciding number is the extra command's overhead, and that is B1's.**
**What changed in the tree.** One new analysis file and one new ~10 s check.sh
stage that gates the STRUCTURE and deliberately not the milliseconds: audio
never shortens a climb, the shipped cadence strands most within-container
branches, F=1 strands none, and the lump read is an order of magnitude cheaper
than the silence it removes. No encoder, player or container byte moved.
## HANDOFF — start here
**THE TREE IS ALL GREEN**, session 38's stage included.
### The work, in the order it should be done
**1. THE AUDIO SEEK PATH (70.3), and it is now the cheapest thing that moves
something.** `PG_AK`/`PG_AKF` start at lump 0 and there is no way to enter a
group off-boundary. One extra read at `PG_ALBA0 + k*(F*PG_RECS + PG_CADA)` plus
a byte offset inside the lump is the whole of it, and until it exists the player
cannot branch with sound. It also turns 70.4's reopened cadence question back
into a non-question.
**2. THE BUFFERING DEPTH, which is still cheap.** Unchanged from session 37's
handoff: `PG_ANBUF` is 3 and `PG_APRE` is a mailbox. Two slots is one constant
and one run. 70.2 adds a reason to care — the audio buffer is the packed
branch's *only* buffer.
**3. THE SILENT-CLIP AND SHORT-AUDIO CASES (69.4).** Unchanged: a scene whose
audio is shorter than its frames (`00199`), and a scene with no audio track at
all (`00176`). Both are decided by what the lump count is computed from.
### What is still BLOCKED, so it is not picked up by mistake
**K4 — the packed player that is on screen — is conditional on B2**, a board
question. **E7, E4 and C1** are parked (61.8), and **P4a's wiring** is parked
with the ring K3 deleted.
**The hardware list is unchanged and is the user's**: B1 (sustained AND the
data-phase BURST rate, 64.2 — acceptance is **589.6 KB/s**, and 70.2 is the
sharpest statement yet of why the two rates are not interchangeable), B2
(blanking), B3 (`#EXREQ`), B4 (a byte write to a palette register), and session
34's fifth, play a known nibble stream on a real MSM6258V and record the line
out. **Session 38 adds a sixth question to B1 and it is small**: what one extra
SCSI command costs, because that is the number 70.4's cadence trade turns on.
### Reproducing this session
python3 tools/analysis/36_branch_audio.py --kbps 451.4 488.0 513.2 600.0 \
--ring 256 512 # ~10 s, the essay
python3 tools/analysis/36_branch_audio.py --gate # the check.sh stage
./tools/bench/check.sh # ALL GREEN
**WHAT IS NEXT.** The audio seek path, which is the first thing in this project
that the content has asked for rather than the hardware.
---
# Status & next-session handoff — end of session 37 (2026-08-25)
## Session 37: the audio level is measured off the whole disc, and the headroom is not worth buying