Inventory of the audio layer for both games. All figures originate from tools/probe_audio.py, which runs against the original data in base/_wolfsdk_backup (the installation is patched). Nothing was written, no game was launched.
Interpretation. A Magic-Byte that was read appears here as a Finding. Anything inferred solely from names, sizes, or analogy appears as a Hypothesis and is marked accordingly.
0. Executive Summary
| What | Part 1 (TNO) | Part 2 (TNC) |
|---|---|---|
| Engine | id Tech 5 | id Tech 6 |
| Audio Middleware | engine-internal | Wwise |
| Audio Data | raw Ogg Vorbis in streamed.resources / english.streamed |
sound.pack / english(us).pack, Container Magic IDCL |
| Control Data | sound Decls in archive, plaintext |
in .bnk Banks, binary |
| Modifiable with this SDK | yes, the Decls (volume, range, random selection, mixbuses) | no |
| Audio bytes swappable | technically possible, but without Revert-Net — see §6 | no |
The short path to "louder and brasher" does not go through new audio files, but rather through three text files: sound:inheritences/master (overwrites 9364 of 9444 Sound Decls), soundmixing:default (13 Mixbuses with gain), and family nodes such as inheritences/weapons/weapons_pl.
Update 2026-10-04. The TNC column is outdated: a TNC sound replacement is built (sections 9–11); held back in WolfSDK 0.2.0, enabled since 0.3.0 (not yet tried in game).
1. Which Asset Types Exist
Of 105 Asset Types and 203,843 Assets, seven are audio-related:
| Type | Count | Path Endings | What It Is |
|---|---|---|---|
sample |
61,318 | .bsnd x61318 |
Descriptor, no audio data |
sound |
43,782 | .decl x37015, .bsnd x6514, .samplepack x253 |
Sound Shader (text) + Variant Descriptors |
voicetrack |
30,627 | .bmvtr x30627 |
Voice Track Descriptor, 4-language |
voiceover |
2,880 | .decl x2880 |
Selection table over Voicetracks (text) |
impactSounds |
56 | .decl x56 |
Hit/Shell impact mapping (text) |
soundmixing |
26 | .decl x26 |
Mixbuses, Gains, Compressor/Limiter (text) |
footstepEvents |
1 | .decl x1 |
Step Events (text) |
The task-named type names soundshader, snd, music, voice, reverb, and soundmaterial do not exist in TNO. What they mean content-wise is located elsewhere:
- soundshader → this is exactly the type
sound; the fields are internally namedsoundShaderFlags. - music → not a type, but a namespace: 225
soundDecls undermusic/…, e.g.,music/menu/main_menu,music/c01p1/mus_c01p1_crashlanding,music/journal/house_of_the_rising_sun. - voice →
voiceover+voicetrack. - reverb → not a type. Reverb is a) a namespace in Sound Decls (
weapons/handgun/player/reverb/dw_large_room,…/dw_outdoor,…_rear) and b) the fieldswetFalloff,wetVolume,wetMaxDistanceOffset. The Asset Typeenv(627 items) is Image Environment (Cubemaps, Color Grading), not Reverb — verified againstenv:default. - soundmaterial → does not exist; material references run via
impactSoundsDecls (metalSound,stoneSound,fleshSound,woodSound,cardboardSound, …).
2. The Actual Data Format
Magic Bytes, all read (Finding):
| Type / Ending | First 4 Bytes | Count |
|---|---|---|
sample/.bsnd |
b'bsnf' |
61,318 (100 %) |
sound/.bsnd |
b'bsnf' |
6,514 (100 %) |
sound/.samplepack |
b'1KPS' |
253 (100 %) |
sound/.decl |
b'{\r\n\t' (text) |
37,009 of 37,015 |
voicetrack/.bmvtr |
b'"VTR' |
30,627 (100 %) |
voiceover/.decl, soundmixing/.decl, impactSounds/.decl, footstepEvents/.decl |
text | all |
streamed.resources (1.08 GB) |
b'OggS' |
File start |
english.streamed (0.39 GB) |
b'OggS' |
File start |
No RIFF/WAVE, no XMA, no MSADPCM, no Bink Audio (BCF/KB2) in the audio paths. The .bik files under base/bink/ are videos with their own audio track and do not belong to the Sound Engine.
The filenames in the Decls end with .wav — this is the source name from production, not the delivered format. The game uses Ogg Vorbis.
bsnf — the Sample Descriptor
There are two variants, both exactly 74 or 272 bytes in size (no other sizes occur: 33.610 × 74 B, 27.708 × 272 B).
Monolingual, 74 Bytes:
u8[4] "bsnf"
BE u32 Number of language entries (= 1)
u8[16] Null bytes
BE u32 @24 Length of the Ogg stream in bytes
BE u32 @28 32 (meaning unconfirmed)
BE u32 @32 Hash/ID
BE u32 @36 0
BE u32 @40 Granule = Number of PCM samples
BE u32 @44 0
BE u32 @48 Length, repetition of @24
--- starting at @52 a WAVEFORMATEX in Little Endian ---
LE u16 wFormatTag 0x674F = Ogg Vorbis Mode 1
LE u16 nChannels 1 or 2
LE u32 nSamplesPerSec 48000
LE u32 nAvgBytesPerSec 192000 (stereo) / 96000 (mono)
LE u16 nBlockAlign 4 / 2
LE u16 wBitsPerSample 16
LE u32 Granule, repetition of @40
Multilingual, 272 Bytes: "bsnf", BE u32 = 4, followed by four 24-byte headers (char[16] language name, BE u32 length, BE u32 offset of the associated 42-byte sub-block within this descriptor), then the four 42-byte blocks starting at offset 104. Observed languages: english, french, italian, spanish.
Example sample:sound/projectile/bullet_impacts/concrete/imp_concrete_01.wav (path generated/sound/…/imp_concrete_01_vorbis.bsnd): Length 17.619 B, Granule 38.822 Samples → 0.81 s, Stereo, 48 kHz.
`"VTR" — the Voicetrack Descriptor
voicetrack:voicetrack/english/ai/efforts/eff_soldier_meleehit_01.vtr is 1.344 bytes in size and contains: Magic 22 56 54 52, BE u32 = 4, four 24-byte language headers (english/french/italian/spanish, each 0x136 = 310 bytes, offsets 0, 414, 724, 1034), then four 310-byte blocks with Magic 22 52 54 56 (`"RTV"). 104 + 4 × 310 = 1.344 — the math adds up exactly. Also no audio data here, only description. Hypothesis: the 310-byte block contains lip-sync/viseme data, because it is too large for simple pointers and the blocks are equal in length per language.
3. Where the actual audio bytes lie — the critical finding
They do not reside in the chunkN.resources. The archives contain only the 74/272-byte descriptors. The Ogg streams are located in two containers that are not listed in master.index:
base/streamed.resources 1.157.177.472 B begins with "OggS"
base/english.streamed 415.137.488 B begins with "OggS"
They are addressed via the variable remainder of the index entry — that section which docs/formats.md describes as "longer for audio types, not fully understood". 20 bytes behind the offset/usize/csize triplet stands a BE u32: the byte offset into the container.
Verification across all 61,318 sample entries: for each one, the Ogg page chain was traversed from the indicated offset to the EOS page, and the measured length was compared against the length from the bsnf.
streamed.resources 33,455 entries, length matches exactly
english.streamed 27,863 entries, length matches exactly
0 deviations
The container assignment is by name: everything under sound/vo/english/… lies in english.streamed, everything else in streamed.resources.
Slot Grid
streamed.resources 14,454 occupied slots, 14,454 of them on the 16384-byte grid (100 %)
free space per slot: min 0, median 8,607, max 3,144,537 B
english.streamed 5,091 occupied slots, 5,091 of them on the 16384-byte grid (100 %)
free space per slot: min 0, median 8,041, max 16,380 B
No single overlap. Each sound receives ceil(Länge / 16384) * 16384 bytes. There are fewer slots than entries because the same samples are indexed in multiple chunks.
Answer to the Core Question
The question was: normal archive entries or named resource blocks with pre-calculated size (such as the particles, which failed with idFile_RingBuffer file '<name>.bin' skipping <n> bytes)?
Neither nor — a third case, and it is cheaper than both.
The structural difference from particles is measurable: particle has two entries per asset, 2.672 .decl and 2.672 .bin under the same name. The .bin (Magic 06 54 52 50) is the compiled particle — that is the named resource block at which all particle mods failed. sound has no .bin counterpart. Its .decl entries carry the same short entry suffix (9 zeros + sequential BE-u32-ID) as entityDef, weapon, and material — exactly the types this SDK already successfully patches.
For audio bytes: they are not an archive entry at all, but a piece of file data at a fixed address with a length field located in the archive. The length is therefore changeable, as long as the slot accommodates it.
4. The sound Decls: the simple Modding Path
9,445 unique sound-Decl names, plaintext, fully readable by the parser in wolfsdk/decl.py. Namespaces: vo 5157, anim_events 1228, ambience 676, weapons 501, enemies 468, movements 272, music 225, footsteps 223, explosions 44, impacts 24.
The Fields Asked For
| Field | Decls setting it | Effect |
|---|---|---|
edit.parms.volume.min / .max |
1695 / 1668 | Random volume per playback, in dB. If both are equal, it is fixed. |
edit.parms.volume.offset |
631 | Fixed dB addition, inherited and added |
edit.parms.maxDistance |
1180 | Range: silent beyond this point |
edit.parms.minDistance |
865 | Full volume up to this point |
edit.soundFiles.num + item[i] |
9331 / 21323 references | Random selection: one drawn from num files |
edit.parms.pitch.min / .max |
259 / 208 | Random pitch |
edit.parms.soundShaderFlags |
1716 | SSF_LOOPING, SSF_GLOBAL, SSF_DISTANCE_LOW_PASS, SSF_PASS_HDR, SSF_NO_OCCLUSION, SSF_DISTANCE_BASED_STEREO, … |
edit.parms.groups |
383 | Mix group, e.g. SSG_WEAPONS_PL, SSG_IMPACTS, SSG_MUSIC_INGAME |
edit.parms.priority |
261 | SPRIORITY_ULTRA … when voice is scarce |
edit.parms.maxPlay.maxShaders |
108 | How many instances simultaneously |
edit.parms.falloff / wetFalloff |
341 / 264 | Curve for dry/wet |
edit.parms.lowPassStrength / lowPassMinDistance |
181 / 54 | Muffling with distance |
edit.parms.controllerShake.intensity |
97 | Rumble on pad |
edit.parms.cameraShake.intensity |
43 | Camera shake |
edit.rmsTable |
557 | Reference to a pre-calculated loudness curve (HDR-Audio) |
Random selection specifics: 1,717 Decls draw from more than one file (Distribution: 1 file 7614x, 3 files 316x, 5 x252, 6 x175, 4 x166, 8 x158). Examples:
sound:projectile/bullet_impacts/imp_flesh num = 15 (Body hits)
sound:weapons/handgun/player/handgun_46_fire num = 9
sound:projectile/bullet_impacts/imp_metal num = 14
A complete example, verbatim from the archive:
{
inherit = "inheritences/weapons/weapons_pl";
edit = {
parms = {
minDistance = 50;
falloff = "sound/falloffs/slow";
wetFalloff = "sound/falloffs/slow";
frontDirectionalAngle = 25;
}
soundFiles = {
num = 9;
item[0] = "sound/Weapons/handgun/handgun_fire_01.wav";
…
item[8] = "sound/Weapons/handgun/handgun_fire_09.wav";
}
rmsTable = "sound/hdr_curves/weapons/handgun/handgun_fire_05";
}
}
This means: custom weapon sounds without new audio data are possible by redirecting item[i] to an existing sample — such as placing the pistol on weapons/m60/… or increasing/decreasing num to alter the spread. The sample name must point to an existing sample asset.
Inheritance — here lies the lever
99.1% of all Sound Decls (9,364 out of 9,445) inherit transitively from one file:
sound:inheritences/master
{
edit = {
parms = {
volume = {
offset = 10;
}
lfeVolume = -60;
}
}
}
A single number, 97 bytes, and everything gets louder. Below that are 105 family nodes targeting groups specifically:
| Node | Descendants | Set |
|---|---|---|
inheritences/master |
9364 | volume.offset = 10 |
inheritences/vo/vo_battle |
1878 | Combat Voice Output |
inheritences/sfx_general/sfx_general_average |
601 | General Effects |
inheritences/sfx_general/sfx_general_loud |
335 | " |
inheritences/movement_pl |
254 | Player Movement |
inheritences/music |
221 | volume.min/max = -11, offset = -6, groups = "SSG_MUSIC_INGAME" |
inheritences/weapons/weapons_pl |
161 | volume.offset = 30, groups = "SSG_WEAPONS_PL" |
inheritences/weapons/weapons_pl_rear |
75 | Rear Channel Player Weapons |
inheritences/weapons/reloads_pl |
68 | Reloading |
inheritences/impacts |
45 | maxDistance = 2000, volume.min = -6, maxPlay.maxShaders = 2 |
inheritences/explosions/explosions_loud |
43 | |
inheritences/impacts_loud |
2 |
For "brutal impacts," these are concrete: inheritences/impacts (raise volume.min, increase maxShaders from 2, so multiple impacts remain audible simultaneously) and sound:projectile/bullet_impacts/imp_flesh.
soundmixing — the mixing console level
26 Decls, soundmixing:default is the base (4,163 bytes), others inherit and override per chapter (c01p1, c01p2, …). Master bus with Limiter (threshold = -0.2) and 13 sub-buses with gain in dB, each with Compressor and Sidechain on SSB_BUS8:
subBus[ 0] World Sfx Master gain = -9
subBus[ 1] Player Weapon gain = -11
subBus[ 2] Music: Scripted gain = -6
subBus[ 3] Music: System gain = -6
subBus[ 4] Ambience gain = -4
subBus[ 5] Explosions gain = -5
subBus[ 6] Special Enemy Voice gain = -5
subBus[ 7] Special Enemy Movement gain = -7
subBus[ 8] VO: player, radio gain = -8
subBus[ 9] VO: Event gain = -4
subBus[10] VO: In game/scripted, battle gain = 2
subBus[11] Mix Group 1 gain = -6
subBus[12] Mix Group 2 gain = -6
subBus[1] Player Weapon sits at −11 dB. This is the most direct knob for "weapons louder," and it is a single number in a text file.
5. Cvars
TNO, read from WolfNewOrder_x64.exe (Finding: the strings are inside the EXE; that they are all registered as Cvars is Speculation, supported by the fact that other names from the same list function in-game verifiably):
s_volume_dB s_voiceVolume_dB s_muteMusic s_noSound
s_reverb s_showReverb s_useOcclusion s_occlusionDistance
s_lowPassFilter s_useDistanceLowPass s_maxSoundDistanceClamp
s_hdrFalloff s_skipHDR s_showHDR s_showDucks
s_showSounds s_drawSounds s_showSoundsFilter s_soundGroupFilter
s_maxEmitterChannels s_debugMaxPlay s_finiteSpeedOfSound s_tinnitusStart
s_volume_dB and s_voiceVolume_dB are accessible via the existing Start Argument path (+s_volume_dB 6), completely without an archive patch. Not verified in-game.
TNC, from the old scraped candidate list (since replaced by the registry catalogue, TNC-CVar-Catalog). Checked against the engine registry: s_printLoadedBanks, s_printMapBankReport and s_loadEditorBanks are not Cvars; the other nine are registered, and s_volume, s_volume_music, s_volume_vo and s_overridevolume are exposed to the retail console:
s_volume s_volume_music s_volume_vo s_overridevolume s_muteSound
s_muteEnvironments s_reverbBus s_skipOcclusion s_printLoadedBanks
s_printMapBankReport s_initForcePreLoadSoundBanks s_loadEditorBanks
(The numerous s_bossshoot*, s_dogchase*, etc., belong to the Wolfenstein-3D engine within the game, not the mixer layer.)
6. What is changeable and what is not
Changeable with existing machinery
sound-, soundmixing-, impactSounds-, voiceover-, and footstepEvents-Decls are ordinary Decl Archive entries without a corresponding .bin counterpart. The existing patch path (wolfsdk/patch.py, deflate_exact, Backup + Journal) applies unchanged, including Revert.
This makes achievable:
- Volume globally (
inheritences/master) or per family - Mixbus Gains (
soundmixing:default) - Range, reverb, lowpass filter, priority, voice count
- Random selection: more/less variants, redirect to other existing samples — this is the practical way to achieve "other weapon sounds"
- Music assignment:
music/*-Decls can point to other existing music tracks
Hypothesis, not verified in-game: that modified Sound Decls actually take effect. Structurally, everything points this way (same entry residue as the patchable entityDef/weapon), but it has not been verified.
Pitfall: 557 Decls carry an rmsTable for a pre-calculated loudness curve. If volume is increased without adjusting the curve, the HDR audio layer may compensate. Hypothesis. To bypass this, change the gain in soundmixing, which sits behind the HDR stage.
Changeable but without backup — replacing real audio data
Technically, this is the simplest case of the entire project: write an Ogg Vorbis stream to a known offset and adjust two BE-u32 fields (length @24 and @48) plus the granule in the 74-byte bsnf. The descriptor is a normal Archive entry, so it fits into the existing patch path. The slot offers median 8.6 KB of headroom, but for some sounds 0 bytes — a longer stream would overwrite the next sound there.
What argues against this, and significantly:
streamed.resourcesandenglish.streamedare not inmaster.index.Installation.ensure_backup()backs up exclusively the 14chunkN.indexfiles and records the lengths ofchunkN.resources. The two streaming containers total 1.5 GB and are never backed up. A failure would only be fixable via Steam's file verification.- There is no Vorbis encoder in the standard library. New audio must be generated externally — the SDK is fixed to "standard library only".
Recommendation: do not touch this unless the containers are included in the backup. If so, first run ensure_backup to expand the two files and write exclusively shorter streams to keep offset and slot untouched.
Not changeable
- TNC Audio. The
IDCLcontainer format has been read (wolfsdk/idcl.py, verified against all 24 Retail.resources), but the unpacker is not connected and there is no write path. The audio data additionally resides in Wwise Banks for which no parser exists — reading the container does nothing about this. (Superseded 2026-10-04: banks are parsed and a replacement path is built, enabled in the Studio since 0.3.0; sections 9–11.) voicetrackblocks: 310 bytes per language, content undeciphered..samplepack(Magic1KPS, 253 items): variant bundles with their own streaming offsets in the entry residue. Not further investigated.
7. Part 2 — Wolfenstein II: The New Colossus
Just a status report. The IDCL container format has been read since wolfsdk/idcl.py (Head, Regions, String table, verified against all 24 Retail .resources); for the .pack files here it is still without consequence because the content is Wwise Banks and the unpacker is not connected.
What lies in the filesystem
base/sound/soundbanks/pc/ sound.pack 1,722,766,110 B IDCL english(us).pack 758,900,091 B IDCL patch_1_sound.pack 110,345,075 B IDCL patch_3_sound.pack 193,042,687 B IDCL patch_2_sound.pack 47,419,238 B IDCL patch_1_english(us).pack 18,712,107 B IDCL patch_3_english(us).pack 16,697,329 B IDCL patch_2_english(us).pack 12,209,825 B IDCL patch_4_sound.pack 132 B IDCL (empty) patch_4_english(us).pack 132 B IDCL (empty) wwise_project.bin 4,493,695 B "WPCv05r" prodspec.json 163,237 B Klartext-JSON
For each DLC (dlc/dlc_1|2|3/base/sound/soundbanks/pc/), the same set applies, including all languages: french(france), italian, russian, portuguese(brazil), spanish(mexico), spanish(spain). In total, 46 files: 34 .pack files, 4 .json files, 4 .bin files, totaling 3.15 GB.
The only extensions found throughout the game directory are: bk2 (122, Bink videos), pages (42, virtual textures), cache (39), pack (34), texdb (27), resources (27), cfg (12), json (11), bin (6).
There are no .streamed files and no .bsnd assets. The audio layer has been fully migrated to Wwise. This is a finding from the filesystem, not an inference: wwise_project.bin carries the magic number WPCv05r and lists in plain text 1,394 .bnk and 78,558 .wem names — .wem is the Wwise Encoded Media Format.
The Plain-Text Configuration
prodspec.json is unencrypted and lists every single soundbank:
{ "banksize": 1699459, "name": "sb_mus_combat_suites.bnk", "streamsize": 102838598 }
- 937 Banks,
patchlevel: 4 - Sum of
banksize: 1.02 GB, Sum ofstreamsize: 8.45 GB - Bank families:
sb_amb(55 Ambience), 30sb_vo_*per language (English(US), French(France), Italian, Spanish(Spain), Russian, Spanish(Mexico), Portuguese(Brazil)),sb_pr24,sb_events23,sb_mus20,sb_ch18,sb_preset16,sb_pl13,sb_ai7,sb_fx5 - Largest streams:
sb_mus_combat_suites.bnk(102.8 MB stream),<Language>/sb_vo_ai.bnk(~70.9 MB each) - The
mapskey maps bank lists to game cards — hence also the Cvarss_printMapBankReportands_initForcePreLoadSoundBanks.
wwise_project.bin also lists languages that are not installed (German/sb_vo_c2.bnk, Japanese/sb_vo_c2.bnk) — it appears to be the complete project directory, not the release list. Hypothesis.
What This Means Practically
In TNC, for now, only the Cvar path works: s_volume, s_volume_music, s_volume_vo, s_overridevolume. The IDCL container is read, but mods=False — there is no write path for Part 2 — and the mixing itself resides in the Wwise banks for which no parser exists. (Superseded 2026-10-04: the packs are plain IDCL archives that wolfsdk/wwise.py reads, banks included; a sound replacement is built and enabled in the Studio since 0.3.0, sections 9–11.)
8. Reproduction
python tools/probe_audio.py
Runs for approximately 70 seconds, reads 203,843 index entries, and checks all 61,318 sample descriptors against the Ogg sidechains in the streaming containers. Writes nothing.
9. TNC Sound Replacement: How a WAV Becomes a Game Sound
Built in WolfSDK Studio; held back in 0.2.0, enabled since 0.3.0, not yet tried in game (section 11).
- Input: a 16-bit PCM WAV with the game sound's channel count and at most its length (0.01 s slack for export rounding), any sample rate. It stays PCM, the game's other codec: there is no Vorbis encoder here.
- Output: a PCM WEM laid out like the game's own PCM sounds (fmt tag
0xFFFE, data at offset 64), saved as assetwem:<sound id>. - Writing: the loader rewrites every sound pack holding the sound, in every patch level. A loose
.wemis replaced whole; in a bank the new slice goes to the end of DATA (16-aligned), its DIDX row is repointed, and the old slice stays unreferenced. - Every Sound object (HIRC type 2) of that medium is switched to the PCM plugin
0x00010001, with the size field of its stream type. Measured: the plugin field names the codec:0x00040001in all 129,705 Vorbis sources,0x00010001in all 409 PCM ones.
Keywords: replace sound, WAV, WEM, Wwise, sound mod, Sound ersetzen, Geräusch austauschen
10. TNC Sounds That Cannot Be Replaced Yet
The Studio refuses these with a reason (wolfsdk/wwise.py):
| Kind | Why |
|---|---|
| Prefetched sounds (stream type 1, 2,429 ids) | The start sits in a bank, the rest is streamed. How Wwise joins a replaced pair is not measured. |
| Media of music tracks (940) | A music track (HIRC type 11) records codec and length itself. |
| An id stored once per language (70 in dlc_2) | Replacing it in one language only is not supported. |
| Banks of another version than 125 | Only version 125 is parsed. |
| The New Order's sounds | Ogg streams in the .streamed files, outside the archives the loader writes; no Vorbis encoder. |
Keywords: music, prefetched, streamed sound, cannot replace, not supported, Musik ersetzen, geht nicht
11. Why Sound and Video Replacement Was Held Back in WolfSDK 0.2.0
Enabled since 0.3.0. In release 0.2.0 the Studio refused sound and video replacements: Revert did not restore the replaced sound packs and video files (the check tools/verify_studio_media.py, "after revert every file of the tree is md5-identical", failed). Since 0.3.0 Revert restores them and the Studio replaces sounds and videos for The New Colossus. Not yet tried in game.
The video replacement is built the same way and was held back with it: a Bink 2 file made with RAD's tools, with the same size and frame rate as the game's video and at most its frame count. The Studio checks it and opens it with the game's own bink2w64.dll; it does not convert. The loose file is replaced whole (asset video:<path>).
Neither path is confirmed in game.
Keywords: held back in 0.2.0, sound replace, video replace, Bink, cutscene video, revert, zurückgehalten, Video ersetzen