Aratu music written to play, and to change while it plays

4. Naming things

▶ Open in Aratu to hear and change the examples

This table is the heart of this part: for each thing in Aratu, the name it would have in programming, and what it is like.

In Aratu In programming terms Like
melody = | c4 d e f | a binding of a name to a value; the value is a sequence of bars a constant: it does not change while playing; each edit defines it again
a line a circular sequence: when it ends, it starts again a looping clip in a DAW
drums { hh = …; bd = … } a record or namespace: a map from names to lines an object (drums.hh)
bass.reverb.mix = 0.42 property assignment on a path through a nested map (part → effect → parameter) bass.reverb.mix = 0.42 in JavaScript, or a CSS rule
bass: synth.saw -> lowpass -> reverb a pipeline: each one's output is the next one's input function composition, reverb(lowpass(saw)), or the shell's |
synth.saw, piano.grand a key in a catalogue (an enum): a name that picks a ready-made sound a value from a fixed list; not a method
motif riff = [e4 d c d] a macro: the name is replaced by its content wherever it appears a function without side effects, expanded in place (inlining)
riff+2, riff+3st the motif with an argument: the transposition riff(2)
riff.inv, riff.retro, serie.P5 a pure transformation written with a dot: it returns a new motif and leaves the original alone a method or computed property without parentheses
row serie = 0 11 3 4 … a vector (array) of whole numbers from 0 to 11 [0, 11, 3, 4, …]
| o o o o | from serie.P0 a zip of the rhythm with the vector, starting it again when it runs out; each o is a placeholder to fill zip(rhythm, cycle(row))
list temas { … } an array of melodies, counted from 1 temas[1] in JavaScript is temas.2 in Aratu
temas.all, temas.random concatenation; a random choice of one item temas.flat(), temas[random()]
{c|g} a random choice, drawn each time round random.choice
c?30% an event with a 30% probability if (random() < 0.3)
seed 7 the seed of the pseudo-random generator: the same seed gives the same result Random(7)
pattern groove { … } a named block of lines a component, a scene, a template
play groove x3, fill a playlist: a sequence with repeats, looping a list of scenes
|: :|, %, D.S. al coda the score's jumps, resolved before playing a goto the compiler unrolls
[e4 d]x4, riffx4 unrolled repetition: it becomes four copies loop unrolling
p:, mf: a state that holds for the following notes of the line the "current colour" in a drawing library
300 Hz -> 4000 Hz over 4 bars interpolation of a value over time (on a logarithmic scale for frequencies) a tween, keyframe automation
a knob a two-way binding: turning it rewrites the number in the text the text stays the source of truth

Is at bar a switch?

Not quite. A switch (or case) picks one path among several, each time it runs, by a value. An at bar is a rule indexed by time: from bar 9 on, it holds, and it keeps holding until another rule changes the same thing. It is closer to a keyframe in an animation, or an event marked on a timeline.

tempo: 110
bass = | c2 _ g1 _ |
at bar 5: bass.reverb.mix = 0.6
at bar 9: bass: out

To know the state at bar 12, Aratu gathers the rules of every bar up to there: the reverb is at 0.6 (since bar 5) and the bass is out (since bar 9). In programming, that is a fold of the changes, in time order. from bar 9 to 16: is a rule with a start and an end: outside its stretch it stays out of the fold, and what came before holds again.

every, on the other hand, is the nearest thing to an if on the bar number:

tempo: 110
pattern groove { hh = cc cc cc cc; bd = b - b -; sd = - s - s }
pattern fill { sd = ss ss SS SS }
play groove
every 4 bars: play fill

every 4 bars: play fill means, bar by bar, "if this is the last of every four, play the fill instead": if (bar % 4 == 0). And every 4 bars, first: is if (bar % 4 == 1).