//-------------------------------------------------------------------- // name: LiSa-trigger.ck // desc: Live sampling utilities for ChucK // // author: Dan Trueman, 2007 // // based on the S.M.E.L.T. (http://smelt.cs.princeton.edu/) envelope // follower trigger program will trigger start and stop to one-shot // LiSa buffers. a sort of triggered delay line, so the delays follow // the player rather than being static. Success depends on tuning the // envelope follower closely to the input gains on however you are // getting audio into ChucK. Mileage will vary.... //-------------------------------------------------------------------- // patch adc => Gain g => OnePole p => blackhole; // square the input, by chucking adc to g a second time adc => g; // set g to multiply its inputs 3 => g.op; // set pole position, influences how closely the envelope follows the input // : pole = 0 -> output == input; // : as pole position approaches 1, follower will respond more slowly to input 0.995 => p.pole; // thresholds .0001 => float threshold; .00005 => float releaseThresh; // duration between successive polling 10::ms => dur pollDur; // LiSa stuff adc => LiSa lisa => dac; lisa.duration(25::second); lisa.recRamp(20::ms); // start recording input lisa.record(1); // voice variable -1 => int voice; // rate float rate; // read command line args; set rate // be nice to have pitch follower determine this, or some kind of table.... Std.atof(me.arg(0)) => rate; if( rate == 0 ) 1. => rate; <<< "setting rate to: ", rate >>>; // events Event attacks[10]; dur newstarttime, newlen; time starttime_real; // infinite time loop while( true ) { // detect onset if( p.last() > threshold ) { // do something <<< "attack!; starting voice", voice >>>; // play last sample if( voice > -1 ) attacks[voice].signal(); lisa.recPos() => newstarttime; now => starttime_real; // wait for release while( p.last() > releaseThresh ) { pollDur => now; } <<< "release..." >>>; // spork off new sample now - starttime_real => newlen; lisa.getVoice() => voice; if( voice > -1 ) spork ~ playlast( attacks[voice], newstarttime, newlen, rate, voice ); } // determines poll rate pollDur => now; } // sporkee fun void playlast( Event on, dur starttime, dur len, float newrate, int myvoice ) { if( newrate == 0. ) 1. => newrate; <<< "sporking shred with rate: ", newrate >>>; if( rate > 0. ) lisa.playPos( myvoice, starttime ); else lisa.playPos( myvoice, lisa.recPos() - 1::ms ); // wait on => now; lisa.rate( myvoice, newrate ); lisa.rampUp( myvoice, 20::ms ); Math.fabs( newrate ) => float absrate; len / absrate => now; lisa.rampDown( myvoice, ( 250 / absrate )::ms ); ( 250 / absrate )::ms => now; // bye bye shred.... }