Commit Graph

4 Commits

Author SHA1 Message Date
Sylpheed port agent
8fba7944d4 port: the game decodes all three voice streams at once, and two baseline rows were comparing blank frames
TWO FINDINGS, one mine and one handed to me, and the second retires a premise I
built on twice.

THE P1 BASELINE HAD ROWS THAT PROVED NOTHING. `build_12` and `build_15` render
pure black in BOTH renderers -- mean 0, max 0 -- so the difference is zero and
`verify-screen` scored them `max 0  over3 0  OK`, the strongest verdict it has.
Two of sixteen rows were comparing nothing against nothing. Worse than a missing
test, because a missing test is visible in the count.

Cause isolated by a control, not by reading: `build_00`/`build_01` are the same
loading screen minus three elements and render fine (mean 1.913, max 214.5). The
dressed variants add `pgloading_eff00`, a 1280x720 primitive resting OPAQUE BLACK
at t=38 inside its own opening black hold, with no layer key so paint order puts
it last.

The rule I was about to write -- "rest.t before the last timed keyframe is the
pathology" -- was killed by running the census first: 152 of 212 elements in this
export have rest.t earlier than their last timed keyframe. It is the norm. What
is actually unusual is the CONTENT, and its reach is one: `pgloading_eff00` is
the only element in the export whose resting pose is a fully opaque full-frame
quad. One instance is not a rule, so the renderer is unchanged and the HARNESS is
fixed: a blank pair now reports BLANK -- both renderers drew nothing; this row
proves nothing. `status` is untouched, so an unrelated DIFFERS still fails.

THE VOICE EXPORT IS KNOWN INCOMPLETE. The Decoder booted Canary with
--xma_param_probe and the game decodes ALL THREE streams CONCURRENTLY, in three
XMA contexts whose byte sizes match the disc payloads exactly. So "three
presentations of one take, pick one" is refuted by the running game and the
question I had been arguing -- WHICH presentation -- has no answer.

This one no census could have caught. Every measurement was right: the streams
are equal-duration, one is silence, one is 0.60x another with the residual 26.8
dB down. The frame around them was wrong, and the file says ChannelMask 0x0002 on
all three. It took the running game -- which is the mission's own sentence
arriving in practice.

BEHAVIOUR HELD DELIBERATELY. An equal-gain 1/n sum of channel pairs is not a
downmix either -- MISSION section 6 pins an explicit matrix for exactly that
reason -- and summing cost S00A 6.02 dB when one stream was silence. Swapping one
guess for another on a message is what produced this entry twice. What changed is
that the wrongness is now LOUD, because this failure sounds like success: one
stream is clean audible dialogue. A top-level manifest warning per movie, the
console line, and the authored entry all say `1 of 3 streams`.

"They are 5.1" is recorded as the Decoder's HYPOTHESIS with its own
counter-evidence attached, and nothing builds on it. What settles it is asked: a
recording of the game's own output over ADV through the null sink, which turns
channel roles into a fit against an oracle.

Refutation attempt, survived: the Decoder's loading-screen variant map. Entries
0/1 carry 7 elements and 12/15 carry those seven plus baseeff, eff00 and loop5 --
exact in count and identity, and it is what made build_00 a control.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N7FiFFFwbvG2uxdcEh8HyF
2026-08-29 15:50:02 +00:00
Sylpheed port agent
c43d44f57e port: withdraw the dual-mono generalisation -- the measurement stands, the rule does not
I argued `highest_rate` had no case because ADV's higher-rate presentation is
dual-mono while its louder one is mono-in-stereo, so the extra bytes buy a
duplicated channel rather than fidelity. The Decoder tested that disc-wide over
the 28 three-stream cues: the stream-3/stream-2 size ratio runs min 0.0778,
median 1.2565, max 2.9163, sd 0.5057, with only 12 of 28 within 15% of 1.0, and
declared rates scatter with them. A 37x spread is not a duplicated channel.

The CHANNEL MEASUREMENT STANDS -- ADV chunk 1 is mono-in-stereo and chunk 2 is
dual-mono at -8.318574, this port's own decode, which the Decoder could not
re-run and did not dispute. What fails is the step from one asset to the format.

NOTHING IN THE EXPORT CHANGES. `loudest` is a per-asset content rule -- it reads
the peak of the streams in front of it -- so a scattering structural ratio cannot
undermine it. What changes is the REASON, in four places: authored/audio.json's
presentation_why, the selector comment in audio.rs, BLOCKED.md's row, and
DECISIONS.md. The honest statement is narrower: `highest_rate` was never refuted,
it was never argued for, and neither is `loudest`. That is why the entry is
marked CHOSEN rather than measured, and why one capture deletes it.

Recorded on the pattern rather than just the instance: this is the third claim of
mine in two iterations that generalised a single-asset observation, after "the
chunks are two stems" and "everything the sequencer paces off rest.t is late".
All three were true of the thing I looked at. The failure is reaching for the
rule a measurement would imply if it held everywhere and writing that down in the
same breath as the measurement.

Also noted, not mine and not affecting export_voice: S12B's three streams are
byte-size identical, and BIRD_224 is three-stream while not being a movie cue.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N7FiFFFwbvG2uxdcEh8HyF
2026-08-29 15:39:22 +00:00
Sylpheed port agent
2939c21b38 port: settle times measured -- the pacing was already right, and my own red flag was half wrong
THE TRANSCODE CACHE HAD NEVER HIT. `video::transcode` has carried one since P4 --
a `.cmd` sidecar with the command, the source size and the channel count -- and
`main.rs` clears the output tree wholesale immediately before the check, deleting
the sidecar and the file it stamps. Six exports in this session paid the full
Theora encode and produced five byte-identical files, roughly 48 minutes. Nothing
reported it, and nothing could: a cache is silent either way and the only symptom
is a wall clock that looks like the job being slow. The wipe now spares `video/`
and `prune_videos` deletes anything in it this run did not claim, so the
wholesale guarantee is kept rather than traded. A re-export is 20 s.

