AshForge Echo · the whole tool, one course
A bubble, a curve,
and a default that must not travel.
Echo authors sound: how far a noise carries, how it fades, and how several clips become one bank the game can vary. Its settings live in two places that disagree, and knowing which one wins is most of the tool.
What it is
Attenuation and banks. A sound has a radius and a falloff curve; a bank groups clips under one name so the game can pick between them.
Modules 1–4 are distance, 5–8 are banks, 9–12 are what ships.
Which wins
The bank's settings win over the individual clip's. And one default is correct locally and wrong the moment it ships.
Modules 6 and 10 — the two that decide whether your audio behaves in game.
Echo is a focused tool. Its content is 12 things worth knowing, not three escalating tiers — the old split implied the later material needed the earlier, and it does not. Read straight through, or jump to the module that matches your problem.
Min distance
The bubble and the curve
Attenuation has two regions, and the boundary between them is Min Distance.
Anywhere at or inside Min Distance the gain is exactly 1.0 — full volume, no fade. Verified at 0 metres, at 4.9 on a min of 5, and at 5 exactly. Only past that boundary does any curve begin.
So Min Distance is not a fade-in point or a minimum audible range. It is the radius of a bubble of full volume around the source, and it is also the number every model measures its falloff from.
The models
Which model reads what
There are five attenuation models, and they do not take the same inputs. This is the table to remember.
| Model | Min Distance | Max Distance | Rolloff |
|---|---|---|---|
| Inverse default | Yes | Ignored | Yes |
| Inverse Square | Yes | Ignored | Yes |
| Linear | Yes | Yes | Yes |
| Logarithmic | Yes | Yes | Yes |
| Disabled | Ignored | Ignored | Ignored |
The two Inverse models are ratios built from Min Distance and Rolloff. Max Distance is simply
not in the expression, so moving it changes nothing — measured, the gain at 50 metres was
0.0200 with a Max of 20 and 0.0200 with a Max of 5000.
Linear and Logarithmic work the other way round: they map the distance onto the range between Min and Max, so Max Distance is what shapes them. Change it and the gain at a fixed distance moves immediately.
The real difference
Does it ever reach silence?
Choosing between the models is usually framed as a question about curve shape. It is more useful to ask a blunter one: does this sound ever become inaudible?
| Model | At Max Distance | Far beyond it |
|---|---|---|
| Linear | exactly 0 | still 0 |
| Inverse | a small number | 0.00001 at 100 km — never 0 |
Inverse is a ratio, so it asymptotes: it gets arbitrarily quiet and never actually arrives at zero. In practice that is inaudible, but it is not silence, and a sound that is technically still playing across the whole map is a sound the engine is still mixing.
Linear reaches exactly zero at Max Distance and stays there — verified at 100 metres on a max of 100, and at 100 kilometres. If you need a guarantee that something cannot be heard past a boundary, that guarantee only exists on Linear.
The last two controls
Rolloff, and loose names
Rolloff steepens whichever curve you are on: a higher value is quieter at the same distance, verified across 0.5, 1 and 3. It is clamped to between 0.05 and 5, so asking for 0 gives you 0.05 and asking for 99 gives you 5.
The model name itself is matched loosely — case-insensitively, and by looking for a substring. That has one consequence worth knowing: a model name the tool does not recognise silently becomes Inverse. Verified, a clip set to "Bouncy Castle" produced exactly the Inverse curve. And "none" is treated as Disabled, alongside "Disabled" itself.
So a typo in a model name is not an error. It is a quiet change of curve, and it will look like whatever Inverse looks like.
| Symptom | What it means | Fix |
|---|---|---|
| Max Distance changes nothing | The clip is on Inverse or Inverse Square, which ignore it. | Switch to Linear if you need the range to matter. |
| A sound is audible across the whole map | Inverse never reaches zero — or the model is Disabled. | Use Linear for a hard cutoff. |
| A "disabled" clip is deafening | Disabled turns off attenuation, not the sound. | Pick a real model. |
| Rolloff past 5 does nothing more | It is clamped at 5. | Lower Min Distance instead to steepen further. |
| Louder up close AND slower to fade | Min Distance was raised; it does both jobs. | Expected — adjust rolloff to compensate. |
The mapping
What a bank becomes
Put three footstep variants in a bank and export. You do not get three sounds. You get one, named after the bank, carrying all three clips.
| In Echo | In the exported bundle |
|---|---|
A bank footstep_gravel with 3 variants | 1 sound named footstep_gravel, 3 clips |
| The 3 variant clips themselves | Not exported separately |
| A clip in no bank | 1 sound of its own, 1 clip |
This is not a compression Echo invented. It is the shape the game already uses: a sound holds a list of clips and picks between them when something triggers it. A bank is that idea, authored.
So the mental model to carry is not "a bank groups my sounds" but "a bank is my sound, and the variants are the ways it can come out". Once a clip is in a bank it stops being a thing the game can trigger on its own — verified, the variants did not appear as sounds of their own in the bundle.
Flattening
The bank's settings win
A sound in the game carries one set of values for all of its clips. A bank therefore has one pitch range, one volume, one set of spatial numbers — and a variant's own tuning has nowhere to go.
Tune one variant to a pitch of 1.3 and a volume of 0.4, put it in a bank, and export: the bank's values are what ship. Echo does not do this quietly — the export names the variant and lists exactly which of its settings were replaced, verified.
The variance controls are where a bank's own expressiveness lives, and they map cleanly: ±0.05 pitch variance becomes the range 0.95 to 1.05. That is the same statement written two ways, which is why this one survives intact.
Figure 01 — three clips, one set of values Tune the bank, not the variants — the variants are there to differ in content.
Collisions
Names are the join
Everything downstream is addressed by name, and a name can only mean one thing. Echo enforces that at export rather than letting two definitions collide later.
| Situation | Result |
|---|---|
| A bank and a clip share a name | The bank wins; the clip is skipped entirely. |
| A clip has no file reference | Skipped, and named in the notes. |
| A bank has no playable variants | Skipped, and named in the notes. |
All three are reported, and all three mean a sound you authored does not reach the game. The name collision is the one to watch, because it is the only one that happens while everything looks healthy — both objects exist, both are visible in the tool, and one of them silently does not ship.
Banks are referenced internally by id rather than by name, so renaming a clip does not break the bank it belongs to. Names matter at the boundary, not inside the project.
footstep_gravel — and
give variants names that are obviously internal, like step_a. It costs nothing and
makes the collision impossible.The Echo-only half
Buses, events, and honesty
Mixer buses with reverb, and named gameplay events, are both real features of Echo. Neither reaches the game.
Verified: a project with a bus called Ambience, a clip routed to it, and an event
named amb_start exported one sound — and the notes named the bus, the event,
the clip's routing and its loop flag as things that could not be carried. The game's sound
definition has no bus, no reverb, no routing and no event list.
That is worth stating plainly rather than treating as a defect. Echo tells you what it could not carry, once for each thing, by name. Most tools in a position to lose something quietly do lose it quietly; this one is built to say so, and reading those notes after an export is the fastest way to learn where the ceiling is.
| Symptom | What it means | Fix |
|---|---|---|
| A clip vanished from the export | It shares a name with a bank. | Rename one of them; the bank always wins. |
| A variant's careful tuning did nothing | The bank's settings replace it. | Move the setting onto the bank. |
| Reverb is missing in game | Buses are not exported at all. | Nothing to fix — audition only. |
| An event name does nothing | Events are not exported either. | The game triggers a sound by its NAME. |
| A bank exported nothing | None of its variants had a file reference. | Check the notes; they name the variant. |
Destination
Two files, one read
Export a bundle and export a runtime file from the same project. Both succeed. Both write real JSON. Then ask the definitions lane what it can see.
| File | Lands in | Found by discovery? |
|---|---|---|
echo.bundle.json | <mod>/export/ | Yes |
| The Godot/runtime export | the tool's own output folder | No |
The lane searches inside a mod root and nowhere else. A file written outside one is invisible to it however correct its contents are — and because the export reported success and produced a real file, there is nothing to notice.
This is why the bundle export refuses to run without a mod folder open, rather than falling back to somewhere convenient. A bundle that cannot be inside a mod has no reason to exist, so it fails early and says why.
export/echo.bundle.json inside your mod folder.
That single file being present is the whole test. If your audio is not reaching the game and
that file is missing or elsewhere, you have found the reason before looking at anything else.Defaults
The default that must not travel
Echo and the game disagree about what a sound's defaults are, and the export has to know the difference between "the author chose this" and "the author never looked".
| Setting | Echo's default | The game's default | Exported for an untouched clip |
|---|---|---|---|
| Max Distance | 100 | 500 | 500 |
| Unit Size | 1 | 10 | 10 |
Copying Echo's own default across would look harmless and would be a real bug. Every clip whose
author never opened the spatial panel would arrive carrying MaxDistance 100 against
a game that assumes 500 — quietly cutting the audible range fivefold on every sound
nobody had an opinion about.
So the rule the export applies is did a human move this? An untouched value is treated as no opinion and the game's own default is left in place. A value you actually changed travels exactly — verified, a Max Distance set to 30 exported as 30.
The boundary
The ceiling, and the notes
The game's sound definition is small: a list of clips, a pitch range, a volume, and three spatial numbers. That is the whole ceiling.
| Carried | Reported as lost |
|---|---|
| Clip list (a bank's variants) | Buses, reverb sends, routing |
| Pitch range (from pitch variance) | Volume variance |
| Volume | Play modes other than Random |
| Max Distance, Unit Size | Min distance, rolloff, attenuation model |
| An attenuation-disabled flag | Loop flags, narrative conditions, events |
The right-hand column is long, and Echo names every item in it, once each, by the clip or bank it belonged to. That is unusual and deliberate. A tool in this position can drop what it cannot carry in silence, or mangle it into a field that means something else; this one reports it.
Which makes the export notes the fastest documentation of the boundary that exists. Export once, read what it says it could not carry, and you have learned the shape of what the game accepts more quickly than any page could tell you — including this one.
The habit
The order that works
Sounds to a merged bundle
- Open the mod folder first. without a mod root the bundle export refuses, and every other export goes somewhere nothing reads
- Name banks as the game will trigger them; keep variant names internal. a clip sharing a bank's name is dropped entirely — tier two
- Put settings on the bank, not on its variants. a game sound carries one set of values for all its clips
- Leave spatial values you have no opinion about alone. an untouched value lets the game's own default stand; typing Echo's default means the same thing
- Export the bundle, then read the notes and check the file is in
export/. the notes name what was lost, and the folder is what decides whether any of it is read
| Symptom | What it means | Fix |
|---|---|---|
| The export succeeded but nothing reached the game | The file is outside the mod, where nothing scans. | Check for <mod>/export/echo.bundle.json. |
| The bundle export refused | No mod folder is open. | Open one — it is the only place a bundle belongs. |
| Sounds carry further than expected in game | An untouched Max Distance became the game's 500. | Set a value you actually want; 100 will not express itself. |
| A clip is missing from the bundle | Name clash with a bank, or no file reference. | The notes name it; both are reported. |
| Reverb and buses did nothing | They have no counterpart and are reported lost. | Audition-only features — expected. |
Course complete
What you now know
Check yourself
- One function turns a distance into a gain, and the spatial controls are its arguments.
- Min Distance is a bubble of full volume, and also the scale the falloff is measured from — it does both jobs.
- Inverse and Inverse Square ignore Max Distance entirely. A new clip is Inverse, so that slider starts inert.
- Only Linear and Logarithmic read Max Distance.
- Linear reaches exactly zero at Max Distance; Inverse never reaches zero at any distance.
- Disabled means full volume everywhere — the loudest setting, not the quietest.
- Rolloff steepens the curve and is clamped between
0.05and5. - Model names are matched loosely, so an unrecognised one silently becomes Inverse.
- A bank is one sound holding several clips, not a folder of sounds — three variants exported as one sound with three clips.
- Clips inside a bank are not exported separately and are not independently triggerable.
- The bank's settings replace a variant's own, because a game sound carries one set of values for all its clips — and Echo names what it replaced.
- ±0.05 pitch variance becomes the range 0.95–1.05; that mapping is exact.
- Volume variance and play modes other than Random have no counterpart and are reported.
- A clip sharing a bank's name is skipped entirely — the bank keeps the name.
- Banks reference variants by id, so renaming a clip is safe inside the project.
- Buses, reverb and events are Echo-only. Useful while authoring, absent from what ships, and reported as such every time.
- Only
export/echo.bundle.jsonis read. The definitions lane searches inside a mod root; Echo's other exports land outside one, where nothing scans. - The bundle export refuses without a mod folder rather than writing somewhere useless.
- An untouched spatial value means "no opinion" and lets the game's default stand — Echo's 100 and 1 become the game's 500 and 10.
- A value you moved travels exactly; typing Echo's own default is the same as not touching it.
- Clips are referenced by file name as
audio:name.ext, never by the path Echo imported from. - The game's sound definition holds clips, a pitch range, a volume and three spatial numbers. That is the whole ceiling.
- Everything outside it is reported by name, once each — the export notes are the fastest documentation of the boundary there is.
That is Echo. It was the first tool wired to write its bundle inside the mod rather than to user://output, which is why its content actually reaches Refinery's merge.
