// 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;
)

// Additive synthesis means adding frequencies together to get to our desired sound
// No subtracting things with filters!
// In the real world most synths have additive and subtractive components!

// 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(\BasicAdditiveSynth, { arg freq=220, attack=0.1, decay=1;
	// you can pass a frequency, attack time, and decay time in as a variable to this synth
	var sig, env;   // this creates 2 variables used in the synth def

	// We're going to add some things together, so the multiply value shouldn't be too big
	// If our sig ever has a total value over 1 it will clip.
	// only uncomment one of these sigs at a time, or only the last one will be sent out as audio
	// sig = (SinOsc.ar(freq,0,0.2,0));
	// sig = (SinOsc.ar(freq,0,0.2,0))+(SinOsc.ar(freq*2.02,0,0.2,0));
	// sig = (SinOsc.ar(freq,0,0.2,0))+(SinOsc.ar(freq*2.02,0,0.2,0))+(SinOsc.ar(freq*3.06,0,0.2,0));

	// There is a more efficient way to specify this using arrays!
	// Watch out for that left-single quote (it's under the tilde)
	sig = Klang.ar(`[[1,2.04,3.08,4.12,5.6],[0.2,0.1,0.9,0.6,0.2],0],freq);

	// Let's define the envelope of our sound:
	// We'll use a percussive envelope!
	// Env.perc(attackTime: 0.01, releaseTime: 1.0, level: 1.0, curve: -4.0)
	env = Env.perc(attack, decay, 1, -4);

	// Multiply the envelope and the signal so our sound has a shape!
	sig = sig*EnvGen.kr(env, doneAction: Done.freeSelf);

	// 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
// Because we defined the envelope with "doneAction: Done.freeSelf" we don't have to stop it.
Synth(\BasicAdditiveSynth, [\freq, 24.midicps, \attack, 0.01, \decay, 2]);
Synth(\BasicAdditiveSynth, [\freq, 36.midicps, \attack, 0.01, \decay, 2]);

// Here's a graphical way to explore different envelope shapes!
// Env.perc(attackTime: 0.01, releaseTime: 1.0, level: 1.0, curve: -4.0)
Env.perc(0.1, 1, 1,-4).test.plot;
Env.perc(0.1, 1, 1,-2).test.plot;
Env.perc(0.1, 1, 1,0).test.plot;
Env.perc(0.1, 1, 1,2).test.plot;
Env.perc(0.1, 1, 1,4).test.plot;

