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 9ca1eb5 -- 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
114 lines
7.5 KiB
JSON
114 lines
7.5 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."
|
|
}
|
|
}
|
|
}
|