/* Class 7 */

/*

Celia says: Aaaaaa! dish - ehs.... dat dat dat dat sssSHA BOOM! 

*/


attachments/class07/DSCF0019.png


/* Randomness - lang and server side representations */


// there are a number of random methods inside the language:


10.rand; // returns ran integers between 0 an 10

10.0.rand; // float between 0.0 and 10.0

10.rrand(20); // ints between 10 and 20

10.0.rrand(20.0); // floats (you get the idea)

10.0.rand2; // between -10.0 and 10.0


10.rand

rand(10)

10.rrand(20);

rrand(10, 20)

a = 0;

1000.do({a = a + 10.sum3rand});

a/1000


10.sum3rand + 440;


10.0.linrand; // between 0.0 and 10.0, with decreasing linear prob from 0 to 10

10.0.bilinrand; // between -10.0 and 10.0, prob highest at 0.0

10.0.sum3rand; // between -10.0 and 10.0, prob highest at 0.0, bell-like distribution

0.001.exprand(1.0); // between 0.001 and 1.0, exponential dist, no values of 0 (or 0 crossing)

0.5.coin; // a 50/50 coin toss

0.9.coin; // a 90/10 coin toss


/* exprand mean of 100 samples */

a = 0;

1000.do({a = a + 0.001.exprand(1.0)});

a/1000; // about 0.145


/* Don't do this */

SynthDef(\sin, {

Out.ar(0, SinOsc.ar(440.rrand(880), 0, 1))

}).load(s);

/* Do this */

SynthDef(\sin, {arg freq;

Out.ar(0, SinOsc.ar(freq, 0, 1))

}).load(s);


s.sendMsg(\s_new, \sin, 1000, 0, 1, \freq, 440.rrand(880));


// seeding the randomness

(

thisThread.randSeed_(30);

10.do({

1000.rand.postln;

})

)


(

r = Routine({

10.do({

1000.rand.postln.yield;

})

}).randSeed_(25);


t = Routine({

10.do({

1000.rand.postln.yield;

})

}).randSeed_(25)

)

r.next;

r.next;

t.next;

r.next;

t.next;


// Arrays also have random methods

a = Array.rand(10, 0.0, 10.0); // 10 values between 0.0 and 10.0

// there are also exprand, rand2 and linrand methods


// randomly pick a value from an Array

a.choose;


// weighted choose

a.wchoose([0.91, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01]);


a = a.scramble; // random re-order of the Array


// Audio rate noise UGens:

{WhiteNoise.ar(0.4)}.play(s); // Random distribution values +- mul

{PinkNoise.ar(0.4)}.play(s); // 8 octaves... higher spectrum is weaker

{GrayNoise.ar(0.4)}.play(s); // "randomly flipped bits" of a word.

{BrownNoise.ar(0.4)}.play(s); // "Brownian" noise

{ClipNoise.ar(0.4)}.play(s); // generates only two values, -mul and mul


// Interpolated Noises - Non band limited

{LFNoise0.ar(1000, 0.4)}.play(s); // freq to produce new values - sample and hold

{LFNoise1.ar(1000, 0.4)}.play(s); // linear interpolated noise

{LFNoise2.ar(1000, 0.4)}.play(s); // quadratic interpolated noise


{LFNoise1.ar(MouseY.kr(4, 1000), 0.5) * SinOsc.ar(MouseX.kr(200, 2000), 0, 0.3)}.play(s);



{Dust.ar(100, 0.4)}.play(s); // density of random impulses from 0 to mul...

{Dust2.ar(100, 0.4)}.play(s); // density of random impulses from -mul to mul


// chaos noise

{Crackle.ar(MouseX.kr(0.99, 2.01), 0.4)}.play(s);


// The LF UGens are particularly useful for controlling parameters at a 'Low Frequency'

{SinOsc.ar(LFNoise2.ar(1).range(220, 440), 0, 0.2)}.play(s);


// single random values... from the lang OR from inside the SynthDef


a = CtkNoteObject(

SynthDef(\ranone, {arg dur = 0.2, freq = 440;

var env, src;

env = EnvGen.kr(Env([0, 1, 0], [0.5, 0.5], \sin), timeScale: dur,

doneAction: 2);

src = SinOsc.ar(freq, 0, 0.2);

Out.ar(0, Pan2.ar(src * env, 0));

})

);


Routine.run({

10.do({

// get a new random freq with each note

a.new.freq_(440.0.rrand(880.0)).play;

0.1.wait;

})

}).randSeed_([25, 26, 27].wchoose([0.5, 0.25, 0.25]));

