// To activate a block of code press put the cursor inside it and press Command+ENTER on Mac
// or Control+ENTER on Linux/Windows - it will flash when you activate it.
// Activated code will usually create some output in the POST WINDOW - look there for error messages.

// If you want to make everything stop press Command+. or Control+.  this is VERY useful!

// You can make very loud and very high pitch sounds that may hurt you!
// I don't recommend wearing headphones unless you know your code works!

// Boot the server - do this first.. the server then dynamically runs the code you activate later.
(
Server.default=s=Server.internal;
s.boot;
)

// If there are no ( )'s around a block of code it will activate one line at a time.
// Sometimes that's desirable! Like preparing to record...
// Make sure to put in an appropriate file path:
s.prepareForRecord("users/mattborland/Desktop/bell.wav");

// Starting the recording.
s.record;

// And stopping the recording - don't forget to stop it or you'll have a HUGE file saved.
s.stopRecording;

// This is a table realting to the sound properties of the bell we're simulating.
// It's not runnable code, so you'll jsut get an error if you try to run it.
f       r       T60     Mag
220     1.0     70.6    0.33
362     1.65    25.6    0.25
480     2.18    15.4    1.0
648     2.95    5.7     0.51
813     3.7     4.6     0.73

// Basic "Bell" Definition
// This creates a SYNTH Definition which we can then call at a later time.
// Activating this block doesn't make any sound. You make the sound when you call this synth def later.
(
SynthDef(\BasicBell, { arg freq=220;     // you can pass a frequency in as a variable to this synth
	var sig, strike;                                  // this creates 2 variables used in the synth def
	strike = LPF.ar(Impulse.ar(0),300);   // defines a sound used to imitate the strike of the bell

	// We'll add 5 frequency components together that are multiples of the fundamental frequency
	// This uses the values from the table above to define the properties of this oscillator, DynKlank.
	sig = DynKlank.ar(`[[freq, 1.65*freq, 2.18*freq, 2.95*freq, 3.7*freq], [0.33,0.25,1.0,0.51,0.73], [70.6, 25.6,15.4, 5.7,4.6]], strike);

	// This sends "sig" out to your soundcard. Pan2 takes the monophonic signal and makes it stereo.
	Out.ar(0,Pan2.ar(sig,0))
}).add;
)

// Activating this code runs the synth above once
Synth(\BasicBell);

// We can change its frequency by including reference to the freq variable
Synth(\BasicBell, [\freq, 110]);

// We can change its frequency by including reference to a MIDI note number that
// gets converted to a frequency byt he .midicps function
Synth(\BasicBell, [\freq, 32.midicps]);


// Let's add a bit more complexity to (hopefully) make it sound better.
// Medium Complexity "Bell" Definition
// This follows a similar approach, but with more frequency components
(
SynthDef(\mediumBell, { arg freq=220;
	var env, sig1, sig2, sig3, sig4, strike1, strike2, strike3, strike4;
	strike1 = LPF.ar(EnvGen.ar(Env.new([0,1,0],[0.01,0.01])),300);
	strike2 = LPF.ar(EnvGen.ar(Env.new([0,1,0],[0.001,0.001])),5000);
	strike3 = LPF.ar(EnvGen.ar(Env.new([0,1,0],[0.001,0.001])),10000);
	strike4= LPF.ar(EnvGen.ar(Env.new([0,1,0],[0.001,0.001])),10000);

	sig1 = Klank.ar(`[[freq, 1.65*freq, 2.18*freq, 2.95*freq, 3.7*freq], [0.33,0.25,1.0,0.51,0.73], [70.6, 25.6,15.4, 5.7,4.6]], strike1);

	sig2 = Klank.ar(`[[5.1*freq, 6.7*freq, 8.1*freq, 9.4*freq, 11.1*freq], [0.7,0.8,0.6,0.7,0.8], [3.0, 2.9,2.8, 2.7,2.6]], strike2);

	sig3 = Klank.ar(`[[12.6*freq, 13.7*freq, 14.9*freq, 16.1*freq, 17.1*freq], [0.7,0.8,0.6,0.7,0.8], [2.5,2.4,2.3, 2.2,2.1]], strike3);

	sig4 = Klank.ar(`[[18.9*freq, 20.1*freq, 22.0*freq, 23.2*freq, 24.5*freq], [0.7,0.8,0.6,0.7,0.8], [2.0,1.9,1.8, 1.7,1.6]], strike4);

	// You can see how easy it is to ADD the different signals toghether.
	Out.ar(0,Pan2.ar(0.1*(sig1+sig2+sig3+sig4),0))
}).add;
)

// Playing the bells just like before
Synth(\mediumBell, [\freq, 110]);
Synth(\mediumBell, [\freq, 130.81]);
Synth(\mediumBell, [\freq, 164.81]);

// Parameterized "Bell" Definition with 10 Formants!
// A similar synthesis approach as before, but we now can change more than just the frequency
// of the bells when we call the SynthDef:
(
SynthDef(\pBell, { arg fq=200, strikeFreq=100, res=1,
	// harmonics as ratio of h1 - there are 10 here!
	ih1 = 1, ih2 = 2, ih3 = 3, ih4 = 4, ih5 = 5,
	ih6 = 6, ih7 = 7, ih8 = 8, ih9 = 9, ih10 = 10,
	// amplitude of each harmonic
	a1 = 1.0, 	a2 = 1.0, 	a3 = 1.0, 	a4 = 1.0, 	a5 = 1.0,
	a6 = 1.0, 	a7 = 1.0, 	a8 = 1.0, 	a9 = 1.0, 	a10 = 1.0,
	// decay time of each harmonic
	t1 = 2, 	t2 = 2, 	t3 = 2, 	t4 = 2, 	t5 = 2,
	t6 = 2, 	t7 = 2, 	t8 = 2, 	t9 = 2, 	t10 = 2;

	var env, sig, strike;
	env = EnvGen.ar(Env.new([1,1],[t1]),doneAction:2); // Assumes t1 is the longest time
	strike = RLPF.ar(Impulse.ar(0),strikeFreq,res); //100 is a dull hit, 1000 has more bite...

	sig = DynKlank.ar(`[
		[fq*ih1, fq*ih2, fq*ih3, fq*ih4, fq*ih5, fq*ih6, fq*ih7, fq*ih8, fq*ih9, fq*ih10],
		[a1, a2, a3, a4, a5, a6, a7, a8, a9, a10],
		[t1, t2, t3, t4, t5, t6, t7, t8, t9, t10]], strike);
	Out.ar(0,0.1*Pan2.ar(sig,0))
}).add;
)

