// day3: in+out & node order, envelopes, tasks, patterns

new docs: 
	to put into help/
		AllDemandUGens.html
		AllPatterns.htm
		OpUGens.rtf

// original
20.do { arg i;  { SinOsc.ar((i+1) * 300, 0, LFNoise2.kr((i+1)*0.5).exprange(0.001, (i+1).reciprocal) * 0.3) }.play }
		
// "home work" solution	:	
(
SynthDef("additiv", { arg freq=300.0, rate=1, amp=1;
	var sig, mod;
	mod = LFNoise2.kr(rate).exprange(0.001, amp);
	sig = SinOsc.ar(freq, 0, mod * 0.3);
	Out.ar(0, sig)
}).store;
)

20.do { arg i; Synth("additiv", [\freq, (i+1) * 300, \rate, (i+1)*0.5, \amp, (i+1).reciprocal]) }

// SinOsc.ar(300).range(0, 30)
		
(
SynthDef("snd", { arg buf=0, rate=1, out=0;
	var sig;
	sig = PlayBuf.ar(1, buf, rate * BufRateScale.kr(buf), loop: 1);
	Out.ar(out, sig);
	}).store;
	
SynthDef("fx", { arg in=0, dt=0.3, out=0;
	var sig;
	sig = In.ar(in, 1);
	sig = CombN.ar(sig, 2.0, dt, 3.0);
	Out.ar(out, sig);
	}).store;
)		

b = Buffer.loadDialog;
b.play

y = Synth("snd", [\buf, b.bufnum])

f = Synth("fx")
f.free	

y = Synth("snd", [\buf, b.bufnum])

f = Synth("fx", [], y, \addAfter)
f.moveBefore(y)
f.moveAfter(y)

(
SynthDef("sndsend", { arg buf=0, rate=1, out=0, aux=30, send=0.4;
	var sig;
	sig = PlayBuf.ar(1, buf, rate * BufRateScale.kr(buf), loop: 1);
	Out.ar(aux, sig * send);
	Out.ar(out, sig);
	}).store;
)

y = Synth("sndsend", [\buf, b.bufnum, \aux, 30])

f = Synth("fx", [\in, 30], y, \addAfter)
y.set(\send, 0)
y.set(\send, 1)
y.set(\aux, 31)		

y = Synth("snd", [\buf, b.bufnum])

f = Synth.after(y, "fx")

(
SynthDef("envtest", { arg freq=300, amp=0.3;
	var sig, env;
	env = EnvGen.kr(Env([0, 1, 0.3, 0], [ 0.1, 0.1, 0.8], -2));
	sig = Saw.ar(freq, env * amp);
	Out.ar(0, sig);
}).play
)	

(
SynthDef("envtest", { arg freq=300, amp=1;
	var sig, env;
	env = EnvGen.kr(Env([0, 1, 0.3, 0], [ 0.1, 0.1, 0.8], -2), doneAction: 2 );
	sig = Saw.ar(freq, env * amp);
	Out.ar(0, sig);
}).play
)	

(
SynthDef("envtest", { arg freq=300, amp=1, gate=1;
	var sig, env;
	env = EnvGen.kr(Env([0, 1, 0.3, 0], [ 0.1, 0.1, 0.8], -2, 2), gate, doneAction: 2 );
	sig = Saw.ar(freq, env * amp);
	Out.ar(0, sig);
}).store
)	

y = Synth("envtest")
y.set(\gate, 0)

y.release(0.1);
y.release(6);

(
SynthDef("snd", { arg buf=0, rate=1, out=0;
	var sig;
	sig = PlayBuf.ar(1, buf, rate * BufRateScale.kr(buf), loop: 1);
	Out.ar(out, sig);
	}).store;
	
SynthDef("fx", { arg in=0, out=0;
	var sig;
	sig = In.ar(in, 1);
	sig = Resonz.ar(sig, LFNoise1.kr(4).range(300, 2000), 0.1);
	ReplaceOut.ar(out, sig);
	}).store;
)

y = Synth("snd", [\buf, b.bufnum])

f = Synth.after(y, "fx")
f.free

