ChucK

pemungkah on 2004-10-19T16:31:27

I've started playing around with ChucK, a new language for music composition and performance.

ChucK has a lot of the things I've always wanted in a music language: it does not require you to link up little boxes to write programs; it does not require you to effectively program in a horrible assembly language because that was good enough in 1968; it does not require you to jump though hoops to figure out how to get multiple intependent processes working.

It primarily uses a single operator, => (known as "chuck"), which does all of the heavy lifting re datatype conversions, etc. Here's an example. Let's say you were going to pass a white noise source through an ADSR (attack-decay-sustain-release), filter it, and then output it through a digital-to-audio converter, all under MIDI control.

In C-like, code this would look something like

/* Advance the time */
dacOut.tick(biQuad.tick(adsr.tick() * noise.tick()));
if( timeCount % 44 == 0 ) {
   /* Time to look for a MIDI message */
    if( midi.nextMessage() == __SK_NoteOn_ ) {
        /* Byte 3 non-zero: note-on, zero: note off */
        (midi.getByteThree() ? adsr.noteOn() : adsr.noteOff());
        /* Set the filter from the velocity */
        biQuad.setFreq( MD2Freq(midi.getByteTwo()) );
    }
}
In csound, you'd decide it wasn't worth the trouble. In ChucK, this is simply
noise3 => ADSR => biquad1 => dac;
midi => (ADSR, biquad1);
No messing with what byte does what in the MIDI message, no having to run the idle timing loop. It just works. The ChucK operator takes care of all the conversion and the individual units use whatever they can.

In the spirit of reasonable languages (like Perl), ChucK lets you decide waht you want to deal with. Durations and time are native datatypes: units run from samp (the length of a single sample, or 1/44K second) to week. Artihmetic is supported:
3:second + 100:ms => dur quarter;
This defines the duration of a quarter-note as 3.1 seconds. Time is dealt with by chucking a new duration into now; you can also (as shown above) allow external events, like incoming MIDI messages, to advance time for you.

These two aspects, dealing with time and setting up flows of data, are the things that are most problematic for me in trying to use so-called "music languages".

ChucK also has a built-in concurrency model called shreds which is possibly of interest to other programming languages. Shreds are unlike threads in that threads are not deterministic and have no timing guarantees; shreds are guaranteed to be deterministic and allow synchronization down to the sample.

Shreds work because the advancement of time happens when the program says time advances. This means that the ChucK core can always know when a shred is supposed to do whatever it is planning on doing and schedule it deterministically.

As if this wasn't all cool enough, the Chuck core can add and delete shreds dynamically; so you can do something like this:
bash $ sudo nice -20 chuck --loop
bash $ chuck + kick.ck
[chuck](VM): sporking incoming shred: 1 (kick.ck)...
bash $ chuck + hihat.ck
[chuck](VM): sporking incoming shred: 2 (hihat.ck)...
... (add a pile more shreds)
bash $ chuck - 1
[chuck](VM): removing shred: 1 (kick.ck)...
bash $
You can start and kill shreds at will; If they're all advancing time at the same rate, the beat lines up and it sounds ... pretty cool. Chuck calls this "on-the-fly" programming; very similar to the Hacking Perl in Nightclubs folks. It might be very interesting to try writing some Perl code that emitted ChucK code instead of MIDI directly. Heck, it sould even system the shreds randomly, letting the shreduler handle the synchronization.

Anyway, it's way cool. I have a little free-running ChucK program which simulates a Fender Rhodes noodling away in the background as I type this; it even runs nicely on my Powerbook G4 with a fair bit of other stuff going on.


Chuck...I like it

runrig on 2004-10-20T05:45:30

It primarily uses a single operator, => (known as "chuck")

I realize it serves an entirely different purpose than in perl, but I like "chuck" alot better than "fat comma" (or even "arrow" which gets confused with "->"). I say let's start a movement to call it "chuck" in perl also. As long as we don't call it "Chucky" :-)