Saturday, February 23, 2008

Archaeopteryx: A Ruby MIDI Generator

If you've been following my tweets, my tumblelog, my RubyForge projects, and my conference schedule, in minute, up-to-the-minute detail, you already know about this, but for the overwhelming majority of humans on Earth, this qualifies as news, so:

I've been building a Ruby MIDI generator called Archaeopteryx. It builds on code from Practical Ruby Projects to create a system for auto-generating, self-modifying music.

Earlier screencasts, 5 and 11MB in size:

Aleatoric Hip-Hop
Dynamic Techno

Screencast developed this morning:



The Vimeo conversion destroyed some of the low end of the audio, so it sounds a bit better in real life, but hey, Vimeo's got HD, it looks great in full-screen mode, they support artists much better and more enthusiastically than YouTube, and it's free.

Anyway. Couple interesting lessons from a programming standpoint.

First, the Pragmatic thing that you should learn a new language every year - maybe. But you should also learn new paradigms and new problem spaces. I'm getting a lot out of this, and I think learning the differences between Python and Ruby is at most equivalent in brain-stretchy to learning the differences between Web programming and algorithmic composition. Second, although I think the Lispers over-rate their language, I think there must be some truth to Paul Graham's remarks about Lisp being well-suited to exploring unfamiliar problem domains, because I found exploring in a lambda-oriented/list-oriented way much quicker and cleaner than exploring in an object-oriented way. I've posted before about learning some other stuff too.

You can grab the code if you wanna:

svn checkout http://archaeopteryx.rubyforge.org/svn/

Expect more to come from this thing, but so far, so good.

Update: For some reason my commentary on my own code is wrong. probabilities is the probability matrix; the things I point to and call probability matrices (for some idiotic reason) are actually just lists. In fact really it's just a probability hash, but what's going on there actually is an implicit matrix, because the indices are used to map the lambdas to specific beats, which is why I used each_with_index instead of the more generally preferable inject.