///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// 1. Simple Sine Sound
// Make and control a simple sound
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////

// Ugen wrapped in a play.  This does all the nasty stuff for you, but then you want to be able to do the nasty stuff.

{ SinOsc.ar(200, 0, 0.5) }.play;

// and here's the nasty stuff
(
SynthDef( "simple", {
	var out;
	out = SinOsc.ar(200, 0, 0.5);
	Out.ar(0, out)
	}).send(s);
)

Synth( "simple" ); //fine, but I can't stop it without cmd-.

// Here I've called it 'a', but it could be ~anything with a tilde (~) in front.
// and now I can play it
a = Synth( "simple" );

// and stop it in code.
a.free;

// now here it is with an envelope
(
SynthDef( "simple", {
	var out, env;
	env = EnvGen.kr(Env.linen(1, 2, 3, 0.6));
	out = SinOsc.ar(200, 0, env);
	Out.ar(0, out)
	}).send(s);
)

// note synths in the localhost server window
a = Synth( "simple" );

// evaluate the above many times, noting the synths.
// then evalute the below, noting the number of synths.
a.free;
// to clear all the synths now, you have to use cmd-.  Use it!

// here, doneAction means that the synth is released after playing.
// Evaluate
(
SynthDef( "simple", {
	var out, env;
	env = EnvGen.kr(Env.linen(1, 2, 3, 0.6), doneAction: 2);
	out = SinOsc.ar(200, 0, env);
	Out.ar(0, out)
	}).send(s);
)

// play
Synth( "simple" );
// note synths in the localhost server window

(
SynthDef( "simple", { arg freq = 400;
	var out, env;
	env = EnvGen.kr(Env.linen(0.1, 0.2, 0.3, 0.6), doneAction: 2);
	out = SinOsc.ar(freq, 0, env);
	Out.ar(0, out)
	}).send(s);
)

Synth( "simple" );

(
SynthDef( "simple", { arg freq = 400;
	var out, env;
	env = EnvGen.kr(Env.perc(0.05, 1, 1, -4), 0.6, doneAction: 2);
	out = SinOsc.ar(freq, 0, env);
	Out.ar(0, out)
	}).send(s);
)

Synth( "simple", [ \freq, 800 ]);

Synth( "simple", [ \freq, 800.rand ]);

Synth( "simple", [ \freq, 60.midicps ]);

Synth( "simple", [ \freq, 127.rand.midicps ]);

Synth( "simple", [ \freq, 127.rand.postln.midicps ]);

Synth( "simple", [ \freq, 127.rand.midicps.postln ]);

(
SynthDef( "simple", { arg freq = 400, dur = 1.0;
	var out, env;
	env = EnvGen.kr(Env.linen(dur*0.1, dur*0.1, dur*0.8, 0.6), 0.6, doneAction: 2);
	out = SinOsc.ar(freq, 0, env);
	Out.ar(0, out)
	}).send(s); // NB send...
)

Synth( "simple", [ \freq, ( 800.rand + 400 ), \dur, 4.0.rand ]);

///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// 2. Tasks
// Automate doing things with the Simple Sound
///////////////////////////////////////////////////////////////////////////
// Do something ten times with a one second wait between each time.
///////////////////////////////////////////////////////////////////////////

(
Task({
	10.do({
		Synth( "simple", [ \freq, ( 800.rand + 400 ), \dur, 1.0 ]);
		1.wait;
	});
}).play;
)

///////////////////////////////////////////////////
// useful to know where we are?
///////////////////////////////////////////////////

(
Task({
	10.do({ arg count;
		Synth( "simple", [ \freq, ( 800.rand + 400 ), \dur, 1.0 ]);
		count.postln;
		1.wait;
	});
}).play;
)

///////////////////////////////////////////////////
// now create a named instance
///////////////////////////////////////////////////
(
a = Task({
	10.do({ arg count;
		Synth( "simple", [ \freq, ( 800.rand + 400 ), \dur, 1.0 ]);
		count.postln;
		1.wait;
	});
}).play; // you don't have to use .play, unless you want it to play when it is evaluated.
)

///////////////////////////////////////////////////
// now we can stop it and restart it, but notice the differences between the stop and reset:
///////////////////////////////////////////////////
a.stop;
a.play;
a.reset;

// note that if the task is completed (played ten times) you need to reset it before you can play it again, so this is useful
a.reset;a.play;

// now this is nice:
b = a;

// and try this:
b = a.copy;

b.stop;
b.play;
b.reset;

