A rate that moves: from to to over bars bars, holding at to after that. Written where a play takes a number — playn(riff, lead, 8, accel(1, 2, 4)) runs eight passes, speeding up to double over the first four bars — and it is a straight line in rate, so the pattern covers the area under it rather than the rate at either end. Measured from the section's own first note, and started afresh each time a wthen window comes round again. to below from is a ritardando. Both rates must be above zero: at zero the pattern would stop rather than slow, and a bounded section would never finish.
Place a section at an absolute bar, counted from the origin: at(8, chorus). Bars are counted from 0, so at(8, …) is the ninth bar — it is a distance from the start, the same number then_after would have added up to. The escape hatch from chaining, for an arrangement whose shape you already know.
How many channels a buffer has — 1 for mono, 2 for a stereo file. Useful for deciding whether a second sample on channel 1 would say anything different.
The current note's length in seconds. Bound only inside a voice — pass it to env.
Read an audio file into a buffer: let amen = load("breaks/amen.wav"). The path is relative to the file it is written in, the same way a use path is, and must be written out rather than computed — every file is decoded once, before the program runs, so no note ever waits on a disk. Any format symphonia reads: wav, mp3, flac, ogg. Nothing comes out of a buffer until sample reads it.
Everything chained so far, times times through: playn(groove, kit, 3).then_fill(roll).loop(4) is four bars of groove-and-fill. The counterpart to then_n — that one names a fn and runs it *after* this section, this one takes no section at all because the section it repeats is the chain it is written on. The whole chain has to finish, so bound an endless part with .take(n) or .stop() first. The passes are copies, so a rand inside the chain was already spent and every pass is the same music; then_n is the one that draws afresh.
Play a section with probability chance (0 to 1), decided afresh each time round: playn(groove, drums, 4).maybe(0.25, fill). A wthen whose other arm is silence — it repeats and rerolls for the same reason, since a coin flipped once is just an if. Unlike then, the sections here must be fns named rather than plays written out: this runs one afresh rather than placing it once.
then, but the section starts bars *before* this one ends, so the two really do sound together over the join: playn(verse, lead, 8).overlap(2, chorus). Never earlier than the receiver's own start. The chain carries on from whichever of the two ends later.
Schedule a pattern on an instrument: pat >> play(kick). The instrument must name a user fn. rate defaults to 1, and may be an accel rather than a number. A list is one pass, filling the bar, divided evenly unless a step is given a length with ; — [220;2, 330, 440, ;4] is a quarter, two eighths and a half of silence — and lengths are relative, so only their ratio matters. A long step is one sustained note, not several. A step may instead be given a written note value — w h q e s — and then the pass is as long as its values add up to rather than one bar: in 4/4 [c4;q, e4, g4] is three beats against a four-beat bar, so it comes round a beat early and rotates against the grid. A value carries to the steps after it. A bare q is a hit of that length. An octave carries the same way: a note written without one takes the octave of the last note that spelled one, so [a1;q, a, a, a] is four a1s and [c4;q, ef, g] is a chord's worth of arpeggio. Only a spelled octave moves it, a group gives it back at the closing bracket like a written value does, and e — the eighth note and also the note E — is refused where an octave is in force rather than quietly becoming one of them. Written values and ratios cannot share a sequence. A group inside one is a tuplet and says so with ;t — [[c4;q, e4, g4];t, c5] is a quarter triplet then a quarter — which needs no number: the count, the unit and the span it is played in all follow from what the group holds. Any further parameter is patterned by name — play(bass, cut: [400, 2000]) — sampled at each note's onset, and lanes may be any length. In a lane a ; is how many notes the value covers, so it has to be a whole number there. Two names are reserved and reach the note rather than the instrument: legato: scales its length, and pan:` places it across the stereo field from -1 (left) through 0 (centre) to 1 (right).
Treat several sections that run at once as one: play_all(verse, bassline).then(chorus). Each is a no-parameter fn or a play written out, exactly as in seq — the difference is that these all start together rather than one after another, and the group finishes when the last of them does. A plain play among them never finishes, so nothing may follow.
play, stopping after one pass of the pattern: [60, 64, 67] >> play_once(stab). Started while something is already playing it begins on the next bar, so the one-shot lands on a downbeat. Re-evaluating fires it again.
play, stopping after times passes of the pattern: playn([220, 330], bass, 4). rate follows the count and still defaults to 1 — at rate 2 the four passes take two bars. Lanes work as they do on play.
Round where the chain has reached up to a multiple of grid bars, without touching what is already playing: playn(pat, inst, 3, 2).quantize().then(chorus). grid defaults to 1. The cure for a section whose length is not a whole number of bars — rate divides into the count, so playn(pat, inst, 3, 2) is 1.5 bars long and every .then after it would otherwise be permanently off the downbeat.
The quarter note in hertz — 1 / qvs, which is 2 at the default 120 bpm. What an oscillator wants: sin(qvh * 2) sweeps on the eighth, sin(qvh / 2) on the half. Multiplying is what makes it faster here, because this is a rate and not a length. Rate and tempo reach it exactly as they reach qvs.
The quarter note in seconds: 0.5 at the default 120 bpm. Anything that takes a length of time can be written in beats with it — perc(0, qvs / 2) decays over an eighth, delay(qvs * 0.75) is a dotted-eighth delay. Inside a voice it is the beat of the clock that note is played on, so a play at rate 2 gives its instrument a beat half as long; in the persistent graph it is the transport's own, fixed at the eval that wrote it.
wthen with every section equally likely: playn(intro, lead, 2).rthen([verse, chorus, bridge]). Rerolls each time round and never finishes, exactly as wthen does. Unlike then, the sections here must be fns named rather than plays written out: this runs one afresh rather than placing it once.
Read a buffer at a position: 0 is the start, 1 is the end, and anything outside that is silence. position is a signal, which is where speed, direction and chopping all come from — sample(b, ramp(1 / b.secs)) plays it forwards, 1 - ramp(...) backwards, ramp(...) * 0.25 reads the first quarter. Cubic interpolation, so it holds up away from its own speed. channel defaults to 0 and wraps if the buffer has fewer.
How long a buffer is, in seconds. A compile-time number, so it divides into a ramp frequency: ramp(1 / amen.secs) is a phasor that reads the whole buffer once at its own speed.
Sections one after another without the nesting: seq(intro, verse, chorus, verse). Each is a no-parameter fn or a play written out, and each must finish for the next to follow.
Every section once each, in an order drawn now: play_once(intro, lead).shuffle_then([verse, chorus, bridge]). The counterpart to rthen rather than a variant of it — a weighted choice may pass a section over for a long time, and this cannot. It settles at eval time like scramble, so it has a length and a .then may follow it. Unlike then, the sections here must be fns named rather than plays written out: this runs one afresh rather than placing it once.
Read a portion of a buffer, once: slice(amen, 0, 0.25) is the first quarter of the break, at the speed it was recorded at. start and end are positions like sample's, 0 at the start of the buffer and 1 at the end, and both are compile-time numbers rather than signals. start past end plays that portion backwards. rate defaults to 1 and multiplies the speed — 2 reads the portion in half the time, an octave up, 0.5 in twice, an octave down — and must be above zero, since at zero the reader would stop rather than slow; backwards is the ends the other way round rather than a negative rate. This is sample with the phasor written for you — sample(b, line(start, end, (end - start) * b.secs / rate)) — and it exists because that duration is the part that is easy to get wrong: scaling a ramp's position without scaling its frequency to match reads the right portion at the wrong speed. The read holds on the last sample once it arrives, so an envelope is what ends the note, exactly as with sample; a slice ending at 1 goes quiet on its own, since past the buffer is silence. For a position or a speed that moves under a signal — scrubbing, stuttering, anything modulated — use sample.
Cut everything still open in this section at the moment its last *counted* part finishes: play_all(play(groove, drums), playn(riff, lead, 8)).stop() lets the eight-bar riff decide when the endless drums give up. One pattern as the trigger to stop the rest. Needs at least one play_once or playn among them, or there is no moment to stop at.
This section, cut to bars: play(riff, lead).take(8).then(chorus). What gives a plain play an end — playn only bounds a single play, not a play_all group or a whole nested section. A part that already stops sooner is left alone, since a cut is a ceiling and not a length.
Sequence one section after another: playn(verse, lead, 4).then(chorus). The left side must be play_once or playn — plain play never finishes. section is either a no-parameter fn named here or a play written out — .then(playn(riff, lead, 2)) needs no name — and either way its own play calls start where this one stops. A play bound to a let is not a section: it already sounded where it was written, so name it as a fn instead. Lowered at eval time, not called by the audio thread.
then, with bars of silence in between: playn(verse, lead, 4).then_after(1, chorus) leaves a bar's rest before the chorus. The gap cannot be negative — overlap is how a section starts early.
One pass of the section per element of the list, in sequence, with the element passed in: play_once(intro, lead).then_each([1, 2, 4], faster) calls faster(1), then faster(2), then faster(4). body takes exactly one parameter — the element. Arrangement by list — every list function in the language already builds the shape of a piece, and this is what spends one. Unlike then, the sections here must be fns named rather than plays written out: this runs one afresh rather than placing it once.
One pass of a pattern on this section's *own* instrument: playn(groove, drums, 4).then_fill([1, 1, 1, 1]). Unlike then there is no fn and no second play — a fill is played by whoever just played, so the instrument and every lane are inherited and only the pattern is new. The left side has to be a single play: a group of them has no one instrument to be a fill for. rate defaults to 1, and here is a plain number — a fill is one pass, with no room to speed up over.
Run a section times times, back to back: play_once(intro, lead).then_n(verse, 4). Lowered afresh each pass rather than written once and repeated, so a rand inside the section is a different number every time round — the same rule a voice already follows, and it holds whether the section is a fn named here or a play written out.
Run a section *alongside* this one, from where it began: playn(verse, lead, 4).with(drums).then(chorus). play_all opens its sections together as a group; this makes one concurrent with a section already placed, so an arrangement reads in the order it happens. The pair finishes when the later of them does.
Choose between sections, afresh each time round: playn(intro, lead, 2).wthen([verse, chorus], [0.7, 0.3]). Weights are relative and need not sum to 1. Unlike choice, which draws once while the program is lowered, this is decided by the scheduler as the music reaches it — so the block repeats forever and deals a new hand every time. Every arm must finish, and they all come back to the same place; the block itself never finishes, so bound it with .take(n) if something should follow. Unlike then, the sections here must be fns named rather than plays written out: this runs one afresh rather than placing it once.