(
var window, scope, alloff, getcontrol, getaudio, getbuffer, inputamp, bfbus, cleanout, mixout, responder, guicontrol, cond, loopgroup, grainnode;
var proc1, proc2a, proc2b, proc3a, proc3b;
var events, event, trombuf, hidebuf, diskbuf;

event = 0;

cond = Condition.new; 

getcontrol = {arg num; s.controlBusAllocator.alloc(num)};

getaudio = {arg num; s.audioBusAllocator.alloc(num)};

getbuffer = {arg num; s.bufferAllocator.alloc(num)};

bfbus = getaudio.value(4);

cleanout = getaudio.value(1);

mixout = getaudio.value(1);

// allocate some controls
inputamp = getcontrol.value(1);

guicontrol = Array.newClear(5);

alloff = {
	AppClock.sched(0.1, {scope.window.close; window.close});
	s.freeAll; responder.remove;
	s.sendMsg(\b_close, hidebuf);
	s.sendMsg(\b_close, trombuf);
	s.sendMsg(\b_close, diskbuf);
	s.sendMsg(\b_free, hidebuf);
	s.sendMsg(\b_free, trombuf);
	s.sendMsg(\b_free, diskbuf);
	};
	
// the functions

proc1 = {arg track;
	var node, bufnum;
	// get a node ID
	node = s.nextNodeID;
	// add controls to the GUI
	{
		window.view.decorator.nextLine;
		EZSlider(window, 400 @ 24, "Input " ++ track ++  " Amp", ControlSpec(0, 2, \lin),
			{|me| s.sendMsg(\n_set, node, \inputamp, me.value)}, 1, labelWidth: 120);
		
		window.view.decorator.nextLine;
		EZSlider(window, 400 @ 24, "Feedback " ++ track ++  " Pct", ControlSpec(0, 2, \lin),
			{|me| s.sendMsg(\n_set, node, \feedback, me.value)}, 0.1, labelWidth: 120);
		
		window.view.decorator.nextLine;
		EZSlider(window, 400 @ 24, "Feedback " ++ track ++  " Dur", ControlSpec(0.01, 4, \lin),
			{|me| s.sendMsg(\n_set, node, \delaytime, me.value)}, 2, labelWidth: 120);
		
		window.view.decorator.nextLine;
		EZSlider(window, 400 @ 24, "Delay randomness", ControlSpec(0, 1, \lin),
			{|me| s.sendMsg(\n_set, node, \delran, me.value)}, 1, labelWidth: 120);

		window.view.decorator.nextLine;
		EZSlider(window, 400 @ 24, "Delay 1 and 2 mul", ControlSpec(0.001, 2, \exp),
			{|me| s.sendMsg(\n_set, node, \delmul, me.value)}, 0.001, labelWidth: 120);

		window.view.decorator.nextLine;
		EZSlider(window, 400 @ 24, "Delay 1 time", ControlSpec(0, 1, \lin),
			{|me| s.sendMsg(\n_set, node, \del1time, me.value)}, 0.1, labelWidth: 120);

		window.view.decorator.nextLine;
		EZSlider(window, 400 @ 24, "Delay 2 time", ControlSpec(0, 1, \lin),
			{|me| s.sendMsg(\n_set, node, \del2time, me.value)}, 0.15, labelWidth: 120);		
		window.view.decorator.nextLine;
		EZSlider(window, 400 @ 24, "Feedback " ++ track ++  " mix", ControlSpec(0, 1, \lin),
			{|me| s.sendMsg(\n_set, node, \balance, me.value)}, 0, labelWidth: 120);
			
		window.view.decorator.nextLine;
		EZSlider(window, 400 @ 24, "Feedback " ++ track ++  " freq", 
				ControlSpec(65.0, 2500.0, \exp),
			{|me| s.sendMsg(\n_set, node, \basefreq, me.value)}, 130.0, labelWidth: 120);

		window.view.decorator.nextLine;
		EZSlider(window, 400 @ 24, "Track " ++ track ++ " mul", ControlSpec(0, 2, \lin),
			{|me| s.sendMsg(\n_set, node, \outlevel, me.value)}, 1, labelWidth: 120);

		window.view.decorator.nextLine;
		SCButton(window, 60 @ 24)
			.states_([["Reset "++ track, Color.green, Color.black]])
			.action_({|me| 
				window.view.children.[window.view.children.indexOf(me) - 4].valueAction_(130)});

//		window.view.refresh;
	}.defer;
	s.sendBundle(0.1, 
		[\s_new, \loop, node, 0, loopgroup, \outbus, bfbus, \cleanout, cleanout, \mixout, mixout, 
			\bufnum, bufnum, \delaytime, 2, \scopeout, 25 + track]);
	};

proc2a = {arg amp = 1;
	var buf, mulenv, rout;
	buf = getbuffer.value(1);
	mulenv = Env([0, amp, 0], [15, 30], \lin, 1).asArray;
	rout = Routine({
		s.sendBundle(0.1, [\b_alloc, buf, 16384]);
		s.sync(cond);
		"Made it".postln;
		s.sendBundle(0.1, [\s_new, \mixgrains, grainnode = s.nextNodeID, 1, loopgroup, 
				\inbus, mixout, \outbus, bfbus], 
			[\n_setn, grainnode, \env, mulenv.size] ++ mulenv);
		});
	rout.play(SystemClock)
	};
	
proc2b = {arg amp = 1;
	var durenv, mulenv, time;
	{
		window.view.decorator.nextLine;
		SCButton(window, Rect(500, 110, 100, 50))
		.states_([
			["Grainy Train", Color.black, Color.white]
			])
		.action_({
			s.sendMsg(\s_new, \trigger, s.nextNodeID, 0, 1);
			});
		
		}.defer;
	time = Main.elapsedTime;
	durenv = Env([2, 6, 2, 1, 10], [3, 3, 4, 10]);
	mulenv = Env([1, 1, 0.01], [20, 40]);
	responder = OSCresponderNode(s.addr, '/tr', {arg resptime, responder, msg;
		var rout;
		rout = Routine({
			var now, dur, mul, buf;
			now = (Main.elapsedTime - time);
			now.postln;
			dur = durenv[now] * 0.8.rrand(1.2);
			mul = mulenv[now] * 0.8.rrand(1.2);
			buf = getbuffer.value(1);
			s.sendBundle(0.1, [\b_alloc, buf, 16384]);
			s.sync(cond);
			s.sendBundle(0.1, 	[\s_new, \grains, s.nextNodeID, 1, loopgroup, \inbus, cleanout, 
					\grainsize, 0.1, \grainfreq, 8.rrand(12.0), 
					\loc, 0.rrand(2pi), \basefreq, 130, 
					\dur, dur, \mul, mul * amp, \bufnum, buf, \outbus, bfbus]);
			SystemClock.sched( dur, {s.sendBundle(0.1, [\b_free, buf])});
			});
		rout.play(SystemClock);
		});
	responder.add;
	};

proc3a = {
	s.sendBundle(0.1, [\n_set, grainnode, \gate, 0],
		[\s_new, \trom_buffer, s.nextNodeID, 0, 1, \bufnum, trombuf, \outbus, bfbus, \amp, 12.dbamp]);
	};

proc3b = {
	s.sendBundle(0.1, 
		[\s_new, \hide_buffer, s.nextNodeID, 0, 1, \bufnum, hidebuf, \outbus, bfbus]);
	};	
	
// events

events = [nil,
/* 1 */	{proc1.value(1)},
/* 2 */	{proc1.value(2)},
/* 3 */	{proc2a.value(4)},
/* 4 */	{[30, 61].do{arg me; window.view.children[me].valueAction_(0.0)}},
/* 5 */	{proc2b.value(8)},
/* 6 */ 	{proc3a.value}, 
/* 7 */ 	{proc3b.value;
			responder.remove;
			//[30, 61].do{arg me; window.view.children[me].valueAction_(0.0)};
			},
/* 8 */ 	{alloff.value},
	];
	
// the GUI

window = SCWindow.new("I Was Born To Sing", Rect(150, 100, 700, 700)).front;

SCButton(window, Rect(500, 10, 100, 50))
	.states_([
		["Next", Color.black, Color.white]
		])
	.action_({
		events[event.postln].value;
		event = event + 1;
		});

SCStaticText(window, Rect(500, 80, 180, 500))
	.string_("1- start loop track 1\n2- start loop track2\n   should start to fade in\n   filter mix.\n3- start grain fade in\n4-cut off loops\n5- bring up grain button\n6- start trom buffer\n   near end, bring filt freqs up, \n   and start to play with those, \n   eventually removing the filt mix\n7- cut off loops again\n   start hide buffer\n8- allOff");
					 
window.onClose_({alloff.value});

window.view.decorator = FlowLayout(window.view.bounds);
		
s = Server.local.boot;

s.waitForBoot({
//	scope = s.scope(4, s.options.numOutputBusChannels);
//	scope.window.bounds_(Rect(900, 100, 200, 900));
	window.front;
	loopgroup = s.nextNodeID;
	trombuf = getbuffer.value(1);
	hidebuf = getbuffer.value(1);
	diskbuf = getbuffer.value(1);
	s.sendBundle(0.1, 
		[\b_alloc, diskbuf, 65536, 4],
		[\b_write, diskbuf, "sounds/IWBTSperf.aiff", "aiff", "int16", 0, 0, 1],
		[\s_new, \bfdecode, s.nextNodeID, 1, 0, \bfbus, bfbus, \diskoutbuf, diskbuf],
		[\g_new, loopgroup, 0, 1],
		[\b_alloc, trombuf, 65536, 3],
		[\b_read, trombuf, "~/SND/DyneTrom.bf".standardizePath, 0, 65536, 0, 1],
		[\b_alloc, hidebuf, 65536, 3],
		[\b_read, hidebuf, "~/SND/HideVoicebf.aif".standardizePath, 0, 65536, 0, 1]
		);
	});

)