///////////////////////////////////////////////////
// you can make the task infinite
///////////////////////////////////////////////////
(
a = Task({
	inf.do({ arg count;
		Synth( "simple", [ \freq, ( 800.rand + 400 ), \dur, 1.0 ]);
		count.postln;
		1.wait;
	});
}).play; // you don't have to use .play, unless you want it to play when it is evaluated.
)

///////////////////////////////////////////////////
// but then you have to start and stop things explicitly
///////////////////////////////////////////////////
a.stop;
a.play;
a.reset;

///////////////////////////////////////////////////
// but if you use an infinite loop, you must include a wait value or you will crash SC
// the following WILL crash, so if you want to try it, make sure you've saved anything you want to save.s
///////////////////////////////////////////////////
(
a = Task({
	inf.do({ arg count;
		Synth( "simple", [ \freq, ( 800.rand + 400 ), \dur, 1.0 ]);
		count.postln;
		// 1.wait;
	});
}).play; // you don't have to use .play, unless you want it to play when it is evaluated.
)

///////////////////////////////////////////////////
// you can, of course, change the length of the delay:
///////////////////////////////////////////////////
(
a = Task({
	10.do({ arg count;
		Synth( "simple", [ \freq, ( 800.rand + 400 ), \dur, 1.0 ]);
		count.postln;
		0.1.wait;
	});
}).play;
)

a.stop;
a.play;
a.reset;

///////////////////////////////////////////////////
// also, be careful of infinite length tasks as,
// if you evaluate them twice without defining them
// separately, you will lose control of the first instance.
// the only option if this happens is command-.
///////////////////////////////////////////////////

///////////////////////////////////////////////////
// you might want to connect the duration and length
///////////////////////////////////////////////////
(
a = Task({
	10.do({ arg count;
		var length = 0.1;
		
		Synth( "simple", [ \freq, ( 800.rand + 400 ), \dur, length ]);
		count.postln;
		length.wait;
	});
}).play;
)

a.stop;
a.play;
a.reset; a.play;

///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// 3. Functions
// Control your tasks easily
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// It would be nice to determine the above value from outside the task
// for this we need to make our own function
// it's exactly the same, but the task is wrapped up in the function
// and we utilise the function by asking for its value:
// ~myFunction.value;
// note the task (a) is still operating and if we want to stop the task we still need to refer to it as 'a'.
///////////////////////////////////////////////////

(
~myFunction = ({
	a = Task({
		10.do({ arg count;
			var length = 0.1;
			
			Synth( "simple", [ \freq, ( 800.rand + 400 ), \dur, length ]);
			count.postln;
			length.wait;
		});
	}).play;
});
)

~myFunction.value;

a.stop;
a.play;
a.reset; a.play;

///////////////////////////////////////////////////
// now we can make our own arguments
///////////////////////////////////////////////////

(
~myFunction = ({ arg length=0.1; // here's the argument, with a default value
	a = Task({
		inf.do({ arg count;
			// we don't need a var anymore as we have an arg
			Synth( "simple", [ \freq, ( 800.rand + 400 ), \dur, length ]);
			count.postln;
			length.wait;
		});
	}).play;
});
)

~myFunction.value(0.3);

a.stop;
a.play;
a.reset; a.play;

///////////////////////////////////////////////////
// note that setting the argument length to zero will crash SC
// now you can use a combined command to alter value as we're going
///////////////////////////////////////////////////

(
~myFunction = ({ arg length=0.1; // here's the argument, with a default value
	a = Task({
		inf.do({ arg count;
			// we don't need a var anymore as we have an arg
			Synth( "simple", [ \freq, ( 800.rand + 400 ), \dur, length ]);
			count.postln;
			length.wait;
		});
	}).play;
});
)

~myFunction.value(0.3);

(
a.stop;
~myFunction.value(0.2);
)

// or

a.stop; ~myFunction.value(0.2.rand);

///////////////////////////////////////////////////
// now the function has a life of it's own, and we can use it in another task!
///////////////////////////////////////////////////

(
	b = Task({
		10.do({ arg count;
			a.stop; ~myFunction.value(0.2.rand);
			[ "b = " ++ count ].postln; // so we know where we are with the second loop
			2.wait;
		});
		a.stop; // without this the last 'a' won't stop
	}).play;
);

// remember stopping b won't stop as well, so
b.stop; 
b.stop; a.stop;
b.reset; b.play;

// now make a function to control b?

///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// 4. Patterns: which notes to play - Arrays and Control Structures
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////

// Let's use a different synth for a change.  Feel free to investigate it, alter it, or choose something else.

