/*
Program Note for Electropoem No. 1 (SuperCollider) - 2023

The Electropoem Series explores the combination of poetic expression and multichannel sound design.
 Electropoem 01, the first piece in the series, presents a structured sound environment consisting of 11
 distinct levels. It uses spatialized sound to create a dynamic listening experience where textures,
 tones, and gestures shift across multiple channels.

This piece emphasizes the relationship between sound and space, allowing the audience to perceive
 music as more than a linear progression. Moments of silence are as important as the sounds
 themselves, creating a balanced and reflective atmosphere.

By integrating multichannel techniques with compositional detail, Electropoem 01 encourages listeners
 to engage actively with its sonic environment, offering a thoughtful perspective on sound and its 
organization in space.

Composer: Ali Balighi
Jul 18 2023
This piece has 11 levels

© 2024 - Ali Balighi - All Rights Reserved

*/

s.plotTree;
s.makeGui;
s.meter;
(
~count = 0;

ServerTree.removeAll;

s.newBusAllocators;
~reverbBus = Bus.audio(s, 2);
~delayBus = Bus.audio(s, 2);

~makeNodes = {
	s.bind({
		~fxGroup = Group.new;
		~reverb = Synth(\reverb, [\in, ~reverbBus], ~fxGroup);
		~delay = Synth(\delay, [\in, ~delayBus], ~fxGroup);
	});
};

~events = [
	{~hpPlayerR = ~hpR.play(quant:1)},
	{~hpPlayerD = ~hpD.play(quant:1)},
	{~fsin3Player = ~fsin3.play(quant:1)},
	{~saw1Player = ~saw1.play(quant:1)},
	{~fsin1Player = ~fsin1.play(quant:1)},
	{~fsin2Player = ~fsin2.play(quant:1)},
	{
		~fsin1Player.stop;
		~fsin2Player.stop;
	},
	{~fsin3Player.stop},
	{~hpPlayerR.stop},
	{~saw1Player.stop},
	{~hpPlayerD.stop},
];

s.waitForBoot({

	s.freeAll;
	Buffer.freeAll;

	s.sync;

	SynthDef.new(\saw1,
		{var sig, env;
			sig = RLPF.ar(
				Saw.ar(ExpRand(40, 52), 0.1),
				SinOsc.ar(XLine.kr(0.7, 30, 2), 0, 3600, 4000),
				0.2);

			env = EnvGen.kr(
				Env.perc(0.01, 4, 0.8, 3),
				gate: 1,
				levelScale: 1,
				levelBias: 0,
				timeScale: 1,
				doneAction: 2
			);
			sig = Pan2.ar(sig, SinOsc.kr(0.6), 1);
			sig = sig * env;
			Out.ar(\out.kr(0), sig);
			Out.ar(\outfx.ir(0), sig * \send.ir(-3).dbamp);

	}).add;

	SynthDef.new(\fsin1,
		{var sig, env;
			sig = FSinOsc.ar(XLine.kr(\xll.kr(200), \xlh.kr(400), 4)) * 0.2;

			env = EnvGen.kr(
				Env.perc(0.01, 5, 0.8, 3),
				gate: 1,
				levelScale: 1,
				levelBias: 0,
				timeScale: 1,
				doneAction: 2
			);
			sig = Pan2.ar(sig, SinOsc.kr(1), 1);
			sig = sig * env;
			Out.ar(\out.kr(0), sig);
			Out.ar(\outfx.ir(0), sig * \send.ir(-3).dbamp)
	}).add;


	SynthDef.new(\fsin2,
		{var sig, env, freq, noise;
			freq = ExpRand(40, 80).midicps;
			sig = SinOsc.ar(freq, 0, 0.6, 0);
			noise = PinkNoise.ar(0.4);
			sig = sig * noise;

			env = EnvGen.kr(
				Env.perc(0.01, 10, 0.3, 3),
				gate: 1,
				levelScale: 1,
				levelBias: 0,
				timeScale: 1,
				doneAction: 2
			);
			sig = Pan2.ar(sig, SinOsc.kr(10), 0.5);
			sig = sig * env;
			Out.ar(\out.kr(0), sig);
			Out.ar(\outfx.ir(0), sig * \send.ir(-3).dbamp)
	}).add;

	SynthDef.new(\fsin3,
		{var sig, env, freq;
			freq = ExpRand(3000, 4000);
			sig = SinOsc.ar(freq) * 0.05;

			env = EnvGen.kr(
				Env.perc(0.01, 2, 0.8, 3),
				gate: 1,
				levelScale: 1,
				levelBias: 0,
				timeScale: 1,
				doneAction: 2
			);
			sig = Pan2.ar(sig, SinOsc.kr(10), 1);
			sig = sig * env;
			Out.ar(\out.kr(0), sig);
			Out.ar(\outfx.ir(0), sig * \send.ir(-1).dbamp);
	}).add;

	SynthDef.new(\hp, { arg out=0, minmax=1, sig;
		sig = FSinOsc.ar(
			LinRand(200.0, 1000.0, minmax),
			0,
			Line.kr(0.2, 0, 0.01, doneAction: Done.freeSelf));
		sig = Pan2.ar(sig, SinOsc.kr(1), 1);
		Out.ar(0, sig);
		Out.ar(\outfx.ir(0), sig * \send.ir(-3).dbamp)
	}).add;

	s.sync;


	// Buses for FX

	SynthDef(\reverb, {
		var sig, wet;
		sig = In.ar(\in.ir(0), 2);
		sig = FreeVerb2.ar(sig[0], sig[1], mix:1, room:0.99, damp:0.99);
		sig = LPF.ar(sig, 900);
		Out.ar(\out.ir(0), sig);
	}).add;

	SynthDef.new(\delay, {
		var sig;
		sig = In.ar(\in.ir(0), 2);
		sig = CombC.ar(sig, 10, 0.9, 10);
		Out.ar(\out.ir(0), sig);
	}).add;

		s.sync;
		ServerTree.add(~makeNodes);
		ServerTree.run;

		s.sync;

		~hpR = Routine({
			loop({
				Synth.new(\hp, [\out, 0, \outfx, ~reverbBus]);
				1.wait;
			})
		});


		~hpD = Routine({
			loop({
				Synth.new(\hp, [\out, 0, \outfx, ~delayBus]);
				1.wait;
			})
		});


		~saw1 = Routine({
			loop({
				Synth.new(\saw1, [\out, 0, \outfx, ~reverbBus]);
				15.wait;
			})
		});

		~fsin1 = Routine({
			loop({
				Synth.new(\fsin1, [\out, 0, \outfx, ~reverbBus]);
				21.wait;
			})
		});

		~fsin2 = Routine({
			loop({
				Synth.new(\fsin2, [\out, 0, \outfx, ~reverbBus]);
				15.wait;
			})
		});

		~fsin3 = Routine({
			loop({
				Synth.new(\fsin3, [\out, 0, \outfx, ~reverbBus]);
				5.wait;
			})
		});
});
)


(
~events[~count].value;
~count = ~count + 1;
)