Team Cereustooling wiki

Add DS3 sounds to the player skill bank

Partly checkedagainst the code on 2026-11-12 11:37

snd_bank.py adds Dark Souls III sounds to cs_c4340.bnk, the bank MoreWeapons uses for player skills. It can also trim levels, swap media, re-route mixers and add Stop events. Everything for one stage sits in a job file.

Checked against code: the command line (argparse in snd_bank.py), the resample values and the op kinds. The job file keys are from tools/snd-py/README.md and the 0.0.88 job files; I did not read every op's code. Nothing was run for this page.

EB means py -3.12 -I -B S:/eclipse-build/eb.py.

What you need

  • The pinned Python: S:/toolchains/python-ds2/Scripts/python.exe.
  • vgmstream and the DS3 sound files. EB tool build vgmstream ds3_fdp_main_sound prints the two folders. They hold vgmstream_cmd.exe (r1776) and DS3's fdp_main.fsb and fdp_main.fev.
  • The input bank: the release's cs_c4340.bnk, or the bank of the stage you chain on.
  • The FSB stream name or FEV event name of each DS3 sound, and the Nightreign event name you want (Play_c<id>).

Steps

  1. Copy a job from S:/eclipse-build/tools/snd-py/jobs-0088/ to a file beside your stage and edit it. Do not copy the old snd_*_088.py scripts.

  2. Run it as an eb job:

    EB run --mem 1 -- S:/toolchains/python-ds2/Scripts/python.exe -I -B S:/eclipse-build/tools/snd-py/snd_bank.py run <job.toml> --in-bank <chain bank> --out-bank <out.bnk> --fsb <fdp_main.fsb> [--fev <fdp_main.fev>] --vgmstream <vgmstream_cmd.exe> --work <dir> [--report <map>]
    

    --in-bank and --out-bank are required. --fsb, --vgmstream and --work are needed by jobs that decode samples (add-sounds, replace-media). --fev is needed when a sound names a fev event. --report writes the job's report text.

  3. Read the output. The tool reads the bank back and checks that only the objects it touched differ. It exits 1 if that fails.

  4. Point the TAE sound events at the new ids (see port-a-weapon-skill.md, soundMap).

  5. If your bank builds on another stage's bank, add base_stage = "<that stage's id>" to the file's [[file]] in stage.toml.

Job file

[job]                    # optional
resample = "none"        # none (default) | poly | legacy-interp ;  rate is required for the last two
[report]                 # optional; written to --report
header = "col1\tcol2"
footer = "read-back: {n_changed} objects changed, {n_added} added, {n_media} media written: {ok}"

[[op]]
kind = "add-sounds"
mixer = "my-stage_mixer" # a NEW actor-mixer, or use into_mixer for an existing one
parent = 61849273
template_mixer = "smallest"
row = "{name}\t{mid}\t{stem} ({nvar} variant(s), {nch} ch, {sr} Hz, {dur:.2f} s)"
[[op.sound]]
stream = "c000004332"    # FSB stream name, or fev = "s000090007" for a DS3 FEV event
name = "Play_c281400201"
media = "my-stage/c281400201.wem"

Ops run in the order they appear.

kind What it does Keys
add-sounds decodes DS3 samples and wraps each as Sound, Play action and Event mixer + parent for a new mixer, or into_mixer (+ optional require_parent) for an existing one; template_mixer, template_sound, template_play; per sound stream or fev, name, media, optional volume_db
replace-media decodes a sample again and swaps the media of an existing Sound per sound sound = "Play_x", stream
trim adds a Volume property in dB to an existing Sound; refuses a Sound that already has one sound = "Play_x", db = -4.0
reparent-mixers sets the parent of existing actor-mixers parent, mixers = [..]
add-stops makes Stop_<n> events that target Play_<n>_snd names = ["c281400101"]

Rules:

  • Exactly one of mixer and into_mixer per add-sounds op.
  • Mixer 61849273 is the player-skill mixer.
  • Event, Sound and Action ids are the FNV-1 hash of name, name_snd and name_act. The media id is the hash of media.
  • Templates are cloned from the bank as it was read, before any op ran. template_sound defaults to the bank's first PCM Sound, template_play to the first Play action, template_mixer to smallest.
  • Extra keys on a sound (the 0.0.88 jobs use nid and why) can be used in row.

Resample

  • none (default): the decoded sample goes in at its own rate. Nightreign's own media are 48 kHz.
  • poly: band-limited resample to rate (needs scipy).
  • legacy-interp: linear interpolation with no low-pass. It aliases. Use it only to reproduce an old stage's bank byte for byte.

Chains

A later job can add sounds into a mixer that an earlier job of the same chain created, with into_mixer. The result holds the same objects as one combined job, but in a different order, so the bank file's bytes differ.

Notes

  • Boss music has no free slots. Dated note (memory nr-boss-music-slots, 2026-11-07, Nightreign 1.3.3.0, from reverse engineering): the game looks boss music up in a fixed table of 114 names in the exe and silently drops any other name. Adding param rows or bank keys gives no new boss music slot. The only routes are trading an existing slot or a DLL remap, which was designed but not built when the note was written. This tool does not change that.
  • A sound that posts many times comes from the FXR or the effect row, not from the bank. See port-a-weapon-skill.md, "What goes wrong".
Source files this page documents (2)
  • eb:tools/snd-py/
  • eb:docs/AGENTS-GUIDE.md

Changed one of these? Update this page: ports/add-ds3-sounds.md (how).