(
SynthDef("MyBlip", { 
	arg pitch=69, nharm=4, amp=0.05, decay=1; 
	var snd, env, pos, wobble, freq;
	freq = pitch.midicps;
	wobble = LFNoise1.kr(Rand(2, 5), freq * 0.0025, freq * 0.0025);
	snd = Blip.ar(freq + wobble, nharm);
	env = EnvGen.kr(Env.perc(releaseTime:decay), doneAction:2); 
	pos = Line.kr(-1, 1, decay);
	Out.ar(0, Pan2.ar(snd * env, Rand(-1, 1), amp));
}).send(s);
)

(
	var pitch;
	d = 1/8; // duration in fraction of a second.  Change it and see... You can also use decimals (1/8 = 0.125)
	// A Task is something that can start and stop and that you can return to.
	// Here the task loops around a series of numbers.
	r = Task({

		loop({
						pitch = 60;
						// pitch = [35, 49, 57, 69, 71, 75, 78].choose;
						Synth( "MyBlip", [ \pitch, pitch, \nharm, [2,3,4,5,6,7,8].choose ] );
						d.wait; // this must be set to a non-zero value
				});
		}).play;
)

r.play;
d = 1
d = 0.1 // setting this to zero will crash SC
r.stop;

///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// Now using arrays:

(
	var pitch, count = 0;
	d = 1/8; // duration in fraction of a second.  Change it and see... You can also use decimals (1/8 = 0.125)
	// A Task is something that can start and stop and that you can return to.
	// Here the task loops around a series of numbers.
	a = [ 60, 62, 63, 65, 67 ];
	r = Task({

		loop({
				(a.size).do({
						pitch = a[count];
						pitch.postln;
						Synth( "MyBlip", [ \pitch, pitch, \nharm, [2,3,4,5,6,7,8].choose ] );
						d.wait;
						count = count + 1;
				});
				count = 0
		});
	}).play;	
)

r.play;
d = 1
d = 0.11
d = 0.03
r.stop;
a = [ 45, 46, 47, 48, 50 ]
a = [ 80, 82, 84, 86 ]
a = [ 60, 62, 46 ]
a = a + 2
a = a - 2

///////////////////////////////////////////////////////////////////////////
// Control Structures
// The above has a problem with the loop.  Assume the 'do' is underway 10 times because the array has 	10 items in it.  It has just reached it's fourth iteration.  At that point you change the array so that it only has three items.  At the next iteration, you try to assign the fifth member of the array to 'pitch'.  This doesn't exist so the task will end in an error.  You can get around it like this - see if you can follow it:

(
	var pitch, count = 0;
	d = 0.125; 
	a = [ 60, 62, 63, 65, 67 ];
	r = Task({

		loop({
				while ( { count < a.size }, 
					{
						pitch = a[count];
						pitch.postln;
						Synth( "MyBlip", [ \pitch, pitch, \nharm, [2,3,4,5,6,7,8].choose ] );
						d.wait;
						count = count + 1;
					});
				count = 0
		});
	}).play;	
)

r.play;
d = 1
d = 0.11
d = 0.03
r.stop;
a = [ 45, 46, 47, 48, 50, 60, 62, 63, 65, 67 ]
a = [ 45 ]
a = a + 2.rand
a = a - 2.rand
a = [ 60, 62, 63, 65, 67 ];

///////////////////////////////////////////////////////
// One level of if:
///////////////////////////////////////////////////////

(
	var pitch, count = 0;
	d = 1/8; // duration in fraction of a second.  Change it and see... You can also use decimals (1/8 = 0.125)
	// A Task is something that can start and stop and that you can return to.
	// Here the task loops around a series of numbers.
	r = Task({
		loop({
					// there's a 50% chance that 0.5.coin will evaluate as 'true'
					// if it does, the first function will be evaluated (pitch will equal 60)
					// otherwise, pitch will be set to 72, an octave higher
					if ( 0.5.coin, { pitch = 60 }, { pitch = 72 });
					Synth( "MyBlip", [ \pitch, pitch ] );
					d.wait;
				});
		}).play;
)

r.play;
r.stop;

///////////////////////////////////////////////////////
// The first if option contains its own array
///////////////////////////////////////////////////////

