Musical timing
Audity can align sounds to a musical grid so that layers start in phase, stingers land on the bar, and quantized triggers snap to the beat. This is built on transports: shared grids that every playing instance agrees on, sample for sample.
Quantized starts and triggers
Section titled “Quantized starts and triggers”The simplest use needs no setup on the graph. When you play or trigger a source, you can ask it to wait for the next musical boundary:
- Immediate - now (the default).
- Next Beat - the next beat.
- Next Bar - the next bar line.
- Next Phrase - the next phrase boundary.
From code:
source.PlayQuantized(AudityQuantize.NextBar);source.Trigger("Stinger", AudityQuantize.NextBeat);The instance renders silence until the boundary, then begins exactly there. With no active transport, it starts immediately.
The Transport block
Section titled “The Transport block”Each graph has a Transport block that sets how it relates to the shared grid.
You find it in the graph asset’s Inspector, not inside the graph editor
window: select the Sound Graph (or Sub Graph) .asset in the Project window and
its Inspector shows a Transport section. (It is a property of the whole graph,
which is why it lives on the asset rather than on a node.)
The block has a Tempo Mode, and the question it answers is: who owns the clock?
- None (default) - this graph does not touch tempo. Its quantized triggers still land on the default grid whenever something else drives one, so an unauthored stinger locks to the music for free.
- Drive - this graph IS the clock. Starting it publishes its authored BPM to its transport channel and re-anchors the grid at its own first sample; the last Drive graph to start wins.
- Follow - this graph listens to the clock. It quantizes against the channel’s grid without ever changing it, for stingers and layers that must lock to music they do not control.
The rule of thumb: one Drive graph per musical moment (the music bed), Follow on everything that syncs to it, None everywhere else.
Pick Drive or Follow and the block reveals the fields None keeps hidden: BPM, Beats Per Bar, Phrase Bars, and an optional Transport name (blank uses the default channel; a name gives you separate grids, for example one per music system). A music template authors “Drive at 120” once; sound-effect graphs leave the Tempo Mode at None and never think about it.
Transports are shared grids
Section titled “Transports are shared grids”A transport is not a running clock object; it is anchor math over the mix’s sample clock. Position is derived, never accumulated, which has two consequences that make cross-instance music work:
- A grid keeps advancing even while nothing referencing it is playing, so a layer that starts late lands on the same grid as the layers already going.
- Every instance, including a late joiner, computes the identical grid, so vertical layers spin up perfectly in phase.
This is why quantize is reliable across many sources: they are all reading one grid, not each keeping their own guess at the beat.
Driving transports from code
Section titled “Driving transports from code”For a music system, publish a named transport once and let every track follow it:
AudityGlobal.SetTransport("Music", bpm: 120, beatsPerBar: 4, phraseBars: 4);AudityGlobal also exposes NowDspSample() and NextBoundary(...) for
sample-exact game-side scheduling, and PublishDrive(...) for the Drive path.
See the Scripting guide. A timeline can own a grid too - the
Transport Track anchors a
named transport so timeline bars and transport bars agree.
There is also a per-source SetTempo(bpm, beatsPerBar) and a global
AudityGlobal.SetTempo(...), which set a simpler per-instance grid. Prefer named
transports for anything that must stay in phase across instances - a per-instance
tempo does not phase-agree between sources.
Interactive music
Section titled “Interactive music”Audity supports interactive music graph-first: there is no separate music asset or window. A music system is an ordinary Sound Graph whose stems are Wave Players (usually Streamed, one long clip each), coordinated by two nodes on the transport grid above.
- Horizontal (sections that change over time) is the State Route node. Drive its State input from a game parameter and wire each state’s Enter/Arrive to a section’s Play and Exit/Depart to its Stop. Entrances fire immediately - the destination Wave Player’s own launch quantize lands them on the grid - while exits hold to the leaving state’s authored exit boundary, so a section always finishes on the bar. Sparse rules attach per-transition content (a stinger, a bridge) without a full from/to matrix.
- Vertical (layers that fade in and out) is the Layer Mixer node. Feed each stem into an input, author a gain curve over a shared Blend, and drive Blend from gameplay; Smoothing sweeps a stepped value through the stack.
Both rely on the transport grid to stay sample-locked: fan one trigger into every stem player with the same launch quantize (see Quantized starts and triggers) and the layers spin up in phase. Set the graph’s Transport to Drive at the music’s tempo so stingers and layers from other graphs can Follow it.