Godot 4.3 and later will mix your stems for you. AudioStreamSynchronized keeps a set of layers sample locked and lets you change each layer's volume while it plays, and AudioStreamInteractive gives you a bar and beat quantized transition table. What the engine does not give you is any musical clock at all: there is no beat signal, no bar signal, and no way to map a gameplay value onto your layer volumes.
Divisi is the missing half. It never reimplements mixing. A section plays as one AudioStreamSynchronized and the engine mixes it, exactly as it already does well. Divisi adds the scheduling on top.
What you get
- A drift free musical clock.
DivisiClockreads musical time from the audio device, not from accumulated frame deltas, and emitsbeatandbarsignals off it. Its beat count sits exactly on the music for as long as the music plays, across loop points and across section changes, and a stalled frame does not make it replay a burst of missed beats. - One number drives the whole mix.
DivisiPlayerholds your sections. One intensity value, from 0 to 1, drives every layer's gain through that layer's own curve, so a single "threat" or "danger" number morphs the whole arrangement in phase. - Transitions that land on the music.
transition_to()schedules an equal power crossfade to another section on the next beat or the next bar, and the incoming stems land in phase on that boundary rather than restarting from zero. - Stingers.
play_stinger()fires a one shot on the next beat over the running mix, with an optional level dip on the music underneath. - Music that survives a scene change. An opt in autoload carries the section, the intensity and the bar position across a scene change, so the music does not restart every time the player walks through a door.
- A live readout. A debug overlay draws the section, bar and beat, and every layer's live gain, and can be asked for one more line: how far the audio device's clock and the system clock have run apart. That last one is off by default, because it is a diagnostic about two clocks rather than a statement about whether Divisi is working, and it reads like the latter.
- Pure GDScript. No GDExtension, no per platform binaries, nothing to rebuild when Godot updates.
The demo
The repository is itself a Godot project. Clone it, open it, press play. A threat slider morphs four stems, a button jumps to a second section on the next bar line and lands on the downbeat, a light pulses on the beat signal, a stinger fires on the next beat, and a button changes scene with the music carrying on and the bar position intact. The four stems in each section were synthesised from scratch for the project and are dedicated CC0, so the demo runs on first clone with nothing to download.
What it deliberately does not do
- No sample accurate scheduling: divisi schedules on frames, so a boundary lands within one frame. Sample accurate scheduling needs engine support that does not exist yet.
- No reimplemented mixing, no generative music, no sound pooling or SFX management, no tempo or key detection, no sidechain compression.
The README has the full table and cites the engine source and issue numbers behind every design decision.
Changelog for version v0.1.5
No changelog provided for this version.