Skip to content

Samplers

A sampler plays back recorded audio — a kick drum, a piano note, a vocal chop. Resonon ships with a built-in sample engine and two flavours of sampler. A Sampler is a drum machine: each name in your pattern triggers a different one-shot sample. A SamplerMelodic is a pitched instrument: it takes a recorded note and transposes it across the keyboard so you can play melodies.

Both live in the std/instruments module, alongside Kit, which loads a folder of samples:

use "std/instruments" { Sampler, SamplerMelodic, Kit };

Here’s the drum sampler from the previous chapter, start to finish:

use "std/instruments" { Sampler, Kit };
let drums = AudioTrack("drums");
drums.load_instrument(Sampler(Kit("CR-78")));
drums << [bd sd bd sd];
PLAY;

Kit("CR-78") loads the built-in CR-78 kit; Sampler(...) wraps it into a playable instrument; load_instrument puts it on the track. The pattern triggers samples by name.

The names in [bd sd bd sd] aren’t keywords — they’re the sample slots of the loaded kit. The CR-78 names follow its original drum machine: bd is the bass drum, sd the snare, hh the hi-hat, cy the cymbal, cp the clap, rs the rimshot, cb the cowbell. There are more — bongos, claves, maracas, a tambourine — enough to write a full groove from one kit:

use "std/instruments" { Sampler, Kit };
let drums = AudioTrack("drums");
drums.load_instrument(Sampler(Kit("CR-78")));
drums << [bd cp sd cp];
PLAY;

Not sure what a kit contains? show() prints its full sample table to the console:

use "std/instruments" { Sampler, Kit };
show(Kit("CR-78"));

Three kits come bundled: CR-78 and TR-808 for drums, and keys for melodic sampling. You can also load your own — a folder of .wav files under kits/, optionally with a kit.toml describing the sample-to-note mapping.

Every slot is mapped to a MIDI note, so you can trigger samples by number instead of name — handy when you think in note numbers or drive a GM-style kit. In the CR-78, 36 is the bass drum, 38 the snare, 42 the hi-hat. Names and numbers mix freely in one pattern:

use "std/instruments" { Sampler, Kit };
let drums = AudioTrack("drums");
drums.load_instrument(Sampler(Kit("CR-78")));
drums << [36 42 38 42]; // kick, hat, snare, hat
drums << [bd 42 sd 42]; // mixed names and numbers
PLAY;

A comma stacks patterns into parallel layers that play at once — kicks, a snare backbeat, and a running hi-hat, all in one bar:

use "std/instruments" { Sampler, Kit };
let drums = AudioTrack("drums");
drums.load_instrument(Sampler(Kit("CR-78")));
drums << [bd _ bd _, _ sd _ sd, hh*8];
PLAY;

The _ is a rest. Nesting [...] inside a step subdivides it, so you can pack a drum roll into a single beat: [[bd bd] sd bd sd]. These are all mini-notation features — the Patterns chapters go through them properly.

Individual hits can be shaped right in the pattern. Attach a method to a sample name and only that hit changes:

  • .vel(n) sets velocity — how hard the hit lands. 1.0 is full; lower values are softer, good for ghost notes.
  • .pitch(semitones) transposes the sample up or down.
  • .pan(position) places the hit in the stereo field, -1 left to 1 right.
use "std/instruments" { Sampler, Kit };
let drums = AudioTrack("drums");
drums.load_instrument(Sampler(Kit("CR-78")));
drums << [bd.vel(1.0) sd.vel(0.4) bd.vel(1.0) sd.vel(0.4)]; // dynamics
drums << [bd bd.pitch(5) bd bd.pitch(-5)]; // pitch moves
drums << [hh.pan(-0.3) hh.pan(0.3) hh.pan(-0.3) hh.pan(0.3)]; // stereo hats
PLAY;

Chain them to combine — a loud, slightly detuned kick panned left:

use "std/instruments" { Sampler, Kit };
let drums = AudioTrack("drums");
drums.load_instrument(Sampler(Kit("CR-78")));
drums << [bd.vel(1.2).pitch(-2).pan(-0.5) sd.vel(0.5).pitch(2)];
PLAY;

For pitched material — bass, keys, pads — reach for SamplerMelodic. It maps a recorded sample across the keyboard, so note names in a pattern come out as a melody. The bundled keys kit is a good place to start:

use "std/instruments" { SamplerMelodic, Kit };
let lead = AudioTrack("lead");
lead.load_instrument(SamplerMelodic(Kit("keys")));
lead << [C4 E4 G4 C5];
PLAY;

Note names, octaves, chords, and rests all behave as they do for drums — a comma still stacks voices, so [C4 E4 G4, D4 F4 A4] plays two chords in sequence.

A melodic sampler has an amplitude envelope — attack, decay, sustain, and release — that decides how each note swells and fades. Set it with .envelope, with all three time values in milliseconds:

use "std/instruments" { SamplerMelodic, Kit };
let lead = AudioTrack("lead");
let keys = SamplerMelodic(Kit("keys"));
lead.load_instrument(keys);
keys.envelope(10, 100, 1.0, 200); // attack, decay, sustain, release
lead << [C3 E3 G3 C4];
PLAY;

A quick attack and short release give a plucky, percussive note; a slow attack and long release turn the same sample into a swelling pad.

Pattern methods like .vel() shape one hit at a time. To change a sample for every hit — its overall gain, pan, or envelope — reach into the sampler’s slot and set a parameter:

use "std/instruments" { Sampler, Kit };
let drums = AudioTrack("drums");
let kit = Sampler(Kit("CR-78"));
drums.load_instrument(kit);
kit.slot("bd").param("gain") << 0.8; // every kick, a touch quieter
drums << [bd sd bd sd];
PLAY;

Because that’s the same << you use for track volume, a slot parameter can take a moving signal too — auto-panning a hi-hat, pulsing a kick — which the Signals & Automation chapter covers. The sampler can also remap samples to new notes and assign choke groups (so an open hi-hat cuts off a closed one); when you need them, those live on the same Sampler value.

You can load kits, write grooves, sample melodies, and shape individual hits. Next, run a track through effects.

  • Effects — delays, filters, and reverb on a track
  • Signals & Automation — move parameters over time with <<
  • Patterns — the mini-notation behind every pattern you’ve written here