(
	var pitch, count = 0;
	d = 0.125;
	
	r = Task({
	a = [ 60, 62, 63, 65, 67 ];
	
		loop({
					if ( 0.5.coin, 
						{ // first choice
								while ( { count < a.size }, 
										{
											pitch = a[count];
											pitch.postln;
											Synth( "MyBlip", [ \pitch, pitch ] );
											d.wait;
											count = count + 1;
										});
									count = 0
						 }, // end first choice
						// second choice (notice how frequently this will be chosen
						// many times in a row...)
						{ pitch = [ 72, 79, 84, 86, 87, 89, 91, 96 ].choose } 
						);
						Synth( "MyBlip", [ \pitch, pitch ] );
						d.wait;
				}); // end loop
		}).play; // end task
)

r.play;
r.stop;
d = 0.2;

///////////////////////////////////////////////////////
// Each if option contains its own array
///////////////////////////////////////////////////////

(
	var pitch, count = 0;
	d = 0.125; 
	
	r = Task({
	a = [ 60, 62, 63, 65, 67 ];
	b = [ 59, 61, 62, 64, 66 ];
	
		loop({
					if (0.5.coin, 
						{ // first choice
							while ( { count < a.size }, 
								{
									pitch = a[count];
									Synth( "MyBlip", [ \pitch, pitch ] );
									d.wait;
									count = count + 1;
								})
						 }, 
						{ // second choice
							while ( { count < b.size }, 
								{
								pitch = b[count];
								Synth( "MyBlip", [ \pitch, pitch ] );
								d.wait;
								count = count + 1;
							})
						 } // end second choice 
						);
						Synth( "MyBlip", [ \pitch, pitch ] );
						d.wait;
						count = 0;
				}); // end loop
		}).play; // end task
)

r.play;
r.stop;
d = 0.1;
a = [ 80, 82, 84, 85, 86 ];
a = a - 2;

///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
// Case
///////////////////////////////////////////////////////

(
	var pitch, myCase, myChoices, myChoice;
	d = 0.125; 
	
	r = Task({

		loop({
				myChoices = [ 0, 1 ]; // just two choices - there could be many...
				myChoice = myChoices.choose; // choose one
				
				case // here's the case
				{ myChoice == 0 } { pitch = 60 }
				{ myChoice == 1 } { pitch = 72 };
	
				Synth( "MyBlip", [ \pitch, pitch ]);
				d.wait;
				});
		}).play;
)

r.play;
r.stop;

///////////////////////////////////////////////////////
// Using Case with arrays
///////////////////////////////////////////////////////

(
	var pitch, myCase, myChoices, myChoice;
	var count = 0;
	d = 0.125; 
	a = [ 60, 63, 67, 72, 74 ];
	
	r = Task({

		loop({
				myChoices = [ 0, 1 ]; // just two choices - there could be many...
				myChoice = myChoices.choose; // choose one
				
				case // here's the case
				{ myChoice == 0 } 
				{ 
					count = 0;
					"myChoice is 0!".postln; // you can get rid of this!
					while ( { count < a.size }, 
						{
							pitch = a[count];
							Synth( "MyBlip", [ \pitch, pitch ] );
							d.wait; // try it without the wait here...
							count = count + 1;
					});
				} // note the lack of semicolon;
				// here all the commands are put on one line separated by semicolons.
				// you can remove the postln part if you want.  Go on, try it...
				{ myChoice == 1 } { 	"myChoice is 1!".postln; pitch = 72; Synth( "MyBlip", [ \pitch, pitch ]); 	d.wait; };

				});
		}).play;
)

r.play;
r.stop;

///////////////////////////////////////////////////////
// Using Case with two arrays - you can use any number of cases...
///////////////////////////////////////////////////////
(
	var pitch, myChoices, myChoice;
	var count = 0;
	d = 0.15; 
	a = [ 60, 63, 67, 72, 74 ];
	b = [ 59, 62, 67, 71 ];
	
	r = Task({

		loop({
				myChoices = [ 0, 1 ]; // just two choices - there could be many...
				myChoice = myChoices.choose; // choose one
				
				case // here's the case
				{ myChoice == 0 } 
				{ 
					count = 0;
					while ( { count < a.size }, 
						{
							pitch = a[count];
							Synth( "MyBlip", [ \pitch, pitch ] );
							d.wait; // try it without the wait here...
							count = count + 1;
					})
				} // end of first case
				
				{ // second case
					count = 0;
					while ( { count < b.size }, 
						{
							pitch = b[count];
							Synth( "MyBlip", [ \pitch, pitch ] );
							d.wait; // try it without the wait here.  Try it without either wait, but you must include the one below!
							count = count + 1;
					})
				};
			// 0.1.wait;
			});  // end loop
		}).play; // end task
)

r.play;
r.stop;

