rhythmicon-rhythm
v0.3.0
Published
Analyze and compute rhythmic patterns
Readme
rhythmicon-rhythm
Analyze and compute rhythmic patterns
This Node package implements class Rhythm to store, analyze and manipulate rhythms.
Table of Contents
- Background
- Install
- Usage
- Rhythm
- Maintainers
- Contributing
- License
Background
Class Rhythm implements a simplified model of musical rhythms. Every rhythm is an array of pulses, each being either a beat (value 1) or a rest (value 0). For instance the tresillo rhythm is array [1,0,0,1,0,0,1,0]. A rhythm can also be encoded as pattern string (x--x--x-) and as durations (array [3,3,2] or string 3+3+2). Rhythms can further be:
- repeated and cut (e.g.
x-x-x-can be cut tox-) - inflated and deflated by a divisor (e.g.
x-xandx---x-with divisor 2). - rotated (e.g.
xx-is rotated-xxandx-x) - shuffled and unshuffled (e.g
x-xx--is shuffle ofxxx-) - normalized to a core rhythm
Related works
- rhythmicon-vue is a JavaScript library of Vue components to display and interact with rhythmic patterns
- rhythmicon further contains a collection of rhythms and a web application to analyze and modify rhythmic patterns
- tonal is a JavaScript library for tonal elements of music (note, intervals, chords, scales, modes, keys). The library also contains the limited class @tonaljs/rhythm-pattern for rhythmic patterns.
Install
This package comes as single file without dependencies.
npm install rhythmicon-rhythmUsage
import Rhythm from "rhythmicon-rhythm"
const r = new Rhytm("x--x--x-")
console.log(`Rhythm has ${r.beats()} in ${r.length} pulses) Rhythm
This is a subclass of Array so all of its properties and methods can be used. Please make sure the Array will contain only 0 and 1 elements when using low-level Array methods.
Constructors
new
The constructor creates a new Rhythm object like new Array. If passed a single string or Array argument, this argument is used to build the rhythm from.
new Rhyth("x--x--x-")
new Rhythm("|RL-RRL--|")
new Rhyth([1,0,0,1,0,0,1,0])
new Rhyth("A","_","_","+","_","_","B","_")
Rhythm(n) // empty rhythm of length nclone
This instance method returns a copy of the Rhythm instance.
Factory methods
fromPattern(pattern)
Generates a Rhythm from a pattern string.
fromDurations(durations)
Generates a rhythm from an Array or string of durations.
euclidean(beats, pulses)
Generates an euclidean rhythm with beats number of beats in pulses number of pulses.
Accessor methods
The following ("member const") methods don't modify instances.
beats()
Get the number of beats in this rhythm.
beatPulses()
Get an array of index numbers of beats in this rhythm.
first()
Get the position the the first beat, or undefined if the rhythm is empty.
rhythm.first() === rhythm.beatPulses()[0]empty()
Get whether the rhytm contains no beats.
durations()
Return an array of durations between beats, starting with the first beat.
divisor()
Get greatest common divisor of all durations. Returns 1 if the rhythm cannot be deflated or if the first pulse is not a beat. Returns the length of the rhytm for an empty rhythm.
repetitions()
Get number of repetitions.
shuffled()
Check whether the rhythm is shuffled. That is the pulses can be organized in groups of three pulses where the second pulse of each group is a rest.
Rhythm.fromPattern("x--x-x").shuffled() // true
Rhythm.fromPattern("xx-x-x").shuffled() // falseodd()
Check whether the rhythm is odd (cannot be split at beats into two parts of equal length).
core()
Check whether the rhythm is normalized to its core rhythm.
rotations()
Calculate all rotations by pulse. Returns a Set of pattern strings.
beatRotations()
Calculate all rotations by beat. Returns a Set of pattern strings.
toString()
Stringify the rhythm with "x" for beat and "-" for rest.
toDurationString(sep)
Stringify the durations of the beat, separated by sep (+ by default) and
preceded by more of this character if the first pulse is not a beat.
Comparator methods
compare(rhythm)
Compare two rhythms, first by length, then lexicographically by its durations. The argument is parsed if it is no Rhythm object.
equivalent(rhythm)
Check whether this rhythm is equivalent to another, possibly under rotation. The argument is parsed if it is no Rhythm object.
equals(rhythm)
Whether the rythm is equal to another rythm (same length, same pulses). The argument is parsed if it is no Rhythm object.
rotation(rhythm)
Get the rotation number if this rhythm is equivalent to another, or undefined otherwise.
Modifying methods
beat(...durations)
Add one or more beats with given duration(s) or one pulse if no parameter is given.
rest(duration)
Add a rest with given duration in pulses.
replace(...rhythm)
Change the rhytm in-place. Takes same arguments as the constructor, except a single number is read is one pulse instead of a number of pulses.
deflate(divisor)
Deflate the rhythm if it has a divisor > 1. The optional parameter must be a prime of the divisor.
inflate(n)
Inflate the rhythm. Each pulse is replaced by n pulses with default n=2.
repeat(n)
Repeat the rhythm n times (default 2 to duplicate it).
cut(n)
Reduce the rhythm by removal of all repetitions or to a smaller number n of repetitions. Does nothing if n is larger than repetitions().
cut(n) results in the same as cut().repeat(n)
Rhythm.fromPattern("x-x-x-x-").cut() // => Rhythm[1,0]
Rhythm.fromPattern("x-x-x-x-").cut(1) // => Rhythm[1,0,1,0]
Rhythm.fromPattern("x-x-x-x-").cut(2) // => Rhythm[1,0,1,0]
Rhythm.fromPattern("x-x-x-x-").cut(3) // => Rhythm[1,0,1,0,1,0]complement()
Convert rhythm into its complement by swapping beats and rests.
shuffle()
If the rhythm can be grouped into groups of two pulses, each of these groups is replaced by three pulses, the second one being a rest.
Rhythm.fromPattern("x-xx").shuffle() // => "x--x-x"unshuffle()
Remove the middle rest of each triple group if the rhythm is shuffled. Does nothing otherwise.
rotate(pulses)
Rotate the rhythm pulses number of pulses to the right (1 by default), or to the left if pulses is negative.
Rhythm.fromPattern("x--x-").rotate(1) // => Rhythm[0,1,0,0,1]rotateBeats(beats)
Rotate the rhythm one or more beats to the right.
If the first pulse is not a beat, the rhythm is first rotated to do so, so rotation by zero beats will rotate the first beat to the first pulse.
normalize()
Normalize to a core rhythm by rotating, deflation, and cutting repetitions.
Static methods
isBeat(value)
Return whether a variable is read as beat. This is true for every true value except for the characters space, underscore, dot, and minus.
isDurationsString(str)
Return whether a string specifies a rhythm in form of durations with optional rotation.
if (Rhythm.isDurationString(s)) {
rhythm = Rhythm.fromDurations(s)
}parse(...rhythm)
Read a string, an Array, or a list of values as rhythm and returns an Array of pulses.
Maintainers
- @nichtich (Jakob Voß)
Contributing
Contributions are welcome! Best use the rhythmicon issue tracker for questions, bug reports, and/or feature requests!
License
MIT license
