pushing from windows too. added LiSa files

This commit is contained in:
Stephen Kerr 2024-10-08 15:52:13 +02:00
parent d8b4beaceb
commit 0fde988d0d
14 changed files with 821 additions and 0 deletions

View File

@ -0,0 +1,2 @@
[InternetShortcut]
URL=http://dtrueman.mycpanel.princeton.edu/LiSa/LiSa_tutorial.html

55
LiSa/LiSa_Basic.ck Normal file
View File

@ -0,0 +1,55 @@
//-----------------------------------------------------------------------------
// name: LiSa
// desc: Live sampling utilities for ChucK
//
// author: Dan Trueman, 2007
//
// to run (in command line chuck):
// %> chuck LiSa_readme.ck
//-----------------------------------------------------------------------------
/*
the LiSa ugens allow realtime recording of audio to a buffer for various kinds
of manipulation.
Below is a simple example demonstrating the basic functionality of LiSaBasic.
See the LiSaMulti_readme for a command summary and instructions for doing
multiple voice playback.
*/
//-----------------------------------------------------------------------------
//signal chain; record a sine wave, play it back
adc => LiSa saveme => dac;
//s => dac; //monitor the input
//440. => s.freq;
//0.2 => s.gain;
//alloc memory; required
60::second => saveme.duration;
//set playback rate
//1.5 => saveme.rate;
//start recording input
saveme.record(1);
//1 sec later, start playing what was just recorded
1000::ms => now;
saveme.rampUp(100::ms);
//use saveme.play(1) to start playing without ramp
//hang for a bit
1000::ms => now;
//rampdown
saveme.rampDown(300::ms);
//use saveme.play(0) to stop playing without ramp
500::ms => now;
//bye bye
//-----------------------------------------------------------------------------

95
LiSa/LiSa_Multi.ck Normal file
View File

@ -0,0 +1,95 @@
//-----------------------------------------------------------------------------
// name: LiSa
// desc: Live sampling utilities for ChucK
//
// author: Dan Trueman, 2007
//
// to run (in command line chuck):
// %> chuck LiSa_readme.ck
//-----------------------------------------------------------------------------
/*
LiSa allows for multiple voice playback from a live-sampled buffer. Useful
for granular sampling (a la [munger~] from PeRColate) and looping (a la LoopLoop,
Jamman, Echoplex, etc....). The methods are overloaded, taking a "voice" number
as a first arg. if no voice number is specified, LiSa assumes 0=>voice.
Below is a simple example to show how to crossfade two voices. See also the
LiSa_munger directory for other approaches.
Below the example find a (lengthy) command summary.
*/
//-----------------------------------------------------------------------------
//signal chain; record a sine wave, play it back
SinOsc s => Envelope e => LiSa loopme => dac;
s => dac;
440. => s.freq;
0.2 => s.gain;
//alloc memory
6::second => loopme.duration;
//play s for a bit
500::ms => now;
//sweep the freq for fun
Envelope pitchmod => blackhole;
pitchmod.duration(2000::ms);
pitchmod.value(s.freq());
pitchmod.target(880.);
//confirm that the length of the buffer is what you expect
<<<"buffer duration = ", loopme.duration() / 44100.>>>;
//set times for recording fade in/out and sample loop length
100::ms => dur recfadetime;
1000::ms => dur mylooplen;
e.duration(recfadetime);
//start recording input; record 1 seconds worth
loopme.record(1);
e.keyOn(); //can also do without the Envelope and use loopme.recramp(dur) to set a recording ramp
now + (mylooplen - recfadetime) => time later;
while(now < later) {
pitchmod.value() => s.freq;
10::ms => now;
}
e.keyOff();
recfadetime => now;
loopme.record(0);
//disconnect input and hangout a bit
s =< dac;
1000::ms => now;
//now, manipulate the sample
// get a voicenumber; note that this voice won't actually be reserved until you play it
loopme.getVoice() => int voice1;
//we'll play voice 1 forward, and then crossfade it with voice 2 backwards
loopme.play(voice1, 1);
(mylooplen - recfadetime) => now;
//just as voice 1 is going to fade, bring in voice 2
loopme.getVoice() => int voice2;
loopme.rate(voice2, -1.);
loopme.playPos(voice2, mylooplen);
loopme.voiceGain(voice2, 0.2);
loopme.play(voice2, 1);
//wait until voice 1 had finished fading, then turn off
recfadetime => now;
loopme.play(voice1, 0);
//wait for voice 2 to finish
1000::ms => now;
//-----------------------------------------------------------------------------

