Skip to content

The Audio Graph

Every sound you make in Resonon flows through an audio graph: a small network of mixer channels that all feed a single master output. If you’ve used a DAW, you already know the shape of it — tracks with instruments and effect chains, faders, aux sends, and a master bus at the end. This page is the mental model for how that graph is wired, so the routing operators and signal modulation you meet later all hang on the same picture.

Here’s a complete session with two channels: a drum track, and a reverb bus that the drums feed into. Run it, then we’ll trace the signal.

use "std/instruments" { Sampler, Kit };
use "std/effects" { Reverb };
let drums = AudioTrack("drums");
drums.load_instrument(Sampler(Kit("CR-78")));
let verb = AudioTrack("reverb");
verb.load_effect(Reverb(0.8, 0.3));
drums << [bd sd bd sd];
drums.send_to(verb, 0.3);
master.volume(-2);
PLAY;

Two tracks, three routes. The drum track plays dry to master, sends a copy of itself to the reverb track at 30%, and the reverb track plays its wet output to master as well. The master bus sums everything and turns it down 2 dB before it reaches your speakers.

A single AudioTrack is a fixed chain. Audio enters at the top as a sound source and leaves at the bottom as routed output:

instrument (the sound source — Sampler, plugin, or DSP)
effect chain (effects applied in order: filter, delay, …)
fader (volume + pan)
sends ───────────▶ other tracks / master (post-fader copies)
master

The order is what matters:

  • The instrument generates the raw sound. A track holds exactly one.
  • The effect chain processes that sound in order — index 0 first. Reordering effects (swap_effects) changes the sound, because a filter-then-delay is not a delay-then-filter.
  • The fader applies volume and pan last, after the effects.
  • Sends branch post-fader: a send copies the faded signal to another destination. Turn the track’s fader down and its sends quiet down with it.

Every track is created with a single default route: straight to master at unity gain. Three tools change where sound goes from there.

source >> dest sets the track’s main output route exclusively — it replaces the default route to master. Chains read left to right and master may only appear at the end, so you can build buses:

let bus = AudioTrack("bus");
drums >> bus;
bus >> master;

track.send_to(dest, amount) adds an additive aux send. The dry route to master stays at unity, and the destination receives an extra copy at amount (0–1) — the classic reverb/delay send. track.xsend_to(dest, amount) is the crossfade variant: it splits the signal energy, sending amount wet and 1 - amount dry, so the total stays constant as you sweep it.

Because tracks can feed other tracks, the graph can be several layers deep (track → bus → master). Resonon processes tracks in dependency order — every track that feeds another is rendered first — and rejects routing cycles, so a bus always has its inputs ready before it runs.

Faders and send levels aren’t just static numbers — they’re modulation targets. The << operator, which sends a pattern to a track, also binds a continuous signal to a fader property:

use "std/signals" { Sine };
drums.volume << Sine(0.5).range(-12, 0);

A signal is a value that changes over time. The audio engine evaluates it continuously as the graph runs — block by block, smoothed per sample — so the fader glides instead of stepping. Send levels modulate the same way through send_level(dest). This is the same machinery that drives signals and automation throughout Resonon.

You now have the shape of the graph: sources flow through effects and a fader, branch through sends, and sum at master. The chapters and reference pages fill in the details.