d = 0.1

a = a + 12;
b = b + 12;
a = a - 12;
b = b - 2;

///////////////////////////////////////////////////////
// Another example
///////////////////////////////////////////////////////
// is there a problem with the below?

(
	var pitch, myCase, myChoices, myChoice;
	var count = 0;
	d = 0.015; 
	a = [ 60, 63, 67, 72, 74 ];
	b = [ 59, 62, 67, 71 ];
	
	r = Task({

		loop({
				myChoices = [ 0, 1 ]; // just two choices - there could be many...
				myChoice = myChoices.choose; // choose one
				
				case // here's the case
				{ myChoice == 0 } 
				{ 
					count = 0;
					while ( { count < a.size }, 
						{
							pitch = a[count];
							Synth( "MyBlip", [ \pitch, pitch ] );
							d.wait; // try it without the wait here...
							count = count + 1;
						}); // end do
					a = a + 1; //!
				} // end of first case
				
				{ // second case
					count = 0;
					while ( { count < b.size }, 
						{
							pitch = b[count];
							Synth( "MyBlip", [ \pitch, pitch ] );
							d.wait; // try it without the wait here...
							count = count + 1;
						}); // end do
					b = b - 1;
				};
				d = d + 0.001; // !
				d.postln;
				});  // end loop
		}).play; // end task
)

r.play;
r.stop;

///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// Arrays with functions

// From above

(
	var pitch, count = 0;
	d = 0.125; 
	a = [ 60, 62, 63, 65, 67 ];
	r = Task({

		loop({
				while ( { count < a.size }, 
					{
						pitch = a[count];
						pitch.postln;
						Synth( "MyBlip", [ \pitch, pitch, \nharm, [2,3,4,5,6,7,8].choose ] );
						d.wait;
						count = count + 1;
					});
				count = 0
		});
	}).play;	
)

r.play;
d = 1
d = 0.11
d = 0.03
r.stop;
a = [ 45, 46, 47, 48, 50, 60, 62, 63, 65, 67 ]
a = [ 45 ]
a = a + 2.rand
a = a - 2.rand
a = [ 60, 62, 63, 65, 67 ];

///////////////////////////////////////////////////////////////////////////
// Encase in a function:

(
~myAlgorithm = ({ arg arpWait = 0.1, loopWait = 1.0;
	var pitch, count = 0;
	d = 0.1; 
	a = [ 60, 62, 63, 65, 67 ];
	
	r = Task({

		loop({
				while ( { count < a.size }, 
					{
						pitch = a[count];
						pitch.postln;
						Synth( "MyBlip", [ \pitch, pitch, \nharm, [2,3,4,5,6,7,8].choose ] );
						arpWait.wait;
						count = count + 1;
					});
				count = 0;
				loopWait.wait;
		});
	}).play;	

});
)

~myAlgorithm.value;
r.stop;

///////////////////////////////////////////////////////////////////////////
// Develop Arguments

(
~myAlgorithm = ({ arg pitchArray = [ 60, 62, 63, 65, 67 ], myWait = 0.125;
	var pitch = 60, count = 0;
	
	r = Task({

		loop({
				while ( { count < pitchArray.size }, 
					{
						pitch = pitchArray[count];
						pitch.postln;
						Synth( "MyBlip", [ \pitch, pitch, \nharm, [2,3,4,5,6,7,8].choose ] );
						//if ( myWait == 0.0, { 0.01.wait}, { myWait.wait} );
						myWait.wait;
						count = count + 1;
					});
				count = 0
		});
	}).play;	

});
)

// now, because of the defaults above, it works without arguments:
~myAlgorithm.value;
r.stop;

// but you can also include them:
~myAlgorithm.value([ 50, 52, 53, 55, 57 ]);
r.stop;

// and so include various controls:
(
r.stop;
~myAlgorithm.value([ 24, 36, 58, 56 ], 0.2);
)

(
r.stop;
a = 10.rand + 60;
~myAlgorithm.value([ a, a+2, a+3, a+5, a+7 ], 0.3.rand);
)

///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// 5. Scheduling
// Decide when to run your functions
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// in one of the above task/function we decided which parameters of our function are going to be run and chose those within a task, according to a wait value.  This is a rudimentary form of scheduling.

(
var myTime = 2.0;

SystemClock.schedAbs( (thisThread.seconds + myTime),
	{
	(
		"your functions go in here".postln;
	);
	}); // end clock
)

///////////////////////////////////////////////////////////////////////////
// More complex...

