SynthDescLib.global.read;

(
SynthDef("Maggot", { arg i_out, freq = 360, gate = 1, pan, amp=0.1; //Ist Synth Def with elements of  
                                                                                                                                   // panning and randomisation
	var out, eg, fc, osc, a, b, w; //variables for the synth
	fc = LinExp.kr(LFNoise1.kr(Rand(0.25,0.4)), -1,1,500,2000); //arguments for a line
	osc = Mix.fill(8, {SinOsc.ar(freq * [Rand(0.99,1.01),Rand(0.95,1.01)], 0, amp) }).distort * 0.2;
	eg = EnvGen.kr(Env.asr(1,1,1), gate, doneAction:2);
	out = eg * RLPF.ar(osc, fc, 0.1);
	#a, b = out;
	Out.ar(i_out, Mix.ar(PanAz.ar(4, [a, b], [pan, pan+0.3])));
}).writeDefFile;  //send/write the synthdef to the folder
)

(

SynthDef("Worm", { arg i_out, freq = 240, gate = 1, pan, amp=0.1; //2nd synth def similar to above
	var out, eg, fc, osc, a, b, w;
	fc = LinExp.kr(LFNoise1.kr(Rand(0.25,0.4,0.5,0.10)), -1,1,500,2000);
	osc = Mix.fill(8, {SinOsc.ar(freq * [Rand(0.95,1.01),Rand(0.60,1.01)], 0, amp) }).distort * 0.2;
	eg = EnvGen.kr(Env.asr(1,1,1), gate, doneAction:2);
	out = eg * RLPF.ar(osc, fc, 0.1);
	#a, b = out;
	Out.ar(i_out, Mix.ar(PanAz.ar(4, [a, b], [pan, pan+0.3])));
}).writeDefFile;
)

(
SynthDef("donkey", { arg i_out, freq = 120, gate = 1, pan, amp=0.1; //3rd Synth Def
	var out, eg, fc, osc, a, b, w;
	fc = LinExp.kr(LFNoise1.kr(Rand(0.25,0.4)), -1,1,500,2000);
	osc = Mix.fill(8, {SinOsc.ar(freq * [Rand(0.99,1.01),Rand(0.95,1.01)], 0, amp) }).distort * 0.2;
	eg = EnvGen.kr(Env.asr(1,1,1), gate, doneAction:2);
	out = eg * RLPF.ar(osc, fc, 0.1);
	#a, b = out;
	Out.ar(i_out, Mix.ar(PanAz.ar(4, [a, b], [pan, pan+0.3])));
}).writeDefFile;
)

(
SynthDef("cow", { arg i_out, freq = 60, gate = 1, pan, amp=0.1; //4th Synth Def
	var out, eg, fc, osc, a, b, w;
	fc = LinExp.kr(LFNoise1.kr(Rand(0.25,0.4)), -1,1,500,2000);
	osc = Mix.fill(8, {SinOsc.ar(freq * [Rand(0.99,1.01),Rand(0.95,1.01)], 0, amp) }).distort * 0.2;
	eg = EnvGen.kr(Env.asr(1,1,1), gate, doneAction:2);
	out = eg * RLPF.ar(osc, fc, 0.1);
	#a, b = out;
	Out.ar(i_out, Mix.ar(PanAz.ar(4, [a, b], [pan, pan+0.3])));
}).writeDefFile;
)

(
SynthDef("modulator", { arg freq=80, amp=1;//modulation
	var osc;
	osc = SinOsc.ar(freq);
	ReplaceOut.kr(10, osc*amp);
}).writeDefFile;
)

//GUI Information

