Friday, November 20, 2009

A "timbre stretching" example in ChucK

As many of us, professional or hobbyist computer music aficionados, I adore Miller Puckette's freely available book on this science, "The Theory and Technique of Electronic Music". If you are more into the material, you may have noticed that the examples in this book are written (more accurately: "drawn") in Pd, or Pure Data, which is a graphical computer music synthesis environment.

I wanted to try the same concepts in my favourite music language, ChucK, which lead me to the conclusion that it's quite different to create the same concepts in these two environments.

So here's my take on "timbre stretching", which is an interesting approach to radically change a waveform without the use of filters or frequency modulation, whatever.

// "timbre stretching" in a ChucKist way
// by Hillaby

// the sinosc can be replaced by any waveform generator
// in this sample it's only used for one period
SinOsc osc => LiSa lisa => dac;

// modulator will modulate duty cycle
SinOsc modulator => blackhole;

/* in case you want to record it...
lisa => WvOut rec => blackhole;
"lisa.wav" => rec.wavFilename;

// play around with these settings:
100.0 => float fr; // the base frequency
1.3 => modulator.freq; // modulator frequency (keep it low :))
5.0 => float modRate; // modulation rate, the minimum duty cycle will be 1 / (1+2*modRate), maximum: 1

// calculate period and set wave generator frequency
1::second / fr => dur period;
fr => osc.freq;

// record one period and unchuck wave generator
period => lisa.duration;
1 => lisa.record;
lisa.duration() => now;
0 => lisa.record;
osc =< lisa;

// play back recorded period
while (1) {
0::samp => lisa.playPos; // start at 0
1 =>;

// set rate, 1.0 when duty cycle is maximum
// and 1.0+modrate*2.0 when minimum
1.0 + modRate*(1.0+modulator.last()) => lisa.rate;

// wait until playback terminates (at specified rate)
lisa.duration()/lisa.rate() => now;
0 =>;

// wait until the "empty part" of the duty cycle passes
period - lisa.duration()/lisa.rate() => now;

No comments:

Post a Comment