Files
Sylpheed/authored/audio.json
Sylpheed port agent 81ea5cb324 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

157 lines
9.7 KiB
JSON

{
"format": "sylpheed.audio/1",
"_": [
"Menu audio. EVERY VALUE IN THIS FILE IS MEASURED OR CHOSEN -- none of it is",
"in a data file the exporter can read, which is why it is here and not in the",
"exporter. `measured` and `chosen` are NOT the same thing and this file keeps",
"them apart: a measurement is deleted when the disc states it, a choice is",
"deleted when somebody measures it.",
"",
"Two different kinds of not-on-the-disc live in this file and they are not",
"interchangeable:",
"",
" * `se` -- MEASURED. `Static.slb` is a delimiter-less run of whole 2048-byte",
" XMA1 packets: no RIFF, no seek chunk, no XACT container. A wave is defined",
" ONLY by (offset, packet_count), and both numbers come from the running",
" game, not from the file. HANDOFF Q8. Delete a row the day a table on the",
" disc states the same thing.",
"",
" * `bgm` -- MEASURED, and only the LOOP POLICY beside it is chosen. HANDOFF",
" Q10's negative is about the TABLES: `SOUNDS`, `FILES` and the bank headers",
" name no screen. The executable does -- cue 1103 = `BGM_103`, corroborated",
" by a byte-for-byte match against what the XMA probe saw at the main menu.",
" An earlier draft read the negative as unbounded, picked a track at random",
" and called it authored. See the `bgm._` block for what that cost.",
"",
"The exporter reads this file and emits `export/audio/**` from it. It holds no",
"cue table of its own: a measured offset compiled into a Rust `const` is a",
"measurement wearing the costume of a decoded field, and MISSION section 3 is",
"explicit that measured values live here."
],
"se": {
"_": [
"MEASURED, HANDOFF Q8, and the RE agent retracted an earlier 'cannot be",
"extracted' to publish these. The waves were located BY PLAYING THEM: Canary",
"with `--xma_param_probe=true` prints a stream's packet count and first 32",
"bytes when it is played, and searching those bytes in the bank gives the",
"offset.",
"",
"WARNING, from the same finding: the file order is NOT cue-id order. These",
"cannot be counted out, and an index here would be a fabrication.",
"",
"`name_match` is the authors' own identifier GUESSED BY NAME. It is carried",
"so the guess is not lost and is never presented as the measurement. Where",
"the RE agent did not separate two candidates, there is no name at all --",
"an absent `name_match` means nobody has claimed one, never that the",
"BINDING is unknown. The binding is the measured part.",
"",
"All three are mono 48 kHz; that is the RE agent's statement in",
"`sylpheed_formats::media::se_wave_riff`, not something re-derived here."
],
"move": {
"bank": "Static.slb",
"offset": "0x1ec0",
"packets": 4,
"channels": 1,
"rate": 48000,
"name_match": "SE_UI_CURSOR",
"why": "HANDOFF Q8, measured: the d-pad move cue, 8 192 B / 0.533 s, reproduced across two boots. Left/right play nothing at all, which is a measurement too and is why there is no `left`/`right` row here rather than a silent file."
},
"confirm": {
"bank": "Static.slb",
"offset": "0x5d6c0",
"packets": 6,
"channels": 1,
"rate": 48000,
"why": "HANDOFF Q8, measured: the (A) confirm cue, 12 288 B / 1.016 s. NO `name_match`: Q8 is explicit that (A)'s wave was not separated between `SE_UI_DECIDE` and `SE_UI_SUB_WIN_OPN`, so naming it would invent the one thing the measurement did not settle."
},
"back": {
"bank": "Static.slb",
"offset": "0x0ec0",
"packets": 2,
"channels": 1,
"rate": 48000,
"why": "HANDOFF Q8, measured: the (B) back cue, 4 096 B / 0.344 s, reproduced across two boots. No `name_match` for the same reason as `confirm` -- Q8 names no identifier for it."
}
},
"bgm": {
"_": [
"MEASURED, NOT CHOSEN -- and the port got this wrong for one iteration.",
"",
"`docs/port/BLOCKED.md` carried a row reading 'not on the disc ... the port",
"is choosing a track, and that choice is authored', and the first draft of",
"this file duly picked BGM_001 and labelled it arbitrary. That row was not",
"stale: `BGM_103` is in HANDOFF at `9ca1eb5`, which is the exact commit the",
"row says it was reconciled against. It was WRONG WHEN WRITTEN.",
"",
"What HANDOFF actually says is a negative with a stated reach, and the reach",
"is what the port dropped: the *tables* cannot say which BGM a screen plays",
"-- `SOUNDS`, `FILES` and the bank headers name no screen. The EXECUTABLE",
"can. `GamePart_Title`'s phase handler `sub_821C5580` carries `li r5, 1103`",
"into a sound call, cue 1103 is `BGM_103`, and `BGM_103.slb`'s two declared",
"waves (3 876 864 / 3 930 112 B) are byte-for-byte the two streams the XMA",
"probe saw decoding at the main menu. Static code, disc census and runtime",
"agree. HANDOFF's own words: 'The port does not have to choose a track.'",
"",
"So this section is a CITATION, not a decision. It lives in `authored/`",
"only because the binding is in the .xex and the exporter reads data files,",
"not code -- and it must be deleted the day something the exporter can read",
"states it. The loop policy below IS still a decision."
],
"main_menu": {
"bank": "BGM_103.slb",
"loop": "restart",
"kind": "measured",
"why": "MEASURED, HANDOFF Q10 -- NOT a port choice. `GamePart_Title`'s phase handler `sub_821C5580` plays cue 1103 = `BGM_103`, and `BGM_103.slb`'s two declared waves (3 876 864 / 3 930 112 B) are byte-for-byte the two streams the XMA probe saw decoding at the main menu. Static code, disc census and runtime all agree; see docs/re/menu-audio-cues.md and docs/re/structures/bgm-two-stems.md. The name carries its `.slb` extension because that is what `sound.pak` hashes -- `BGM_103` alone resolves to nothing, which is how the first draft of this file failed.",
"loop_why": "AUTHORED, and it will be AUDIBLY WRONG AT THE SEAM. HANDOFF Q10: no loop-point field has been identified anywhere, so the file carries no marked restart. `restart` replays from sample 0, which means the listener hears the track's own fade-out and the silence after it before the music comes back. Trimming to the fade would sound better and would be worse: it would INVENT a loop point, and an invented one is indistinguishable from a decoded one a month later. The seam stays ugly until a loop point is measured or a capture of the real menu looping settles it.",
"stems": "sum",
"stems_why": "MEASURED, HANDOFF Q10: a bank is exactly TWO waves of identical duration (32/32 banks on the disc), sample-synchronous -- transient correlation peaks at lag 0.00 s over +/-5 s and both stop at the same millisecond. Concatenating them plays the piece twice, the second time as a bass-less stem; that was the previous reading and it is refuted. Emitting two files would be wrong for a second reason: MODDING rule 1 is one logical asset, one file, and handing a modder two stems to line up by hand is the reassembly the exporter exists to have already done. WHAT IS SUMMED IS SETTLED; WHAT WAVE 1 IS, IS NOT -- HANDOFF calls it quieter, far more L/R-decorrelated and almost bass-free, so it reads as a surround-rear pair OR a second intensity layer, and `ChannelMask` is 0x0002 on both so the file will not say. A unity sum is right under either reading; a weighting would only be justified once that is settled."
}
},
"voice": {
"_": [
"WHICH PRESENTATION of a cutscene's voice to export. CHOSEN, not measured and",
"not decoded -- delete this the day a capture says which one the game plays.",
"",
"A voice region carries THREE PRESENTATIONS OF ONE TAKE (decoded disc-wide by",
"the Decoder: 258 inter-descriptor spans hold one stream, 28 hold three, none",
"holds two). The exporter drops the leading one, which this port measured to",
"be the tail of the others, and must then pick between the two full-length",
"ones. Nothing on the disc ranks them: wEncodeOptions, channel count and",
"channel mask are byte-identical across them.",
"",
"This lives here rather than in the exporter because MISSION section 3 puts a",
"value we chose in authored/ with a why. A selection rule compiled into Rust",
"reads like something the exporter derived, and nobody deletes what nobody",
"can see."
],
"presentation": "loudest",
"presentation_why": [
"`loudest` = the full-length stream whose peak is nearest full scale.",
"",
"IT USED TO BE `highest_rate`, on the Decoder's recommendation, and that",
"recommendation was WITHDRAWN as self-contradictory -- it read 'the",
"highest-rate, highest-gain one is chunk 1', and those two criteria select",
"different streams: ADV chunk 1 is 1118268 B at 0.0 dBFS, chunk 2 is",
"1171516 B at -8.3 dBFS.",
"",
"The reason for switching is a measurement of this port's, not a preference.",
"The case for `highest_rate` was that more bytes per second means a better",
"encode. It does not, here: ADV chunk 1 is MONO-IN-STEREO (channel 2",
"digitally silent) and chunk 2 is DUAL-MONO (both channels identical at",
"-8.318574). So chunk 2's extra bytes go into encoding a duplicate of its own",
"channel, not into fidelity, and the byte-rate difference is explained without",
"any appeal to quality. That removes the only argument for it.",
"",
"What is left points the other way, and both parts are weak on their own:",
"the disc masters its other audio near full scale (the SE cues decode to",
"+0.18 dBFS), and S00A's only surviving full-length stream is its louder one",
"at -4.2 dBFS -- so `loudest` makes the two cutscenes' dialogue sit at",
"comparable levels instead of 4.4 dB apart.",
"",
"STILL A CHOICE. One capture of the intro with dialogue audible settles it,",
"and it is the last unforced decision in the voice pipeline."
]
}
}