//Out.kr(0,   writes to the first Control bus
//Out.ar(0, 	 writes to the first Audio bus	
(
// sine grain SynthDef:
SynthDef("sinegrain", { arg freq=400, amp=0.2, dur=0.3, pan=0;
	var env, sig;
	// envelope with 2 s-like segments of the same length:
	env = EnvGen.ar(Env([0, amp, 0], [dur*0.5, dur*0.5], \sine), doneAction: 2);
	sig = SinOsc.ar(freq, 0, env);
	sig = Pan2.ar(sig, pan);
	// OffsetOut for a more precise timing
	OffsetOut.ar(0, sig); 
}).send(s);

// Synthdef for buffer granulation:
SynthDef("bufgrain", { arg buf=0, rate=1, start=0, amp=0.2, dur=0.3, pan=0;
	var env, sig;
	env = EnvGen.ar(Env([0, amp, 0], [dur*0.5, dur*0.5], \sine), doneAction: 2); 
	sig = PlayBuf.ar(1, buf, rate * BufRateScale.ir(buf), 1, start * BufSamples.ir(buf), 0);
	sig = Pan2.ar(sig * env, pan);
	OffsetOut.ar(0, sig);
}).send(s);
)	

// just a test with the defaults:
Synth("sinegrain"); 

// ... and also other values
Synth("sinegrain", [\freq, 2000, \dur, 0.01, \amp, 0.9, \pan, 0]); 

t = Task({ 3.postln; 2.wait; "hello".postln; 1.5.wait; "done".postln })

t.start
t.stop

t = Task( { inf.do { 1.5.wait; "tick".postln } }).start

// example 1: harmonic series sucessively
(
t = Task({
	var next, fr, vol, pos, dur;
	20.do({ arg i;
		dur = 0.2;  
		next = dur * 0.8; // calculation of the inter-onset time
		vol 	= 0.1;
		pos 	= rrand(-1.0, 1.0);
		fr	= (i+1) * 200;
		Synth("sinegrain", [\dur, dur, \freq, fr, \pan, pos, \amp, vol]);
		next.wait;	// wait before doing the next iteration of the do-loop
	});
})
)

t.start

// example 2: granular reconstructed sine tone 
(
t = Task({
	var next, fr, vol, pos, dur;
	inf.do({ arg i;
		dur = 0.2;
		next = dur * 0.5;	// this means an overlap of 2 grains
		vol 	= 0.5;
		pos 	= 0;
		fr	= 300;
		// start the synths in the future but precisely !:
		s.makeBundle(0.1, { Synth("sinegrain", [\dur, dur, \freq, fr, \pan, pos, \amp, vol]) });
		// try it without makeBundle!:
		// Synth("sinegrain", [\dur, dur, \freq, fr, \pan, pos, \amp, vol]) ;
		next.wait;	
	});
})
)

t.start

// example 3: dense random texture:
(
t = Task({
	var next, fr, vol, pos, dur;
	inf.do({ arg i;
		dur 	= 0.02;
		next = dur * rrand(0.1, 0.4);	// variable overlap
		vol 	= 0.1;
		pos 	= rrand(-1.0, 1.0);
		fr	= rrand(1000.0, 1040.0);
		Synth("sinegrain", [\dur, dur, \freq, fr, \pan, pos, \amp, vol]);
		next.wait;	
	});
})
)

// example 4: dense harmonic texture:
(
t = Task({
	var next, fr, vol, pos, dur;
	inf.do({ arg i;
		dur 	= 0.4;
		next = dur * rrand(0.02, 0.04);
		vol 	= 0.1;
		pos 	= rrand(-1.0, 1.0);
		fr	= rrand(1, 20) * 100;	// only integer multiples of 100
		Synth("sinegrain", [\dur, dur, \freq, fr, \pan, pos, \amp, vol]);
		next.wait;	
	});
})
)

t.start

e = Env([0, 100, 0], [5, 20], \lin)
a = Array.series(5, 100, 5);

a.at(1)
a.at(10)
a.wrapAt(9)
a.foldAt(9)
a.clipAt(-3)
a.wrapAt(-9)

a[3]

e[0]
e[5]
e[4]
e[4.1]
e[4.111]
e[25]
e[26]