// or... an angry R2-D2


(

Routine.run({

10.do({

Routine.run({

10.do({

// get a new random freq with each note

a.new.freq_(440.0.rrand(880.0)).play;

0.1.wait;

})

}).randSeed_([25, 26, 27].wchoose([0.5, 0.25, 0.25]));

1.5.wait;

})

})

)


a = CtkNoteObject(

SynthDef(\rantwo, {arg dur = 0.2;

var env, src;

env = EnvGen.kr(Env([0, 1, 0], [0.5, 0.5], \sin), timeScale: dur, doneAction: 2);

src = SinOsc.ar(Rand.new(440.0, 880.0), 0, 0.2); // the Rand UGen

Out.ar(0, Pan2.ar(src * env, 0));

})

);

Routine.run({

10.do({

// get a new random freq with each note

a.new.play;

0.1.wait;

})

});

// IRand.new(lo, hi) // produces random integers

// NRand.new(lo, hi, n) // produces a single ran value from a sum of n ran numbers. 

// Hi n = gaussian

// ExpRand.new(lo, hi) // exponential dist between lo and hi


// Triggered randomness - triggers are any signal that moves from <0 to >0

a = CtkNoteObject(

SynthDef(\trand, {arg gate = 1;

var env, src;

env = EnvGen.kr(Env([0, 1, 0], [0.5, 0.5], \sin, 1), gate, doneAction: 2);

// the TRand UGen - the MouseX control is the trigger

src = SinOsc.ar(TRand.kr(440.0, 880.0, MouseX.kr(-1, 1)), 0, 0.2); 

Out.ar(0, Pan2.ar(src*env, 0));

})

);

b = a.new.play;

b.release;


// also, TIRand, TExpRand

// randomness on the Server can also be seeded:

a = CtkNoteObject(

SynthDef(\seedrand, {arg gate = 1, seed = 100, id = 1;

var env, src, freq, loc;

RandID.kr(id);

RandSeed.kr(1, seed);

env = EnvGen.kr(Env([0, 1, 0], [0.5, 0.5], \sin, 1), gate, doneAction: 2);

freq = TRand.kr(440.0, 880.0, Dust.kr(1));

loc = LFNoise1.ar(1);

src = SinOsc.ar(freq, 0, 0.2);

Out.ar(0, Pan2.ar(src * env));

})

);


b = a.new.id_(1).play;

b.release;


b = a.new.id_(1).play;

b.release;


// to generate random values from 2 different synths at the same time, give them

// unique ids and the same seed

b = a.new.id_(1).seed_(100).play;

c = a.new.id_(2).seed_(100).play;

b.release;

c.release;


/* Arrays and multi-channel expansion */

/*


On the server, Arrays hae a special meaning. They indicate multiple channels of sound, and they can be used in UGen arguments to create multiple copies of a UGen across these channels:


*/

(

a = CtkNoteObject(

SynthDef(\monosin, {arg dur = 1, freq = 440;

var env, src;

env = EnvGen.kr(Env([0, 1, 0], [0.5, 0.5], \sin), timeScale: dur, doneAction: 2);

src = SinOsc.ar(freq, 0, 0.2);

Out.ar(0, src * env);// sound comes out of the left

})

);


b = CtkNoteObject(

SynthDef(\stereosin, {arg dur = 1, freq = 440;

var env, src;

env = EnvGen.kr(Env([0, 1, 0], [0.5, 0.5], \sin), timeScale: dur, doneAction: 2);

src = SinOsc.ar([freq, freq + 5], 0, 0.2);

src.postln; // src is an array of 2 channels -> [ a BinaryOpUGen, a BinaryOpUGen ]

Out.ar(0, src * env);// sound comes out of the left AND right

})

)

);


c = a.new.play;

d = b.new.play;


// Panning UGens (like Pan2) take a mono input, and output a 2 channel array, with 

// the sound attenuated between the speakers to give the effect of appearing between 

// them


a = CtkNoteObject(

SynthDef(\pansin, {arg dur = 1, freq = 440;

var env, src, pan;

env = EnvGen.kr(Env([0, 1, 1, 0], [0.1, 0.8, 0.1], \sin), timeScale: dur, 

doneAction: 2);

src = SinOsc.ar(freq, 0, 0.2) * Saw.ar(-10).range(0, 1);

src.postln; // -> a BinaryOpUGen

pan = Pan2.ar(src * env, Line.kr(-1, 1, dur)); 

pan.postln; // -> [ an OutputProxy, an OutputProxy ]

Out.ar(0, pan);// sound comes out of the left

})

);


