The library enumerator kept only names containing VOICE or \Briefing\, and read
eng\sounds.tbl unconditionally. So the Explorer could reach 4382 of the 9519
banks in sound.pak: no music, no jingles, no sound effects, and no Japanese
voice at all -- roughly half the disc's audio had no route to the UI.
`slb::list_audio_entries` now returns every named bank with the category its
path implies (Music / Jingles / Sound effects / Radio / Dialogue / Movie voice /
Briefing). `list_voice_clips` is that, restricted to the spoken categories, so
its existing test still guards the old behaviour. The 36 root banks carry no
language component and appear whichever table is read; the window gets an
English/Japanese switch that re-reads the other sounds.tbl, since the table name
IS the selector.
Two defects the decode found, both recorded in
docs/re/structures/sound-pak-contents.md:
* `Static.slb` -- the SFX bank -- declares 616768 bytes more than sound.p04
holds. Not our extraction: p04 matches the ISO's own directory record, and a
sweep of every pak on the disc finds this one entry over-running and no other.
It is the highest-offset entry, so its comp_size is an allocation size. A
short read is now allowed for the tail entry ONLY; any other overrun stays an
error, because clamping it would hide real damage behind a half-decoded asset.
The bank went from unreadable to 514 s of audio.
* the left-channel downmix was applied to everything. Right for voice (mono
content however stored), wrong for music (a real stereo mix, half of it
discarded). The caller now decides from the category.
35 of the 36 shared banks decode; JNGL_001 does not, and says so in the player
instead of the panel silently closing. Its payload is not a whole number of XMA1
packets from any known data offset, so it is likely not a plain headerless
stream -- written up rather than papered over.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Chasing w0 I decoded leading waves and the output matched neither trailer word.
Following that into RIFF waves, where the extent is certain, the decoded sample
count exceeds the seek table's last cumulative sample by a median 9.7%.
The tiebreak is the bank's own PsuedoBytesPerSec: over 14 banks it agrees with
an actual FFmpeg decode to a mean of 0.007 s and with the seek-table duration
only to 0.287 s. Two independent quantities agree with each other and both
disagree with the seek total, so that last entry is the last SEEK POINT, not the
sample count.
Both artifacts regenerated with data_bytes / PsuedoBytesPerSec. Total audio is
408.3 minutes, not the 390.9 I published -- 4.3% in aggregate. Dialogue timings
all rise, e.g. 'They got Leader!' from 1.78/2.46 s to 2.25/2.93 s.
What made this hard to catch is worth recording: the seek total gave BGM of 2.4
minutes, chatter of 2.8 seconds and cutscenes of 11 minutes, and I cited that as
the chain validating itself. It validated the structure, not the scale -- a
uniform 10% error preserves every ratio I checked.
With the wave boundary exact and Channels read rather than assumed, every field
describing a bank can be read: path, cue, sound id, channels, rate, data bytes,
packets, samples, seconds. Duration comes from the last cumulative sample in the
seek table over the sample rate -- arithmetic, no decoding.
Nothing was fitted to an expectation, yet every category lands where its content
says it should: BGM mean 146 s, Movie mean 79 s with an 11-minute maximum,
Briefing 10.8 s, in-mission Voice 2.79 s never exceeding 7.3. If the boundary
rule, the channel field or the seek table were misread, the numbers would not
sort into those five shapes.
Incidental: 4 banks run at 44100 Hz against 48000 everywhere else, and the BGM
tracks are the stereo ones. 1021 of the 5135 FILES paths have no RIFF and are
excluded as headerless.
static.slb (8970240 bytes, the shared SE bank) and Pj_Silph.xgs (533 bytes, XACT
global settings) both hash into the TOC. Their names come from the BANK_SE and
SETTINGS records of the very IDXD object this page documents -- I had printed
them at the top of the write-up and then reported the entries as unidentified.
9519 of 9519 now: 5100 jpn + 4382 eng + 35 root + these 2.
Every FILES path hashes straight into the sound.pak TOC (5135/5135, path as
stored). The archive is then almost fully accounted for: 5100 jpn + 4382 eng +
35 BGM/JNGL = 9517 of 9519. Only eng and jpn resolve -- deu/fra/ita/esp give
zero, which is the archive-side measurement behind 'two voice sets shipped'.
718 Japanese banks have no English counterpart.
More importantly this bounds an existing result. The leading-region rule from
voice-bank-leading-region.md reproduces its five documented banks EXACTLY under
eng\etc\ (16384/2048/14336/45056/59392), so the pipeline is sound -- but it
holds for only 1571 of 4382 English banks and for ZERO of 5100 Japanese ones.
It is a property of some English banks, not of .slb in general, and the Japanese
layout is undecoded.
I nearly misread this as a broken extractor, because FILES lists jpn paths and
those gave non-multiples of 2048. Reproducing the recorded figures exactly under
eng is what distinguished a wrong assumption from a wrong reader.