(
SynthDef(\string_model, {arg freq, gate = 1, del, sustain, amp, dur, attack, release = 1, busIndex = 0;
	var trig, exc, sig1, sig2, noHarms;
	noHarms = rrand(20, 40);
	exc = Saw.ar(freq, TRand.ar(0.5, 1, Impulse.ar(freq))) * 0.001 + Dust.ar(10000, 0.01);
	sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq),
		Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}),
		Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip;
	//note that the delay cuts into the sustain portion of the tone!!!
	Out.ar([0, 1], 0.75 * sig1 * amp * EnvGen.kr(Env.dadsr(del, attack, 0.3, 0.9, release, 0.9, -3), gate, doneAction: 2));
}).add;
)

(
var primes, hsArrayToFreq, hsArrayDimDiff, file, seq, phraseLengths, musicData, patterns;

thisThread.randSeed = 1954111620240509; //everything in between
//thisThread.randSeed = 20240509; //rise yitgadal

primes = [2, 3, 5, 7, 11];

hsArrayToFreq = {
	arg array;
	array.collect({arg dim, d; pow(primes[d], dim)}).product
};

hsArrayDimDiff = {
	arg array1, array2;
	var fArray;
	fArray = array2.drop(1) - array1.drop(1);
	if(fArray.sum == 0, {1}, {(primes[fArray.abs.indexOf(1) + 1] * fArray.sum)})
};

file = File("/home/mwinter/Sketches/compact_sets/everything_in_between.txt".standardizePath,"r");
//file = File("/home/mwinter/Sketches/compact_sets/rise_yitgadal.txt".standardizePath,"r");
seq = file.readAllString.interpret;

//seq = seq.collect({arg item; item.sort});
seq = seq.collect({arg chord, index;
	var ref_ins;
	ref_ins = if(index == 0, {
		[0] // this should actually check which is the 'centered' pitch
	}, {
		[seq[index - 1], chord].postln.flop.collect({arg pair, p; if(pair[0] == pair[1], {p}, {-1})}).postln.removeEvery([-1])
	});
	chord.collect({arg pitch;
		var dimDiff;
		ref_ins.postln;
		if(ref_ins.size == 1, {
			[pitch, [ref_ins[0], hsArrayDimDiff.value(chord[ref_ins[0]], pitch)]]
		}, {
			var min_ref_ins;
			min_ref_ins = ref_ins.minItem({arg ins; (chord[ins].drop(1) - pitch.drop(1)).abs.sum});
			[pitch, [min_ref_ins.postln, hsArrayDimDiff.value(chord[min_ref_ins], pitch)]]
		});
	})
});

seq.do({arg chord; chord; chord.collect({arg pitch; hsArrayToFreq.value(pitch[0])}).postln});
//seq.postln;


phraseLengths = [];
while({phraseLengths.sum < seq.size}, {phraseLengths = phraseLengths ++ [rrand(1, 3)]});
//phraseLengths.postln;

musicData = seq.clumps(phraseLengths).collect({arg subSeq, seqIndex;
	var baseRound, baseDurs, minDelay, maxDelay, baseSubtract;
	baseRound = 0.5;
	baseDurs = subSeq.size.collect({arg subSeqIndex; if(subSeqIndex != (subSeq.size - 1), {rrand(5.0, 7.0)}, {rrand(10.0, 15.0)})}).round(baseRound);
	//baseDurs = subSeq.size.collect({arg subSeqIndex; if(subSeqIndex != (subSeq.size - 1), {rrand(5.0, 7.0)}, {rrand(15.0, 20.0)})}).round(baseRound);
	//maxDelay = rrand(1.0, 3.0);
	//maxDelay = 5;
	minDelay = 0;
	maxDelay = 0;
	baseDurs[0] = baseDurs[0] + maxDelay;
	baseSubtract = rrand(0.0, 3.0);
	subSeq.flop.collect({arg voice, v;
		var phrases, freqs, durs, delays, attacks, rels, sustains, amps, refs;
		phrases = voice.separate({arg a, b; a[0] != b[0]});
		freqs = phrases.collect({arg phrase; if(phrase[0][0] != ["Rest"], {45.midicps * pow(2, (v * 2).clip(0, 1)) * hsArrayToFreq.value(phrase[0][0])}, {Rest(0)})});
		refs = phrases.collect({arg phrase; if(phrase[0][0] != ["Rest"], {phrase[0][1]}, {Rest(0)})});
		durs = baseDurs.clumps(phrases.collect({arg phrase; phrase.size})).collect({arg c; c.sum});
		delays = durs.collect({arg dur, d; if((d == 0) && (refs[d][0] != v), {[rrand(minDelay, maxDelay), 0].wchoose([1, 1].normalizeSum)}, {0})}).round(baseRound);
		//delays = durs.collect({0}}).round(baseRound);
		attacks = durs.collect({arg dur, d; if(d == 0, {rrand(3.0, 5.0)}, {rrand(1.0, 3.0)})}).round(baseRound);
		rels = durs.collect({arg dur, d; if(d != (durs.size - 1), {rrand(0.5, 1.0)}, {rrand(3.0, 5.0)})}).round(baseRound);
		sustains = durs.collect({arg dur, d;
			if(d != (durs.size - 1), {
				dur - rels[d]
			}, {
				dur - rels[d] - baseSubtract - rrand(0.0, 1.0)})
		}).round(baseRound);
		amps = freqs.collect({rrand(0.6, 0.7) / [1, 2, 2, 2][v]});
		[freqs, durs, attacks, delays, sustains, rels, amps, refs].flop;
	});
}).flop.collect({arg voice; voice.flatten});

musicData = musicData.collect({arg voice, v;
	var clumps;
	//(v + "~~~~~~~~~~").postln;
	clumps = voice.separate({arg a, b; [true, a[0] != b[0]].wchoose([1, 2].normalizeSum)});
	clumps = clumps.collect({arg clump;
		if(clump.size == 1, {clump[0]}, {
			var mergedClump;
			mergedClump = clump[0].deepCopy;
			mergedClump[1] = clump.slice(nil, 1).sum;
			mergedClump[4] = (mergedClump[1] - (clump.last[1] - clump.last[4]));
			mergedClump[5] = clump.last[5];
			mergedClump
		});
	});
});

~musicData = musicData;

~patterns = Ppar(
	musicData.collect({arg voice, v;
		var freqs, durs, attacks, delays, sustains, rels, amps;
		# freqs, durs, attacks, delays, sustains, rels, amps = voice.flop;
		//# durs, attacks, delays, sustains, rels = [durs, attacks, delays, sustains, rels].collect({arg data; data / 16});
		Pbind(
			\instrument, \string_model,
			\freq, Pseq(freqs, 1),
			\dur, Pseq(durs, 1),
			\attack, Pseq(attacks, 1),
			\sustain, Pseq(sustains, 1),
			\release, Pseq(rels, 1),
			\amp, Pseq(amps, 1),
			\del, Pseq(delays, 1),
			\busIndex, v
		)
	});
);

~patterns.play
)