b = a.new.dur_(2).play;


// array manipulations can also be done on the multi-channel arrays

[0.2, 0.2].sum; // add the elements of the array together


a = Array.fill(10, {arg i; i});

a.sum; // -> 45


// you can also perform BinaryOps to all the items in an Array

a = Array.series(10, 1, 2); // 10 elements, start at 1, skip 2 

// -> [ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 ]

a * 440.0; // -> [ 440, 1320, 2200, 3080, 3960, 4840, 5720, 6600, 7480, 8360 ]

(

a = CtkNoteObject(

SynthDef(\addsin, {arg dur = 1, freq = 440, start = 1, step = 2;

var env, src, pan, freqs, numpars;

numpars = 10;

env = EnvGen.kr(Env([0, 1, 1, 0], [0.1, 0.8, 0.1], \sin), timeScale: dur, 

doneAction: 2);

freqs = freq * Array.series(numpars, start, step);

src = SinOsc.ar(freqs, 0, freqs.size.reciprocal);

src.postln; // -> [ a BinaryOpUGen, a BinaryOpUGen, a BinaryOpUGen, 

// a BinaryOpUGen, a BinaryOpUGen, a BinaryOpUGen, a BinaryOpUGen, 

// a BinaryOpUGen, a BinaryOpUGen, a BinaryOpUGen ]

src = src.sum * Saw.ar(-10).range(0, 1);

// src = Mix.newScale(src * Saw.ar(10).range(0, 1));

src.postln; // -> a BinaryOpUGen 

pan = Pan2.ar(src * env, Line.kr(-1, 1, dur)); 

Out.ar(0, pan);// sound comes out of the left

})

);

)

b = a.new.play;


// in the above example, all the partials use the same mul - freqs.size.reciprocal, 

// however, arrays can also be multiplied by other arrays! The corresponding slots 

// will be multiplied together

[1, 2, 3] * [6, 5, 4]; // -> [ 6, 10, 12 ]


// and, any BinaryOp will act this way (+, -, etc. )


a = CtkNoteObject(

SynthDef(\addsin, {arg dur = 1, freq = 440, start = 1, step = 2;

var env, src, pan, freqs, amps, numpars;

numpars = 10;

env = EnvGen.kr(Env([0, 1, 1, 0], [0.1, 0.8, 0.1], \sin), timeScale: dur,

doneAction: 2);

freqs = freq * Array.series(numpars, start, step);

amps = Array.series(numpars, 0.01, 0.05);

src = SinOsc.ar(freqs, 0, amps).sum;

pan = Pan2.ar(src * env, Line.kr(-1, 1, dur)); 

Out.ar(0, pan);// sound comes out of the left

})

);


a.new.play;


/*


It is important to keep in mind that while this gives some flexibility, there is still one very important limitation! The number of UGens created in a synthdef is fixed. This means that the numpars variable can not be an arg to the synth... this synthdef will ALWAYS create 10 partials.


The other place that you will see this is in the UGens that use a buffer (e.g. PlayBuf). PlayBufs first arg is the number of channels that your soundfile (loaded into a memory buffer) has. Once again, this is a fixed parameter:

*/


// use CtkBuffer to load a soundfile into memory (or a buffer)

a = CtkBuffer.playbuf("sounds/mozart.aiff").load;


b = CtkNoteObject(

SynthDef(\player, {arg gate = 1, buffer, rate;

var env, src;

env = EnvGen.kr(Env([0, 1, 0], [0.1, 0.1], \sin, 1), gate, doneAction: 2);

// BufRateScale - account for differences in SR between soundfile and SC

src = PlayBuf.ar(1, buffer, BufRateScale.kr(buffer) * rate, loop: 1);

Out.ar(0, Pan2.ar(src * env, 0));

})

);

c = b.new.buffer_(a).rate_(1).play;

c.release;


// use midiratio to lower a number of semitones

c = b.new.buffer_(a).rate_(-12.midiratio).play;

c.release;


// if you try to play this with a PlayBuf with 2 channels... it will fail silently!


b = CtkNoteObject(

SynthDef(\player, {arg gate = 1, buffer, rate;

var env, src;

env = EnvGen.kr(Env([0, 1, 0], [0.1, 0.1], \sin, 1), gate, doneAction: 2);

src = PlayBuf.ar(2, buffer, BufRateScale.kr(buffer) * rate, loop: 1);

Out.ar(0, src * env);

})

);


