(
// ---------------------------- //
// --- RUN THIS WHOLE BLOCK --- //
// ---------------------------- //

// configure the sound server: here you could add hardware specific options
// see http://doc.sccode.org/Classes/ServerOptions.html
//s.options.outDevice = "Soundflower (64ch)";
//s.options.inDevice = "Soundflower (64ch)";
s.options.numBuffers = 1024 * 16; // increase this if you need to load more samples
s.options.memSize = 8192 * 16; // increase this if you get "alloc failed" messages
s.options.maxNodes = 1024 * 32; // increase this if you are getting drop outs and the message "too many nodes"
s.options.numOutputBusChannels = 8; // set this to your hardware output channel size, if necessary
s.options.numInputBusChannels = 2; // set this to your hardware output channel size, if necessary
// boot the server and start SuperDirt
s.waitForBoot {
	~dirt = SuperDirt(2, s); // two output channels, increase if you want to pan across more channels
	~dirt.loadSoundFiles;   // load samples (path containing a wildcard can be passed in)
	// for example: ~dirt.loadSoundFiles("/Users/myUserName/Dirt/samples/*");
	s.sync; // wait for samples to be read
	~dirt.start(57120, [0,2,4,6,8,10,12,14]);   // start listening on port 57120, create four busses each sending audio to channel 0
	(
		SynthDef(\plucklead, {
			|out, sustain = 1, freq = 440, speed = 1, begin=0, end=1, pan, accelerate, offset|
			var line = Line.ar(begin, end, sustain, doneAction:2);
			var env = Env([0, 1, 0.333, 0],[5, 70, 1000]);
			var envGen = IEnvGen.ar(env, line*env.times.sum*abs(speed));
			var speedFreq = freq*abs(speed);
			var pulseLfo = SinOsc.ar(Rand(-1,1));
			var sound = RLPF.ar(Pulse.ar([speedFreq*Rand(0.99,1.01)*2,speedFreq*Rand(0.99,1.01)*2],pulseLfo)*0.5+Saw.ar(speedFreq), (20000*(envGen**2.8))+DC.ar(10), 0.5);
			Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, envGen));
		}).add;
	);
	~modBus.free;
	~carBus.free;
	~dirt.orbits[0].outBus = 0;
	~dirt.orbits[1].outBus = 0;
	// --- //
	~modBus = Bus.audio(s, numChannels:2); // assuming stereo, expand if needed
	~carBus = Bus.audio(s, numChannels:2);
	~dirt.orbits[0].outBus = ~modBus; // play into that bus.
	~dirt.orbits[1].outBus = ~carBus;
	(
		Ndef(\x, {
			var modBus = In.ar(~modBus, 2);
			var carBus = In.ar(~carBus, 2);
			var out = modBus+carBus;
			//carBus = FreeVerb.ar(carBus, 0.9, 0.8, 0.8);
			carBus = carBus+((-7).dbamp*Compander.ar(FreeVerb.ar(carBus, 0.9), carBus, -30.dbamp, 1, 0.01, 0.01, 0.07));
			carBus = Compander.ar(carBus,carBus,-20.dbamp,1,0.5,0.01,0.35)*(-5).dbamp;
			out = Compander.ar(carBus, modBus, -30.dbamp, 1, 0.01, 0.01, 0.07)+modBus;
			out = Compander.ar(out, out, -15.dbamp, 1, 0.2)*4;
			Out.ar(0, out);
		});
	);
	(
		MIDIClient.init;
		MIDIIn.connectAll;
		~tidalSocket = NetAddr("localhost", 6010);
		~notes=[];
		//MIDIFunc.cc( {|val, num, chan, src| ~tidalSocket.sendMsg('/ctrl', num, val/127.0);}, nil, nil, nil);
		MIDIFunc.noteOn({|veloc, num, chan, src| ~notes=~notes.add(num); ~tidalSocket.sendMsg('/ctrl', "notes", format("%", ~notes)); });
		MIDIFunc.noteOff({|veloc, num, chan, src| ~notes=~notes.takeThese({|x| x==num}); ~tidalSocket.sendMsg('/ctrl', "notes", format("%", ~notes)); });
	);
};
);

// check me out for the current notes being played
~notes.postln;
