Make a Reproducible Random Choice
The functions in std/random take a seed and return the same
result for the same seed, so a piece that uses them plays the same way every time, and after every
seek. How Patterns Work
explains why.
Pick one value
Section titled “Pick one value”choose(seed, values) picks one element; choose_weighted(seed, values, weights) takes a parallel
array of weights:
use "std/random" { choose, choose_weighted };
let notes = #[C4, E4, G4, B4];print(choose(0, notes)); // the same element on every run
let chords = #[[C4 E4 G4], [F4 A4 C5], [G4 B4 D5]];let weights = #[3, 1, 1]; // C major three times as likelyprint(choose_weighted(0, chords, weights));rand(seed) returns a number from 0 to 1 the same way. Change the seed for a different pick.
Pick anew each cycle
Section titled “Pick anew each cycle”Seed with the cycle number, inside a stream or an
on_cycle callback, and the pick changes
from cycle to cycle but is the same on every playback:
use "std/instruments" { SamplerMelodic, Kit };use "std/random" { choose };
let lead = AudioTrack("lead");lead.set_instrument(SamplerMelodic(Kit("keys")));
let notes = #[60, 64, 67, 71];on_cycle(fn(cycle) { lead << Sequence(#[choose(cycle, notes)]);});
PLAY;Check that it is reproducible
Section titled “Check that it is reproducible”Assert that the same seed gives the same value:
use "std/random" { rand };assert rand(7) == rand(7), "same seed must give the same value";print("deterministic");rand_true() and choose_true() are unseeded and fail this check on purpose. Use them only when
you want a different result on every call.
Related
Section titled “Related”- Random — every seeded and unseeded function
- Generate a Random Walk — a value that moves from cycle to cycle