List and edit in-memory sounds in soundbanks

This commit is contained in:
2026-10-09 20:12:10 +02:00
parent 61bbf26f3b
commit 5d6c2447f7
36 changed files with 71568 additions and 54823 deletions

15405
data/catalog/BANK.csv Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2,9 +2,10 @@
| file | content |
|------|---------|
| `<ARCHIVE>.csv` | every sound of one audio archive: `ITA`, `INT`, `FRA`, `DEU`, `ESN` (speech, one per language) and `SFX` (music, ambience, effects of the SFX WAD; sounds stored inside soundbanks are not listed, see `docs/formats/banks.md`) |
| `<ARCHIVE>.csv` | every sound of one audio archive: `ITA`, `INT`, `FRA`, `DEU`, `ESN` (speech WADs, one per language), `SFX` (music, ambience and effects streamed from the SFX WAD) and `BANK` (in-memory sounds stored inside soundbanks: footsteps, foley, combat, weapons, UI, efforts; `docs/formats/banks.md`) |
| `BANK_locations.csv.gz` | every stored copy of the `BANK` sounds, and the prefetch heads of speech lines (below) |
| `characters.csv` | `name,character`: verified speaker per sound name (language independent) |
| `index.json` | fingerprint of the game WAD each CSV was built from (`ackit/game.py: wad_fingerprint`) and counts |
| `index.json` | per archive: fingerprint of the game files the CSV was built from (`ackit/game.py: wad_fingerprint`, `ackit/banks.py: game_fingerprint`) and counts |
| `source/<lang>/*.txt` | **the curated original lists** (one file per character, one wemscan-style file name per line, e.g. `Speech_TAPE_JOKER_1_4.wem`). `Files.txt` = all files, `Stats.txt` = counts, `Checkpoint.txt` = progress marker. Never edited by tools. |
All CSVs are UTF-8 with a header row. They contain only names and metadata (no game audio).
@@ -12,26 +13,42 @@ All CSVs are UTF-8 with a header row. They contain only names and metadata (no g
## `<ARCHIVE>.csv` columns
| column | meaning |
|--------|---------|
| `archive` | `ITA`, `INT`, ... or `SFX` |
| `target` | location inside the archive: `HASH` (entry with one WEM), `HASH:i` (i-th variation, 0-based), `PACK/MEDIA` (music stream pack) |
| `name` | display name (`NAME`, `NAME_1..n` for variations, see `ackit/catalog.py`) |
| `aliases` | other accepted names, `\|`-separated (`NAME_1` for single entries, `NAME#i` for variations) |
| `archive` | `ITA`, `INT`, ..., `SFX` or `BANK` |
| `target` | location: `HASH` (WAD entry with one WEM), `HASH:i` (i-th variation, 0-based), `PACK/MEDIA` (music stream pack), `MEDIA` (BANK: Wwise media ID) |
| `name` | display name: `NAME`, `NAME_1..n` for variations (`NAME#i` when `NAME_i` is already another entry's own name); BANK: the Wwise event that plays it (`Play_..._i`) or `<Bank>_<n>` |
| `aliases` | other accepted names, `\|`-separated (`NAME_1` for single entries, `NAME#i` for variations, `<Bank>/<MEDIA>` for BANK) |
| `group` | Speech, Music, Ambience, SFX, Unknown (`docs/categories.md`) |
| `category` | finer category (`docs/categories.md`) |
| `bank` | BANK: the soundbank holding the sound (first by name if several do); empty for WAD sounds |
| `character` | verified speaker(s) from `characters.csv`, `; `-separated, empty if unknown |
| `characters_inferred` | characters/roles mentioned by the name (hint only) |
| `characters_inferred` | characters/roles mentioned by the name (and bank) (hint only) |
| `seconds`, `rate`, `channels` | of the original sound |
| `size` | size of the original WEM in bytes = maximum size of a replacement (except music packs: any size) |
| `sha1` | first 16 hex digits of the original WEM's SHA-1 (detects files changed outside the tool) |
| `sha1` | first 16 hex digits of the original WEM's SHA-1 (detects files changed outside the tool; empty when the copies of a BANK sound differ) |
| `notes` | free text (empty; for future curation, e.g. transcripts) |
The editor uses these files directly when the installed WAD matches `index.json`; for another game build it
scans the WAD itself and applies the same rules (no checksums then).
## `BANK_locations.csv.gz` columns (gzip-compressed CSV)
| column | meaning |
|--------|---------|
| `media` | Wwise media ID (hex) |
| `file` | file under `BmGame/CookedPCConsole`, `/`-separated (`SFX/xxxxxxxx.bnk` or `Name.upk`) |
| `offset` | position of the WEM in the *uncompressed* file (hex; `docs/formats/upk.md`) |
| `size` | bytes reserved for it there |
| `kind` | `m` = copy of a BANK sound, `p` = prefetch head of a speech line |
| `sound` | `p` rows: key of that speech line (e.g. `ITA:2B14E472:3`); each language has its own lines and heads |
A replacement is written into every `m` copy of a BANK sound; replacing a speech line also rewrites its `p`
heads (`docs/formats/banks.md`).
The editor uses these files directly when the installed game matches `index.json`; for another game build it
scans the game itself and applies the same rules (no checksums then; the bank scan takes a few minutes).
`ackit verify --catalog` cross-checks the catalog in use against the game files (`--quick` samples packages).
## Rebuilding / adding a language
1. Make sure the game files are original (`ackit status`; `ackit revert --all`).
2. Optional: add listening-based lists for another language in `source/<lang>/<Character>.txt` (same format;
names are the same in every language, so the Italian lists already label all languages).
3. Run `python tools/build_catalog.py` - it scans every archive of the installed game (all languages present)
and rewrites the CSVs, `characters.csv` and `index.json`.
3. Run `python tools/build_catalog.py` - it scans every archive and all soundbanks of the installed game (all
languages present; ~5 minutes) and rewrites the CSVs, the location index, `characters.csv` and `index.json`.
4. Run `ackit verify --catalog` (no issues expected).
New character labels need a display name in `ackit/classify.py: USER_LABELS` (otherwise the file name is used).

File diff suppressed because it is too large Load Diff

View File

@@ -1381,6 +1381,7 @@ Speech_GCPD_Joker_laugh_2,Joker
Speech_GCPD_Radio_intro_1,Penguin
Speech_GCPD_Radio_intro_2,Penguin
Speech_GCPD_Radio_intro_3,Penguin
Speech_INTERROGATION_Cat_01#3,Catwoman
Speech_INTERROGATION_Cat_01_2,Catwoman
Speech_INTERROGATION_Cat_01_3,Catwoman
Speech_INTERROGATION_CH5_MAYOR_01_4,Batman
@@ -1994,6 +1995,7 @@ Speech_RIDDLER_Enigma_Control_box_goto_church_3,Riddler
Speech_RIDDLER_Enigma_Control_box_too_soon_1,Riddler
Speech_RIDDLER_Enigma_Control_box_too_soon_2,Riddler
Speech_RIDDLER_Enigma_Control_box_too_soon_3,Riddler
Speech_RIDDLER_Enigma_Fail#1,Riddler
Speech_RIDDLER_Enigma_Fail_1,Riddler
Speech_RIDDLER_Enigma_Fail_10,Riddler
Speech_RIDDLER_Enigma_Fail_11,Riddler
1 name character
1381 Speech_GCPD_Radio_intro_1 Penguin
1382 Speech_GCPD_Radio_intro_2 Penguin
1383 Speech_GCPD_Radio_intro_3 Penguin
1384 Speech_INTERROGATION_Cat_01#3 Catwoman
1385 Speech_INTERROGATION_Cat_01_2 Catwoman
1386 Speech_INTERROGATION_Cat_01_3 Catwoman
1387 Speech_INTERROGATION_CH5_MAYOR_01_4 Batman
1995 Speech_RIDDLER_Enigma_Control_box_too_soon_1 Riddler
1996 Speech_RIDDLER_Enigma_Control_box_too_soon_2 Riddler
1997 Speech_RIDDLER_Enigma_Control_box_too_soon_3 Riddler
1998 Speech_RIDDLER_Enigma_Fail#1 Riddler
1999 Speech_RIDDLER_Enigma_Fail_1 Riddler
2000 Speech_RIDDLER_Enigma_Fail_10 Riddler
2001 Speech_RIDDLER_Enigma_Fail_11 Riddler

View File

@@ -61,5 +61,25 @@
},
"with_character": 0
},
"BANK": {
"fingerprint": "3f9766af425b8eef",
"sounds": 15404,
"groups": {
"Ambience": 1015,
"SFX": 6912,
"Speech": 7471,
"Music": 2,
"Unknown": 4
},
"copies": 93910,
"files": 1499,
"named_by_event": 6416,
"prefetch_heads": {
"lines": 396,
"copies": 2101,
"unmapped": 0
},
"issues": []
},
"_info": "unmodified game files"
}