(
var pbind, pbind2, pbind3, pbind4, pbind5, pbind6, pbind7, pbind8, eventstreamplayer, x, w, a, b, c, d, n, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, sl1, sl2, sl3, sl4, sl5, sl6, sl7, sl8, sl9, sl10, sl11, sl12, num1, num2, num3, num4, num5, num6, num7, num8, num9;    //variables
var str1, str2, str3, str4, str5, str6, str7, str8, str9, str10, str11, str12, str13, str14, str15, str16, str17, str18, s;

s = Server.local;			// instance of a local server

// Create window - 350 x 500 pixels
w = SCWindow("Marc's GUI", Rect(100, 800, 825, 500));

w.front;						// Bring the window to the front

//  3 buttons for the synths and server
b1 = SCButton(w, Rect(5, 5, 110, 25));	// The first button starts and stops the server
b1.states = [
		["Boot Server", Color.red, Color.black],
		["Quit Server", Color.black, Color.red],
			];
b1.action = { arg view;
		if (b1.value == 1, {
				s.boot;
		},{
				s.quit;
		});
};

b2 = SCButton(w, Rect(120, 5, 110, 25));	// This button sends all the SynthDefs and effects
b2.states = [
		["Load SynthDefs", Color.black, Color.red]
			];
b2.action = { arg view;
	s.sendSynthDef("Maggot");
	s.sendSynthDef("Worm");
	s.sendSynthDef("modulator");
	s.sendSynthDef("donkey");
	s.sendSynthDef("cow");

};

b3 = SCButton(w, Rect(235, 5, 110, 25));	// This one starts and stops the synths
b3.states = [
		["Play Synths", Color.black, Color.red],
		["Stop Synths", Color.black, Color.red],
			];
b3.action = { arg view;
		if (b3.value == 1, {
				s.sendMsg("/s_new", "Maggot", 1000, 1, 0, "freq", 80, "freq2", 1, "freq3", 20, "freq4", 2);
				s.sendMsg("/s_new", "Worm", 1001, 0, 0, "freq", 20, "freq2", 1);
				s.sendMsg("/s_new", "modulator", 1002, 0, 0, "freq", 80);
				s.sendMsg("/s_new", "donkey", 1006, 1, 0, "freq", 40, "freq2", 1 );// send them...
				s.sendMsg("/s_new", "cow", 1007, 1, 0, "freq", 60, "freq2", 1);
				
                  s.sendMsg("n_map", 1000, \freq2, 10);  
                  s.sendMsg("n_map", 1001, \freq2, 10);
                                                         s.sendMsg("n_map", 1002, \freq2, 10);
                                                         s.sendMsg("n_map", 1006, \freq2, 10);
                                                         s.sendMsg("n_map", 1007, \freq2, 10);

                  
				sl2.value = 0;	// These two commands set sliders 2 and 4 to values of
				sl4.value = 0;	// 1 and 1/20 whenever you start the synth
		},{
				s.sendMsg("/n_free", 1000); // These messages free or stop the synths
				s.sendMsg("/n_free", 1001);
				s.sendMsg("/n_free", 1002);
                                s.sendMsg("/n_free", 1006);
          s.sendMsg("/n_free", 1007);
});
};

//The Sequences button section

b4 = SCButton(w, Rect(350, 5, 125, 25));	// The first button starts the 1st sequence
b4.states = [
		["Pbind", Color.red, Color.black],   //Messages that appear for starting
		["end seq", Color.black, Color.red], //and stopping
			];
b4.action = { arg view;
if (b4.value == 1, {
pbind=Pbind(\instrument,\berlinb, \dur,Pseq([0.25,0.5,0.25,0.10,0.35,0.5,0.15,0.40,],inf), \root,90,
	 \degree,Pseq([0,3,5,7,9,11,5,1,2,11,32,6,8,22,3,6,5,12,],inf), \pan,Pfunc({1.0.rand2}),
	 \cut,Pxrand([1000,500,2000,300],inf), \rez,Pfunc({0.7.rand +0.3}), \amp,0.6).play;},
{pbind.stream.stop;   //stops the sequence eventstream is placed like each Pbind within the variables at the top

});
};
//the sequence is embedded within a Pbind  within the buttons action. Here there are messages to  control the  
//pitch and 
//duration of each note. Additionaly there are some random elements, panning and filtering. All of 
//these control the overal envelope, timbre and structure of the sequence
b5 = SCButton(w, Rect(350, 35, 125, 25));	// The first button starts the second sequence
b5.states = [
		["Pbind2", Color.red, Color.black],
		["end seq", Color.black, Color.red],
			];
b5.action = { arg view;
if (b5.value == 1, {
pbind2=Pbind(\degree, Pseq([0,3,5,7,9,11,5,1,2,11,10,6,8,0,3,6,5,12,],inf), \dur,Pseq([0.25,0.5,0.25,0.10,0.35,0.5,0.15,0.40,],inf), \pan,Pfunc({1.0.rand2}),
	 \cut,Pxrand([1000,500,2000,300],inf), \rez,Pfunc({0.11.rand +0.9}), \amp,0.1, \root, 60).play;
},
{pbind2.stream.stop;

});
};
//different sequences at different pitches some that use instruments from the library others that 
//don't

b6 = SCButton(w, Rect(350, 65, 125, 25));	// etc
b6.states = [
		["Pbind3", Color.red, Color.black],
		["end seq", Color.black, Color.red],
			];

b6.action = { arg view;
		if (b6.value == 1, {
		pbind3=Pbind(\instrument,\gpdef, \dur,Pseq([0.5,0.10,0.15],inf), \root,[-24,-17], 
	\degree,Pseq([0,-6,0,-6,0,-6,0,-6,0,-12,0,-12,0,-12,0,-12],inf), 
	\pan,Pfunc({1.0.rand2}),\cut,Pxrand([1000,500,2000,300],inf), \rez,Pfunc({0.7.rand +0.3}),
	\amp,0.4).play;
},
{pbind3.stream.stop;

});
};

b7 = SCButton(w, Rect(350, 95, 125, 25));	// The first button starts the sequence
b7.states = [
		["Pbind4", Color.red, Color.black],
		["end seq", Color.black, Color.red],
			];
b7.action = { arg view;
		if (b7.value == 1, {
		pbind4=Pbind(\instrument,\acid, \dur,Pseq([0.5,0.10,0.15],inf), \root,[-6,-22], 
	\degree,Pseq([0,-6,0,-6,0,-6,0,-6,0,-12,0,-12,0,-12,0,-12],inf), 
	\pan,Pfunc({1.0.rand2}),\cut,Pxrand([1000,500,2000,300],inf), \rez,Pfunc({0.9.rand +0.6}),
	\amp,0.1).play; 

},
{pbind4.stream.stop;

});
};

b8 = SCButton(w, Rect(350, 125, 125, 25));	// The first button starts the sequence
b8.states = [
		["Pbind5", Color.red, Color.black],
		["end seq", Color.black, Color.red],
			];

b8.action = { arg view;
if (b8.value == 1, {
pbind5=Pbind(\instrument,\pgrain, \dur,Pseq([0.01,0.1,0.01,0.01,0.1,0.01,0.1,0.01,0.01,0.01,0.01],inf), \root,80,
	 \degree,Pseq([0,],inf), \pan,Pfunc({1.0.rand2}),
	 \cut,Pxrand([1000,500,2000,300],inf), \rez,Pfunc({0.7.rand +0.3}), \amp,1.0).play;

},
{pbind5.stream.stop;

});
};

b9 = SCButton(w, Rect(350, 155, 125, 25));	// The first button starts the sequence
b9.states = [
		["Pbind6", Color.red, Color.black],
		["end seq", Color.black, Color.red],
			];
b9.action = { arg view;
		if (b9.value == 1, {
		pbind6=Pbind( \dur,Pseq([0.25,0.5,0.25,0.10,0.35,0.5,0.15,0.40,],inf), \root,-30,
	 \degree,Pseq([0,],inf), \pan,Pfunc({1.0.rand2}),
	 \cut,Pxrand([1000,500,2000,300],inf), \rez,Pfunc({0.7.rand +0.3}), \amp,0.2).play;

},
{pbind6.stream.stop;

});
};

b10 = SCButton(w, Rect(350, 185, 125, 25));	// The first button starts the sequence
b10.states = [
		["Pbind7", Color.red, Color.black],
		["end seq", Color.black, Color.red],
			];

b10.action = { arg view;
if (b10.value == 1, {
pbind7=Pbind(\instrument,\cfstring1, \dur,Pseq([0.25,0.5,0.25,0.10,0.35,0.5,0.15,0.40,],inf), \root,80,
	 \degree,Pseq([[0,3,9,12,15,18,21,24,27,30,33,],[5,7],[9,11,13,15,17,19,21,23,25,],[5,1],[3,5],[7,9,11,13,15,17,19],[3,0],[3,5],[7,11],[0,3,6],[3,6,9,12,15,18,21,24],[5,8,11],[7,10,13],11,5,1,3,5,7,9,3,0,3,5,7,11,],inf), \pan,Pfunc({1.0.rand2}),
	 \cut,Pxrand([1000,500,2000,300],inf), \rez,Pfunc({0.7.rand +0.3}), \amp,0.2).play;//notes can  
	 //be braketed together to form chords, you can also use flats b

},
{pbind7.stream.stop;

});
};

b11 = SCButton(w, Rect(350, 215, 125, 25));	// The first button starts the sequence
b11.states = [
		["Pbind8", Color.red, Color.black],
		["end seq", Color.black, Color.red],
			];

b11.action = { arg view;
		if (b11.value == 1, {
		pbind8=Pbind(\type, \phrase, // phrase event from global library
	\instrument, \berlinb,
	\n, 16,
	\degree, Pseq([0, 4, 6, 3,  5,  9, 13, 5], inf), \pan,Pfunc({1.0.rand2}),
		\cut,Pxrand([1000,500,2000,300],inf),\rez,Pfunc({0.7.rand +0.3}), \amp,0.2,
	\sustain, Pseq([1.3, 0.2, 0.4],inf)
).play;
eventstreamplayer=pbind8.play;

},
{pbind8.stream.stop;

});
};
//some mouse controlled buttons
b12 = SCButton(w, Rect(350, 245, 125, 25));	// The  button starts the mouse, whose x axis    
                                                                                        //       controls the pitch

b12.states = [
		["Mouse", Color.black, Color.red],
			];
b12.action = { arg view;
		(
{ SinOsc.ar(MouseX.kr(4000, 1000, 1), 0.1, 0.1) + RLPF.ar(LFPulse.ar([70,100,44,22,10].midicps, 0.15),
SinOsc.kr(0.1, 0, 10, 72, 9.midicps, 0.1, 0.1))}
.play;)};

b13 = SCButton(w, Rect(350, 275, 125, 25));	// The  button starts the mouse, whose x axis    
                                                                                        //       controls the pitch
b13.states = [
		["Mouse2", Color.black, Color.red],
			];
b13.action = { arg view;
		(

{ Impulse.ar(4, [0, MouseX.kr(0, 1)], 0.2) }.play;)};

b14 = SCButton(w, Rect(350, 305, 125, 25));	
b14.states = [
		["Mouse3", Color.black, Color.red],
			];
b14.action = { arg view;
		(

{ SinOsc.ar(MouseX.kr(40, 10000, 1), 0, 0.1) }.play;)}; 

b15 = SCButton(w, Rect(350, 335, 125, 25));	// a sequence modified from an example
b15.states = [
		["Strangeness", Color.black, Color.red],
			];
b15.action = { arg view;
		(
n = 20;
a = { arg freq, amp, pan;
	Pan2.ar(SinOsc.ar(freq), pan, amp);
};
b =  { arg amp, pan, freq;
	Pan2.ar(RLPF.ar(Saw.ar(freq), freq * 10, 0.1), pan, amp);
};
c =  { arg pan, freq, amp;
	Pan2.ar(Resonz.ar(GrayNoise.ar, freq * 3, 0.1), pan, amp * 2);
};

Task({
	n.do({ arg i;
		SynthDef("strangeness" ++ i.asString, {
			var out;
			Environment.use({
					// set values in the environment
				~freq = exprand(100, 1200);
				~amp = 0.1 + 0.3.rand;
				~pan = 1.0.rand2;
				
					// call a randomly chosen instrument function 
					// with values from the environment
				out = [a,b,c].choose.valueEnvir;
			});
			out = CombC.ar(out, 0.2, 0.2, 3, 1, out);
			out = out * EnvGen.kr( 
				Env.sine, doneAction: 2, timeScale: 1.0 + 6.0.rand, levelScale: 0.3 
			);
			Out.ar( 0, out );
		}).send(s);
		0.02.wait;
	});
	loop({
		Synth( "strangeness" ++ n.rand.asString );
		(0.5 + 2.0.rand).wait;
	});
}).play;
)};

//  sliders

sl1 = SCSlider(w, Rect(25, 100, 50, 300)); //size of slider and position
sl1.action = {
		var val;
		val = ((800*sl1.value)+80);
		s.sendMsg("/n_set", 1000, "freq", val); //assign it to the relevant node
		num1.value = val;		// This will set the value of number box 1 = value of slider 1
};

sl2 = SCSlider(w, Rect(107, 100, 50, 300)); //etc
sl2.action = {
		var val;
		val = sl2.value;
		s.sendMsg("/n_set", 1000, "amp", val);
		num2.value = val;		// This will set the value of number box 2 = value of slider 2
};

sl3 = SCSlider(w, Rect(191, 100, 50, 300));
sl3.action = {
		var val;
		val = ((800*sl3.value)+1);
		s.sendMsg("/n_set", 1001, "freq", val);
		num3.value = val;		// This will set the value of number box 3 = value of slider 3
};

sl4 = SCSlider(w, Rect(274, 100, 50, 300));
sl4.action = {
		var val;
		val = (1*sl4.value);
		s.sendMsg("/n_set", 1001, "amp", val);
		num4.value = val;		// slider 4 and number box
};

sl5 = SCSlider(w, Rect(75, 40, 200, 15));			// This slider will control the pan
sl5.value = 0.5;								// The default position is set to 0.5 (halfway)
sl5.action = {
		var val;
		val = (1*sl5.value);
		s.sendMsg("/n_set", 1000, "pan", val);	
		num9.value = val;                                                                 // The value of the slider position is sent to the
};	

sl6 = SCSlider(w, Rect(75, 60, 200, 15));			
sl6.value = 0.5;								
sl6.action = {
		var val;
		val = sl6.value;
		s.sendMsg("/n_set", 1001, "pan", val);	 
};

//sliders for the second set of synths

sl7 = SCSlider(w, Rect(500, 100, 50, 300));			
sl7.action = {
		var val;
		val = ((800*sl7.value)+80);
		s.sendMsg("/n_set", 1006, "freq", val);               // This slider will control the frequency
		num5.value = val;		
};

sl8 = SCSlider(w, Rect(583, 100, 50, 300));			// This slider will control the amp 
sl8.action = {
		var val;
		val = sl8.value;
		s.sendMsg("/n_set", 1006, "amp", val);
		num6.value = val;		// 	
};

sl9 = SCSlider(w, Rect(666, 100, 50, 300));			// This slider will control the frequency
sl9.action = {
		var val;
		val = ((800*sl9.value)+80);
		s.sendMsg("/n_set", 1007, "freq", val);
		num7.value = val;		
};

sl10 = SCSlider(w, Rect(750, 100, 50, 300));			                                                                                         // This slider will control the amplitude
sl10.action = {
		var val;
		val = sl10.value;
		s.sendMsg("/n_set", 1007, "amp", val);
		num8.value = val;		// 	
};

sl11 = SCSlider(w, Rect(550, 40, 200, 15));			// This slider will control the pan
sl11.value = 0.5;								// The default position is set to 0.5 (halfway)
sl11.action = {
		var val;
		val = sl11.value;
		s.sendMsg("/n_set", 1006, "pan", val);	
};	

sl12 = SCSlider(w, Rect(550, 60, 200, 15));			
sl12.value = 0.5;								
sl12.action = {
		var val;
		val = sl12.value;
		s.sendMsg("/n_set", 1007, "pan", val);	};

//  text strings that send the text messages and their positions
str1 = SCStaticText(w, Rect(23, 70, 133, 30));		//give it a name  and choose a font
str1.string = "|-------Maggot-------|";		
str1.font = Font("Futura-Medium", 14);			

str2 = SCStaticText(w, Rect(189, 70, 133, 30));      //etc
str2.string = "|---------Worm---------|";
str2.font = Font("Futura-Medium", 14);

str3 = SCStaticText(w, Rect(23, 400, 55, 25));
str3.string = "Freq(Hz)";
str3.font = Font("Futura-Medium", 14);

str4 = SCStaticText(w, Rect(112, 400, 55, 25));
str4.string = "Amp.";
str4.font = Font("Futura-Medium", 14);

str5 = SCStaticText(w, Rect(189, 400, 55, 25));
str5.string = "Freq(Hz)";
str5.font = Font("Futura-Medium", 14);

str6 = SCStaticText(w, Rect(280, 400, 55, 25));
str6.string = "Amp.";
str6.font = Font("Futura-Medium", 14);

str7 = SCStaticText(w, Rect(165, 42, 50, 25));
str7.string = "Spread";
str7.font = Font("Futura-Medium", 12);

str8 = SCStaticText(w, Rect(62, 42, 10, 25));
str8.string = "L";
str8.font = Font("Futura-Medium", 14);

str9 = SCStaticText(w, Rect(279, 42, 10, 25));
str9.string = "R";
str9.font = Font("Futura-Medium", 14);

//  text strings for second synth 
str10 = SCStaticText(w, Rect(500, 70, 133, 30));		//  text strings are assigned a position of equal 
//distance to each other,
str10.string = "|-------Donkey-------|";		//give it a name
str10.font = Font("Futura-Medium", 14);		//font type	

str11 = SCStaticText(w, Rect(666, 70, 133, 30));
str11.string = "|---------Cow---------|";
str11.font = Font("Futura-Medium", 14);

str12 = SCStaticText(w, Rect(500, 400, 55, 25));
str12.string = "Freq(Hz)";
str12.font = Font("Futura-Medium", 14);

str13 = SCStaticText(w, Rect(583, 400, 55, 25));
str13.string = "Amp.";
str13.font = Font("Futura-Medium", 14);

str14 = SCStaticText(w, Rect(666, 400, 55, 25));
str14.string = "Freq(Hz)";
str14.font = Font("Futura-Medium", 14);

str15 = SCStaticText(w, Rect(750, 400, 55, 25));
str15.string = "Amp.";
str15.font = Font("Futura-Medium", 14);

str16 = SCStaticText(w, Rect(640, 42, 50, 25));
str16.string = "Spread";
str16.font = Font("Futura-Medium", 12);

str17 = SCStaticText(w, Rect(540, 42, 10, 25));
str17.string = "L";
str17.font = Font("Futura-Medium", 14);

str18 = SCStaticText(w, Rect(755, 42, 10, 25));
str18.string = "R";
str18.font = Font("Futura-Medium", 14);

//create our number boxes
num1 = SCNumberBox(w, Rect(25, 430, 50, 25));		
num2 = SCNumberBox(w, Rect(107, 430, 50, 25));		
                                                                                              // Each one is assigned a size and position.
num3 = SCNumberBox(w, Rect(191, 430, 50, 25));		
num4 = SCNumberBox(w, Rect(274, 430, 50, 25));
num5 = SCNumberBox(w, Rect(500, 430, 50, 25));	
num6 = SCNumberBox(w, Rect(583, 430, 50, 25));	
num7 = SCNumberBox(w, Rect(666, 430, 50, 25));		
num8 = SCNumberBox(w, Rect(750, 430, 50, 25));  
	
)