Monday, January 21, 2008

myTunes: Groovy and JFugue

I write this from CtJ HQ, waiting on a heat repair. The experience has been rather infuriating. I am tempted to write a personal rant or make a comic , but instead I thought I would make some music with JFugue and Groovy. As I've blogged before, it is completely addictive.

The Setup

My friend and colleague (we need a new term for that), Lance Finney, has written a comprehensive article over at the OCI Java News Brief.

For a blog post, we don't have to be as formal with respect to background, examples, or setup. Let's jump in. Here's the setup:


The following examples are trivial both from a coding standpoint and musical arrangement. The point is two-fold: (a) Groovy makes everything easier and (b) playing with music is fun. As I've mentioned, this might be a great way to introduce kids to computing.

Eg. 1 Crazy Train

The first example is minimal. This is the main hook to Crazy Train, which sounds rather eerie on the default instrument of piano. (As a musical aside, it is interesting that this hook uses each note in the F# natural minor scale -- quite rare for blues-based rock of that era.)

import org.jfugue.Player

new Player().play("""
F# F# C#6 F#
D6 F# C#6 F#
B A Ab A
B A Ab E

Eg. 2 Ode to Joy

With Groovy's G-Strings, there is a temptation to pick Bach's Air on a G-String. However, this obligation is trumped by choosing part of the extraordinary melody from which this blog's theme is derived. (Check out this tribute by Leonard Bernstein).

(Note: G-Strings are used in the next example. This one has hard-coded rhythm notation.)

import org.jfugue.Player

// q = quarter note, i = eighth note
// the "." acts like the dot in music notation

new Player().play("""
Eq. Di D
Dq. Ci Cw

Note that I[60] sets the instrument as French Horn. Here is a list of MIDI instruments.

Eg. 3 Waiting for the Repairman Blues

Not that it compares in any way, but here is a little bluesy hook that I wrote on guitar some years back. Thanks again to Groovy's G-strings, we can set the rhythm as a relative variable: this allows one to tweak rhythm settings across an entire piece. (It's easy to see that a DSL in Groovy would be good fit for this subject).

import org.jfugue.Player

// q = quarternote, i = eighth, s = sixteenth
// doo, be, bop are relative: easier to read and tweak

def doo = "q"
def be = "i"
def bop = "s"
def hum = "w"

def phrase1 =
"D${doo} E${doo} D${be} E${be} C#${doo} A${doo} R"

new Player().play("""
C${doo} F#${doo} C${be} F#${be} B4${doo} G${doo} R
C${bop}+F#${doo} C#${bop}+G${doo}
C${bop}+F#${doo} C#${bop}+G${doo}
For this example, the instrument is an Orchestra Hit. This has a dual effect: (a) possibly introducing you to a commonly used MIDI sound and (b) distracting you from the rhythm problems in the 3rd bar. (It should be played more fluidly. This is left as an exercise for the listener.)


Try it out... Tinkering in this way is both easy and enchanting. It isn't hard to imagine a custom Ant task that plays homegrown tunes based on the success or failure of a build.


Guillaume Laforge said...

Perhaps you could even remove the curly braces in the last example? They are not mandatory in GStrings if they just refer to some identifiers. So "C$doo" works, and is perhaps nicer on the ey than "C${doo}"?

Regarding the bottom line: a couple years ago, I played with the idea of an Ant build listener that played JFugue little tunes when certain targets were started and finished, to have an audible indication of what was going on. Pretty funny :-)

Michael Easter said...

Thanks for the note, Guillaume...

re: curly braces. I didn't know that they could be removed: that's cool. I tried it, but in my editor the syntax colouring actually looks better with them in there. A rare case where it might be easier to read with more (versus less).

re: Ant build. I hadn't considered a linear progression of targets... Excellent.

Also, it might be 'interesting' to use mod arithmetic to collapse text into basic notes. e.g. H = A, I = B, etc. In that way, if the build failed, we could play the error message! I wonder what a stack trace sounds like ;-)