re: a music bank is two stems that play together -- not intro+loop, and

not something to concatenate

Q10, and it starts by withdrawing the question's own premise. BGM_001 is
not three sub-waves of 10 KB / 4.47 MB / 4.67 MB: the 10 KB is the bank
header. A bank is exactly TWO waves, and across all 32 BGM banks on the
disc the two always have the SAME duration -- equal to 0.01 s over
lengths from 37 s to 277 s. That alone kills intro+loop and kills two
halves of one piece, both of which require unequal lengths.

Four banks appear to break the rule and do not: BGM_106-109 are the known
leading-region straddle, and the giveaway is that the entry named
BGM_107.slb contains BANK id=1108. The seek packet counts pin each join
exactly, so they realign to the same two-equal-waves shape rather than
being dropped as noise. That trap goes in METHOD.

Then the roles, by decoding both waves to PCM. They are
sample-synchronous: transient-envelope correlation searched over +/-5 s
peaks at lag +0.00 s, and both waves stop at the same millisecond,
167.663 s. Two stems of one performance, meant to sound at once. Wave 1
is quieter, has almost no bass and is far more L/R-decorrelated, which
reads as a surround-rear pair or a second intensity layer -- I cannot
separate those two from the file, and say so: ChannelMask is 0x0002 on
both, and this game's channel metadata is already documented as
meaningless.

Two things the port needs that are NOT on the disc, both marked as
authored: the track is not a seamless loop (BGM_001 fades out and is
followed by 6.15 s of silence, no loop-point field found), and nothing
names which bank the menu plays -- all 32 BGM cues are numeric.
This commit is contained in:
Sylpheed RE agent
2026-08-28 18:13:10 +00:00
parent 43dba9d6e0
commit c848668b1f
7 changed files with 220 additions and 6 deletions

View File

@@ -103,6 +103,7 @@ files, which is how the same ground got covered twice.
| [`structures/slb-data-offset.md`](structures/slb-data-offset.md) | `.slb` data offset = `(cumulative start of the `.pNN` segment) mod 2048`; the leading bytes are the previous bank's audio, not a header | ✅ CONFIRMED — exact for 8 783/8 783 banks, 0 mismatches; the four values (1392/1468/1600/1728) are the running sums of the five segment sizes mod 2048, which supersedes the earlier `first_riff % 2048` scan heuristic. Decoding at the right offset yields more audio in 85 of 140 sampled banks (median 70×), 54 identical controls. Wave boundaries are exact — `seek` magic at `data_at + declared_size`, **7 620/7 620** — and `Channels` must be read from `RIFF+49` (2.12 % are stereo) |
| [`structures/sound-pak-contents.md`](structures/sound-pak-contents.md) | Census of `sound.pak`, and the limit of the leading-region rule | ✅ CONFIRMED, 5 135/5 135 names hash into the TOC, **9 519/9 519** entries accounted for, and a full 4 114-bank manifest (408.3 min of audio) computed from PsuedoBytesPerSec without decoding; ⚠️ leading-region rule holds for 1 571/4 382 eng and 0/5 100 jpn |
| [`structures/sound-cue-table.md`](structures/sound-cue-table.md) | The cue index in `tables.pak` — message id -> cue -> sound id -> `.slb` bank | ✅ CONFIRMED, 1 326/1 338 script message ids bind to a bank; SOUNDS and FILES agree on the same 12 absentees, 0 orphan files |
| [`structures/bgm-two-stems.md`](structures/bgm-two-stems.md) | A music bank is two stems of one performance, played together | ✅ decoded structure, 32/32 banks two waves of equal duration (4 explained by the leading-region straddle); stems measured sample-synchronous; 🟡 rear-pair vs intensity-layer unsettled; ❔ no bank names a screen |
| [`structures/cutscene-message-table.md`](structures/cutscene-message-table.md) | Cutscene dialogue — speaker, portrait, on-screen seconds, audio cue per page | ✅ CONFIRMED, field count = 9·PageCount+2 for all 7 PageCounts, 1 252/1 252 caption keys match, 138 ids close both ways |
| [`structures/preset-message-rules.md`](structures/preset-message-rules.md) | The reactive-chatter rule table — 64 events, the (message, Yes/No) pair payload, the `Sperkers` roster | ✅ CONFIRMED, the seven fields read off `sub_82213980`, phase tables merge non-additively (224 variants discarded); 8 firing sites share one entry, Probability is a per-cent roll against rand*100.0; Yes = one-shot line; queue is Priority-ordered and capped at 128; the cooldown is Interval + Fluctuation*rand held in the lingering queue node; the 14 player-facing events are voiced by the player set alone (13/15 Katana tables, 0/129 others) (three are seconds ×60, the Yes/No element is a u32 mask, hence the 32 clamp); MessageCount·2 == positional count in 9 216/9 216; five naming routes union to 144/144 (six names predicted from the speaker roster before hashing, control 0/4); 2 388/2 405 message ids bind to a cue |
| [`structures/mission-scoring.md`](structures/mission-scoring.md) | Mission scoring and the S/A/B/C/D rank thresholds — 24 tables x 3 difficulties | ✅ CONFIRMED, one 22-field schema over 72 records; difficulty moves 10 of 22 fields and never the RankScore thresholds; ✅ all 24 named stage\StageParameter_S<NN>.tbl (+ _Tutorial shared by six, + _Test) |