Patterning a Pattern, Patterning a Ribbon.
Imagine writing a song with the most succinct notation possible, where a clause like "<4.25@2 <4.5 4> <6.5 1.5>>/2" would create an entire song.
ⓘ While this article will NOT go in-depth into discussing how livecoding is fundamentally unrelated to A.I, I will say that any discussion of A.I / LLM related topics will need to go somewhere else.
The Language of Livecoding
In the live-coding world we often talk about patterned loop constructs. Just like in traditional programming languages, loop constructs in Strudel REPL can be “nested” within one another.
note("<A C E>")
// a simple loop of playing notes A, C, E sequentially for 3 cycles before repeating itself
note("<A C <D E>>")
// a nested loop construct
// the "outer" loop is actually <D E>, so it plays
// A -> C -> D in the first 3 cycles
// A -> C -> E in the next 3 cyclesThe above example shows how you can write a nested loop construct with mini-notation.
The first construct
<A C E>can be thought of a simple loop that plays three notes in sequence.The second construct
<A C <D E>>consists of an “outer” loop alternating between notesDandE. While the inner loop consists ofA,Cand then a variable that depends on the current position of the outer loop.
For those of you who are more programming-centered, I wrote some pseudocode in plain JavaScript to illustrate this behavior:
[D, E].forEach(x => // <D E> outer loop
[A, C, x].forEach(n => play(n)) // <A C <x>> inner loop, where x depends on the outer iteration
)This pattern has become so common that we often call it “patterning the pattern”, because you are simply patterning the base pattern <A C x> with a broader pattern <D E>.
Patterning the Pattern
💡 Did you know?
The phrase “patterning the pattern” was originally coined by Switch Angel in her song In the beginning, there was Trance back in Nov 2025.
Sample lyrics:
1:41 > Let's create a breakdown - by isolating the lead.1:47 > We create a progression - by patterning the pattern1:52 > Seven. Hold, hold. Six, five, hold, hold, six...
from Switch Angel - In the beginning, there was Trance
Such a technique is not new, and is quite often used in an algorithmic live-coding EDM rave (algorave) setting. Livecoders write lines of very terse code live on stage to create the most elaborate melodies and rhythms.
For instance, a concise notation could be used to segment off and repeat (or “ribbon”) from a long, continuous run of randomized melodic notes:
<4.25@2 <4.5 4> <6.5 1.5>>/2But don’t worry if you can’t quite wrap your head around this block code yet…
…since I will need to introduce to you the magic of ribbon() !
A Crash Course on Ribboning
The official reference documentation of the ribbon() function reads:
ribbonclass:
temporal, synonyms:ribLoops the pattern inside an
offsetforcycles. If you think of the entire span of time in cycles as a ribbon, you can cut a single piece and loop it.
offset: number - start point of loop in cycles (0-based index)
cycles: number - loop length in cycles// Cut from the end of 1st cycle, then loop for 2 cycles // plays D -> E (total of 2 cycles) then repeats note("<C D E F>").ribbon(1, 2)
The first given example illustrates the function of ribbon():
Starts from the end of the 1st cycle, which is the note
DPlays for a total of 2 cycles
D → Ebefore repeating itself
Since it has played a total of 2 cycles, ribbon() will then repeat itself.
// Looping a portion of randomness n(irand(8).segment(4)).scale(”c:pentatonic”).ribbon(1337, 2)
The second example however, is much more interesting. Remember what I said about ribboning off a continuous randomized note sequence? Well this is it!
For those of you who have little experience with this technique, I will break it down further:
Use
irand()as an integer-based random number generator (RNG).irand(8)generates randomly an integer from 0 to 7Use
segment()to determine how many notes should be played in each cycle.segment(4)subdivides a cycle into 4 segmentsSince
irand()is a continuous generator with no fixed duration, using it withsegment(4)will yield exactly 4 randomized integers, e.g.“4 2 3 7”Then we apply
n()with ascale()to turn them into notes —
look up the official reference forscale()for detailed explanationBecome a master of composing melodic notes.
with algorithms, of course!
A Community Example
Someone from the livecoding community recently asked an interesting question:
I’m playing with ribbon but can’t figure out how to alternate between measures, ie “three sets of bars 4 and 5, then one set of bars 6 and 7”
So maybe we can write the ribbon function as:
rib("<4 4 4 6>", 2)But wait — if you play it back, you will notice that the first hap “4” do not wait until the set of 2 bars (cycles) before advancing to the next value, essentially ending up a sequence like so:
5 → 6 → 5 → 1
Moreover, it started playing from the 5th bar, not the 4th!
To fix this, we must understand how the ribbon function works. Here’s a clearer example to show what’s going on:
n(`<1 2 3 4 5 6 7>`).rib("<4 4 4 6>", 2).scale("C:major")There is two important caveats here:
rib()takes in a 0-index based cycle value as the first argument, so the4means the end of 4th cycle, or the start of 5th cycleThe second argument determines at most how long each ribboned loop should play, meaning if the first argument value changes, the loop will terminate early
In order to fix this, we must then:
Use the numbers
<3 3 3 5>instead so the ribboning can start at the 4th cycle 3 times before starting the ribbon at the 5th cycleSince we want each “set” of ribboning to last for exactly 2 cycles, we must then
slow()down the pattern such that each “hap” value advances to the next one once every 2 cycles.
n(`<1 2 3 4 5 6 7>`).rib("<3 3 3 5>".slow(2), 2).scale("C:major")Much better!
Now it plays “three sets of bars 4 and 5, then one set of bars 6 and 7”.
Of course if you are an expert mini-notationist (one who has extensive experience with live-coding), you may rewrite this as:
"<3 3 3 5>".slow(2)
// can be refactored into
"<3!3 5>/2"
// !3 means to repeat 3 times, /2 means to slow down by 2x, or play at half the tempoTranslating it into a Track
In live-coding, there is no use if you are only an expert in notational syntax.
You must be able to show you can make variations from your pattern, taking the listener on a melodic journey. That’s why EDM is progressive in nature.
A Note About What Constitutes “Live” Coding
Algorave shows will have livecoders writing very succinct pattern to produce elaborate melodic / chord progressions. While it is a nice skill to have, in my opinion this way of livecoding is an artistic choice rather than a requirement.
But for most people, this kind of improvisation requires a lot of practice, and possibly years of experience.
Writing and improvising succinct code on stage can be risky, so unless you have already memorized good patterns, or have rehearsed improv techniques, I would not recommend this approach in your first live show.
In fact, if you are like me who prefers painstakingly typing every single note on the editor (e.g. my first released track produced using only code), there is simply no shame in loading up your full song on stage and just play it live.
A livecoder did a presentation about this, and I encourage those who are just started in their livecoding journey to take a listen. I think we all can agree that commenting / uncommenting a prepared piece to mute / start patterns is an equally valid technique!
Definitionally, I am on the side that live-coding means your code runs live on stage (ie: not prerecorded), such that you are afforded complete freedom in how you want to express your musical code!
So the original person who posed the question about “how to ribbon” now has a good framework on how to generate melodic verses using the ribboning technique.
And so started making a track:
n(irand(14).seg(16)).rib("<4.25@3 6.5>/2",2).scale("d:minor")._pianoroll()I am impressed by the use of ribboning this way, especially segmenting off cycles <4.25@3 6.5> from a randomly-generated melodic sequence.
The numbers here were intentionally chosen for the most decent-sounding melodic progression — because when you play it back from start to finish, there is flow to it, even if not every note hits perfectly.
Especially when it is structured in an A A A B verse pattern like so:
I illustrated the above graphic to show how ribbon works in a nutshell —
Top row: original pattern generated with n(irand(14).seg(16)), a total of 8.25 cycle-length “ribbon” is shown
Bottom row: modified pattern from trimming the original and recomposed using .rib(“<4.25@3 6.5>/2”,2) - each ribboned set spans 2 cycles long.
. . .
The Spectrum of Algorithmic Composition
There are two ends of a spectrum in which a person can compose a track:
Compose with intent by carefully crafting each note by hand
Create songs algorithmically, by defining and controlling parameters to change how an algorithm should behave over time
(e.g. the amount of randomization, scales changes, the segmentation of generated notes, etc)
On one end you have manual composition — DAW, playing melody on a piano, or translating notes into a software fall under this category.
On the other end you have a more automatic composition — in traditional algoraves or in creating algorithmic visual art.
And I think to a certain degree, we need both. Which is why I like to work this way:
[More algorithmic] Use a programmatic approach to quickly sketch an outline of a song, for example using the
chord().voicing()function without having to think about individual notes.[Manual] Compose melody by hand, as such to have more control over the outcome of the melodic progression.
[Algorithmic] Use patterning techniques to apply alternate panning and velocity to “humanize” melodies, then apply filter automation.
[Manual] Arrange intro, verses, chorus and outro into a final track
My end result blends the best of both worlds: manually and automatically, by hand and algorithmically, which is why I believe livecoding can position itself quite distinctively in music production.
Note that A.I. generation methods are not mentioned here — A.I generated output is neither music nor art, as it is simply an uncreative way to produce, and therefore, irrelevant.
Patterning the pattern, Patterning the ribbon
Out of curiosity, I wanted to apply the “patterning the pattern” approach (see Language of Livecoding section) to this, essentially going one level higher in complexity.
Building off the original ribboned pattern,
rib("<4.25@3 6.5>/2",2)I’m going to explore making it into two 8-cycle verses, where the second verse is going to be slightly different than the first one, with the goal of making a progression track pattern like so:A A B C | A A D E
So after a bit of “fragging” (slang in livecoding to say, “I’m modifying your original code to make it sound the way I like it to sound” ), I came up with the following pattern:
rib("<4.25@2 <4.5 4> <6.5 1.5>>/2",2)Which can be translated into this sequence:
Verse 1: ribbon sets (each lasting 2 cycles) of
4.25th → 4.25th → 4.5th → 6.5th
Verse 2: ribbon sets (each lasting 2 cycles) of 4.25th → 4.25th → 4th → 1.5th
Since the 4.25th ribbon set already works, I find that nudging it slightly forwards or backwards will also likely to work. The 1.5th ribbon set was done by trial and error, which I find giving the most feeling of finality.
And here it is, the final “fragged” version:
About this post
This post would be the first of many written in my new publication, Flower of Livecode. I started this publication as a platform to express my ideas, in hopes that someone will learn something new, or to offer a new perspective in order to change minds.
If you like what I write, please consider subscribing (it’s free!) — you will receive previews whenever I post something new here.
Meanwhile, I promise that my next post won’t be this long! Further down the road I may also offer paid content such as courses.
I also plan to cover other topics like:
Cultural implications in the livecoding space
Personal experiences with livecoding communities
Technical deep dives on livecoding / music / math topics
Featuring diverse live coding artists
… and many more!





