Skip to content

Play Samples

Sampler plays a kit as a drum machine: each name in a pattern triggers its own one-shot sample. SamplerMelodic plays one sample across the keyboard. Both, and Kit, are in std/instruments. Every method is listed in the instruments reference.

Put a Sampler with a kit on a track, and name the kit’s samples in a pattern:

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

The bundled kits include CR-78, TR-808 and TR-909 for drums and keys for melodic sampling. Your own kits are folders of .wav files under kits/, optionally with a kit.toml.

show() prints a kit’s samples, with the MIDI note each one is mapped to:

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

Every sample is mapped to a note, so a number triggers it too. Names and numbers mix in one pattern:

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

Attach a method to a sample name in the pattern and only that hit changes. .vel() sets velocity (0–1), .pitch() transposes in semitones, .pan() places the hit (-1–1), and .gain() scales its level — past 1 if you need it:

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

A hit’s .pan() and .gain() apply on top of the pad’s own settings: pan adds to the pad’s pan, and gain multiplies the pad’s gain.

To change a sample for every hit — its gain, pan, envelope, slice points or reverse — set a parameter on its slot. Put the sampler on the track first; a slot names something inside a live sampler:

use "std/instruments" { Sampler, Kit };
let drums = AudioTrack("drums");
let kit = Sampler(Kit("CR-78"));
drums.set_instrument(kit);
kit.slot("bd").parameter("gain") << 0.8;
drums << [bd sd bd sd];
PLAY;

A slot parameter takes a signal too — see Sweep a Parameter with an LFO. Remapping a sample to another note and choke groups are on the same Sampler value; see set_note and set_choke_group.

SamplerMelodic(Kit(...)) loads the kit’s default_sample and maps it across the keyboard. Note names play as a melody, and a comma stacks voices:

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

A kit with only one sample needs no default_sample. A missing sample, a missing root note, or a multi-sample kit with no default is an error when the kit loads.

To load another sample from the kit, name it:

use "std/instruments" { SamplerMelodic, Kit };
let keys = SamplerMelodic(Kit("keys"));
keys.load_sample("sound2");

SamplerMelodic() with no kit is an empty sampler; load content into it later with .load_kit() or .load_sample().

On a melodic sampler, a hit’s .pitch(n) is relative to the note you played: C4.pitch(12) sounds at C5.

.set_envelope(attack, decay, sustain, release) shapes how every note swells and fades. The three times are in milliseconds; sustain is a level from 0 to 1:

use "std/instruments" { SamplerMelodic, Kit };
let lead = AudioTrack("lead");
let keys = SamplerMelodic(Kit("keys"));
lead.set_instrument(keys);
keys.set_envelope(10, 100, 1.0, 200);
lead << [C3 E3 G3 C4];
PLAY;

A fast attack and short release give a plucked note; a slow attack and long release turn the same sample into a pad.