VAB sound bank Confirmed
A VAB is Sony's standard PlayStation instrument bank: the set of sampled sounds (drums, strings, sound effects) that sequenced music plays against. Every bank starts with the magic bytes VABp and holds up to 128 programs (instruments), each with up to 16 tones (key-range variants), pointing into SPU-ADPCM voice bodies - the PSX sound chip's compressed sample format. If you want Legaia's music out of the disc, VAB is one half; the note data is the other half (SEQ).
Overview
Implementation: crates/vab (header parser + extractor + ADPCM decoder, sharing F0/F1 filter constants with crates/xa). The format itself is documented externally; the Legaia-specific notes - the parts that trip up a stock VAB extractor - are:
- The bank is usually wrapped. The dominant on-disc carrier is the scene-VAB-prefixed streaming shape - the VAB body is preceded by a 4-byte chunk0 header, so the
VABpmagic is not at offset 0.crates/vab::parse_header(buf, offset)accepts a starting offset so callers can skip the wrapper. - There are a lot of them. A bulk scan finds 1191
VABpheaders across 239 PROT entries (numbered entries inPROT.DAT, the disc's single big archive). Top:0889_sound_data2(207),0891_level_up(206),0890_sound_data2(203) - multi-bank archives. Thevab_01cluster (1072..1194) is the standard distributed-bank layout: 120 entries with 1–3 banks each. - Don't trust the filename. Extraction filename labels carry the +2 CDNAME numbering shift (the historical “vab_01 without VAB headers” was that shift - the retail
vab_01block, extraction 1070..1192, is wall-to-wall VAB); trust theVABpmagic + loader constant over a filename label. - Program numbers are not tone-page indices. The 128-slot
ProgAtrtable is indexed by program number (what a SEQ ProgramChange or SFX descriptor names), but the tone pages that follow are packed - one page per used program, in slot order - so a program resolves to its page by rank among the used slots. Retail builds that rank map at VAB open (FUN_80068D94writes it into the ProgAtr+8reserved words; the program-changeFUN_80068B98reads it back). It matters: 66 of the 217 wrapped PROT-entry banks - 43 of 77 music banks - use sparse program sets, and indexing pages with the raw program number mis-tones or silently drops most of their instruments. The engine expands pages into slot space at upload (VabBank::upload). - The VAG size table is 1-indexed. The trailing VAG size table (256 ×
u16; a VAG is one sample body) hasvag_table[1..=vs]holding each sample's size in 8-byte units, sovag_table[0]is a reserved leading spacer. It is universally0across the retail corpus (986 / 986 VABs, asserted by the disc-gatedcorpus_vag_spacertest) - it is not a master pitch / sample-rate shift, so no pitch offset is derived from it (VabReport::vag_table_spacersurfaces the raw byte only).
API
use legaia_vab::parse_header;
let header = parse_header(buf, offset)?;
println!("VAB v{} ps={} ts={}", header.version, header.ps, header.ts);
For bulk extraction of every VAB and per-program WAV files, see the vab CLI documented in tooling/extraction.md.