c = b.new.buffer_(a).rate_(1).play;

c.release;


// we are done with this buffer... free it. This is important, you are using precious

// RAM

a.free;


/* Buffers and async commands */

/*


In SC, loading a sound to a buffer is referred to as an asyncronous command. The Server will do it as fast as it can without disrupting sound processes. Using buffers means allocating and filling RAM with data... and this can take some time (usually less then a second, but VERY large sound files may take longer). The server has some functionality to help with this, we can sync to the server with a Condition:


*/

(

a = CtkNoteObject(

SynthDef(\player, {arg gate = 1, buffer, rate;

var env, src;

env = EnvGen.kr(Env([0, 1, 0], [0.1, 0.1], \sin, 1), gate, doneAction: 2);

src = PlayBuf.ar(1, buffer, BufRateScale.kr(buffer) * rate, loop: 1);

Out.ar(0, Pan2.ar(src * env, 0));

})

);

b = {arg path, rate = 1;

var cond, buffer, node, routine, start, time;

// Conditions and syncing are a pause... they need to be run in a Routine

// first, create the node

node = a.new;

buffer = CtkBuffer.playbuf(path);

Routine.run({

cond = Condition.new;

// record the current time (so we can see how long the sf takes to load)

start = Main.elapsedTime;

// use .load, and pass the Condition object to the server

buffer.load;

s.sync(cond);

// show us how much time it took to load the file

("File loaded, server synced, time elapsed= " ++ (Main.elapsedTime - start)).postln;

// the file is ready... store the data to the node

node.buffer_(buffer).rate_(rate);

// and play it

node.play;

});

[buffer, node]; // return the buffer and node

};

)

#c, n = b.value("sounds/SS-VioPartEdited2E.aiff", 1);

n.release;

c.free;


/* 


some basic and not so basic signal processing- here, using a soundfile, but you can also do all of this with real-time input. The structure of all these examples will follow the same pattern. Our goal is to create a block of code that will create a single process that we can start and stop whenever we want to. The source for the transformations (the soundfile in this case) and the processing need to take Order-of-execution into account now! Our source will be sent to the output (Bus 0) and to a virtual bus for the processes to read off of.


*/


/* Basic filters */

/* BPF - Band Pass Filter */

(

var player, filter;

player = CtkNoteObject(

SynthDef(\player, {arg gate = 1, buffer, rate, routebus, start = 0, clean = 1;

var env, src;

env = EnvGen.kr(Env([0, 1, 0], [0.1, 0.1], \sin, 1), gate, doneAction: 2);

src = PlayBuf.ar(1, buffer, BufRateScale.kr(buffer) * rate, 

startPos: start * BufSampleRate.kr(buffer),loop: 1);

Out.ar(0, Pan2.ar(src * env * clean, 0));

Out.ar(routebus, src * env); // route the sound to a virtual bus for processing

})

);


filter = CtkNoteObject(

SynthDef(\filter, {arg dur = 1, amp = 1, inbus, lowfreq = 440, highfreq = 880;

var env, src, freq, rq, filt, loc;

env = EnvGen.kr(Env([0, 1, 1, 0], [0.1, 0.8, 0.1], \sin), timeScale: dur, doneAction: 2);

// read the playbuf output from the sourcebus

src = In.ar(inbus);

freq = LFNoise2.kr(dur.reciprocal * 2).range(lowfreq, highfreq);

rq = LFNoise2.kr(dur.reciprocal * 2).range(0.001, 0.005);

filt = BPF.ar(src, freq, rq, rq.reciprocal * amp);

loc = LFNoise2.kr(dur.reciprocal);

Out.ar(0, Pan2.ar(filt * env, loc));

}).load(s)

);

// this function will-

// 1- load the soundfile into a buffer

// 2- play the soundfile startting at start, play it at rate

// 3- the soundfile will be routed to a virtual bus

// 4- instances of the filter synth will be created every windowsize / overlaps seconds


a = {arg path, rate = 1, start = 0, windowsize = 2, overlaps = 8, clean = 1,

filtamp = 1;

var cond, buffer, node, routebus, routine, group, waittime;

group = CtkGroup.new;

node = player.new(addAction: 0, target: group);

routebus = CtkAudio.new;

buffer = CtkBuffer.playbuf(path);

waittime = windowsize / overlaps;

routine = Routine({

cond = Condition.new;

buffer.load;

s.sync(cond);

group.play;

node.buffer_(buffer).rate_(rate).routebus_(routebus).clean_(clean).play;

// use a do loop to create a constantly changing texture of filters

// since we don't know how long this will last, use inf

loop({

filter.new(addAction: 1, target: group).dur_(windowsize).amp_(filtamp)

.inbus_(routebus).lowfreq_(4000).highfreq_(8000).play;

waittime.wait;

});

});

// play the routine

routine.play;

// return some info to use later

[buffer, node, routine, group]; // return the buffer id, node id, the task and the group

};

)


