Skip to content

Sidechain a Custom Effect

An effect has one stereo input unless it declares its inputs. Declare a second one, and feed another track into it with connect_input.

Declare the inputs and the output. process takes one argument per channel, in the order the inputs are declared — a stereo input gives two, a mono input one:

use "std/instruments" { Sampler, Kit };
dsp effect Ducker {
input main: stereo;
input sidechain: mono;
output: stereo;
param threshold: 0.3 range(0, 1);
param ratio: 4.0 range(1, 20);
state env: 0.0;
fn process(main_l, main_r, sc) -> (out_l, out_r) {
let over = __native("max", __native("abs", sc) - threshold, 0.0) * (1.0 - 1.0 / ratio);
if over > env {
env = env + (over - env) * 0.01;
} else {
env = env + (over - env) * 0.001;
}
let gain = 1.0 / (1.0 + env);
return (main_l * gain, main_r * gain);
}
}
let drums = AudioTrack("drums");
drums.set_instrument(Sampler(Kit("CR-78")));
drums << [bd _ bd _];
let pad = AudioTrack("pad");
pad.set_instrument(Sampler(Kit("CR-78")));
pad << [cy cy cy cy];
let duck = Ducker("ducker");
pad.set_effects(#[duck]);
duck.connect_input("sidechain", drums);
PLAY;

The pad passes through main; the drums arrive on sidechain and pull the pad down on every hit. connect_input takes the name of a declared input, and the effect must be on its track first. The source reaches the input only; it is not mixed into the output.

Declare one mono input and a mono output, and process takes one sample and returns one:

use "std/instruments" { Sampler, Kit };
dsp effect MonoGain {
input main: mono;
output: mono;
param level: 1.0 range(0, 2);
fn process(input) -> output {
return input * level;
}
}
let bass = AudioTrack("bass");
bass.set_instrument(Sampler(Kit("CR-78")));
bass << [bd _ bd _];
bass.set_effects(#[MonoGain("monogain")]);
PLAY;