24
LiSa/LiSa_SndBuf.ck Normal file
View File

@ -0,0 +1,24 @@
//ugens
SndBuf buf;
LiSa lisa => dac;
//change this path to your own sample
"/Users/dan/Files/Chuck/LiSa_examples/TomVega.wav" => buf.read;
//set lisa buffer size to sample size
buf.samples()::samp => lisa.duration;
//transfer values from SndBuf to LiSa
//works properly for mono; need to skip samples for multichannel
for ( 0 => int i; i < buf.samples(); i++ ) {
(buf.valueAt(i), i::samp) => lisa.valueAt;
}
//party on...
1 => lisa.play;
2. => lisa.rate;
//hang on until it's done...
lisa.duration() * 0.5 => now;

View File

@ -0,0 +1,27 @@
//this is broken in current release 1.2.1.4-dev-1 (dracula); something changed in SndBuf
//will be fixed in next release.
//ugens
SndBuf buf;
LiSa lisa => dac;
//change this path to your own sample
"/Applications/Max5/examples/sounds/cello-f2.aif" => buf.read;
//set lisa buffer size to sample size
buf.samples()::samp => lisa.duration;
//buf.samples() returns frames now!
//transfer values from SndBuf to LiSa
for ( 0 => int i; i < buf.samples(); i++ ) {
(buf.valueAt(i * buf.channels()), i::samp) => lisa.valueAt;
}
//party on...
1 => lisa.play;
2. => lisa.rate;
//hang on until it's done...
lisa.duration() / lisa.rate() => now;

85
LiSa/LiSa_munger1.ck Normal file
View File

@ -0,0 +1,85 @@
//-----------------------------------------------------------------------------
// name: LiSa
// desc: Live sampling utilities for ChucK
//
// author: Dan Trueman, 2007
//
// to run (in command line chuck):
// %> chuck LiSa_readme.ck
//-----------------------------------------------------------------------------
/*
These three example files demonstrate a couple ways to approach granular sampling
with ChucK and LiSa. All are modeled after the munger~ from PeRColate. One of the
cool things about doing this in ChucK is that there is a lot more ready flexibility
in designing grain playback patterns; rolling one's own idiosyncratic munger is
a lot easier.
Example 1 (below) is simple, but will feature some clicking due to playing back
over the record-point discontinuity.
*/
//-----------------------------------------------------------------------------
SinOsc s => LiSa l => dac;
s=>dac;
//freq params
s.freq(440.);
s.gain(0.2);
SinOsc freqmod => blackhole;
freqmod.freq(0.1);
//LiSa params
l.duration(1::second);
//set it recording constantly; loop records by default
l.record(1);
l.gain(0.1);
now + 1000::ms => time later;
while(now<later) {
freqmod.last() * 500. + 200. => s.freq;
10::ms => now;
}
l.record(0);
s.gain(0.);
l.recRamp(20::ms);
l.maxVoices(30);
//<<<l.maxvoices()>>>;
//this arrangment will create some clicks because of discontinuities from
//the loop recording. to fix, need to make a rotating buffer approach.
//see the next two example files....
while (true) {
Std.rand2f(1.5, 2.0) => float newrate;
Std.rand2f(250, 750) * 1::ms => dur newdur;
spork ~ getgrain(newdur, 20::ms, 20::ms, newrate);
10::ms => now;
}
fun void getgrain(dur grainlen, dur rampup, dur rampdown, float rate)
{
l.getVoice() => int newvoice;
//<<<newvoice>>>;
if(newvoice > -1) {
l.rate(newvoice, rate);
//l.playpos(newvoice, Std.rand2f(0., 1000.) * 1::ms);
l.playPos(newvoice, 20::ms);
//<<<l.playpos(newvoice)>>>;
l.rampUp(newvoice, rampup);
(grainlen - (rampup + rampdown)) => now;
l.rampDown(newvoice, rampdown);
rampdown => now;
}
}

