//----------------------------| // Jeff Smith, Music 220a // HW #2, Oct 12, 2007 // composition, adapted from Perry & Ge (and other's): // dinky module // Moog module (yummy) // various sample code // // structure: // - a sound file (taken from performance of Handel's Messiah) is run // backwards, while the slice of time between 'samples' is constantly reduced // - concurrently, and in non-random slices, the Dinky instrument is given a // pitch to play // - i use the Echo and NRev unit generators to create a nice reverb // - concurrently, and synchronous with the above loop, the Mooger is sporked // - eventually, we either run out of samples in the messiah, or (more likely) // we've reduced the slice of time between samples to zero // - if any more samples remain, they are played, and the volume is reduced // providing a diminuendo of sorts, with the Mooger getting softer faster // // the result is rhythmic because the rate of reduction of time slices // is everything is sync-ed, and time constantly marches forward by 'the_beat', // although you have some nice rhythms between mooger, dinky, and the vibrato voice // // note that i would prefer to not-sync the mooger rhythm with dinky & the voice, to // create some nice poly-rhythms. however, i wanted to be a good student... //--------------------------------------| // the Dinky class class Dinky { // impulse to filter to dac Impulse i => BiQuad f => Envelope e; // set the filter's pole radius .99 => f.prad; // set equal gain zeros 1 => f.eqzs; // set filter gain .2 => f.gain; // set the envelope .004::second => e.duration; public void radius( float rad ) { rad => f.prad; } public void gain( float g ) { g => i.gain; } public void connect( UGen ugen ) { e => ugen; } // t is for trigger public void t( float freq ) { // set the current sample/impulse 1.0 => i.next; // set filter resonant frequency freq => f.pfreq; // open the envelope e.keyOn(); } // t is for trigger (using MIDI notes) public void t( int note ) { t( Std.mtof( note ) ); } // another lazy name: c (for close) public void c() { e.keyOff(); } } Dinky imp; // here is our 'period' or beat 210 => int the_beat; class the_mooger { Moog mog => dac; 0 => int moog_cur_beat; 6 => int mooger_period; // poly-rhythm (play with this ratio if you like) // the_beat * 4 / 3 => int the_mooger_beat; // non-poly-rhythm the_beat => int the_mooger_beat; 0.0 => float mog_time; 0.10 => float vel_min; 0.30 => float vel_max; public void varmod() { while ( true ) { 0.5 + 0.4 * Math.sin ( mog_time * 0.1 ) => mog.modDepth; 0.5 + 0.4 * Math.sin ( mog_time * 0.2 ) => mog.modSpeed; 0.5 + 0.4 * Math.sin ( mog_time * 0.3 ) => mog.filterQ; 0.5 + 0.4 * Math.sin ( mog_time * 0.4 ) => mog.filterSweepRate; 10::ms => now; mog_time + 0.01 => mog_time; } } public void atouch( float imp) { imp => float atouch; while ( atouch >= 0.0 ) { atouch => mog.afterTouch; atouch - 0.05 => atouch; 10::ms => now; } } public void go_mooging_sir() { // spork varmod shred spork ~varmod(); while ( true ) { 278.43 => mog.freq; Std.rand2f(vel_min, vel_max) => float vel; vel => mog.noteOn; spork ~ atouch(vel); ((moog_cur_beat % mooger_period) * the_mooger_beat)::ms => now; ++moog_cur_beat; } } } // introducing mr_moog the_mooger mr_moog; // construct the patch SndBuf buf1 => Gain g => NRev r => Echo e => dac; // a section of Handel's Messiah: "I Know" from I know my redeemer lives "data/myredeemer.wav" => buf1.read; .25 => g.gain; .15 => r.mix; e => dac; 1500::ms => e.max => e.delay; .5 => e.gain; .8 => buf1.gain; // connect the Dinky // (in a future version of chuck, Dinky can be defined as an UGen) imp.connect( g ); // set the radius (should never be more than 1) imp.radius( .999 ); //<<< "\n", buf1.samples() >>>; // base_sample_rate must be greater than 10 200 => int base_sample_rate; // an array (our scale) [ 0, 2, 4, 7, 9, 10 ] @=> int hi[]; // main function -- this loop plays the buf file backwards at chunks of // cur_sample_rate, reducing the amount of time between playbacks in the // process; Dinky will be struck intermittently in the loop fun void buf_plus_dinky() { buf1.samples() => int i; while (i > 0 ) { false => int imped; i => buf1.pos; if( (i % 3) == 1 ) { 45 + Std.rand2(0,3) * 12 + hi[Std.rand2(0,hi.cap()-1)] => imp.t; true => imped; } (the_beat - 10)::ms => now; if (imped) { imp.c(); false => imped; } 10::ms => now; // constant 'vibrato' -- move backward base_sample_rate to next sample i - base_sample_rate => i; } } // main() // launch the mooger! spork ~mr_moog.go_mooging_sir(); // invoke our main loop buf_plus_dinky(); // a couple more twangs of the mooger please; buffer play from start (finally) 0.6 => mr_moog.mog.gain; 0.3 => buf1.gain; 0 => buf1.pos; (base_sample_rate * 2)::ms => e.max => e.delay; 3::second => now; // shut down mooger & buffer & echo 0.0 => mr_moog.mog.gain; 0.0 => buf1.gain; 0.0 => e.gain; 1::second => now;