#b, n, t, g = a.value("sounds/SS-VioPartEdited2E.aiff", 1, 0, 6, 8, 1, 0.01);

#b, n, t, g = a.value("sounds/accordian.wav", 1, 0, 6, 8, 1, 0.1);


// change the amount of clean sound

n.clean_(0.0);

// stop the soundfile input, and the loop;

n.release; t.stop;

// free the buffer

b.free;



/* Resonz - Resonant Band Pass Filter */

(

var player, filter;

player = CtkNoteObject(

SynthDef(\player, {arg gate = 1, buffer, rate, routebus, start = 0, clean = 1;

var env, src;

env = EnvGen.kr(Env([0, 1, 0], [0.1, 0.1], \sin, 1), gate, doneAction: 2);

src = PlayBuf.ar(1, buffer, BufRateScale.kr(buffer) * rate, 

startPos: start * BufSampleRate.kr(buffer),loop: 1);

Out.ar(0, Pan2.ar(src * env * clean, 0));

Out.ar(routebus, src * env); 

})

);


filter = CtkNoteObject(

SynthDef(\filter, {arg dur = 1, amp = 1, inbus, lowfreq = 440, highfreq = 880;

var env, src, freq, rq, filt, loc;

env = EnvGen.kr(Env([0, 1, 1, 0], [0.1, 0.8, 0.1], \sin), timeScale: dur, doneAction: 2);

src = In.ar(inbus);

freq = LFNoise2.kr(dur.reciprocal * 2).range(lowfreq, highfreq);

rq = LFNoise2.kr(dur.reciprocal * 2).range(0.0001, 0.0005);

filt = Resonz.ar(src, freq, rq, rq.reciprocal) * amp;

loc = LFNoise2.kr(dur.reciprocal);

Out.ar(0, Pan2.ar(filt * env, loc));

})

);

a = {arg path, rate = 1, start = 0, windowsize = 2, overlaps = 8, clean = 1,

filtamp = 1;

var cond, buffer, node, routebus, routine, group, waittime;

buffer = CtkBuffer.playbuf(path);

node = player.new(addAction: 0, target: group);

routebus = CtkAudio.new;

group = CtkGroup.new;

waittime = windowsize / overlaps;

routine = Routine({

cond = Condition.new;

buffer.load;

s.sync(cond);

group.play;

node.buffer_(buffer).rate_(rate).routebus_(routebus).clean_(clean).play;

inf.do({

filter.new(addAction: 1, target: group).dur_(windowsize).amp_(filtamp).inbus_(routebus)

.lowfreq_(2000).highfreq_(4000).play;

waittime.wait;

});

});

routine.play;

[buffer, node, routine, group]; // return the buffer id, node id, the task and the group

};

)


#b, n, t, g = a.value("sounds/SS-VioPartEdited2E.aiff", 1, 0, 6, 8, 1, 0.01);

#b, n, t, g = a.value("sounds/accordian.wav", 1, 0, 6, 8, 1, 0.01);

// change the amount of clean sound

n.clean_(0.0);

// stop the soundfile input, and the loop;

n.release; t.stop;

// free the buffer

b.free;


/* Comb filters (or Comb Delays) */

