↓
iaen.es Devlog Leer en español

Gotic · 3 min read

Procedural ambient sound in Godot 4 that I still haven't heard

Footsteps that change with the ground, swim strokes, birds, crickets, waves and wind, all synthesised in Python. The tests say nothing clips. Whether it sounds good, I don't know yet.

#audio#procedural#godot#mods#testing

Procedural ambient sound in Godot 4 that I still haven't heard

This mod has a confession in its title. Sonido ambiente ("ambient sound") makes Gotic's island audible: your footsteps crunch on grass, hiss on sand and knock hollow on the wooden pier; when you swim, as in the cover shot, every stroke splashes; and in the background, birds by day, crickets at night, waves near the shore and wind when you climb high or fly the broom all blend together. It respects the game's sound-effects setting and, like every mod, works on its own.

And nobody has actually heard any of it yet.

How it's built

There isn't a single third-party sound file in Gotic: everything is synthesised by a plain Python script, modulos/ambiente/sonidos.py, with fixed seeds so it always comes out the same. A step on grass, for example, is a short crunch of filtered noise plus a dull 95 Hz thump for the heel; on sand, a longer hiss with no thump; the waves, a low rumble that swells and breaks every 4 seconds with foam at the crash; and the crickets, two of them at 4.3 and 4.9 kHz chirping in stumbling bursts of three pulses. Loops are closed by crossfading their last second into the beginning, so there's no seam when they wrap. Generating everything (four effects and four loops) takes 2 s.

In game, footsteps come from the animation: the character's body is animated in code with a stride phase, and each time that phase crosses 0 or π, a foot hits the ground and a step plays. Which step depends on where you are: swimming, a stroke (one per cycle, and only when moving forward); above the ground, wood (the pier, a roof); near beach height, sand; otherwise, grass. Below 0.6 m/s there are no steps.

The background is four loops that always play, with a volume that follows a mix. Every quarter of a second, 16 points around the player (at 30 and 60 m) are sampled to see how much sea is nearby, along with height above ground, whether it's night, whether it's raining and whether there's forest:

return {
	"amb_olas": coast * (1.0 - wind * 0.5),
	"amb_viento": wind,
	"amb_pajaros": (1.0 - night) * (1.0 - coast * 0.6) * (1.0 - wind) * (0.55 + 0.45 * forest) * (1.0 - wet),
	"amb_grillos": night * (1.0 - coast * 0.5) * (1.0 - wind) * (1.0 - wet),
}

(olas is waves, viento wind, pajaros birds, grillos crickets.) Each loop's volume eases towards its target, so nothing cuts in or out abruptly. Night comes from the day–night mod and rain from the weather mod, but this one knows neither: it reads world.scenery.night and world.scenery.rain, which are zero when those mods aren't there.

An ordering gotcha that made it into the project's lessons file: the game's audio system is created after the mods load, so a mod that registers its effects at startup finds no audio yet. The footsteps register on the first frame instead. Tests create no audio players, but the mix is still computed and can be checked.

Still unverified

The main thing: hearing it. There was no way to listen to it while building it, so all I know is what the numbers say. All eight sounds come out without clipping, and the loop seams jump between 0 and 1.4 times the normal step from one sample to the next: there shouldn't be an audible click. Running on grass with the game's physics produces 7 to 13 steps in 2 s, and a test fails if I remove the sand or the stride detection. But not clipping doesn't mean sounding good.

In the same round, the cat's meow came out far louder than everything else, and I turned it down to −16.7 dBFS without ever hearing it. It's the lesson that keeps coming back in this project: things generated in code can pass every test and still sound wrong. Listening to the audio is still on the list of things blocking the game's release.

More from Gotic →