// Open in SuperCollider, then double-click on the open parentheses character below the comments.
// It should highlight everything in the parentheses, after which you just hit 'enter,' NOT 
// 'return' (on Mac keyboards there's usually an enter key on the number pad, but if you're on a 
// laptop or other keyboard lacking it, holding function while you hit the return key should work.).
// I've tried to provide really informative comments, but feel free to e-mail me if you have any
// questions or anything.  Also, make sure to boot a server (click 'boot' on either the localhost
// or internal server windows that should open when you open SuperCollider.

(
	// Hammond Organ
	
	// Set variables for patterns and Leslie variables
	var pattern1, pattern2, pattern3, pattern4, bdpat, sdpat, lt, ht, lp, hp;
	
	lt = {FSinOsc.kr(5,0,0.2,0.8)};			// Leslie tremolo for low freq. horn
	ht = {FSinOsc.kr(12,0,0.2,0.8)};			// Leslie tremolo for high freq. horn
	lp = {FSinOsc.kr(5,3pi/4,0.05)};			// Leslie pan for low freq. horn
	hp = {FSinOsc.kr(12,3pi/4,0.05)};		// Leslie pan for high freq. horn
	
	// Synth definition for our Hammond organ
	SynthDef
	(
		"Hammond",  // The instrument name
		{
			// determine any arguments we'll want to send in from patterns
			arg freq, drawbars, dur, pan;
			
			// set variables for the synth
			var discs, eg, lo, hi, out, reverb;
			
			// drawbars control different tone wheels which are whole number ratios of key note.
			// the numbers represent what multiple their frequency is of the base frequency.
			discs = [1/2,3/2,1,2,3,4,5,6,8];
			
			// envelope to shape the note
			// Change the first and last values in the second array in order to change the 
			// attack and release time for each note.
			eg = EnvGen.kr(Env.new([0,0.4,0.35,0],[0.01,dur,0.1],'sine'), doneAction:2);
			
			// tone wheels are approximately sine waves, so we mix together 9 sine waves,
			// consisting of the frequency multiplied by the values in the disc array, with the 			// volume determined by the position of the drawbars (0-8).
			out = Mix.new(SinOsc.ar(freq*discs, 0, eg*drawbars/144)).distort;
			
			// Leslie speakers have two horns, one that puts out frequencies below 800Hz,
			lo = Pan2.ar(LPF.ar(out, 800, lt), lp);
			
			// and one that puts out those frequencies above 800Hz.
			hi = Pan2.ar(HPF.ar(out, 800, ht), hp);
			
			// We mix both horns together, and voila!  For no Leslie, comment out this line,
			out = Mix.new([lo,hi]).distort*0.5;
			// and remove the comment slashes from this one:
			//out = Pan2.ar(out, pan);
			
			// Last thing to do is tell what our output is.
			Out.ar([0], out);
		}
	).store;
	
	// Synth definition for a bass drum
	SynthDef
	(
		"bd",
		{
			arg freq=70;
			
			var wave, eg, out;
			
			// Basically we're ring modulating a saw wave to get a nonharmonic series
			wave = Saw.ar(freq, SinOsc.kr(freq*2));
			
			// and then passing it through a low pass filter so we just get the low frequencies.
			wave = LPF.ar(wave, 200);
			
			// Then we put on a simple envelope that's basically a diagonal line down
			eg = EnvGen.kr(Env.linen(0,0,0.1,1,'sine'), doneAction: 2);
			
			// and multiply the waveform by the envelope to get the final result.
			out = wave * eg;
			
			Out.ar
			(
				[0,1],
				out
			);
		}
	).store;
	
	// Synth definition for a snare drum
	SynthDef
	(
		"sd",
		{ 
			arg amp=1, pan=0;
			
			var eg1, eg2, snare, drum, out;
			
			// One of the envelopes is for the snare, the other's for the drum.
			eg1 = EnvGen.kr(Env.perc(0.01,0.3,amp),doneAction:2);
			eg2 = EnvGen.kr(Env.perc(0.01,0.2,amp/4));
			
			// A res. filter on white noise for the snare, a ring modded sine wave for the drum.
			snare = Resonz.ar(WhiteNoise.ar,1400,0.25,eg1);
			drum = SinOsc.ar(210,0,SinOsc.kr(70)*eg2);
			out = Pan2.ar(snare + drum, pan);
			
			Out.ar
			(
				[0],
				out
			);
		}
	).store;

	pattern1 = Pbind
	(
		\degree, Pseq([[2,4,6],[2,4,7],[0,2,7],[2,4,7]],12), // which notes to play (chords here)
		\dur, 2,							// length of notes
		\drawbars, [8,4,8,4,0,0,0,0,0],  	// drawbars determine a Hammond's sound
		\octave, 4,						// octave on keyboard
		\instrument, "Hammond",				// "Hammond" is the instrument it's sending args to.
		\pan, -0.6						// Here in case the Leslie line is commented out.
	);
	
	pattern2 = Pbind
	(
		\degree, Pseq
		(
			[Pseq([2, 6, 0, 2, 4, 2, 5, 7, 5, 0, 2, 0, 2], 6),
			Pseq([4,2,0],1)],
			1
		),
		\dur, Pseq 
		(
			[Pseq([1.5,0.5,0.75,0.25,0.75,0.25,0.5,1,0.5,0.25,0.75,0.25,0.75],6),
			Pseq([1,1,2],1)],
			1
		),
		\drawbars, [8,8,8,0,0,0,0,0,0],
		\instrument, "Hammond",
		\pan, 0.6
	);
	
	pattern3 = Pbind
	(
		\degree, Pseq
		(
			[Pseq([2, 6, 0, 2, 4, 2, 5, 7, 5, 0, 2, 0, 2], 6),
			Pseq([4,2,0],1)],
			1
		),
		\dur, Pseq 
		(
			[Pseq([1.5,0.5,0.75,0.25,0.75,0.25,0.5,1,0.5,0.25,0.75,0.25,0.75],6),
			Pseq([1,1,2],1)],
			1
		),
		\drawbars, [0,8,8,8,0,0,8,0,0],
		\instrument, "Hammond",
		\pan, 0
	);
	
	pattern4 = Pbind
	(
		\degree, Pseq([2,4,6,4,7,9,11,9,5,7,9,7,9,11,15], 8),
		\dur, Pseq([Pseq([0.5],14), 1], 8),
		\drawbars, [0,0,8,8,7,7,8,8,8],
		\octave, 5,
		\instrument, "Hammond",
		\pan, 0
	);
	
	bdpat = Pbind
	(
		\dur, Pseq([1],72),
		\instrument, "bd"
	);
	
	sdpat = Pbind
	(
		\dur, Pseq([1,0.25,0.5,0.5], 32),
		\amp, 1,
		\instrument, "sd",
		\pan, Pseq([-0.1,0.1], 64)
	);
	
	Ptpar		// Allows you to play more than one pattern at a time, at a set number of sec.
	(
		[
			0, pattern1,  // So at 0 seconds the first pattern starts playing, and so on.
			8.0, pattern2,
			18.0, pattern3,
			24.0, pattern4,
			8.0, bdpat,
			16.0, sdpat
		],
		1
	).play;
)

// 5-limit just intonation vs. 12-tone equal temperament (only use after playing the above)
(
	c = 130.81;  // C below middle C (C3, aka c)
	
	Pbind
	(
		\freq, Pseq([[c,c*5/4,c*3/2,c*2],[130.81,164.81,196,261.63]], 8),
		\dur, 4,
		\drawbars, [0,0,8,8,0,8,0,0,8],
		\instrument, "Hammond",
		\pan, 0
	).play;
)