Routing
Quick Start
Section titled “Quick Start”use "std/instruments" { Sampler, Kit };
let drums = AudioTrack("drums");drums.load_instrument(Sampler(Kit("cr78")));drums << [bd sd bd sd];
let reverb_bus = AudioTrack("reverb");reverb_bus.load_effect(Reverb(0.8, 0.3));drums.send_to(reverb_bus, 0.3);PLAY;The >> Operator
Section titled “The >> Operator”The >> operator routes audio from one node to another:
drums >> master;Master Destination
Section titled “Master Destination”master is the built-in constant for the main audio output. All audio must eventually route to master to be heard.
Tracks without explicit >> routing go to master automatically:
let hats = AudioTrack("hats");hats.load_instrument(Sampler(Kit("cr78")));hats << [hh*8];// No >> routing needed -- goes to master automaticallyMulti-hop Chains
Section titled “Multi-hop Chains”Chain multiple nodes with >>. Each hop is unity gain (1.0):
kick >> drum_bus >> master;Routing Rules
Section titled “Routing Rules”>> with Send Amounts
Section titled “>> with Send Amounts”Use .send(amount) to create a Send value for >> chains. The amount accepts a Number, Signal, or Pattern:
drums >> reverb_bus.send(0.3) >> master;drums >> delay_bus.send(Sine(4).range(0.1, 0.5)) >> master;.send_to()
Section titled “.send_to()”Routes a copy of audio to another track. The dry signal still flows to its normal destination at full level:
let delay_bus = AudioTrack("delay_bus");delay_bus.load_effect(Delay(0.3, 0.5));
melody.send_to(delay_bus, 0.3); // 30% to delay returnMultiple sends from one track:
perc.send_to(short_delay, 0.2);perc.send_to(long_delay, 0.4);.xsend_to()
Section titled “.xsend_to()”Exclusive send — routes audio to a destination while reducing the dry signal to master. Useful for routing entirely through a bus:
drums.xsend_to(drum_bus, 1.0);Choosing Between send_to and xsend_to
Section titled “Choosing Between send_to and xsend_to”| Behavior | send_to | xsend_to |
|---|---|---|
| Dry to master | Always 1.0 | 1.0 - amount |
| Total energy | Increases | Preserved |
| Can target master | Yes | No |
| Use case | Parallel FX, reverb sends | Full submix routing |
Pattern and Signal Send Amounts
Section titled “Pattern and Signal Send Amounts”Send amounts accept Numbers, Signals, or Patterns. Signal and pattern values update at block rate:
perc.send_to(short_delay, Sine(4).range(0.1, 0.5));perc.send_to(long_delay, [0.1 0.3 0.5 0.3]);Submix Buses
Section titled “Submix Buses”Any AudioTrack can serve as a submix bus. Route multiple tracks with >>:
let drum_bus = AudioTrack("drum_bus");kicks >> drum_bus;snares >> drum_bus;hats >> drum_bus;drum_bus.load_effect(Delay(0.1, 0.2));Sidechain Routing
Section titled “Sidechain Routing”Effects with sidechain inputs can receive audio from other tracks via .connect_input(). This works with both custom DSP effects and external VST3/CLAP plugins that have sidechain buses.
dsp effect Compressor { input main: stereo; input sidechain: mono; output: stereo;
param threshold: 0.5 range(0, 1); state env: 0.0;
fn process(main_l, main_r, sc) -> (out_l, out_r) { let level = abs(sc); if level > threshold { env = env + (level - env) * 0.01; } else { env = env + (level - env) * 0.001; } let gain = 1.0 / (1.0 + env); return (main_l * gain, main_r * gain); }}
let drums = AudioTrack("drums");let bass = AudioTrack("bass");
let comp = Compressor();drums.load_effect(comp);comp.connect_input("sidechain", bass); // Bass triggers compression on drumsFor external plugins, the sidechain port name comes from the plugin itself (typically "Sidechain" or "Aux Input"):
let drums = AudioTrack("drums");let kick = AudioTrack("kick");
let comp = Effect("My Compressor");drums.load_effect(comp);comp.connect_input("Sidechain", kick); // Kick triggers sidechain on plugin compressorHow It Differs from Sends
Section titled “How It Differs from Sends”| Feature | send_to / >> | connect_input |
|---|---|---|
| Purpose | Mix audio into a destination track | Feed audio into an effect’s sidechain port |
| Target | Track or master | Named port on an effect |
| Audio mixing | Additive (summed) | Read-only (doesn’t modify source) |
| Ordering | Automatic via topological sort | Automatic via topological sort |
- The source track must not create a routing cycle with the destination
- Mono sidechain ports auto-downmix stereo sources to
(L + R) / 2 - For DSP effects, the port name must match a declared
input(e.g.,"sidechain") - For external plugins, the port name must match the plugin’s sidechain bus name (e.g.,
"Sidechain") .connect_input()returns the effect for chaining
Routing Introspection
Section titled “Routing Introspection”routing() — Global
Section titled “routing() — Global”Print the full routing graph for all tracks:
routing();routing(track, ...) — Per-Track
Section titled “routing(track, ...) — Per-Track”Print routing info for specific tracks. Accepts one or more track arguments:
routing(drums); // Single trackrouting(drums, bass); // Multiple tracks.routing() — Method Form
Section titled “.routing() — Method Form”Call .routing() on a track to print its routing info:
drums.routing();Routing Management
Section titled “Routing Management”.reset_routing()
Section titled “.reset_routing()”Clears all routes and send modulations, restoring the default master route at 1.0. Chainable:
drums.reset_routing();drums.reset_routing().send_to(reverb_bus, 0.5); // Clear and re-route.send_level(dest)
Section titled “.send_level(dest)”Returns a SendParam reference for an existing send:
drums.send_to(reverb_bus, 0.3);let rev_send = drums.send_level(reverb_bus);rev_send << automation(#[0, 0.3], #[8, 0.8]);Requires an existing send route to the destination.
Examples
Section titled “Examples”Layered with Sends
Section titled “Layered with Sends”let delay_bus = AudioTrack("delay_bus");delay_bus.load_effect(Delay(0.3, 0.4));
let clap = AudioTrack("clap");clap.load_instrument(Sampler(Kit("cr78")));clap << [_ _ cp _];clap.send_to(delay_bus, 0.3);
let cowbell = AudioTrack("cowbell");cowbell.load_instrument(Sampler(Kit("cr78")));cowbell << [_ cb _ cb];cowbell.send_to(delay_bus, 0.3);Parallel Effects
Section titled “Parallel Effects”let parallel_bus = AudioTrack("parallel");parallel_bus.load_effect(Distortion(0.8, 0.6));
let drums = AudioTrack("drums");drums.load_instrument(Sampler(Kit("cr78")));drums << [bd sd bd sd];drums.send_to(parallel_bus, 0.3);// Result: dry drums + 30% distorted drums blendedCrossfade Routing
Section titled “Crossfade Routing”Use xsend_to to crossfade between dry and wet signal paths:
let wet_bus = AudioTrack("wet");wet_bus.load_effect(Reverb(0.9, 0.2));
let drums = AudioTrack("drums");drums.load_instrument(Sampler(Kit("cr78")));drums << [bd sd bd sd];
// At 0.7: 70% wet, 30% dry to masterdrums.xsend_to(wet_bus, 0.7);Dynamic Send Automation
Section titled “Dynamic Send Automation”Automate send levels over time with signals or automation breakpoints:
let delay_bus = AudioTrack("delay_bus");delay_bus.load_effect(Delay(0.3, 0.5));
let drums = AudioTrack("drums");drums.load_instrument(Sampler(Kit("cr78")));drums << [bd sd bd sd];
// LFO-modulated send amountdrums.send_to(delay_bus, Sine(0.5).range(0.0, 0.6));See Also
Section titled “See Also”- Effects — built-in effects, chaining, CLAP plugins
- Signals & Automation
- Effects Reference