(

var player, filter;

player = CtkNoteObject(

SynthDef(\player, {arg gate = 1, buffer, rate, routebus, start = 0, clean = 1;

var env, src;

env = EnvGen.kr(Env([0, 1, 0], [0.1, 0.1], \sin, 1), gate, doneAction: 2);

src = PlayBuf.ar(1, buffer, BufRateScale.kr(buffer) * rate, 

startPos: start * BufSampleRate.kr(buffer),loop: 1);

Out.ar(0, Pan2.ar(src * env * clean, 0));

Out.ar(routebus, src * env); 

})

);


filter = CtkNoteObject(

SynthDef(\filter, {arg dur = 1, amp = 1, inbus, lowfreq = 440, highfreq = 880;

var env, src, freq, ringtime, filt, loc;

env = EnvGen.kr(Env([0, 1, 1, 0], [0.1, 0.8, 0.1], \sin), timeScale: dur, doneAction: 2);

src = In.ar(inbus);

freq = LFNoise2.kr(dur.reciprocal * 2).range(lowfreq, highfreq);

ringtime = LFNoise2.kr(dur.reciprocal * 2).range(2, 4);

filt = CombC.ar(src, lowfreq.reciprocal, freq.reciprocal, ringtime) * amp;

loc = LFNoise2.kr(dur.reciprocal);

Out.ar(0, Pan2.ar(filt * env, loc));

})

);

a = {arg path, rate = 1, start = 0, windowsize = 2, overlaps = 8, clean = 1,

filtamp = 1;

var cond, buffer, node, routebus, routine, group, waittime;

buffer = CtkBuffer.playbuf(path);

node = player.new(addAction: 0, target: group);

routebus = CtkAudio.new;

group = CtkGroup.new;

waittime = windowsize / overlaps;

routine = Routine({

cond = Condition.new;

buffer.load;

s.sync(cond);

group.play;

node.buffer_(buffer).rate_(rate).routebus_(routebus).clean_(clean).play;

inf.do({

filter.new(addAction: 1, target: group).dur_(windowsize).amp_(filtamp).inbus_(routebus)

.lowfreq_(1).highfreq_(3).play;

waittime.wait;

});

});

routine.play;

[buffer, node, routine, group]; // return the buffer id, node id, the task and the group

};

)


#b, n, t, g = a.value("sounds/SS-VioPartEdited2E.aiff", 1, 0, 6, 8, 1, 0.1);

#b, n, t, g = a.value("sounds/accordian.wav", 1, 0, 6, 8, 1, 0.1);

// change the amount of clean sound

n.clean_(0.0);

// stop the soundfile input, and the loop;

n.release; t.stop;

// free the buffer

b.free;



/* PitchShift */

(

var player, pshift;


player = CtkNoteObject(

SynthDef(\player, {arg gate = 1, buffer, rate, routebus, start = 0, clean = 1;

var env, src;

env = EnvGen.kr(Env([0, 1, 0], [0.1, 0.1], \sin, 1), gate, doneAction: 2);

src = PlayBuf.ar(1, buffer, BufRateScale.kr(buffer) * rate, 

startPos: start * BufSampleRate.kr(buffer),loop: 1);

Out.ar(0, Pan2.ar(src * env * clean, 0));

Out.ar(routebus, src * env); 

})

);


pshift = CtkNoteObject(

SynthDef(\pshift, {arg dur = 1, amp = 1, inbus, psratio = 1;

var env, src, ps, loc;

env = EnvGen.kr(Env([0, 1, 1, 0], [0.1, 0.8, 0.1], \sin), timeScale: dur, doneAction: 2);

src = In.ar(inbus);

ps = PitchShift.ar(src, 0.11, psratio, 0, 0.02);

loc = LFNoise2.kr(dur.reciprocal);

Out.ar(0, Pan2.ar(ps * env, loc));

})

);

a = {arg path, rate = 1, start = 0, windowsize = 2, overlaps = 8, clean = 1,

psamp = 1, freqs = [1, 0.5, 2];

var cond, buffer, node, routebus, routine, group, waittime;

buffer = CtkBuffer.playbuf(path);

group = CtkGroup.new;

node = player.new(addAction: 0, target: group);

routebus = CtkAudio.new;

waittime = windowsize / overlaps;

routine = Routine({

cond = Condition.new;

buffer.load;

s.sync(cond);

group.play;

node.buffer_(buffer).rate_(rate).routebus_(routebus).clean_(clean).play;

inf.do({arg i;

pshift.new(addAction: 1, target: group).dur_(windowsize).amp_(psamp).inbus_(routebus)

.psratio_(freqs.wrapAt(i)).play;

waittime.wait;

});

});

routine.play;

[buffer, node, routine, group]; // return the buffer id, node id, the task and the group

};

)


#b, n, t, g = a.value("sounds/SS-VioPartEdited2E.aiff", 1, 0, 10, 3, 1, 1, [3, -5, 12, -7, 3, -7].midiratio);

#b, n, t, g = a.value("sounds/accordian.wav", 1, 0, 10, 3, 1, 1, [3, -5, 12, -7, 3, -7].midiratio);

// change the amount of clean sound

n.clean_(0.0);

// stop the soundfile input, and the loop;

n.release; t.stop;

// free the buffer

b.free;


/* For tonight

[UGens] - look at the filters and delays especially

[BEQSuite]

[PitchShift]

*/