Creating Fractal Music — In Very Few Lines of Code

[The following is a reprint from part of The Complete Guide to JFugue (Second Edition), Section 7.1]

The Hungarian theoretical botanist Aristid Lindenmayer originally developed Lindenmayer systems, or L-systems, to formally describe the development of types of algae; this was later used to represent plants and fractals. An L-system is a grammar rewrite system, which means it consists of a set of rules for replacing one character in a string with a sequence of other characters. For example, if I give you a string, like “A”, and tell you to change every “A” to “B”, and every “B” to “AB”, you’ll wind up with the following sequence of strings:

Initial string     A
Iteration 1 B
Iteration 2 AB
Iteration 3 BAB
Iteration 4 ABBAB
Iteration 5 BABABBAB
Iteration 6 ABBABBABABBAB
Iteration 7 BABABBABABBABBABABBAB
…and so on

If you then take the resulting string and convert the characters to some actionable result—for example, drawing a picture using A and B as commands for moving a pen on a drawing surface—you may get an interesting result. You can see some cool results on the Wikipedia page for L-system, and some especially beautiful results are presented in the book, “The Algorithmic Beauty of Plants” by Przemyslaw Prusinkiewicz and Aristid Lindenmayer. This book is now available for free on the site.

What does this have to do with music? L-systems exhibit self-similarity (which is why L-system fractals are interesting), and music itself is often self-similar. And instead of transforming characters, we can actually transform Staccato tokens! Of course, we also know that we can play Staccato tokens, so we have our actionable result. Here’s an example; you can follow along with the code below by finding LSystemMusic.java in the demo section of the JFugue library.

First, let’s create a set of transform rules. When the preprocessor sees the key, it will replace it with the value. Notice that the values contain things that will be recognized as keys during the next iteration.

// Specify the transformation rules for this Lindenmayer system
// (Note: Since writing this code sample, I have learned that the
// "double-brace initialization" for a map in Java is not efficient.
// Nevertheless, it will work here.
Map<String, String> rules = new HashMap<String, String>() {{
put("Cmajw", "Cmajw Fmajw");
put("Fmajw", "Rw Bbmajw");
put("Bbmajw", "Rw Fmajw");
put("C5q", "C5q G5q E6q C6q");
put("E6q", "G6q D6q F6i C6i D6q");
put("G6i+D6i", "Rq Rq G6i+D6i G6i+D6i Rq");
}};

Next, we will set up the ReplacementMapPreprocessor, including setting the number of iterations to three and eliminating the need forangle brackets around the keys—and we will also provide the replacement map.

// Set up the ReplacementMapPreprocessor to iterate 3 times
// and not require brackets around replacements
ReplacementMapPreprocessor rmp =
ReplacementMapPreprocessor.getInstance();
rmp.setReplacementMap(rules);
rmp.setIterations(3);
rmp.setRequireAngleBrackets(false);

Now we just have to create the “axiom” – the initial string that will be transformed. We will put this into a Pattern.

// Create a Pattern that contains the L-System axiom
Pattern axiom = new Pattern("T120 " + "V0 I[Flute] Rq C5q "
+ "V1 I[Tubular_Bells] Rq Rq Rq G6i+D6i "
+ "V2 I[Piano] Cmajw E6q "
+ "V3 I[Warm] E6q G6i+D6i "
+ "V4 I[Voice] C5q E6q");

And now to play the result!

Player player = new Player();
player.play(axiom);

The music you are listening to now is a piece called “Kebu”, which I originally created in 2007 and which I describe in detail on my website in an article describing a small portion of my work in algorithmic music.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.