Sure. I’ll do my best to give a high-level explanation of what I’m trying to do, though you’ll have to forgive me – experience tells me that when I’m tied close in to the details of a project, I do a bad job of communicating to folks outside the project. Please tell me which places I’m not making sense or motivating my technical choices!
I’m dabbling with algorithmic composition; eventually I’d like to reach a point where I can just hit “go” and have some randomly shifting chiptunes playing in the background while I stream on twitch.
In the first versions of this, I did the composition on the fly; my
live_loop invented one musical phrase at a time, played it all the way through, then began again. But more and more I found that the modifications I wanted to make were inter-phrasal. The very simple motivating example I’m using in the current refactoring that introduced class usage is to tie together the bassline notes from one phrase to the next, if one phrase’s bass note happens to be the same as the next phrase’s starting note. (N.B. this may mean planning several phrases ahead if some phrase has just one bass note!) I’d love to get into more complicated inter-phrasal planning eventually, though; e.g. planning when to replay an old motif with a slight variation, when and how to do key changes, and the like, that may require looking arbitrarily far in the past (or future, depending on how you look at it).
So the approach I tried is to do some high-level planning first (before entering the
live_loop), then have the
live_loop “just” play the music made by the plan. Since I want it to go indefinitely, for me this meant building a lazy, infinite plan object – that is, one which initially had just a small part of the plan, but which could be expanded on the fly as needed. You can see how this manifests as code in this branch, which uses Ruby’s
Enumerator and a memoized version that allows multiple consumers to iterate over it of my own devising called
Of course it doesn’t work at all, even after avoiding the syntactic pitfall described earlier in the thread… I’m still thinking about what alternate approach to take to deal with that. (Try the master branch if you want to see something that does work and does almost the same thing, minus tying together consecutive equal bass notes.) Suggestions welcome. =)