JCRev r; 0.1 => r.mix; Gain g; 0.9 => g.gain; // use 3 LiSa buffers to prevent clicking (will rotate) LiSa l[3]; 5::second => dur bufferlen; 0 => int recbuf; 2 => int playbuf; // LiSa params for( 0 => int i; i < 3; i++ ) { l[i].duration( bufferlen ); l[i].maxVoices( 1 ); l[i].clear( ); l[i].gain( 0.01 ); l[i].feedback( 0.65 ); l[i].recRamp( 10::ms ); l[i].record( 0 ); adc => l[i] => r => g => dac; } // rates to choose from -- we can probably randomize this [ 0.0625, 0.125, 0.5, 1.0, 1.5, 2.0 ] @=> float rates[ ]; // create grains and rotate the record and play bufs when needed // as long as grainlen < bufferlen, we will not click fun void loopForever( ) { while( true ) { now + bufferlen => time later; while( now < later ) { // Std.rand2f( 0.2, 2.0 ) => float newrate; // rates[Std.rand2( 0, 5 )] => float newrate; 1.0 => float newrate; // Std.rand2f( 250.0, 600.0 ) * 1::ms => dur newdur; // Std.rand2f( 3000.0, 9000.0 ) * 1::ms => dur newdur; 2000.0::ms => dur newdur; spork ~ getgrain( playbuf, newdur, 20::ms, 20::ms, newrate ); 10::ms => now; } // rotate the record and play bufs // turn off current recording buf l[recbuf].record(0); // increment and wrap the rec buf recbuf++; if( recbuf == 3 ) 0 => recbuf; // turn on recording for the new recording buf l[recbuf].record(1); // increment and wrap the play buf playbuf++; if( playbuf == 3 ) 0 => playbuf; } } fun void getgrain( int which, dur grainlen, dur rampup, dur rampdown, float rate ) { l[which].getVoice( ) => int newvoice; // i think this is checking that the buffer has been recorded into if( newvoice > -1 ) { // and set panning for here // Std.rand2f(-1.0, 1.0 ) => p[which].pan; l[which].rate( newvoice, rate ); l[which].playPos( newvoice, Std.rand2f( 0.0, 1.0 ) * bufferlen ); l[which].rampUp( newvoice, rampup ); ( grainlen - (rampup + rampdown) ) => now; l[which].rampDown( newvoice, rampdown ); rampdown => now; } } spork ~ loopForever( ); while( true ) 50::second => now;