Wrap plain rhythm data.
The onsets and the meter they are counted in; copied, never retained.
The onsets, in time order.
The meter the onsets are counted in.
Where the pattern stops: the furthest point any onset sounds to.
A copy of the underlying plain data.
StaticgenerateGenerate a pattern over a meter.
The time signature the bars are counted in, in any form that names one; a meter map is read as the signature it opens in.
Optionalopts: RhythmOptions
Length, grid resolution and the context; see
RhythmOptions. The context's complexity.rhythmic is the onset
density, and its seed fixes which grid slots are taken.
The generated pattern.
StaticofBuild a pattern from onsets that already exist.
The meter is asked for rather than assumed. A pattern in 6/8 read as 4/4
answers every metric question — which beats are strong, where the bars
fall, how dense it is — on the wrong pulse, and nothing downstream can tell
that reading from a meter the caller meant. Its two siblings,
Rhythm.generate and generateRhythm, ask for it the same way.
The onsets, in any order.
The meter they are counted in, in any form that names one.
The pattern.
StaticfromRebuild a pattern from the plain data Rhythm.data hands out.
StaticfromHow busy the pattern is: the mean number of onsets per bar.
The onset count divided by the number of bars it spans.
Drop the onsets carrying the least of the metre.
The metre is the pattern's own: the ranks are read from Rhythm.ts, so a pattern in 6/8 keeps its dotted-quarter pulses and one in 3/4 keeps its three-beat downbeats rather than the beats a four-beat bar would have.
How much to thin, in [0, 1]; at 0 nothing goes, and a full turn leaves the downbeats alone.
The thinned pattern.
Anticipate beats, one sixteenth early.
The beats anticipated are the ones Rhythm.ts counts as main pulses or stronger, so a pattern is not syncopated against accents its own meter does not have. The anticipations are added rather than displaced, so raising the amount only ever adds onsets and the ones already sounding stay where they are.
How much syncopation, in [0, 1].
Optionalctx: GenerationContextInput
The context, or the seed alone; it fixes which beats are anticipated.
The syncopated pattern.
Compress the pattern to half its length and play it twice.
The span is the pattern's own, so it stays as full as it was.
The compressed pattern.
Stretch the pattern to twice its length: everything falls half as often.
Onsets stretched past the span are dropped, since the span is the span however the pattern is felt.
The stretched pattern.
Keep as much decoration as the ornament dial asks for.
Each decorated onset survives on its own draw, so raising the amount brings more of them back without disturbing the ones already sounding. Onsets the predicate does not claim are untouched.
Which onsets count as decoration.
The ornament dial, in [0, 1].
Optionalctx: GenerationContextInput
The context, or the seed alone; it fixes which decoration stays.
The pattern with the surviving decoration.
Apply the complexity dials to the pattern in one pass.
The dials are read from the context, which is where they live for every
generator: complexity.rhythmic below its neutral middle thins the pattern
and above it syncopates, and complexity.ornament decides how much of what
isOrnament claims survives. The span the rate is measured against is the
pattern's own.
Optionalopts: RhythmDeformOptions
The rate, and which onsets are decoration; see RhythmDeformOptions.
Optionalctx: GenerationContextInput
The context, or the seed alone; it carries the dials.
The deformed pattern.
Whether one player can sustain the pattern at the context's tempo.
The ceiling is measured against the closest pair of onsets, which is what actually stops a hand. A context naming no tempo or no ceiling has nothing to measure against, and the pattern passes.
Optionalctx: GenerationContextInput
The context, or the seed alone; its bpm and its
complexity.difficulty are what the answer is read from.
True when the pattern is inside the ceiling.
The pattern as sounding notes at one pitch, in its own meter.
This is where a rhythm reaches the rest of the class API: the score it hands back can be humanized, grooved, analysed, or written out like any other line.
The MIDI pitch to give every onset.
Optionalvelocity: number
Velocity for every onset; a mezzo-forte 96 by default.
The score holding the pattern.
Whether another pattern holds the same onsets in the same meter.
The comparison is made through the other pattern's public data, so two patterns built by different copies of the module still compare.
The pattern to compare.
True when the onsets and the meter match.
The plain form of the pattern, for JSON.stringify.
A pattern of onsets over a meter, and the transformations that reshape one.
The library generates a rhythm as a bare array and deforms one with a family of functions — thinning, syncopating, halving and doubling the rate — that each take an array and hand one back. They are shaped to chain and cannot: every step has to name the pattern again, and the meter it is counted in travels beside it by hand. A
Rhythmholds the two together, so the family reads as the chain it always was.The transformations are written against a sixteenth grid, so the onsets are converted to it and read back afterwards. A rhythm carries no dynamics, and the softer stroke a transform gives an added note is not part of what comes back.
Example