(
var wholeTime = 0.0;

wholeTime = thisThread.seconds + 0.0;

SystemClock.schedAbs( wholeTime,
	{
	(
		"start".postln;
	);
	}); // end clock
	
wholeTime = thisThread.seconds + 2.0;

SystemClock.schedAbs( wholeTime,
	{
	(
		"Two seconds".postln;
	);
	}); // end clock
	
wholeTime = thisThread.seconds + 6.0;
// or
// wholeTime = wholeTime + 4.0;

SystemClock.schedAbs( wholeTime,
	{
	(
		"Six seconds from the start, four seconds later".postln;
	);
	}); // end clock
)

///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// 6. Synthesis
// Colour your music
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// Additive Synthesis:
// Creating a bell sound

// John-Claude Risset
// Introductory catologue of copmputer-synthesized sounds
// Bell Telephone Laboritories, 1967.
// Data reproduced in Dodge, C. and Jerse, T.A. (1997), Computter Music, 2nd Edn. London: Schirmer, p.105.

(
h = [0.56, 0.56, 0.92, 0.92, 1.19, 1.7, 2, 2.74, 3, 3.76, 4.07];
g = [0, 1, 0 , 1.7, 0, 0, 0, 0, 0, 0, 0]; // g is an added to the freq
d = [1, 0.9, 0.65, 0.55, 0.325, 0.35, 0.25, 0.2, 0.15, 0.1, 0.075];
a = [1, 0.67, 1, 1.8, 2.67, 1.67, 1.46, 1.33, 1.33, 1, 1.33];

(
~out = { 
	Pan2.ar(
		Mix.fill(11, { |i|
			SinOsc.ar(LFNoise0.kr(20.reciprocal, 100, 300) * h[i] + g[i], 0, a[i]/20) * EnvGen.ar(Env.perc(0, 20*d[i], 1, -2), Impulse.kr(2.reciprocal))
		} ), 
		pos: LFNoise0.kr(20.reciprocal)
	)
};
)
)

~out.play; 

///////////////////////////////////////////////////////////////////////////
// Subtractive Synthesis

Noise + Filter model 
Noise are as shown in earlier lessons
What distinguishes noise from other UGens is that noise UGens have no single frequency.

Filters "filter out" certain parts of the frequency spectrum according to their type.

///////////////////////////////////////////////////////////////////////////
// Common filter UGens (see help files)

///////////////////////////////////////////////////////////////////////////
// LPF
{ LPF.ar(Saw.ar(200, 0.1), SinOsc.kr(XLine.kr(0.7, 300, 20), 0, 3600, 4000)) }.play;

///////////////////////////////////////////////////////////////////////////
// HPF
{ HPF.ar(Saw.ar(200,0.1), FSinOsc.kr(XLine.kr(0.7, 300, 20), 0, 3600, 4000), 5) }.play;

///////////////////////////////////////////////////////////////////////////
// BPF
{ BPF.ar(Saw.ar(200, 0.5), SinOsc.kr(XLine.kr(0.7, 300, 20), 0, 3600, 4000), 0.3) }.play;

///////////////////////////////////////////////////////////////////////////
// MidEQ
{ MidEQ.ar(Saw.ar(200,0.2), FSinOsc.kr(1, 0, 24, 84).midicps, 0.3, 12) }.play

///////////////////////////////////////////////////////////////////////////
// RLPF
{ RLPF.ar(Saw.ar(200, 0.1), FSinOsc.kr(XLine.kr(0.7, 300, 20), 0, 3600, 4000), 0.2) }.play;

///////////////////////////////////////////////////////////////////////////
// "Resonant Filters" are 

///////////////////////////////////////////////////////////////////////////
// Resonz
{ Resonz.ar(WhiteNoise.ar(0.5), 2000, 0.1) }.play

// modulate frequency
{ Resonz.ar(WhiteNoise.ar(0.5), XLine.kr(1000,8000,10), 0.05) }.play

// modulate bandwidth
{ Resonz.ar(WhiteNoise.ar(0.5), 2000, XLine.kr(1, 0.001, 8)) }.play

// modulate bandwidth opposite direction
{ Resonz.ar(WhiteNoise.ar(0.5), 2000, XLine.kr(0.001, 1, 8)) }.play

///////////////////////////////////////////////////////////////////////////
// Ringz 
{ Ringz.ar(Dust.ar(3, 0.3), 2000, 2) }.play

{ Ringz.ar(WhiteNoise.ar(0.005), 2000, 0.5) }.play