128
LiSa/LiSa_munger2.ck Normal file
View File

@ -0,0 +1,128 @@
//-----------------------------------------------------------------------------
// name: LiSa
// desc: Live sampling utilities for ChucK
//
// author: Dan Trueman, 2007
//
// to run (in command line chuck):
// %> chuck LiSa_readme.ck
//-----------------------------------------------------------------------------
/*
These three example files demonstrate a couple ways to approach granular sampling
with ChucK and LiSa. All are modeled after the munger~ from PeRColate. One of the
cool things about doing this in ChucK is that there is a lot more ready flexibility
in designing grain playback patterns; rolling one's own idiosyncratic munger is
a lot easier.
Example 2 (below) demonstrates the rotating buffer approach used in the munger~
see after the code for an explanation of this approach. presumably someone
smarter than me will dream up a more elegant technique.
*/
//-----------------------------------------------------------------------------
//oscillator as source
//fun scary sounds!!!
SinOsc s=>dac;
s.freq(440.);
s.gain(0.2);
SinOsc freqmod => blackhole;
freqmod.freq(0.1);
//use three buffers
LiSa l[3];
1::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(30);
l[i].clear();
l[i].gain(0.1);
l[i].feedback(0.5);
l[i].recRamp(20::ms);
l[i].record(0);
s => l[i] => dac;
}
l[recbuf].record(1);
//create grains, rotate record and play bufs as needed
//shouldn't click as long as the grainlen < bufferlen
while(true) {
now + bufferlen => time later;
//toss some grains
while (now<later) {
Std.rand2f(0.5, 2.5) => float newrate;
Std.rand2f(250, 600) * 1::ms => dur newdur;
spork ~ getgrain(playbuf, newdur, 20::ms, 20::ms, newrate);
freqmod.last() * 400. + 800. => s.freq;
10::ms => now;
}
//rotate the record and playbufs
l[recbuf++].record(0);
if(recbuf == 3) 0 => recbuf;
l[recbuf].record(1);
playbuf++;
if(playbuf == 3) 0 => playbuf;
}
fun void getgrain(int which, dur grainlen, dur rampup, dur rampdown, float rate)
{
l[which].getVoice() => int newvoice;
//<<<newvoice>>>;
if(newvoice > -1) {
l[which].rate(newvoice, rate);
l[which].playPos(newvoice, Std.rand2f(0., 1.) * bufferlen);
l[which].rampUp(newvoice, rampup);
(grainlen - (rampup + rampdown)) => now;
l[which].rampDown(newvoice, rampdown);
rampdown => now;
}
}
/*
Rotating Buffer Explanation (from the munger~ source code).
the munger~ (and scrubber~) use a rotating three-buffer scheme for creating clickless grains.
basically, you don't want to be recording new data anywhere in the buffer where a grain might
be playing. so, we divide the buffer into three equal parts (B1, B2, B3). at the outset, let's say:
B1 = the recording buffer part (RB)
B2 = a part where nothing is happening (QB, for Quiet Buffer)
B3 = a part where grains are playing from (PB)
let's say each part is N samples long. after we have recorded N sample into B1, we rotate
the functionality, so now:
B1 = PB
B2 = RB
B3 = QB
why?
as long as the grains are guaranteed to be no longer than N samples (adjusted for playback rate) we
are assured that none of them will have clicks due to recording discontinuities. we need the Quiet Buffer
because when the rotation happens, there may still be grains playing in what was the PB and is now the QB.
*/