// Parameterized Bell Definition
// We have more control, but need to specify a lot more each time now, too!
// If you don't specify a value it will use the default included with the original SynthDef
(
Synth(\pBell, [\fq,200, \strikeFreq, 5000, \res, 1,
	\ih1,1, \ih2,2.31, \ih3,3.73, \ih4,4.81, \ih5,5.43,
	\ih6,6.8, \ih7,7.31, \ih8,8.93, \ih9,10.1, \ih10,11.43,
	\a1,1.0, \a2,0.9, \a3,0.6, \a4,0.1, \a5,0.5,
	\a6,0.1, \a7,0.3, \a8,0.2,
	\a9,0.1, \a10,0.05,
	\t1,8, \t2,7.5, \t3,7, \t4,6.5, \t5,6,
	\t6,5.5, \t7,5, \t8,4.5, \t9,4, \t10,3.5]);
)

(
Synth(\pBell, [\fq,130.81, \strikeFreq, 1200, \res, 1,
	\ih1,1, \ih2,2.31, \ih3,3.73, \ih4,4.81, \ih5,5.43,
	\ih6,6.8, \ih7,7.31, \ih8,8.93, \ih9,10.1, \ih10,11.43,
	\a1,1.0, \a2,0.9, \a3,0.6, \a4,0.1, \a5,0.5,
	\a6,0.1, \a7,0.3, \a8,0.2, \a9,0.1, \a10,0.05,
	\t1,8, \t2,7.5, \t3,7, \t4,6.5, \t5,6,
	\t6,5.5, \t7,5, \t8,4.5, \t9,4, \t10,3.5]);
)

// We can use a "do" function to play things automatically
(
{
	5.do{
		Synth(\pBell, [\fq,130.81, \strikeFreq, 1200, \res, 1,
			\ih1,1, \ih2,2.31, \ih3,3.73, \ih4,4.81, \ih5,5.43,
			\ih6,6.8, \ih7,7.31, \ih8,8.93, \ih9,10.1, \ih10,11.43,
			\a1,1.0, \a2,0.9, \a3,0.6, \a4,0.1, \a5,0.5,
			\a6,0.1, \a7,0.3, \a8,0.2, \a9,0.1, \a10,0.05,
			\t1,8, \t2,7.5, \t3,7, \t4,6.5, \t5,6,
			\t6,5.5, \t7,5, \t8,4.5, \t9,4, \t10,3.5]);
		rrand(0.5,1.0).wait;

		Synth(\pBell, [\fq,110.1, \strikeFreq, 1200, \res, 1,
			\ih1,1, \ih2,2.31, \ih3,3.73, \ih4,4.81, \ih5,5.43,
			\ih6,6.8, \ih7,7.31, \ih8,8.93, \ih9,10.1, \ih10,11.43,
			\a1,1.0, \a2,0.9, \a3,0.6, \a4,0.1, \a5,0.5,
			\a6,0.1, \a7,0.3, \a8,0.2, \a9,0.1, \a10,0.05,
			\t1,8, \t2,7.5, \t3,7, \t4,6.5, \t5,6,
			\t6,5.5, \t7,5, \t8,4.5, \t9,4, \t10,3.5]);
		rrand(1,2.0).wait;

		Synth(\pBell, [\fq,164.81, \strikeFreq, 1200, \res, 1,
			\ih1,1, \ih2,2.31, \ih3,3.73, \ih4,4.81, \ih5,5.43,
			\ih6,6.8, \ih7,7.31, \ih8,8.93, \ih9,10.1, \ih10,11.43,
			\a1,1.0, \a2,0.9, \a3,0.6, \a4,0.1, \a5,0.5,
			\a6,0.1, \a7,0.3, \a8,0.2, \a9,0.1, \a10,0.05,
			\t1,8, \t2,7.5, \t3,7, \t4,6.5, \t5,6,
			\t6,5.5, \t7,5, \t8,4.5, \t9,4, \t10,3.5]);
		rrand(0.5,1).wait;
	}
}.fork;
)