In Roll You Own Syntax, I theorized how users could construct their own systems of notation using strings. I’ve constructed a working function, called trig(), to show how it’s done.
First, let’s see trig() in action. The following is complete conceptual prototype Slipmat program that generates a rock drum groove with 8th note hats:
#!/usr/bin/env slipmat from JakeLib.Generators import trig from EasyKit import hat, snare, kick @trig('x.x. x.x. x.x. x.x.') hat() @trig('.... x... .... x...') snare() @trig('x... .... x... ....') kick()
This horizontal system for notating triggers, and others like it, can greatly improve the legibility of a piece, while catering to a composer’s preferred style of working. A composer quickly scans this and comprehends it without having to reconstruct it in their head from a list of individual events:
@0 hat() @0 kick() @0.5 hat() @1 hat() @1 snare() @1.5 hat() @2 hat() @2 kick() @2.5 hat() @3 hat() @3 snare() @3.5 hat()
The form is lost in translation.
Building the function is pretty straight forward if you’re somewhat experienced with Python. I put together the following function definition, with docstrings, in roughly 15 minutes:
def trig(seq, res=0.25): ''' Creates a numeric sequence from a string and returns a list. Description: A string trigger sequencer, where an 'x' creates a trigger, and a '.' creates a rest. All other glyphs are ignored. The resolution of triggers and rests are determined by the argument res. Input: seq -- A string containing a sequence of 'x' triggers and '.' rests res -- Resolution of note triggers and rests Output: return -- A numeric list ''' L = [] # The return list p = 0 # Position in sequence for c in seq: if c == 'x': L.append(p * res) p += 1 elif c == '.': p += 1 return L
The trig() function accepts a string formatted in what I call ‘x trigger notation.’ The function parses the string and auto-generates a list of numbers representing trigger times. A trigger is denoted by an ‘x’, while a rest is a ‘.’. All other glyphs are ignored. I use a single space between beats for clarity. The default resolution is a 16th note, though trig() accepts an optional argument for changing the resolution, increasing its usefulness.
Import, Reuse, Remix
The best part about custom functions is that they can be reused multiple times in multiple programs by multiple people with the use of the import. No refactoring of code, no copy and paste, no reinventing of the wheel. Just import, reuse, remix.