By utilizing a Python list as a stack, it is possible to move the stylus to a specific time in the score, schedule events relative to the stylus, and then pop it back into its previous position. This is inspired by Processing functions pushMatrix() and popMatrix().
I’ll explain what I’m talking about through example. The following is an excerpt from the pushpop.py example in the Slipmat github repo:
# Measure 1 s.event(0, 0.25, Sine(1, cpspch(7.00))) s.event(1, 0.25, Sine(1, cpspch(7.03))) s.event(2, 0.25, Sine(1, cpspch(7.07))) s.event(3, 0.25, Sine(1, cpspch(7.10))) # Measure 2 s.time.append(4) s.event(0, 0.25, Sine(1, cpspch(8.00))) s.event(1, 0.25, Sine(1, cpspch(8.03))) s.event(2, 0.25, Sine(1, cpspch(8.07))) s.event(3, 0.25, Sine(1, cpspch(8.10))) s.time.pop()
In measure 1, four Sine() events are created at times 0, 1, 2 and 3, specified in the first parameter of s.event().
In measure 2, before any calls to s.event() are made, the value 4 is append to a list object called “time,” part of class ScoreEvents. Until “time” is popped or appended, the value 4 is added to every start time in method event(). Measure 2 generates 4 events, created at times 4, 5, 6 and 7.
If these two measures were explicitly written, it would look like this:
s.event(0, 0.25, Sine(1, cpspch(7.00))) s.event(1, 0.25, Sine(1, cpspch(7.03))) s.event(2, 0.25, Sine(1, cpspch(7.07))) s.event(3, 0.25, Sine(1, cpspch(7.10))) s.event(4, 0.25, Sine(1, cpspch(8.00))) s.event(5, 0.25, Sine(1, cpspch(8.03))) s.event(6, 0.25, Sine(1, cpspch(8.07))) s.event(7, 0.25, Sine(1, cpspch(8.10)))
The current position of the stylus is the combined sum of all values stored in list “time.” For example:
s.time.append(16) s.time.append(30) s.time.append(11) s.event(7, 1, foo()) s.time.pop() s.event(2, 1, bar())
The foo() event is scheduled at beat 64. That’s (16 + 30 + 11) for “time” plus an additional 7 for the first parameter of event(). After “time” is popped, bar() plays at beat 48; (16 + 30) for “time” plus 2 for the relative start of the event.
For the record, I think the s.event() code is a bit ugly, which I’m already addressing behind the scenes. If you’ve been keeping up with this blog, you might already have a good idea as to where I’m going with this.