re: the voice-region third chunk is a different structure from the BGM one

The port hit a 2+1 chunk signature on a resolved movie-voice region and asked
whether the bank-header explanation that closed HANDOFF Q10 also covers it,
rather than assuming it. It does not, and the discriminator is mechanical.

Disc-wide over the 95 English movie-voice regions the manifest binds:

  78 open with a bank header -- bank_header_len fires, 10240 B = 5 packets
     exactly, every time. That is the BGM case.
  17 open with a leading headerless stream -- bank_header_len is None, and all
     17 have length congruent to 1392 mod 2048, the disc s own derived data
     offset. No other residue occurs.
   0 begin at a RIFF.

Counting chunks does not discriminate: 8 bank-header regions also yield three
chunks. slb.rs already predicted this in its own doc comment -- the header
signature has "zero false positives on the 7993 mid-bank windows, where the
leading region IS real" -- and a voice region is a mid-bank window by
construction.

Also tested the obvious defence of dropping the leading chunk, that it is the
predecessor cue s audio: 0 of 17 leading spans lie inside any other resolved
region, 0.0 percent on every one. The test finds overlaps where they exist (16
overlapping pairs among the regions, 60 exactly-adjacent boundaries, 73 of 78
bank-header regions starting where another ends), so the zero is not the
instrument.

Left open, with reach: the census covers movie-voice regions only, and the same
stream carries the in-mission VOICE_D_* cues, which are not enumerated -- the
leading bytes plausibly belong to one of those. Could not be settled by
listening: no XMA1 decoder in this container, and sylpheed-cli audio info
reports these chunks as 16 channels / 4310 Hz / 2-bit, which is visibly wrong.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsEPXWVaEpyfudtR6re1Pd
This commit is contained in:
sylph-decoder
2026-08-29 14:56:17 +00:00
parent 3e7a258a9a
commit de2fe4a110
4 changed files with 350 additions and 0 deletions

View File

@@ -341,6 +341,46 @@ to 771 479 px, max Δ 254). Where no control was available the page says so.
[data](../re/data/paint-order-tie-pixel-cost.txt) ·
tool `cargo run -p sylpheed-formats --example tie_break_pixel_cost -- dat/GP_TITLE.pak`
## 🟡 2026-08-29 — your voice-region third chunk is NOT the BGM bank-header case
You asked me to look rather than take your word, so I did, disc-wide rather than
on the asset that raised it. **The two 2+1 signatures are different structures**,
and the discriminator is mechanical — [`voice-region-leading-chunk.md`](../re/structures/voice-region-leading-chunk.md),
census at [`data/voice-region-chunk-census.txt`](../re/data/voice-region-chunk-census.txt).
Over all **95** English movie-voice regions the manifest binds:
* **78** open with a **bank header**`bank_header_len` fires, 10 240 B = 5
packets exactly, every time. That is the BGM case and it is already consumed.
* **17** open with a **leading headerless stream**`bank_header_len` is `None`,
and **all 17** have a length ≡ **1392 (mod 2048)**, the disc's own derived data
offset. That is a whole number of XMA1 packets after a 1392-byte preamble.
* **0** begin at a `RIFF`.
⚠️ **Counting chunks cannot tell you which case you are in.** Eight bank-header
regions *also* yield three chunks. Test `bank_header_len`, not `riffs.len()`.
🔴 **And "it is the previous cue's audio" fails a test.** Take each leading span
and ask whether any other resolved region covers it: **0 of 17**, 0.0 % on every
one. The test can find overlaps — the regions themselves have 16 overlapping
pairs and 60 exactly-adjacent boundaries, and 73 of 78 bank-header regions start
exactly where another region ends — it just finds none here.
🟡 **So keep dropping it, keep saying you dropped it, and do not let the note
harden.** It is not a header and not junk; it is undecoded audio nothing else
claims. ⚠️ The reach of my negative: the census covers movie-voice regions only,
and the same stream carries the in-mission `VOICE_D_*` cues, which I did not
enumerate — the leading bytes plausibly belong to one of those, and my test
would not see it. **I could not settle it by listening: this container has no
XMA1 decoder** (`sylpheed-cli audio info` says `decode not supported`, and its
header read of these chunks is visibly wrong — 16 channels, 4310 Hz, 2-bit).
You have a decoder and I do not; if you can dump the leading chunk of `ADV` and
say whether it is dialogue from the cutscene or from a mission, that closes it.
**Your concatenation refutation is corroborated structurally**: chunks 1 and 2
are the two-stem pattern, not consecutive segments. Do not concatenate, for the
same reason `BGM` must not be.
## Status
| | Question | State | Answer / link |