SETTLE TIMES, MEASURED, and they refute more of my row than they confirm. The
principle holds -- the title's rest.t is 251 units = 4.183 s where its art
finishes at ~2 s -- but "everything the sequencer paces off that landmark is
therefore late" does not. Measured the port the way the game was measured, by
VISIBLE SPAN rather than arrival-to-arrival:

  publisher wordmark  port 4.25 s   game 4.297 / 4.604 / 4.370
  developer logos     port 3.50 s   game 3.508 / 3.503 / 3.366
  black hold          port ~0.25 s  game 0.2 - 0.3
  title -> plate      port 2.000 s (declared 120 units)   game 2.247 s

Dead on. My earlier reading compared the port's transition timestamps against the
game's visible spans, which differ by the exit ramp plus the black hold -- the
whole of the discrepancy I was about to chase, and the same definitional trap
that cost this corpus 0.48 s on the plate delay. Nothing in the sequencer is
changed. `dwell_seconds` stays null, now for a measured reason rather than an
absent one: `timing.json` said "if a capture ever times the real boot, this is
where that number goes", and the answer is that nothing goes there.

Not authored, deliberately: an (A)->menu dwell, which measures 3.763 s and
contains a 1.53 s guest load stall on a cold cache; and the menu build-in and
(B)->title, which rest on one run where the port is already within ~0.1 s.

THE VOICE PRESENTATION MOVED TO authored/, because the recommendation behind it
was withdrawn as self-contradictory and the choice is now unambiguously mine.
`voice.presentation` = `loudest`, and the reason to switch is a measurement, not
a preference: ADV chunk 1 is MONO-IN-STEREO and chunk 2 is DUAL-MONO, so chunk
2's extra bytes encode a duplicate channel rather than fidelity. That explains
the byte-rate difference and removes the only argument for `highest_rate`. ADV's
dialogue now exports at +0.3 dBFS instead of -8.7, which is the SE bound's
documented decode overshoot on a wave mastered at full scale.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N7FiFFFwbvG2uxdcEh8HyF
2026-08-29 15:35:24 +00:00
Sylpheed port agent
d6252481e1 port: P6 -- the menu has sound, and the BGM I "chose" was decoded all along
The three Static.slb cues and the menu bed now export to Ogg Vorbis and play.
`sylpheed_formats::media` does the assembly; nothing in port/ has heard of XMA.

Three things this milestone got wrong before it got right, all recorded in
docs/port/DECISIONS.md because the corrections are the useful part:

1. The cue offsets were a Rust `const` in the exporter. They are MEASURED, not
   decoded -- a measured value compiled into the exporter is a measurement
   wearing the costume of a decoded field, and nobody deletes it because nobody
   can see it. They are authored/audio.json now.

2. I picked BGM_001 and wrote a careful `why` calling the choice arbitrary. The
   menu's music is BGM_103, and it is in HANDOFF at 0fd8e69 -- the exact commit
   BLOCKED.md says that row was reconciled against. Not stale: wrong when
   written. I had summarised a negative without its reach, so "the TABLES cannot
   say which BGM a screen plays" became "it is not on the disc". One word of
   scope was the whole answer, and the export failed only because BGM_001
   without its .slb extension hashes to nothing. That is luck, not design.

3. The comment above the BGM sum argued for unity gain "because halving is a mix
   decision nobody made". It clipped at +1.8 dBFS. 1/n is the smallest constant
   that provably cannot clip -- the same reasoning video.rs already carried for
   its 5.1 downmix, in this repository, unread.

Unsettled and shipped as such: media::sound_bank_riffs returns THREE sub-waves
for BGM_103.slb where HANDOFF Q10's census says exactly two (the third is the
leading headerless region slb.rs emits for the voice path). The exporter sums all
three and writes a manifest warning, because which bytes belong together is the
decoders' question, not this exporter's -- and dropping one would destroy the
evidence, since a corrected export looks exactly like a correct one. Raised with
the Decoder; row in BLOCKED.md.

The gate is a null control, not a peak reading. A master-bus WAV that is
non-silent proves nothing -- the bed alone would look identical. So the same
scripted walk was run with <- in place of <v>, which fires no cue (Q5, measured),
and the difference is one 0.55 s burst at t=1.10 s and silence everywhere else.
The first attempt at that control returned bit-identical zero and I nearly filed
it as "cues never reach the bus": both runs ended at 1.115 s and the first press
lands at 1.17 s. A null result from an instrument that was not running is not a
null result.

Refutation attempt: HANDOFF Q8's three cue durations. They looked attackable --
0.133/0.172/0.169 s per packet, no shared rate -- but an XMA1 packet carries a
variable number of 512-sample frames, and the three come to 50.0/32.3/95.3
frames. Measured off the decoded Ogg: 0.533, 0.344, 1.016 s, every published
digit. SURVIVES, with its reach stated -- it confirms the assembly path and my
transcription, not the event bindings, which only an oracle can retake.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WM5XL4HfrHuxz8RiMWdCMC
2026-08-29 12:29:13 +00:00