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:
110
docs/re/structures/voice-region-leading-chunk.md
Normal file
110
docs/re/structures/voice-region-leading-chunk.md
Normal 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.
|
||||
Reference in New Issue
Block a user