(
// synth for hl 6
SynthDef(\hl_6_sine, {arg freq, amp = 1, pos = 0;
	Out.ar(0,  Pan2.ar(SinOsc.ar(freq, 0, Lag.kr(amp, 2)), pos))
}).store;

// synth for hl 5
SynthDef(\hl_5_high_noise, {arg amp = 1, pos = 0;
	Out.ar(0,  Pan2.ar(HPF.ar(WhiteNoise.ar(Lag.kr(amp * (1 / 128), 0.05)), 5000), pos))
}).store;

// synth for hl 4
SynthDef(\hl_4_low_noise, {arg amp = 1, pos = 0;
	Out.ar(0,  Pan2.ar(LPF.ar(WhiteNoise.ar(Lag.kr(amp * (1 / 4), 0.05)), 300), pos))
}).store;

// synth for amp curves for score
SynthDef(\lamp, {arg freq, amp = 1;
	Out.ar(0, Lag.ar(K2A.ar(amp), 2))
}).store;

// synth for playback
SynthDef(\play, {arg sinePlayer1, sinePlayer2, highNoisePlayer, lowNoisePlayer,
	sineBuf1 = 0, sineBuf2 = 1, highNoiseBuf = 2, lowNoiseBuf = 3,
	eTracks, eTracksPanned, eMaster,
	eVol = #[0.8, 0.8, 0.8, 0.8], eMute = #[1, 1, 1, 1], ePan = #[0, 0, 0, 0], masterVol = 1, masterMute = 1,
	playRate = 0, startPos = 0, startTrig = 0, hash;
	var dStartTrig, phasor, countOff, imp, curBeat;

	countOff = PulseCount.kr(Impulse.kr(4), startTrig) * startTrig;
	dStartTrig = countOff > 17;
	phasor = Phasor.ar(dStartTrig, Select.kr(playRate * dStartTrig, [0, BufRateScale.kr(sineBuf1)]),
		0, BufFrames.kr(sineBuf1), startPos * BufFrames.kr(sineBuf1));
	curBeat = ((A2K.kr(phasor) / BufFrames.kr(sineBuf1)) * BufDur.kr(sineBuf1) * 4).trunc;
	curBeat = Select.kr(dStartTrig, [countOff - 18, curBeat]);

	sinePlayer1 = PlayBuf.ar(2, sineBuf1, playRate * dStartTrig, dStartTrig, startPos * BufFrames.kr(sineBuf1));
	sinePlayer2 = PlayBuf.ar(2, sineBuf2, playRate * dStartTrig, dStartTrig, startPos * BufFrames.kr(sineBuf2));
	highNoisePlayer = PlayBuf.ar(2, highNoiseBuf, playRate * dStartTrig, dStartTrig, startPos * BufFrames.kr(highNoiseBuf));
	lowNoisePlayer = PlayBuf.ar(2, lowNoiseBuf, playRate * dStartTrig, dStartTrig, startPos * BufFrames.kr(lowNoiseBuf));

	eTracks = {arg i;
		[Mix.new(sinePlayer1), Mix.new(sinePlayer2), Mix.new(highNoisePlayer), Mix.new(lowNoisePlayer)][i] * eVol[i] * eMute[i]} ! 4;
	eTracksPanned = {arg i; Pan2.ar(eTracks[i], ePan[i])} ! 4;
	eMaster = Mix.new(eTracksPanned) * masterVol * masterMute * dStartTrig.lag;
	Out.ar(0, eMaster);

	// optional click - uncomment and send to an output not used
	//Out.ar(2, 10 * BPF.ar(WhiteNoise.ar * EnvGen.kr(Env.perc(0.01, 0.1), curBeat % 2 <= 0), 440 * ((curBeat % 8 <= 0) + 1), 0.02));
	SendTrig.kr(Changed.kr(curBeat), hash, curBeat);
	imp = Impulse.kr(10);
	SendReply.kr(imp, '/masterLevel', [Amplitude.kr(eMaster)], hash);
	SendReply.kr(imp, '/trackLevels', [Amplitude.kr(eTracks)], hash)}).add;

// generate audio for playback
~genPattern = {arg data, ins, durMult, genAudio = false, cond = nil;
	var pattern;
	pattern = Ppar(data.collect({
		arg seq, p;
		switch(ins,
			"hl_6_fundamental", {Pmono(\hl_6_sine, \freq, 31.midicps,
				\dur, ~dur, \amp, Pseq(seq), \pos, 0)},
			"hl_6_harmonics", {Pmono(\hl_6_sine, \freq, 31.midicps + ((31.midicps * 4) * (p + 1)),
				\dur, ~dur, \amp, Pseq(seq * (1 / pow(1 + ((p + 1) * 4), 1))), \pos, 0)},
			"hl_5_high_noise", {Pmono(\hl_5_high_noise, \dur, ~dur * durMult, \amp, Pseq(seq), \pos, 0)},
			"hl_4_low_noise", {Pmono(\hl_4_low_noise, \dur, ~dur * durMult, \amp, Pseq(seq), \pos, 0)})}));
	if(genAudio, {File.mkdir(~dir +/+ ".." +/+ "audio" +/+ "transform_" ++ ~transform.join ++ "_audio");
		pattern.render(~dir +/+ ".." +/+ "audio" +/+ "transform_" ++ ~transform.join ++ "_audio" +/+ ins ++ ".wav", ~dur * durMult * data[0].size,
			headerFormat: "WAV", sampleRate: s.sampleRate, action: {if(cond != nil, {cond.unhang})})});
	pattern};
)