A sound bank is a named sound. Content never references an audio file directly — it
references a bank id, and the bank decides what actually plays.
Banks live in World/sound-banks.xml and are edited in Hydra's
Sound Bank editor. They are id‑keyed and merged across active modules
like every other resource, so a module can add banks or replace existing ones. See
Modules.
The simplest bank
<sound-bank id="ShieldsUp" category="system" instances="2">
<description>Shields raised</description>
<alias>sounds/shields-up.mp3</alias>
<layer source="sounds/shields-up.mp3" volume="1" />
</sound-bank>
That is what a component means when it says
activated="ShieldsUp".
Referencing a bank
Banks are referenced by id from component sound slots, model audio cues, effect banks and
mission actions. category groups them for the editor and for mixing;
instances caps how many copies can sound at once.
instances is a real design decision, not a technical limit.
An ambient hum wants 1 — a second copy is just louder. An explosion wants around 10,
because in a real fight several land together and a cap of 1 makes a battle sound thin. Laser
fire sits in between. Getting these wrong is the most common reason a mix sounds wrong when
every individual sound is fine.
Aliases, and why they exist
A bank can declare aliases, and an alias can be a bare file path:
<sound-bank id="LaserFire" category="weapon" instances="6">
<alias>sounds/laser-fire.mp3</alias>
<alias>laser-fire</alias>
<layer source="sounds/laser-fire.mp3" volume="1" variance="300" />
</sound-bank>
This is the compatibility mechanism. Older content that named a raw file path still
resolves — it lands on the bank instead, and inherits everything the bank has since gained.
So you can improve a sound for all existing content by improving its bank, without touching
any of the content that plays it.
When you replace a base game bank in your own module, carry its aliases across or the
older references stop resolving.
Layers
A bank can stack several samples, each with its own settings. This is how you build a
sound that is more than one recording — a weapon with a transient and a body, an engine
with a rumble and a whine.
| Attribute | Effect |
source | The audio file. |
volume | Layer gain. |
detune | Fixed pitch offset in cents against the recording. |
variance | Random pitch spread in cents, applied per play. |
loop | Whether it repeats. |
loop-start, loop-end | Loop points in seconds. Both 0 means the whole file. |
filter | Low‑pass cutoff in Hz. 0 means open. |
attack, release | Gain ramp in and out, in seconds. |
variance is the cheapest quality win available. A repeated
sample played identically reads as a machine gun of one recording; a few hundred cents of
random pitch spread makes ten explosions sound like ten explosions. The base game's weapon
banks use 300.
attack and release matter for loops. A hum that starts and stops
abruptly clicks; a short ramp removes it.
Variants: one bank, several recordings
A bank can instead name other banks as variants, and playback picks one at random:
<sound-bank id="HullImpact" category="weapon" instances="8">
<variant id="HullImpactA" />
<variant id="HullImpactB" />
<variant id="HullImpactC" />
</sound-bank>
Content references HullImpact and gets one of the three. This is the better
answer than pitch variance when you have genuinely different recordings, and the two combine.
Modulation: sound driven by game state
The most powerful feature, and the least used. A bank can bind a playback property to a
live game parameter:
<sound-bank id="Engine" category="engine" instances="1">
<layer source="sounds/engine.mp3" volume="1" loop="true" />
<modulate parameter="throttle" target="pitch" min="-200" max="400" />
<modulate parameter="throttle" target="volume" min="0.75" max="1" from="0" to="0.4" />
</sound-bank>
| Attribute | Meaning |
parameter | The game value driving it — throttle, speed, heat, and so on. |
target | volume, pitch or filter. |
min, max | Output range. Gain scale for volume, cents for pitch, Hz for filter. |
from, to | The input span that maps onto min..max, clamped outside it. Defaults to the whole parameter. |
curve | linear or squared. |
layer | Which layer to drive, one‑based. Omitted means the whole bank. |
from and to are what let you express a knee without an expression
language. "Full gain by 40% throttle" is from="0" to="0.4".
Bindings that share a target combine, and not all the same way:
- pitch sums — cents are additive, so two offsets stack into one interval.
- volume multiplies — gains compose, each scaling what the others left.
- filter takes the minimum — the darkest constraint wins, because cutoffs
do not add.
The trap follows from the volume rule. A volume binding that reaches 0
multiplies the layer to silence regardless of every other binding. A contributor meant only to
lean on the gain wants a non‑zero minimum — min="0.75", not
min="0".
Module-level settings
The wrapper element carries calibration that belongs to the asset set rather than the
engine:
<sound-banks master-volume="1" clip-radius="550">
master-volume trims every layer in the module — the control for a set of
masters that were recorded hotter or quieter than the base game's.
clip-radius is the positional audio horizon in world units, beyond which a
sound is not heard. A module working at a different scale needs a different horizon.
Practical advice
- Set
instances from how often the sound really overlaps.
It is the difference between a battle and a stutter.
- Add
variance to anything that repeats. Weapons, impacts,
footsteps.
- Give loops an attack and release. Otherwise they click.
- Keep aliases when you override a base bank, or older content stops
finding it.
- Fill in
description. It round‑trips through the editor,
and it is what makes a bank list navigable a year later.