(
var primes, hsArrayToFreq, hsArrayDimDiff, file, seq, phraseLengths, musicData, patterns;

//thisThread.randSeed = 1954111620240509; //everything in between
thisThread.randSeed = 20240509; //rise yitgadal

primes = [2, 3, 5, 7, 11];

hsArrayToFreq = {
	arg array;
	array.collect({arg dim, d; pow(primes[d], dim)}).product
};

hsArrayDimDiff = {
	arg array1, array2;
	var fArray;
	fArray = array2.drop(1) - array1.drop(1);
	if(fArray.sum == 0, {1}, {(primes[fArray.abs.indexOf(1) + 1] * fArray.sum)})
};

//file = File("/home/mwinter/Sketches/compact_sets/everything_in_between.txt".standardizePath,"r");
file = File("/home/mwinter/Sketches/compact_sets/rise_yitgadal.txt".standardizePath,"r");
seq = file.readAllString.interpret;

//seq = seq.collect({arg item; item.sort});
seq = seq.collect({arg chord, index;
	var ref_ins;
	ref_ins = if(index == 0, {
		[0] // this should actually check which is the 'centered' pitch
	}, {
		[seq[index - 1], chord].postln.flop.collect({arg pair, p; if(pair[0] == pair[1], {p}, {-1})}).postln.removeEvery([-1])
	});
	chord.collect({arg pitch;
		var dimDiff;
		ref_ins.postln;
		if(ref_ins.size == 1, {
			[pitch, [ref_ins[0], hsArrayDimDiff.value(chord[ref_ins[0]], pitch)]]
		}, {
			var min_ref_ins;
			min_ref_ins = ref_ins.minItem({arg ins; (chord[ins].drop(1) - pitch.drop(1)).abs.sum});
			[pitch, [min_ref_ins.postln, hsArrayDimDiff.value(chord[min_ref_ins], pitch)]]
		});
	})
});

seq.do({arg chord; chord; chord.collect({arg pitch; hsArrayToFreq.value(pitch[0])}).postln});
//seq.postln;


phraseLengths = [];
while({phraseLengths.sum < seq.size}, {phraseLengths = phraseLengths ++ [rrand(1, 3)]});
//phraseLengths.postln;

musicData = seq.clumps(phraseLengths).collect({arg subSeq, seqIndex;
	var baseRound, baseDurs, minDelay, maxDelay, baseSubtract;
	baseRound = 0.5;
	baseDurs = subSeq.size.collect({arg subSeqIndex; if(subSeqIndex != (subSeq.size - 1), {rrand(5.0, 7.0)}, {rrand(10.0, 15.0)})}).round(baseRound);
	//baseDurs = subSeq.size.collect({arg subSeqIndex; if(subSeqIndex != (subSeq.size - 1), {rrand(5.0, 7.0)}, {rrand(15.0, 20.0)})}).round(baseRound);
	//maxDelay = rrand(1.0, 3.0);
	//maxDelay = 5;
	minDelay = 0;
	maxDelay = 0;
	baseDurs[0] = baseDurs[0] + maxDelay;
	baseSubtract = rrand(0.0, 3.0);
	subSeq.flop.collect({arg voice, v;
		var phrases, freqs, durs, delays, attacks, rels, sustains, amps, refs;
		phrases = voice.separate({arg a, b; a[0] != b[0]});
		freqs = phrases.collect({arg phrase; if(phrase[0][0] != ["Rest"], {45.midicps * pow(2, (v * 2).clip(0, 1)) * hsArrayToFreq.value(phrase[0][0])}, {Rest(0)})});
		refs = phrases.collect({arg phrase; if(phrase[0][0] != ["Rest"], {phrase[0][1]}, {Rest(0)})});
		durs = baseDurs.clumps(phrases.collect({arg phrase; phrase.size})).collect({arg c; c.sum});
		delays = durs.collect({arg dur, d; if((d == 0) && (refs[d][0] != v), {[rrand(minDelay, maxDelay), 0].wchoose([1, 1].normalizeSum)}, {0})}).round(baseRound);
		//delays = durs.collect({0}}).round(baseRound);
		attacks = durs.collect({arg dur, d; if(d == 0, {rrand(3.0, 5.0)}, {rrand(1.0, 3.0)})}).round(baseRound);
		rels = durs.collect({arg dur, d; if(d != (durs.size - 1), {rrand(0.5, 1.0)}, {rrand(3.0, 5.0)})}).round(baseRound);
		sustains = durs.collect({arg dur, d;
			if(d != (durs.size - 1), {
				dur - rels[d]
			}, {
				dur - rels[d] - baseSubtract - rrand(0.0, 1.0)})
		}).round(baseRound);
		amps = freqs.collect({rrand(0.6, 0.7) / [1, 2, 2, 2][v]});
		[freqs, durs, attacks, delays, sustains, rels, amps, refs].flop;
	});
}).flop.collect({arg voice; voice.flatten});

musicData = musicData.collect({arg voice, v;
	var clumps;
	//(v + "~~~~~~~~~~").postln;
	clumps = voice.separate({arg a, b; [true, a[0] != b[0]].wchoose([1, 2].normalizeSum)});
	clumps = clumps.collect({arg clump;
		if(clump.size == 1, {clump[0]}, {
			var mergedClump;
			mergedClump = clump[0].deepCopy;
			mergedClump[1] = clump.slice(nil, 1).sum;
			mergedClump[4] = (mergedClump[1] - (clump.last[1] - clump.last[4]));
			mergedClump[5] = clump.last[5];
			mergedClump
		});
	});
});

~musicData = musicData;

~patterns = Ppar(
	musicData.collect({arg voice, v;
		var freqs, durs, attacks, delays, sustains, rels, amps;
		# freqs, durs, attacks, delays, sustains, rels, amps = voice.flop;
		//# durs, attacks, delays, sustains, rels = [durs, attacks, delays, sustains, rels].collect({arg data; data / 16});
		Pbind(
			\instrument, \string_model,
			\freq, Pseq(freqs, 1),
			\dur, Pseq(durs, 1),
			\attack, Pseq(attacks, 1),
			\sustain, Pseq(sustains, 1),
			\release, Pseq(rels, 1),
			\amp, Pseq(amps, 1),
			\del, Pseq(delays, 1),
			\busIndex, v
		)
	});
);

~patterns.play
)