140
LiSa/LiSa_munger3.ck Normal file
View File

@ -0,0 +1,140 @@
//-----------------------------------------------------------------------------
// name: LiSa
// desc: Live sampling utilities for ChucK
//
// author: Dan Trueman, 2007
//
// to run (in command line chuck):
// %> chuck LiSa_readme.ck
//-----------------------------------------------------------------------------
/*
These three example files demonstrate a couple ways to approach granular sampling
with ChucK and LiSa. All are modeled after the munger~ from PeRColate. One of the
cool things about doing this in ChucK is that there is a lot more ready flexibility
in designing grain playback patterns; rolling one's own idiosyncratic munger is
a lot easier.
Example 3 (below) uses the same structure as Example 2, but replicates the groovy
tune munging from the original munger~ helppatch (with pitch transposition filtering
and all!).
*/
//-----------------------------------------------------------------------------
//oscillator as source
SinOsc s=>dac;
s.freq(440.);
s.gain(0.2);
//play the munger song!
Envelope fsmooth => blackhole;
spork ~ playtune(250::ms);
spork ~ smoothtune(20::ms);
//transposition table
[0, 4, 7, -2, 12, 15] @=> int pitchtable[];
//use three buffers to avoid clicks
LiSa l[3];
1::second => dur bufferlen; //allocated buffer size -- remains static
0.1::second => dur reclooplen;//portion of the buffer size to use -- can vary
0 => int recbuf;
2 => int playbuf;
//LiSa params, set
for(0=>int i; i<3; i++) {
l[i].duration(bufferlen);
l[i].loopEndRec(reclooplen);
l[i].maxVoices(30);
l[i].clear();
l[i].gain(0.2);
//if you want to retain earlier passes through the recording buff when loop recording:
//l[i].feedback(0.5);
l[i].recRamp(20::ms); //ramp at extremes of record buffer while recording
l[i].record(0);
s => l[i] => dac;
}
//start recording in buffer 0
l[recbuf].record(1);
//create grains, rotate record and play bufs as needed
//shouldn't click as long as the grainlen < bufferlen
while(true) {
//will update record and playbufs to use every reclooplen
now + reclooplen => time later;
//toss some grains
while (now<later) {
Std.rand2f(0, 6) $ int => int newpitch; //choose a transposition from the table
Std.mtof(pitchtable[newpitch] + 60)/Std.mtof(60) => float newrate;
Std.rand2f(50, 100) * 1::ms => dur newdur; //create a random duration for the grain
//spork off the grain!
spork ~ getgrain(playbuf, newdur, 20::ms, 20::ms, newrate);
//wait a bit.... then do it again, until we reach reclooplen
5::ms => now;
}
//rotate the record and playbufs
l[recbuf++].record(0);
if(recbuf == 3) 0 => recbuf;
l[recbuf].record(1);
playbuf++;
if(playbuf == 3) 0 => playbuf;
}
//for sporking grains; can do lots of different stuff here -- just one example here
fun void getgrain(int which, dur grainlen, dur rampup, dur rampdown, float rate)
{
l[which].getVoice() => int newvoice;
//<<<newvoice>>>;
if(newvoice > -1) {
l[which].rate(newvoice, rate);
l[which].playPos(newvoice, Std.rand2f(0., 1.) * reclooplen);
l[which].rampUp(newvoice, rampup);
(grainlen - (rampup + rampdown)) => now;
l[which].rampDown(newvoice, rampdown);
rampdown => now;
}
}
//the munger song lives! thanks to luke dubois....
fun void playtune(dur notelen)
{
0 => int notectr;
[45, 45, 57, 57, 45, 57, 57, 47, 55, 47, 59, 60, 60, 57, 57, 57] @=> int notes[];
Std.mtof(notes[0]) => fsmooth.value => s.freq;
while (true) {
//<<<notes[notectr]>>>;
Std.mtof(notes[notectr++] + 12) => fsmooth.target;
if(notectr == notes.size()) 0 => notectr;
notelen => now;
}
}
fun void smoothtune(dur smoothtime)
{
fsmooth.duration(smoothtime);
while (true) {
fsmooth.value() => s.freq;
1::ms => now;
}
}