(
t = Task({
	var next, fr, vol, pos, dur, env, time;
	env = Env([300, 2000, 500], [10, 10], \lin);
	time = 0;
	inf.do({ arg i;
		dur = 0.1;  
		next = dur * 0.2; // calculation of the inter-onset time
		vol 	= 0.1;
		pos 	= rrand(-1.0, 1.0);
		fr	= env[time];
		Synth("sinegrain", [\dur, dur, \freq, fr, \pan, pos, \amp, vol]);
		next.wait;	// wait before doing the next iteration of the do-loop
		time = time + next;
	});
})
)

t.start

b = Buffer.loadDialog(s);   // only mono soundfiles!

// alternative way (adapt it to your path names) :
b = Buffer.readChannel(s, "/Users/abart/snd/tam-tam.aif", channels: [0]);

// check it if needed:
b.query
b.play

// the duration of the soundfile:
b.duration
// or
b.numFrames / b.sampleRate

// example 5: randomized starting positions (try it with speech sounds):
(
t = Task({
	var next, rate, st, vol, pos, dur;
	inf.do({ arg i;
		dur 	= 0.2;
		next = dur * 0.1;
		vol 	= 0.8;
		pos 	= rrand(-1.0, 1.0);
		rate	= 1;
		st 	= 0.9.rand;	// start position between  0% and 90% of the total duration
		Synth("bufgrain", [\buf, b.bufnum, \dur, dur, \rate, rate, \start, st, \pan, pos, \amp, vol]);
		next.wait;	
	});
})
)

t.start;

t.stop;

// example 7: granular recnstruction of the soundfile,
// constantly rising start position:
(
t = Task({
	var next, rate, st, vol, pos, dur, ovlp, n, totaldur;
	// explizite Angabe des Overlap-Faktors:
	ovlp = 2;
	dur 	= 0.06;
	totaldur = b.numFrames / b.sampleRate;
	// calculation of the number of iterations with the sound durations, the grains duration and the overlap:
	n = ( totaldur / dur * ovlp).asInteger;
	n.do({ arg i;
		next = dur / ovlp;
		vol 	= 0.7;
		pos 	= 0;
		rate	= 1;
		// the start position depends on the iteration number related to the total duration:
		st 	= i * next / totaldur;
		// s.makeBundle(0.1, { Synth("bufgrain", [\buf, b.bufnum, \dur, dur, \rate, rate, \start, st, \pan, pos, \amp, vol]) });
		// try also without makeBundle:
		Synth("bufgrain", [\buf, b.bufnum, \dur, dur, \rate, rate, \start, st, \pan, pos, \amp, vol]);
		next.wait;	
	});
})
)

t.start;

t.stop;

// example 8: time stretching with a ratio of 5:2
(
t = Task({
	var next, rate, st, vol, pos, dur, ovlp, n, totaldur, time;
	time = 1 / 1;
	ovlp = 4;
	dur 	= 0.2;
	totaldur = b.numFrames / b.sampleRate;
	n = (totaldur / dur * ovlp * time).asInteger;
	inf.do({ arg i;
		next = dur / ovlp;
		//next = dur / ovlp * rrand(0.98, 1.02);		// slightly randomized overlap
		vol 	= 0.7;
		pos 	= 0;
		rate	= -1 ;
	 	//rate = rrand(0.98, 1.02);		// slightly randomized pitch
		st 	= (i % n) * next / totaldur / time;
		//st 	= (n-i) * next / totaldur / time   // backwards!
		s.makeBundle(0.1, { Synth("bufgrain", [\buf, b.bufnum, \dur, dur, \rate, rate, \start, st, \pan, pos, \amp, vol]) });
		next.wait;	
	});
})
)

t.start;
t.stop;

11.wrap(0, 9)
11 % 10

(
SynthDef("test", {
	var freqpatt, freq, trig, sig;
	trig = Impulse.kr(2);
	freqpatt = Dseries(1, 1, 10);
	freq = Demand.kr(trig, 0, freqpatt);
	sig = Saw.ar(freq * 300);
	Out.ar(0, sig)
	}).play
)	
	
[0, 2,2,1,2,2,1].integrate
	
(
SynthDef("test", {
	var freqpatt, freq, trig, sig, env;
	trig = Impulse.kr(20);
	freqpatt = Dxrand( [0,1,3,1,1,3,1,2].integrate, 1000);
	freq = Demand.kr(trig, 0, freqpatt);
	env = Decay2.kr(trig, 0.01, 0.5);
	sig = Saw.ar((freq + 60).midicps, env);
	Out.ar(0, sig)
	}).play
)	

