mattalcock.com/labs

Labs · Library

Pattern core

The core Jump is built on. Patterns, mini-notation, clocks and quantise grids, with no dependencies and nothing about audio or games.

Patterns

A Pattern<T> answers one question: what happens in this span of time? Time is in cycles, and one cycle is one bar.

import { mini, seq, pure, stack, euclid } from "@chop-jump/jump";

const p = mini("kick ~ kick [~ kick]");
p.cycle(0);            // events that start in bar 0
p.onsets(4, 4.5);      // events that start in the first half of bar 4

Each event is a Hap: { whole: { begin, end }, value }.

Mini-notation

Write Meaning
"a b c d" four steps in one cycle
"a ~ b ~" ~ is a rest (- works too)
"a [b c]" brackets subdivide a step
"a*4", "a/2" repeat a step faster, or spread it over cycles
"<a b c>" one per cycle, in turn
"a, b c" layers, at the top level or inside brackets
"a!3", "a ! b" replicate a step
"a _ b" stretch the previous step by one step
"a@3 b" weight a step
"a?", "a?0.8" drop at random, deterministically (same result every time)
"x(3,8)", "x(3,8,2)" Euclidean rhythm, optional rotation

Words can carry an argument after a colon, like "rock:L" or "c:minor". word("rock:L") returns { name: "rock", arg: "L" }.

Syntax errors throw a MiniSyntaxError with the position.

Combinators

pure(v), seq(...), stack(...), slowcat(...), timecat([[w, p], ...]), euclid(p, k, n, rot) and silence() build patterns. Methods transform them: fast, slow, late, early, every(n, f), degradeBy(p, seed), rev, compress(b, e), fmap, filter.

Clocks

import { Clock } from "@chop-jump/jump";

const clock = new Clock({ bpm: 126, now: () => audio.currentTime, origin: startedAt });
clock.beat();                 // beats since the origin, now
clock.cycle();                // bars since the origin, now
clock.timeOfCycle(16);        // seconds at bar 16
clock.next("16n");            // the next sixteenth-note line, in seconds
clock.next("4n", t, 0.03);    // a hit up to 30 ms late counts as on the beat it aimed at
clock.offGrid("4n", t);       // how far t is from the nearest beat

Grids are written in music notation: "16n", "8n", "4n", "2n", "8t" (eighth-note triplet), "1m", "2m", "4m", "8m", or a number of beats.

Chop's trackClock and Jump's default tempo clock are both Clocks. The origin is beat 0, the first downbeat.

Music helpers

noteToMidi("eb2"), midiToFreq, parseKey("a:minor"), keyName, degreeToMidi(key, degree, octave), chord(key, degree), and SCALES.

Randomness

mulberry32(seed) returns a seeded random function, and hashString(s) turns a name into a seed. Both are used to keep games deterministic.