The LiSa Tutorial by Dan Trueman Tutorial #1: the Basics LiSa is for sampling a live input (though it can readily be used/abused for other things as well). Let's sample something: //a simple signal path SinOsc sin => LiSa saveme => dac; //give the oscillator a frequency 500 => sin.freq; //gotta tell LiSa how much memory to allocate 5::second => saveme.duration; //start recording 1 => saveme.record; //hang out 1::second => now; //stop recording 0 => saveme.record; Yippee, we've recorded 1 second of a sine wave into a buffer. Now let's play it back: 1 => saveme.play; 1::second => now; 0 => saveme.play; Holy cow! A sine wave! Let's make it just a little more fun; go ahead, replace the SinOsc with the adc analog-digital converter ugen and sample yourself snoring or something. Let's say you don't want it to click: //gotta go back to the beginning 0::ms => saveme.playPos 50::ms => saveme.rampUp; 950::ms => now; 50::ms => saveme.rampDown; 50::ms => now; Let's say you want to transpose it: //gotta go back to the beginning, again! 0::ms => saveme.playPos 50::ms => saveme.rampUp; 2 => saveme.rate; 950::ms => now; 50::ms => saveme.rampDown; 50::ms => now; Now, why is it clicking?? Cause it's going through the buffer twice as fast, and running out of recorded sample. How about this: 0::ms => saveme.playPos //tell it to loop through what we've sampled 1 => saveme.loop; //also tell it where the loop endpoint is 1::second => saveme.loopEnd; 50::ms => saveme.rampUp; 2 => saveme.rate; 950::ms => now; 50::ms => saveme.rampDown; 50::ms => now; Now, you still might hear a click, this time because as it goes across the end of what we've sampled and loops back to the beginning of the sample, there may be a discontinuity. Can we fix it? Yes we can! But we have to go back and re-record into our buffer with a nice envelope so that when playback loops over the record buffer edges it's nice and smooth. Let's start over: //signal path and setup SinOsc s => LiSa loopme => dac; 440. => s.freq; 0.2 => s.gain; //alloc memory 1::second => loopme.duration; loopme.recRamp(200::ms); //start recording input, with 200ms ramp loopme.record(1); //stop recording 1 second later, start playing what was just recorded 1000::ms => now; 0 => loopme.record; //set playback rate 1.5 => loopme.rate; 1 => loopme.loop; 1 => loopme.play; //loop backwards and forwards 1 => loopme.bi; while(true) {500::ms => now;} now the internal buffer has a little ramp on either end so when you loop it there shouldn't be any clicking. This is distinct from the ramping that is created when you use rampUp() and rampDown() to start and stop playback. If you set the recRamp length to zero, you'll hear this click nicely at each end of the loop. Here's another example to belabor how all this works: SinOsc s => LiSa loopme => dac; 440. => s.freq; 0.2 => s.gain; //alloc memory 1::second => loopme.duration; 10::ms => loopme.recRamp; //start recording input 1 => loopme.record; //begin ramping down 600::ms => now; 400::ms => loopme.recRamp; //wait for ramp to finish, then stop recording 400::ms => now; 0 => loopme.record; //set playback rate 1.5 => loopme.rate; 1 => loopme.loop; 1 => loopme.bi; 1 => loopme.play; while(true) {500::ms => now;} and yet another example, illustrating some other bookkeeping issues that might come up: SinOsc s => LiSa loopme => dac; 440. => s.freq; 0.2 => s.gain; //alloc memory; different length this time 10::second => loopme.duration; 10::ms => loopme.recRamp; //need to specify where the recording will end if //we want the recRamping to work when turning //off recording 1::second => loopme.loopEndRec; //start recording input 1 => loopme.record; //stop recording 1 second later, start playing what was just recorded 600::ms => now; 400::ms => loopme.recRamp; 400::ms => now; 0 => loopme.record; //set playback rate 1.5 => loopme.rate; //now we need to tell it where to end the looping for playback //since the buffer size is longer than our actual desired //loop length 1::second => loopme.loopEnd; //now go ahead and play.... 1 => loopme.loop; 1 => loopme.bi; 1 => loopme.play; while(true) {500::ms => now;} ok lot's of basic semi-tedious info there. Now let's look at how to handle multiple voices with LiSa.