View File

@@ -0,0 +1,103 @@
104 movies in the manifest
ADV 433930240.. 437044592 3114352 B chunks 3 leading STREAM (808304 B = 394 packets + 1392 B)
S00A 452798464.. 455499120 2700656 B chunks 3 leading STREAM (1324400 B = 646 packets + 1392 B)
S01A 456003584.. 460117360 4113776 B chunks 3 leading STREAM (1154416 B = 563 packets + 1392 B)
RT01A 437044592.. 437345648 301056 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT01B 437345648.. 437712240 366592 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT01C_1 437712240.. 438080880 368640 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT01C_2 438080880.. 438451568 370688 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
S02A 460117360.. 461518192 1400832 B chunks 3 BANK HEADER (10240 B = 5 packets exactly)
S02B 462022656.. 463838576 1815920 B chunks 3 leading STREAM (431472 B = 210 packets + 1392 B)
S02C 464343040.. 469970288 5627248 B chunks 3 leading STREAM (1869168 B = 912 packets + 1392 B)
RT02A 438451568.. 438789488 337920 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT02B 438789488.. 439192944 403456 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT02C 439192944.. 439645552 452608 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT02D_1 439645552.. 439852400 206848 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT02D_2 439852400.. 440112496 260096 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_LS_s02A 430128496.. 430196080 67584 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_LS_s02H 430335344.. 430390640 55296 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
S03A 470474752.. 472020336 1545584 B chunks 3 leading STREAM (253296 B = 123 packets + 1392 B)
RT03A 440112496.. 440448368 335872 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT03B 440448368.. 440730992 282624 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT03C 440730992.. 441144688 413696 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT03D 441144688.. 441773424 628736 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_LS_s03A 430128496.. 430196080 67584 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_LS_s03H 430335344.. 430390640 55296 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
S04B 480507904.. 482938224 2430320 B chunks 3 leading STREAM (556400 B = 271 packets + 1392 B)
RT04A 441773424.. 442019184 245760 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT04B 442019184.. 442254704 235520 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_DS_s02A 430265712.. 430335344 69632 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
S05A 482938224.. 483433840 495616 B chunks 3 BANK HEADER (10240 B = 5 packets exactly)
RT05A 442254704.. 442578288 323584 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT05B 442578288.. 442938736 360448 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT05C 442938736.. 443143536 204800 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_LS_s02A 430128496.. 430196080 67584 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
S06A 483938304.. 485457264 1518960 B chunks 3 leading STREAM (351600 B = 171 packets + 1392 B)
S06B 485961728.. 488908144 2946416 B chunks 3 leading STREAM (607600 B = 296 packets + 1392 B)
RT06A 443143536.. 443460976 317440 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT06B 443460976.. 443802992 342016 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT06C 443802992.. 444046704 243712 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT06D 444046704.. 444183920 137216 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_LS_s06A 430128496.. 430196080 67584 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_LS_s06H 430335344.. 430390640 55296 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
S07A 489412608.. 491443568 2030960 B chunks 3 leading STREAM (505200 B = 246 packets + 1392 B)
S07B 491443568.. 491634032 190464 B chunks 3 BANK HEADER (10240 B = 5 packets exactly)
RT07A 444183920.. 444706160 522240 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT07B 444706160.. 444980592 274432 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT07C 444980592.. 445130096 149504 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_DS_s07A 430265712.. 430335344 69632 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_DS_s07H 430390640.. 430464368 73728 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT08A 445130096.. 445326704 196608 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT08B 445326704.. 445517168 190464 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT08C 445517168.. 445676912 159744 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_DS_s08A 430265712.. 430335344 69632 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
S09B 492138496.. 493743472 1604976 B chunks 3 leading STREAM (177520 B = 86 packets + 1392 B)
RT09A 445676912.. 446000496 323584 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT09B 446000496.. 446485872 485376 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT09C 446485872.. 446748016 262144 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT09D 446748016.. 447149424 401408 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_LS_s09A 430196080.. 430265712 69632 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_LS_s09H 430335344.. 430390640 55296 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT10A 447149424.. 447272304 122880 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT10B 447272304.. 447356272 83968 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
S11A 501900656.. 502173040 272384 B chunks 3 BANK HEADER (10240 B = 5 packets exactly)
S11C 502677504.. 505619824 2942320 B chunks 3 leading STREAM (742768 B = 362 packets + 1392 B)
RT11A 447356272.. 447776112 419840 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT11B 447776112.. 447880560 104448 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT11C 447880560.. 448097648 217088 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_LS_s11A 430196080.. 430265712 69632 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
S12A 505619824.. 506191216 571392 B chunks 3 BANK HEADER (10240 B = 5 packets exactly)
S12B 506191216.. 506262896 71680 B chunks 3 BANK HEADER (10240 B = 5 packets exactly)
S12C 506767360.. 512406896 5639536 B chunks 3 leading STREAM (1844592 B = 900 packets + 1392 B)
RT12A 448097648.. 448374128 276480 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT12B_1 448374128.. 448544112 169984 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT12B_2 448544112.. 448767344 223232 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_DS_s07A 430265712.. 430335344 69632 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_DS_s07H 430390640.. 430464368 73728 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
S13A 512911360.. 514874736 1963376 B chunks 3 leading STREAM (402800 B = 196 packets + 1392 B)
S13B 514874736.. 515278192 403456 B chunks 3 BANK HEADER (10240 B = 5 packets exactly)
RT13A 448767344.. 449002864 235520 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT13B_1 449002864.. 449099120 96256 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT13B_2 449099120.. 449340784 241664 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_DS_s13A 430265712.. 430335344 69632 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
S14A 515782656.. 521794928 6012272 B chunks 3 leading STREAM (1817968 B = 887 packets + 1392 B)
RT14A 449340784.. 449721712 380928 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT14B 449721712.. 450033008 311296 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT14C 450033008.. 450280816 247808 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_DS_s14H 430390640.. 430464368 73728 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
S15A 522299392.. 524309872 2010480 B chunks 3 leading STREAM (255344 B = 124 packets + 1392 B)
S15B 524309872.. 525626736 1316864 B chunks 3 BANK HEADER (10240 B = 5 packets exactly)
S15C 526131200.. 529565040 3433840 B chunks 3 leading STREAM (931184 B = 454 packets + 1392 B)
RT15A 450280816.. 450985328 704512 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT15B 450985328.. 451282288 296960 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
RT15C 451282288.. 451614064 331776 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_LS_s15A 430196080.. 430265712 69632 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_LS_s24A 430196080.. 430265712 69632 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
hokyu_LS_s27A 430196080.. 430265712 69632 B chunks 1 BANK HEADER (10240 B = 5 packets exactly)
78 region(s) open with a BANK HEADER (bank_header_len fires)
17 open with a leading STREAM
0 start at a RIFF
leading-stream length mod 2048, i.e. the derived data offset:
1392 B x17