(
SynthDef("test", {
	var freqpatt, freq, trig, sig, env;
	trig = Impulse.kr(20);
	freqpatt = Dwhite(0, 12 , 1000);
	freq = Demand.kr(trig, 0, freqpatt);
	env = Decay2.kr(trig, 0.01, 0.5);
	sig = Saw.ar((freq + 60).midicps, env);
	Out.ar(0, sig)
	}).play
)	

(
SynthDef("test", {
	var freqpatt, freq, trig, sig, env;
	trig = Dust.kr(3);
	freqpatt = Dseq([ Diwhite(0, 5, 3), 20, Dseq([2,4,6,8,10], 1)] , 1000);
	freq = Demand.kr(trig, 0, freqpatt);
	env = Decay2.kr(trig, 0.01, 0.5);
	freq= (freq + 60).midicps;
	sig = Saw.ar(freq, env);
	sig = RLPF.ar(sig, (env*8+1)*freq, 0.1);
	Out.ar(0, sig)
	}).play
)	

Pattern

p = Pseq([10, 20, 30, 40], 1);
q = p.asStream;

p
q		

q.next
q.next

p = Pseq([10, 20, 30, 40], inf);
q = p.asStream;

q.next

p = Prand([10, 20, 30, 40], inf);
q = p.asStream;
q.next

p = Prand([10, 20, 30, 40], 3);
q = p.asStream;
q.next

p = Pwhite(0, 20, 3);
q = p.asStream;
10.do { q.next.postln }

p = Pseq(["hello", \symbol, 30.0, 3.sqrt], inf);
q = p.asStream;
10.do { q.next.postln }

p = Pseq([ Pwhite(-10, 10, 4), \symbol, Prand([\a, \b, \c, \d], 2), 3.sqrt], inf);
q = p.asStream;
10.do { q.next.postln }
q.reset
10.do { q.next.postln }

p = Pfunc({ rrand(20, 40) })
q = p.asStream;
10.do { q.next.postln }

(
p = Pfuncn({ rrand(20, 40) }, 100);
q = p.asStream;
10.do { q.next.postln };
)

// -----------------
(
SynthDef("chick", {arg freq, dur;
	var res1, res2, sig;
	res1 = XLine.ar(8*freq, freq, dur * 0.7);
	res2 = XLine.ar(3*freq, freq, dur * 0.5);
	sig =  RLPF.ar(Saw.ar([freq, freq/4]),[res1, res2] , 0.09, 
		EnvGen.kr(Env.perc(0.01, dur, 0.5), doneAction: 2));
	Out.ar(0, sig)
	}).send(s);

SynthDef("rev", {
	var in, rev;
	in = In.ar(0, 2);	
	rev = Mix(in);	
	6.do({ rev = LPF.ar(AllpassN.ar(rev, 1.0, [0.05.rand, 0.05.rand], 2.0), 7000)});
	ReplaceOut.ar(0, (in * 0.6) + (rev * 0.3))
	}).send(s);
)	

( // Chick Corea meets Iannis Xenakis
var pnote, rhythms, weights, pdur, tempo;

// random walk between 36 and 86, maximum step 7 :
pnote = Pbrown(48, 92, 7, inf).asStream; 
// MM / BPM:
tempo = 140;			
// various note durations :		
rhythms = [1/2, 1/4, 1/8, 1/16, 1/12, 1/6]; 
// with different weights :
weights = [2, 2, 4, 20, 12, 3];		
// weighted random access pattern for durations:
pdur = Pwrand( rhythms * 60 * 4/tempo, weights / weights.sum, inf).asStream; 

t = Task({
	var dur, freq, rev, group;
	// start a group on the server:
	group = Group(s);
	// start the reverb synth after this group:
	rev = Synth.after(group, "rev");
	// an infinite do-loop:
	loop({
		// read the next pitch value from the pnote stream:
		freq = pnote.next.midicps;	
		// read the next duration value from the pdur stream:
		dur = pdur.next;							// start the notes within the group on the server:
		Synth("chick", [\freq, freq, \dur, dur], group);
		// pause before playing the next note:
		dur.wait;
		})
	})	
)

t.start;

t.stop;