Chuck: An Audio programming language - it's like a dream come true.
chuck.cs.princeton.edu
chuck.cs.princeton.edu
The only sad thing is that it's not really managed to make the leap to a community project. It's still mostly a Princeton Sound Lab / Ge Wang (previously there, now at Stanford) project and I'm uncertain, well, sadly, skeptical, that it will ever really fully mature. It's still got some rough edges and there's not been very little progress on it in the year and a half that I've been using it. The couple of times I've submitted patches they've been ignored.
I've written a bunch of useful boilerplate classes and a preprocessor for it to allow includes, if anyone's interested. (These have also been posted to the chuck-users list.)
Is it more than just sequencing samples or transforming input with code? Can it create samples? If so, is there any decent documentation on this for the beginner?
http://chuck.cs.princeton.edu/doc/learn/tutorial.html
These days synthesizers, samplers and whatnot are naturally just software. If you want to have fine-grained control of how synthesis, sampling or other sound manipulation is done, it's often useful to have a programming environment specifically made for that. The competitors that I mentioned to ChucK in my last comment are the best known environments for such.
I personally use ChucK mostly to process MIDI instructions and reroute them to a separate synthesizer or to send control signals to a sequencer. For instance, in one case I wanted to play a pattern of notes at an increasing tempo stretched to the track's tempo using a specific function of time so that the notes would be in synch / out of synch with the original in a predictable pattern. Doing that was reasonably easy to hook up with ChucK.
http://developer.kde.org/~wheeler/images/polysynth-jmax.png
And the same in ChucK:
http://developer.kde.org/~wheeler/files/polysynth.ck
There are other more concrete examples mentioned in some of my posts here. (Didn't post the article, but I've been one of the more active people on the ChucK mailing list for a long while now, so it was a surprise to see it turn up here.)
I'm terribly unproductive with music, and this is just one more way of procrastination :). Very cool, though. I can see why writing programs for a standard language makes sense.
Imagine that you want to write some music that can be reproduced anywhere with any hardware. Kind of like sheet music for orchestral works. This may be the only way. Right now, we have problems to reproduce analog synthesizers from the 50's-70's. For example, Bernard Hermann 'It's alive II" soundtrack has a great synth lead (together with an orchestral arrangement). If some orchestra wanted to play that work live in say 100 years, good luck finding a working synth to reproduce that sound exactly. Of course, software replicates anything, but it may never be the same thing. On the other hand, a violin is the same as a violin 100 years ago (I hope).
Things like Chuck fix this problem. You can write electronic music that is 100% reproductible 100 years from now.
Right from the tutorial:
// connect sine oscillator to D/A convertor (sound card)
SinOsc s => dac;
// allow 2 seconds to pass
2::second => now;
Why not something like: SineOscillator connectTo: digitalToAnalogConverter.
2 seconds wait.
Why do programmers continue to create cryptic-looking languages? Saving a few characters doesn't buy you anything except confusion.Like look at the functions: http://chuck.cs.princeton.edu/doc/language/func.html
Why should a sound/audio engineer be concerned with the return type of a function? Have one simple rule: every function returns something. Static typing makes sense for optimization but I would expect at least some minimal level of inference.
Yet another language designed for creative work that's hindered by the illogical mind of a programmer.
And another example for your earlier point:
// print out the shred id <<< me.id(); >>>;
In ChucK you have different "shreds" (threads) where you advance time explicitly by doing something like:
1::second => now;
That makes the flow of time between different elements very clear and in theory (though not always in practice) it's sample accurate between different shreds. Durations are an ordinal type in ChucK, so you can also do something like: 1::minute / beatsPerMinute => dur beatLength;
And then do: for(0 => int i; i < 4; i++)
{
spork ~ snare();
beatLength => now;
}
Where "snare()" is a function that plays a snare drum sample and "spork ~" spawns a new shred to play that sample (where time is advanced independantly).