5.9 KiB
Soundbanks and in-memory sounds
Most short sound effects (footsteps, foley, combat, weapons, objects, UI, grunts) are not in the WADs: they
are WEMs stored inside Wwise soundbanks, either loose in SFX\*.bnk or embedded in the UE3 packages (.upk).
ackit lists them as the catalog archive BANK and writes them (see the end of this page).
Survey of the installed game (buildid 3718300), 2026-10-09.
Inventory
| where | banks | unique in-memory WEMs | in the catalog |
|---|---|---|---|
loose SFX\*.bnk (Batman/Catwoman footsteps, 32 surfaces each, + TST_Prep_Media) |
65 | 1,117 | 0 |
banks embedded in .upk packages (in 1,432 of the 2,650 packages) |
3,340 | 15,641 (~276 MB) | 0 |
The two sets share 119 media IDs: 15,800 unique media IDs in 96,011 places (bank copies). 396 of them are
prefetch heads of streamed WAD sounds (below), so there are 15,404 in-memory sounds. All copies of a
media ID are byte-identical except 1C898731 (two variants). The WADs, by comparison, are fully covered: the
BKPK tables in the packages reference 2,543 WAD entries, all of them in the catalog.
Embedded WEMs by bank name prefix: Speech 7,872, CHR (character foley, combat, bosses) 3,896, PSO 781,
WPN 664, NPC 475, OBJ 439, SEQ 265, GUI 208, PSA 203, MTN 196, PX 195, DVC 100, GEN 80,
PHY 73, AMB 65, SBJ 50, others < 30. The Speech_ banks (e.g. Speech_EMOTE_Batman, ..._GRUNT) hold
speech: grunts and efforts (language-neutral, 165) and localized lines (about 1,460 per language, see
Localized banks).
All WEMs seen are Vorbis (format tag 0xFFFF), the same codec as the WADs: the footsteps are mono (4 stereo),
the embedded ones mono or stereo (~22 % stereo in a 2,533-WEM sample).
Names
- The community hash list names none of these media IDs; only the bank names are known.
CookedPCConsole\CookedBanks.txtlists all 3,345 cooked bank names. Bank ID = FNV-1 32 of the lowercased name (the same hash Wwise uses for every name). 3,338 of them are embedded in packages, 4 are loose.bnkfiles (Init,Global,Music,Music_PDLC);AMB_OW_A6,AMB_OW_C1,AMB_OW_E1,Speech_EMOTE_Thug_Muffled_StopandSpeech_GFxUI_ArkhamCityStorieswere found nowhere.- Loose footstep banks are named in their STID chunk (
CHR_BatmanFootsteps_Concrete_Media, ...).
Bank layout (version 56, Wwise 2011.1)
Chunks BKHD {u32 version 56, u32 bank id, ...}, DIDX N x {u32 media id, u32 offset, u32 size} (offsets
relative to the DATA payload, WEMs 16-byte aligned), DATA, HIRC, STID {u32 type, u32 count,
count x {u32 bank id, u8 len, name}}. Init (50C63A23.bnk) has STMG/ENVS instead of media.
701C1363.bnk holds only BKHD.
HIRC Sound object (type 2) payload: u32 object id, u32 plugin id (0x00040001 = Vorbis), u32 stream type
(0 = in memory, 1 = streamed, 2 = prefetch), u32 media id, u32 bank id of the media; for in-memory sources
then u32 offset, u32 size, where offset = DATA payload position (from the start of the bank) + DIDX offset
and size = DIDX size (checked on every in-memory source of the footstep banks and of BmGame.upk).
Source kinds over all bank copies: 115,861 in-memory sources of the bank's own media; 2,233 in-memory sources
with bank id 0 whose media is not in the same bank (loaded by another bank); 133,075 streamed sources;
2,101 prefetch sources. Every streamed or prefetched media ID is in a BKPK table, i.e. a WAD sound
(wad.md). A prefetch source's media is also in the bank's DIDX: that in-memory copy is the head of the
streamed WEM (its size = the source's size), which the game plays while the rest is read from the WAD. 396
WAD sounds have such heads (2,101 copies); replacing one of them must rewrite the heads too.
Localized banks
Speech banks are localized inside the (language-neutral) packages: one AkBank export starts with a language
list (FStrings INT FRA ITA DEU ESN) and then holds one complete bank per language, in that order, all with
the same bank ID; each language's copy has its own media IDs (checked on 215 banks against the WAD languages
of their streamed lines). ackit labels every in-memory media with its language (BANK.csv column language):
8,098 language-neutral sounds, ~1,460 per voice language. A catalog shows the neutral sounds plus the loaded
language's lines; names are unique per language.
Banks inside packages
- The packages are LZO-compressed UE3 packages (
upk.md); ackit decompresses them itself and searches the uncompressed data forBKHD(banks) andBKPK(WAD indexes). (The first survey used Gildor's decompress.exe;ackit/upk.pygives identical data.) - Bank blobs in packages: 41,798 for 3,340 bank IDs. Many banks are copied into several packages (e.g.
CHR_CatwomanFoleySuit31 times,CHR_BatmanFoleyBelt26). 302 bank IDs occur as several blobs with different media subsets (often one WEM each, several per package), so a bank's media set is the union of all its blobs. - Largest:
CHR_RobinFoleyCape300 WEMs,CHR_BatmanFoleyCape282,CHR_Clayface263,CHR_NightwingFoley242,CHR_CatwomanFoleySuit225,CHR_MrFreeze176,CHR_Combat166.
How ackit edits them
- Catalog archive
BANK(one row per media ID) +data/catalog/BANK_locations.csv.gz(every copy, and the prefetch heads of speech lines); built bytools/build_catalog.py, checked byackit verify --catalog. - A replacement is written in place into every copy (no larger than the smallest copy, zero-padded), so
DIDX/HIRC offsets and sizes and the package layout never change. Loose banks are patched directly; in
packages only the touched blocks are re-encoded (
upk.md). A sound left in one package only would let the game load the original from another one. - Replacing a speech line that has prefetch heads rewrites the heads (first bytes of the new, zero-padded line).
- Design and revert rules:
docs/decisions.md(4b). The same WEM rules apply (wem.md).