58
LiSa/LiSa_track1.ck Normal file
View File

@ -0,0 +1,58 @@
//-----------------------------------------------------------------------------
// name: LiSaBasic and LiSaMulti
// desc: Live sampling utilities for ChucK
//
// author: Dan Trueman, 2007
//
// to run (in command line chuck):
// %> chuck LiSa_readme.c
//-----------------------------------------------------------------------------
//demonstrate using track=1 mode with LiSa
//
//when track == 1, the input is used to control playback position
//input [0,1] will control playback position within loop marks
//values less than zero are multiplied by -1, so it is possible to use
//audio signals [-1, 1] to control playback position, as in waveshaping
//signal chain; record a sine wave, play it back
SinOsc s => LiSa loopme => dac;
//s => dac;
440. => s.freq;
0.2 => s.gain;
//alloc memory
6::second => loopme.duration;
1000::ms => loopme.loopEndRec;
1000::ms => loopme.loopEnd;
//set recording ramp time
loopme.recRamp(250::ms);
//start recording input
loopme.record(1);
//1 sec later, stop recording
1000::ms => now;
loopme.record(0);
//set track mode to 1, where the input chooses playback position
//note that you can still record this input
1 => loopme.track;
s =< loopme; //disconnect sinosc as input
Step i => Envelope e => loopme; //use envelope to control playback position
1. => i.next;
//play it forward twice speed
500::ms => e.duration;
e.keyOn();
loopme.play(1);
500::ms => now;
//now backwards half speed
2000::ms => e.duration;
e.keyOff();
2000::ms => now;
loopme.play(0);
//bye bye

41
LiSa/LiSa_track2.ck Normal file
View File

@ -0,0 +1,41 @@
//demonstrate using track=1 mode with LiSa
//
//when track == 1, the input is used to control playback position
//input [0,1] will control playback position within loop marks
//input values less than zero are multiplied by -1, so it is possible to use
//audio signals [-1, 1] to control playback position, as in waveshaping
//signal chain; record a sine wave, play it back
SinOsc s => LiSa loopme => dac;
//s => dac;
440. => s.freq;
0.2 => s.gain;
//alloc memory
6::second => loopme.duration;
1000::ms => loopme.loopEndRec;
1000::ms => loopme.loopEnd;
//set recording ramp time
loopme.recRamp(50::ms);
//start recording input
loopme.record(1);
//1 sec later, stop recording
1000::ms => now;
loopme.record(0);
//set track mode to 1, where the input chooses playback position
1 => loopme.track;
0.5 => s.freq;
1. => s.gain; //need to reset gain if we want to get the full loop length
loopme.play(1);
loopme.gain(0.1);
5000::ms => now;
loopme.rampDown(250::ms);
500::ms => now;
//bye bye

40
LiSa/LiSa_track3.ck Normal file
View File

@ -0,0 +1,40 @@
//demonstrate using track=1 mode with LiSa
//
//when track == 1, the input is used to control playback position
//input [0,1] will control playback position within loop marks
//input values less than zero are multiplied by -1, so it is possible to use
//audio signals [-1, 1] to control playback position, as in waveshaping
//signal chain; record a sine wave, play it back
SinOsc s => LiSa loopme => dac;
//s => dac;
440. => s.freq;
//alloc memory
6::second => loopme.duration;
1000::ms => loopme.loopEndRec;
1000::ms => loopme.loopEnd;
//set recording ramp time
loopme.recRamp(50::ms);
loopme.feedback(0.99); //retain some while loop recording
//start recording input
loopme.record(1);
//1 sec later, this time DON'T stop recording....
1000::ms => now;
//set track mode to 1, where the input chooses playback position
1 => loopme.track;
//this time don't change the freq; scan through zippy quick
loopme.play(1);
loopme.gain(0.01);
5000::ms => now;
loopme.rampDown(250::ms);
500::ms => now;
//pretty farking scary
//bye bye

