A Max-based sequencer for branching Lindenmayer System strings.
This project is a Max Package that provides three Max abstractions for working with branching Lindenmayer Systems (L-systems). The core abstraction, the
[lsq.sequencer] object, is a high-level, symbolic sequencer. You can define L-system production rules and process lists of symbols through the rules in the standard manner of L-system string rewriting.
However, the primary use case for this sequencer is not its simple string rewriting as this has been done before and in much more detailed and better implementations. …what this book presupposes, is maybe he didn’t… uhhh, I mean, the focus of the package is on interpreting L-system strings with branching symbols so that a sequence can branch into simultaneous events in a manner similar to a polyphonic sequencer. Consider the following L-system string of characters:
+ + F Y X [ F + Y ] - F [ X ] [ - Y + F ]
The symbol pairs
] have special meaning within the l-sequencer package. The first set are “metadata” symbols that can be paired with sequencer events (see the Max documentation for more details). The second set are the branching symbols. Branches cause new sub-sequences of events to start occurring simultaneous to the events from which they are offshoots. As noted above, the simplest way to think about this would be polyphony: if the symbols represent notes, when a branch happens, simultaneous notes will play as a chord.
The 1-dimensional string above (that is, a simple array-like sequence of characters) would be represented in a 2-dimensional matrix in the sequencer as:
1 2 3 4 5 ++F Y X -F F +Y X -Y +F
The numbers are not part of the representation, they are just step indices in the sequencer and are added to aid in explanation. Because the first branching character “[” happens after the first “X” event character, the next event character in the string, an “F”, happens at the same time as its preceding event. Therefore both the “X” and “F” events occur on step 3 in the sequencer. The symbols started in a branch will stay in the same matrix row until the branch terminates with the “]” character.
I refer to this as a symbolic sequencer because it deals in symbols only. The meaning and interpretation of any symbols is left entirely to you, the composer. The symbols could represent low-level data points like MIDI note numbers, but they could also be used as events that fire off a subsequent complex process.
Internally, the sequencer uses a Jitter matrix for data storage and access. It is not an efficient use of the matrix and a lot of cells in the matrix will go unused (because managing branches is hard, yo). If you
advance a given L-system past a certain point, it will very likely begin to produce strings that exceed the number of events the matrix might store.
The package contains no externals and is built entirely from core Max objects, so hopefully there are no problems with installation. In this way, I hope that it can also serve as a useful reference implementation for others to tear apart and improve for their own needs. But doing this entirely in Max objects is also, shall we say, Super Finicky Event Circuitry™. I would not be surprised if there are bugs and if some of the bugs be dragons.
This sequencer is functional for me, but I have not pushed it particularly hard in terms of seeing where it hits any limits. You can configure the
@steps count and the
@maxbranches (matrix row count) attributes, but at this point I don’t have any idea if or when it would fall over under the strain of trying to process too many simultaneous events. Feel free to report back here if you notice this happening, a la, share the knowledge!
Aside from the README, documentation is done entirely within Max itself. The three objects in the package
[lsq.translator] have help files and reference pages so you should be able to see within Max how they work and the kinds of messages they accept. The screenshot above is one such help patcher.
I have also created a Max “vignette” that should show up if you use the Max search feature and search for “l-sequencer”.
Finally, in the package’s
extras directory/folder you will find a simple Max patcher that illustrates the sequencer’s use. It uses the default rules that the system loads by default and plays 3 notes that are transformed by walking through the circle of 5ths depending on the metadata symbols associated with a given step. It is a very rudimentary version of one of the branching L-system musical applications in R. Luke DuBois’ dissertation.
I am my own primary reader of the docs (“Your worst collaborator is you from six months ago and that person doesn’t respond to email…”), so please let me know if something is unclear.
v0.1.0 - Download or
git clone the repository into your Max Packages folder. For me, on a Mac, this means I have the files saved in the following location:
Note that if you download the zip it may append the version or branch name, so you may want to make sure it is not named “l-sequencer-main” or something similar.
This package is inspired by R. Luke DuBois’ dissertation, which I learned about through the generous knowledge sharing that happens here (see the Generative systems thread). Please kick the tires on this weird little bundle of patchers. I hope it might inspire someone. And of course, let me know if anything is unclear.