Skip to content

Signals and Modulation

On this page you turn a fixed drum filter into a moving one, then move the drums across the stereo field. A signal is a value that changes over time; modulation uses it to move a parameter for you.

Finish Your First Mix. Open src/main.non in your project. Evaluate RESET; on its own, then remove it from the file. Check that the earlier mix is silent. Select and evaluate each block below in order. You need only the bundled CR-78 kit and your audio output.

use "std/instruments" { Sampler, Kit };
use "std/effects" { Lowpass };
set_bpm(120);
let drums = AudioTrack("drums");
drums.set_instrument(Sampler(Kit("CR-78")));
drums.volume << -9;
drums << [bd _ sd _, hh*8];
let filter = Lowpass("filter", 1200);
drums.set_effects(#[filter]);
filter.parameter("Cutoff") << 1200;
PLAY;

The drums sound dark. Cutoff is a frequency in hertz; 1200 holds it steady. The effect is on the track before you address its parameter.

use "std/signals" { Sine, Sine2 };
let sweep = Sine(1).range_exp(300, 6000);
filter.parameter("Cutoff") << sweep;

Wait for the next cycle, then listen. The drums brighten and darken once each bar. Sine(1) rises and falls between 0 and 1 once per cycle. .range_exp(300, 6000) converts that motion into a cutoff between 300 Hz and 6000 Hz.

For frequency, an exponential range spreads motion evenly across octaves. Compare it with a linear range, then return to the exponential one:

filter.parameter("Cutoff") << Sine(1).range(300, 6000);
filter.parameter("Cutoff") << sweep;

Listen for where the sweep spends its time: the linear version spends more of it at high frequencies. sweep stores the moving signal, rather than a snapshot of its current value.

filter.parameter("Cutoff") << Sine(4).range_exp(300, 6000);

There are now four sweeps per cycle: one per beat with the default four-beat cycle. Slow it down:

filter.parameter("Cutoff") << Sine(0.25).range_exp(300, 6000);

One sweep now takes four cycles. Change tempo and listen:

set_bpm(90);

The sweep slows with the music. Its speed is in cycles, not seconds. Return to 120 BPM:

set_bpm(120);

Pan runs from −1 (left) to 1 (right), so use a signal that already covers both sides:

drums.pan << Sine2(0.5) * 0.6;

The drums cross the stereo field once every two cycles. Sine2 swings from −1 to 1; multiplying by 0.6 narrows the movement to −0.6 through 0.6. Use headphones or a stereo pair to hear the movement.

Send fixed values to replace the moving bindings:

filter.parameter("Cutoff") << 1200;
drums.pan << 0;

The filter holds steady again, and the drums return to the centre. You do not need to remove the effect or recreate the track. Finish with:

STOP;