// modulate frequency
{ Ringz.ar(WhiteNoise.ar(0.005), XLine.kr(100,3000,10), 0.5) }.play

{ Ringz.ar(Impulse.ar(6, 0, 0.3),  XLine.kr(100,3000,10), 0.5) }.play

// modulate ring time
{ Ringz.ar(Impulse.ar(6, 0, 0.3),  2000, XLine.kr(4, 0.04, 8)) }.play

// modulate ring time opposite direction
{ Ringz.ar(Impulse.ar(6, 0, 0.3), 2000, XLine.kr(0.04, 4, 8)) }.play

///////////////////////////////////////////////////////////////////////////
// Klank
{ Klank.ar(`[[800, 1071, 1153, 1723], nil, [1, 1, 1, 1]], Impulse.ar(2, 0, 0.1)) }.play;

{ Klank.ar(`[[800, 1071, 1353, 1723], nil, [1, 1, 1, 1]], Dust.ar(8, 0.1)) }.play;

{ Klank.ar(`[[800, 1071, 1353, 1723], nil, [1, 1, 1, 1]], PinkNoise.ar(0.007)) }.play;

{ Klank.ar(`[[200, 671, 1153, 1723], nil, [1, 1, 1, 1]], PinkNoise.ar([0.007,0.007])) }.play;