36
LiSa/LiSa_track4.ck Normal file
View File

@ -0,0 +1,36 @@
//ugens
SndBuf buf;
LiSa loopme => dac;
//change this path to your own sample
"/Users/dan/Files/Chuck/LiSa_examples/TomVega.wav" => buf.read;
//set lisa buffer size to sample size
buf.samples()::samp => loopme.duration;
//transfer values from SndBuf to LiSa
for ( 0 => int i; i < buf.samples(); i++ ) {
loopme.valueAt(buf.valueAt(i), i::samp);
}
//set sync/track mode to 1, where the input chooses playback position
1 => loopme.sync;
//use an oscillator to set playback position
SinOsc tracker => loopme;
Step off => loopme;
//tracker parameters; will determine how far into the buffer
//to go (gain), with what offset (off) and with what speed (freq)
0.05 => tracker.freq;
0.2 => tracker.gain;
0.3 => off.next;
//play it back
1 => loopme.play;
0.5 => loopme.gain;
while ( true ) { 1::second => now; }

44
LiSa/LiSa_track4b.ck Normal file
View File

@ -0,0 +1,44 @@
//ugens
SndBuf buf;
LiSa loopme => dac;
//change this path to your own sample
"/Users/dan/Files/Chuck/LiSa_examples/TomVega.wav" => buf.read;
//set lisa buffer size to sample size
buf.samples()::samp => loopme.duration;
//transfer values from SndBuf to LiSa
for ( 0 => int i; i < buf.samples(); i++ ) {
loopme.valueAt(buf.valueAt(i), i::samp);
}
//set sync/track mode to 1, where the input chooses playback position
1 => loopme.sync;
//use an oscillator to set playback position
SinOsc tracker => loopme;
Step off => loopme;
//tracker parameters; will determine how far into the buffer
//to go (gain), with what offset (off) and with what speed (freq)
0.31 => tracker.freq;
0.2 => tracker.gain;
0.3 => off.next;
loopme.getVoice() => int v1;
loopme.loopStart(v1, 0::ms);
loopme.loopEnd(v1, 1600::ms);
loopme.play(v1, 1);
loopme.getVoice() => int v2;
loopme.loopStart(v2, 2000::ms);
loopme.loopEnd(v2, 6600::ms);
loopme.play(v2, 1);
0.5 => loopme.gain;
while ( true ) { 1::second => now; }

46
LiSa/LiSa_track5.ck Normal file
View File

@ -0,0 +1,46 @@
//ugens
SndBuf buf;
LiSa loopme => dac;
//change this path to your own sample
"/Users/dan/Files/Chuck/LiSa_examples/TomVega.wav" => buf.read;
//set lisa buffer size to sample size
buf.samples()::samp => loopme.duration;
//transfer values from SndBuf to LiSa
for ( 0 => int i; i < buf.samples(); i++ ) {
loopme.valueAt(buf.valueAt(i), i::samp);
}
//set sync/track mode to 2, where the input chooses playback position
//interpreted as a time value
//again, negative values are multiplied internally by -1
2 => loopme.sync;
//use an oscillator to set playback position
SinOsc tracker => loopme;
Step off => loopme;
//tracker parameters; will determine how far into the buffer
//to go (gain), with what offset (off) and with what speed (freq)
0.05 => tracker.freq;
//we'll loop over half of the buffer
loopme.duration() / 4::samp => tracker.gain;
//starting at the midpoint
loopme.duration() / 2::samp => off.next;
//play it back
1 => loopme.play;
0.5 => loopme.gain;
while ( true ) {
//monitor where we're playing back from in the buffer
<<<off.last() / 44100>>>;
50::ms => now;
}