(
// breysheet
var primes, hsArrayToFreq, hsArrayDimDiff, refs, file, seq, durs, chords, phraseLengths, musicData, patterns;

thisThread.randSeed = 20240509;

primes = [2, 3, 5, 7, 11, 13];

hsArrayToFreq = {
	arg array;
	array.collect({arg dim, d; pow(primes[d], dim)}).product
};

hsArrayDimDiff = {
	arg array1, array2;
	var fArray;
	fArray = array2.drop(1) - array1.drop(1);
	//fArray.postln;
	if(fArray.sum == 0, {1}, {(primes[fArray.abs.indexOf(1) + 1] * fArray.sum)});
};

file = File("/home/mwinter/Sketches/compact_sets/breysheet.txt".standardizePath,"r");
seq = file.readAllString.interpret;


//seq.do({arg data, index; [data[0], data[1].collect({arg pitch; (110 * hsArrayToFreq.value(pitch)).cpsmidi})].postln});
//seq.postln;


# durs, chords = seq[..(seq.size / 2).asInteger].flop;

//seq = seq.collect({arg item; item.sort});


refs = chords.collect({arg chord, index;
	var ref_ins;
	ref_ins = if(index == 0, {
		[0] // this should actually check which is the 'centered' pitch
	}, {
		[chords[index - 1], chord].flop.collect({arg pair, p; if(pair[0] == pair[1], {p}, {-1})}).removeEvery([-1])
	});
	//if(ref_ins == [], {"here".postln});
	"-----".postln;
	chord.collect({arg pitch;
		var dimDiff;
		ref_ins.postln;
		if(ref_ins.size == 1, {
			//"here1".postln;
			[pitch, [ref_ins[0], hsArrayDimDiff.value(chord[ref_ins[0]], pitch)]].postln
		}, {
			var min_ref_ins;
			//this is a bug!!!!
			min_ref_ins = ref_ins.minItem({arg ins; (chord[ins].drop(1) - pitch.drop(1)).abs.sum});
			//pitch.postln;
			//chord[min_ref_ins].postln;
			//"here2".postln;
			[pitch, [min_ref_ins, hsArrayDimDiff.value(chord[min_ref_ins], pitch)]].postln
		});
	})
}).flop;


/*
refs = chords.collect({arg chord, index;
	var ref_ins;
// ref_ins = [0];
	//if(ref_ins == [], {"here".postln});
	"-----".postln;
	chord.collect({arg pitch;
		[[0, 0, 0, 0], [0, 1]]
	})
}).flop;
*/



"here".postln;
refs.postln;

chords.postln;

musicData = chords.flop.collect({arg voice, v;
	var phrases, freqs, vDurs, delays, attacks, rels, sustains, vRefs, amps;
	phrases = voice.separate({arg a, b; a != b});
	freqs = phrases.collect({arg phrase; if(phrase[0] != ["Rest"], {55.midicps * pow(2, ([0, 1, 1][v]).clip(0, 2)) * hsArrayToFreq.value(phrase[0])}, {Rest(0)})});
	vDurs = durs.clumps(phrases.collect({arg phrase; phrase.size})).collect({arg c; c.sum});
	vRefs = refs[v].clumps(phrases.collect({arg phrase; phrase.size})).collect({arg r; r[0].postln[1]});

	vDurs[vDurs.size - 1] = 3;
	attacks = (vDurs / 2).clip(0, 0.01);
	delays = vDurs * 0;
	rels = (vDurs / 2).clip(0, 0.01);
	sustains = vDurs - rels;

	amps = freqs.collect({rrand(0.6, 0.7) / [2, 2, 2, 2][v]});
	//[freqs, vDurs, amps].flop;
	[freqs, vDurs, attacks, delays, sustains, rels, amps, vRefs].flop;
});

~musicData = musicData.postln;

~patterns = Ppar(
	musicData[0..2].collect({arg voice, v;
		var freqs, durs, attacks, delays, sustains, rels, amps;
		//# freqs, durs, amps = voice.flop;
		# freqs, durs, attacks, delays, sustains, rels, amps = voice.flop;
		//# durs, attacks, delays, sustains, rels = [durs, attacks, delays, sustains, rels].collect({arg data; data / 16});

		/*
		durs = durs;
		durs.postln;
		rels = (durs / 2).clip(0, 0.01);
		attacks = (durs / 2).clip(0, 0.05);
		sustains = durs - rels;
		*/

		Pbind(
			\instrument, \string_model,
			\freq, Pseq(freqs, 1),
			\dur, Pseq(durs.postln, 1),
			\attack, Pseq(attacks, 1),
			\sustain, Pseq(sustains, 1),
			\release, Pseq(rels, 1),
			\amp, Pseq(amps, 1),
			\del, 0,
			\busIndex, v
		)
	});
);

~patterns.play;

(durs.sum / 60).postln
)

{ SinOsc.ar([110, 110 * 3/2], 0, 0.15) }.play;