(
play({
	Klank.ar(`[ 
		Array.rand(12, 800.0, 4000.0),		// frequencies
		nil,  							// amplitudes (default to 1.0)
		Array.rand(12, 0.1, 2)				// ring times
		], Decay.ar(Impulse.ar(4), 0.03, ClipNoise.ar(0.01)))
})
)

///////////////////////////////////////////////////////////////////////////
// JITLib example
(
Server.default = Server.local;
s = Server.default;
s.boot;
)

//p= ProxySpace.push(s);
//
//p.pop

~out.play

// NB multichannel mul expand
~out = {Resonz.ar(LFNoise0.ar(400), Line.kr(10000, 1000, 10), [0.1, 0.1])} 

~rate = 200

~out = {Resonz.ar(LFNoise0.ar(~rate), Line.kr(10000, 1000, 10), [0.1, 0.1])} 

~rate = {Line.kr(400, 10, 10)}

~rate = {Line.kr(10, 400, 10)}

~out = { Ringz.ar(Dust.ar([3, 4], 0.3), 200, 2) }

~out = { Ringz.ar(Dust.ar([3, 4], 0.3), ~rate * 10, 2) }

~rate = {Line.kr(400, 10, 10)}

~rate.fadeTime = 4

~rate = 200

~out = { Ringz.ar(Dust.ar([3, 4], 0.3), [~rate * 10, ~rate * 11], 2) }

~rate = 250

~out = { Ringz.ar([Impulse.ar(2.5.reciprocal), LFNoise0.ar(4, 0.3)], [~rate * 10, ~rate * 11], 2, 0.3) }

~env = {EnvGen.kr(Env.sine(20), gate: Impulse.kr(20.reciprocal))}

~out = { Ringz.ar([Impulse.ar((~env * 4) + 1), LFNoise0.ar((~env * 4) + 1, 0.3)], [~rate * 10, ~rate * 11], 2, ~env * 0.3) }

///////////////////////////////////////////////////////////////////////////
// PMOsc

Document.open("/Users/rich/Documents/Music/HCI2009/Gaggle/GaggleScore/GaggleScore_v0.004.rtf")

// see /Users/rich/Documents/Music/HCI2009/Gaggle/GaggleScore/GaggleScore_v0.004.rtf

///////////////////////////////////////////////////////////////////////////
// Simple??? FM example.

(
SynthDef("fm1", { arg bus = 0, freq = 440, carPartial = 1, modPartial = 1, index = 3, mul = 0.05, dur = 1.0;

	// index values usually are between 0 and 24
	// carPartial :: modPartial => car/mod ratio
	
	var mod, car, env;
	
	env = EnvGen.kr(Env.linen(dur*0.1, dur*0.1, dur*0.8, 0.1), 0.1, doneAction: 2);
	
	mod = SinOsc.ar(
		freq * modPartial, 
		0, 
		freq * index * LFNoise1.kr(5.reciprocal).abs
	);
		
	car = SinOsc.ar(
		(freq * carPartial) + mod, 
		0, 
		env
	);
	
	Out.ar( 0, car );
}).send(s); // check
)

(
Synth("fm1", [ \freq, ( 800.rand + 400 ), \carPartial, 2.0.rand, \modPartial, 3.4.rand, \dur, 2.0.rand ]);
)

///////////////////////////////////////////////////////////////////////////
// now a task

(
	var pitch, count = 0;
	d = 0.125; 
	a = [ 60, 62, 63, 65, 67 ];
	r = Task({

		loop({
				while ( { count < a.size }, 
					{
						pitch = a[count];
						pitch.postln;
						Synth( "fm1", [ \freq, pitch.midicps, \carPartial, ( 0.4.rand ) + 1.0, \modPartial, ( 1.4.rand ) + 1.0, \dur, 0.1.rand ] );
						d.wait;
						count = count + 1;
					});
				count = 0
		});
	}).play;	
)

r.play;
d = 1
d = 0.11
d = 0.03
r.stop;
a = [ 45, 46, 47, 48, 50, 60, 62, 63, 65, 67 ]
a = [ 45 ]
a = a + 2.rand
a = a - 2.rand
a = [ 60, 62, 63, 65, 67 ];

///////////////////////////////////////////////////////////////////////////
// now a function

(
~myFMAlg = ({
		var pitch, count = 0;
		d = 0.125; 
		a = [ 60, 62, 63, 65, 67 ];
		r = Task({
	
			loop({
					while ( { count < a.size }, 
						{
							pitch = a[count];
							pitch.postln;
							Synth( "fm1", [ \freq, pitch.midicps, \carPartial, ( 0.4.rand ) + 1.0, \modPartial, ( 1.4.rand ) + 1.0, \dur, 0.1.rand ] );
							d.wait;
							count = count + 1;
						});
					count = 0
			});
		}).play; // end task
});
);

~myFMAlg.value;
r.play;
r.stop;

///////////////////////////////////////////////////////////////////////////
// now arguments

(
~myFMAlg = ({ arg pArray = [ 60, 62, 63, 65, 67 ], myCarPartial = 1.0, myModPartial = 1.0, myDur = 1.0, myWait = 0.125;
		var pitch, count = 0;
		d = 0.125; 
		
		r = Task({
	
			loop({
					while ( { count < pArray.size }, 
						{
							pitch = pArray[count];
							Synth( "fm1", [ \freq, pitch.midicps, \carPartial, myCarPartial, \modPartial, myModPartial, \dur, myDur ] );
							myWait.wait;
							count = count + 1;
						});
					count = 0
			});
		}).play; // end task
});
);

~myFMAlg.value;
r.stop; ~myFMAlg.value( [ 77, 75, 73, 72, 70 ] );
r.stop; ~myFMAlg.value( [ 40, 42, 43, 45, 47 ] );
r.stop; ~myFMAlg.value( [ 77, 75, 73, 72, 70, 68 ], 10.1, 30.4, 0.1, 0.05 );
r.play;
r.stop;

///////////////////////////////////////////////////////////////////////////
// now making choices

(
~myFMAlg = ({ arg pArray = [ 60, 62, 63, 65, 67 ], myCarPartial = 1.0, myModPartial = 1.0, myDur = 1.0, myWait = 0.125, myRand = false;
		var pitch, count = 0;
		var myCPartial, myMPartial;
		
		r = Task({
	
			loop({

					while ( { count < pArray.size }, 
						{	
							if ( myRand == true, { myCPartial = myCarPartial.rand; myMPartial = myModPartial.rand }, { myCPartial = myCarPartial; myMPartial = myModPartial } );
							myMPartial.postln;
							pitch = pArray[count];
							Synth( "fm1", [ \freq, pitch.midicps, \carPartial, myCarPartial, \modPartial, myModPartial, \dur, myDur ] );
							myWait.wait;
							count = count + 1;
						});
					count = 0
			});
		}).play; // end task
});
);

~myFMAlg.value;
r.stop; ~myFMAlg.value( [ 77, 75, 73, 72, 70 ] );
r.stop; ~myFMAlg.value( [ 40, 42, 43, 45, 47 ] );
r.stop; ~myFMAlg.value( [ 77, 75, 73, 72, 70, 68 ], 1.1, 4.4, 0.5, 0.15, true);

a = [ 77, 75, 73, 72, 70, 68 ];

r.stop; ~myFMAlg.value( a, 1.1, 4.4, 0.05, 0.05, true);

a = a - 2

r.play;
r.stop;

///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// 7. Reverberation and Panning
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////

 Code may produce code for other programs—a simple example is a quine, a program that returns its own source code; an example in SuperCollider is: 
(_ + '.(*' +  quote(_)  + '! 2)').(*"(_ + '.(*' +  quote(_)  + '! 2)')" ! 2)