/* Chant.ck by Perry R. Cook 2006 modified by Rebecca Fiebrink and Ge Wang 2007 demonstrating multi-shredding, variable rates */ // patch Impulse i => TwoZero t => TwoZero t2 => OnePole p; // formant filters p => TwoPole f1 => Gain g; p => TwoPole f2 => g; p => TwoPole f3 => g; // verbs g => JCRev r => dac; g => JCRev rL => dac.left; g => JCRev rR => dac.right; // delays g => Delay d1 => Gain g1 => r; g => Delay d2 => Gain g2 => rL; g => Delay d3 => Gain g3 => rR; // feedback g1 => d1; g2 => d2; g3 => d3; // gain 0.25 => float masterGain; // filter parameters 1.0 => t.b0; 0.0 => t.b1; -1.0 => t.b2; 1.0 => t2.b0; 0.0 => t2.b1; 1.0 => t2.b2; // gains 0.1 => g1.gain; 0.1 => g2.gain; 0.1 => g3.gain; // reverb mix 0.025 => r.mix; // delay 1.5 :: second => d1.max; 2.0 :: second => d2.max; 2.8 :: second => d3.max; 1.41459 :: second => d1.delay; 1.97511 :: second => d2.delay; 2.71793 :: second => d3.delay; // filter radii and gain 0.997 => f1.radius; 0.997 => f2.radius; 0.997 => f3.radius; 1.0 => f1.gain; 0.8 => f2.gain; 0.6 => f3.gain; // initial formant frequencies Std.rand2f( 230.0, 660.0 ) => f1.freq; Std.rand2f( 800.0, 2300.0 ) => f2.freq; Std.rand2f( 1700.0, 3000.0 ) => f3.freq; // variables to store current and target freqs 400.0 => float f1freq; 1000.0 => float f2freq; 2800.0 => float f3freq; 400.0 => float target_f1freq; 1000.0 => float target_f2freq; 2800.0 => float target_f3freq; // leaky integrate 0.99 => p.pole; 1.0 => p.gain; // control voice source pulses 0.013 => float period; 0.013 => float target_period; 0.0 => float modphase; // scale [0, 1, 5, 7, 8, 11, 8, 7, 11, 12, 14, 15, 19, 17, 20, 24] @=> int scale[]; // names ["ut0", "ra0", "fa0", "ut0", "ra0", "mi0", "ra1", "ut1", "mi0", "ut1", "re1", "mi1", "ut1", "fa1", "re1", "ut2"] @=> string names[]; // current location in scale 9 => int scalepoint; // the other two shreds! spork ~ ramp_stuff(); // interpolate pitch and formants spork ~ do_impulse(); // voice source int dir; float freq; float temp; // main shred while( true ) { // determine new formant targets Std.rand2f( 230.0, 660.0 ) => target_f1freq; Std.rand2f( 800.0, 2300.0 ) => target_f2freq; Std.rand2f( 1700.0, 3000.0 ) => target_f3freq; // next pitch Std.rand2(-1,1) + scalepoint => scalepoint; if( scalepoint < 0 ) 0 => scalepoint; if( scalepoint > 15 ) 15 => scalepoint; 55.0 * Math.pow(1.059, scale[scalepoint]) => freq; <<< names[scalepoint], freq >>>; // corresponding target period 1.0 / freq => target_period; // wait until next note Std.rand2f( 0.2, 0.9 )::second => now; } // shred for source pulse fun void do_impulse() { // go! while( true ) { // fire impulse masterGain => i.next; modphase + period => modphase; // wait until next, modulation applied -> vibrato (period + 0.0001 * Math.sin(6.28*modphase*6.0))::second => now; } } // interpolation shred fun void ramp_stuff() { 0.10 => float slew; // go towards targets while( true ) { (target_period - period) * slew + period => period; (target_f1freq - f1freq) * slew + f1freq => f1freq => f1.freq; (target_f2freq - f2freq) * slew + f2freq => f2freq => f2.freq; (target_f3freq - f3freq) * slew + f3freq => f3freq => f3.freq; // choose appropriate rate 0.010::second => now; } }