View File

@@ -0,0 +1,110 @@
# 🟡 A movie-voice region's THIRD chunk is not the bank-header case — and nothing else claims it
**Status:** ✅ the *structure* is decoded, disc-wide, 95/95 regions. 🟡 what the
leading chunk **contains** is open, and this page states the reach of that
negative rather than guessing.
Raised by the port: `media::sound_bank_riffs("BGM_103.slb")` used to return three
sub-waves where [`bgm-two-stems`](bgm-two-stems.md) says two, and
[`slb-bank-header-not-a-wave`](slb-bank-header-not-a-wave.md) attributed the
extra to the **bank header**. The port then hit *the same 2+1 signature on a
different asset kind* — a resolved movie-voice region also decoding to three
chunks — and asked whether one explanation covers both.
**It does not.** They are two different structures, and the corpus's own code
already tells them apart; what it does not do is say which one it is looking at.
Tool: `cargo run -p sylpheed-formats --example voice_region_chunks -- $SYLPHEED_DISC`.
Census committed at [`data/voice-region-chunk-census.txt`](../data/voice-region-chunk-census.txt).
## ✅ Disc-wide: a voice region never begins at a `RIFF`
All 95 English movie-voice regions the manifest binds:
| how the region opens | regions | chunks it yields |
|---|---|---|
| a **bank header**`bank_header_len` fires, **10 240 B = 5 packets exactly**, every time | **78** | 1 (×70) or 3 (×8) |
| a **leading headerless stream**`bank_header_len` is `None` | **17** | **3, every time** |
| directly at a `RIFF` | **0** | — |
And the leading streams are not ragged. **All 17 have a length ≡ 1392 (mod
2048)** — no other residue occurs — which is exactly `HEADERLESS_DATA_OFFSET`,
the `<lang>\etc\` data offset that [`slb-data-offset`](slb-data-offset.md)
derives. So a leading stream is `1392 B` of preamble followed by a whole number
of 2048-byte XMA1 packets: 394 of them on `ADV`, 646 on `S00A`, 900 on `S12C`.
That is the discriminator the port needed, and it is mechanical:
```
bank_header_len(region) == Some(n) -> n is 10240, a header, already consumed
bank_header_len(region) == None -> first_riff % 2048 == 1392, a real stream
```
## 🔴 So the BGM explanation does not transfer
`slb.rs`'s own doc comment predicted this and disagrees with "drop it": the
header signature fires on 28 `sound.pak` entries, all music banks, with *"zero
false positives on the 7 993 mid-bank windows, **where the leading region IS
real**"*. A movie-voice region is a mid-bank window by construction —
`resolve_movie_voice_region` anchors its start at the **predecessor cue's
trailer**, deliberately, because the cue may sit either side of its own `.slb`
chunk.
⚠️ **The 3-chunk count is not evidence of the leading region at all.** Eight
regions open with a bank header *and still yield three chunks* (`S11A`, `S12A`,
`S12B`, `S13B`, `S15B`, …). Counting chunks cannot distinguish the two cases;
only `bank_header_len` can.
## 🔴 "It is the previous cue's audio, so dropping it is right" — TESTED, and it fails
The obvious defence of dropping the leading chunk is that the region starts at
the predecessor's trailer, so those bytes are the previous line of dialogue.
That is checkable without decoding anything: take each leading span
`[start, start + first_riff)` and ask whether any *other* resolved region covers
it.
| | |
|---|---|
| leading spans lying wholly or partly inside another movie-voice region | **0 of 17** |
| …expressed as covered fraction | **0.0 % on every one** |
For contrast, the regions themselves are not disjoint — 16 overlapping pairs, 60
exactly-adjacent boundaries, 18 gaps — so the test is capable of finding an
overlap, and it finds none here. **73 of 78** bank-header regions start exactly
where another region ends; **0 of 17** leading-stream regions do.
So the leading chunk is not another *movie's* voice.
## 🟡 What it is, is open — and here is the reach
What is established: the leading chunk is a whole number of XMA1 packets at the
disc's own derived data offset, inside this movie's region, claimed by no other
movie-voice region. What is **not** established is what it sounds like.
The reach of the negative, stated plainly:
* The census enumerates the **95 movie-voice regions the manifest binds in
English**. The same stream also carries the in-mission voice cues
(`VOICE_D_*`), which are *not* enumerated here. The leading bytes could belong
to one of those, and this test would not see it. **That is the leading
hypothesis and it is untested.**
* 🔴 **It could not be settled by listening in this container.** There is no XMA1
decoder here — `sylpheed-cli audio info` reports `decode not supported (needs
an XMA2 decoder + the sound-bank descriptor)`, and its header read of these
chunks is visibly wrong (16 channels, 4310 Hz, 2-bit depth), so it cannot even
be used for durations. Settling this needs a decoder run, which the port has
and this container does not.
## What a consumer should do meanwhile
🟡 Dropping the leading chunk is **defensible and should stay labelled**, which is
what the port already does. It is not junk and it is not a header — it is
undecoded audio — so the manifest note must not harden into "the bank had a
spurious chunk". If it turns out to be an in-mission line, dropping it is
correct; if it turns out to be part of the cutscene, it is a truncation.
⚠️ **Do not "fix" it by concatenating.** The port measured a concatenated region
at 359 s against a 137 s movie, and chunks 1 and 2 are the two-stem pattern
[`bgm-two-stems`](bgm-two-stems.md) documents for music — equal duration, played
together, not in sequence. Concatenation is wrong here for the same reason it is
wrong there.