(
//~~FUNCTION THAT GENERATES THE LILYPOND FILES
~generateLilypond = {
	var sf, data, notes, perc, parts, noteNames, durSum, lastState, lastDur, n, beatPos, lastBassNote, lGrey, dGrey, lilyRepeat, lilyTime;
	var inFile, outFile, inString, outString;
	sf = SoundFile.openRead(~dir +/+ "../supercollider/gen_data_resources/ostinato_and_interrupt_data.wav");
	sf.readData(data = FloatArray.newClear(10000)); sf.close;
	data = data.clump(5).drop(1);
	notes = []; perc = []; parts = [[], [], [], [], [], [], []];
	noteNames = ["d\'", "f\'", "a\'", "c\'\'", "e\'\'", "g\'\'"];
	durSum = 60; lastState = -1; lastDur = -1; n = 0; beatPos = 0; lGrey = 70; dGrey = 50; lastBassNote = 11;
	while( {data[n][4] != 0}, {
		var state, string, note, sound, dur;
		state = data[n][0]; string = data[n][1]; note = data[n][2]; sound = data[n][3]; dur = data[n][4];
		data[n].postln; durSum = durSum + dur; durSum.postln;
		if(lastState != state, {beatPos = 0}, {});
		for(0, dur - 1,{
			arg b;
			var lilyStem, lilyRhythmMark, lilyStartBeam, lilyEndBeam, lilyBar, sec, minString, secString, lilyTime, lilyBracket, lilyNote;

			lilyStem = case
			{b == 0 && lastState == 0 && state == 1} {
				" \\override Staff.Stem #\'transparent = ##f "}
			{b == 0 && ((lastState == 1 && state == 0) || (lastState == -1))} {
				" \\override Staff.Stem #\'transparent = ##t "}
			{true} {""};

			lilyRhythmMark = case
			{state == 0} {""}
			{dur > 3} {""}
			{lastState != state} {" _" ++ dur.asString ++ " "}
			{lastDur != dur} {" _" ++ dur.asString ++ " "}
			{true} {""};

			lilyStartBeam = if(beatPos % 4 == 0, {" [ "}, {""});
			lilyEndBeam = if(beatPos % 4 == 3, {" ] "}, {""});
			beatPos = beatPos + 1;

			lilyBar = if(b == 0 && (lastState != state), {' \\bar \"||\" '}, {""});

			sec = (((durSum - dur) + b) / 5);
			minString = (sec.trunc / 60).trunc.asString;
			secString = (sec.trunc % 60).asString;
			if(secString.size == 1, {secString = "0" ++ secString}, {});
			lilyTime = case
			{(b == 0 && lastState == 0 && state == 1) || (sec % 12 == 0)} {
				' \\mark \\markup{ \\fontsize #-2 \"' ++ minString ++ "\'" ++ secString ++ '\\"\" } '}
			{b == 0 && ((lastState == 1 && state == 0) || (lastState == -1))} {""}
			{true} {""};

			lilyBracket = case
			{b == 0 && state == 0 && string == 1 && (note != 7)} {
				var res = if(lastBassNote != note, {"\\bracketify "}, {""}); lastBassNote = note; res}
			{b == 0 && state == 0 && string == 0} {
				var res = if(lastBassNote != note, {"\\bracketify "}, {""}); lastBassNote = note; res}
			{true} {lastBassNote = lastBassNote; ""};


			lilyNote = case
			{(state == 0) && (b != 0)} {"s16 "}
			{state == 0 && string == 0 && note == 0} {lilyBracket ++ noteNames[string] ++ "16 "}
			{state == 0 && string == 1 && (note - 7) == 0} {lilyBracket ++ noteNames[string] ++ "16 "}
			{(state == 0) && (string <= 1)} {
				"\\once \\override NoteHead #\'stencil = #ly:text-interface::print " ++
				"\\once \\override NoteHead #\'text = \\markup { \\translate #\'(-0 . -0.8) \\whiteout \\pad-markup #0.5 " ++ '\"' ++
				if(string == 0, {note.asString}, {(note - 7).asString}) ++ '\" } ' ++ lilyBracket ++ noteNames[string] ++ "16 "}
			{state == 0 && (string >= 2)} {noteNames[string] ++ "16 "}

			{(state == 1) && (b != 0)} {"r16 " ++ lilyStartBeam ++ lilyEndBeam}
			{state == 1 && sound == 0} {noteNames[string] ++ "16 " ++ lilyRhythmMark ++ lilyStartBeam ++ lilyEndBeam}
			{state == 1 && sound == 1} {noteNames[string] ++ "16 " ++ "\\harmonic " ++ lilyRhythmMark ++ lilyStartBeam + lilyEndBeam}
			{state == 1 && sound == 2} {"\\xNote " ++ noteNames[string] ++ "16 " ++ lilyRhythmMark ++ lilyStartBeam ++ lilyEndBeam};

			notes = notes.add(lilyBar ++ lilyTime ++ lilyStem ++ lilyNote);

			perc = perc.add(if(sound == 2 || (state == 0),
				{lilyBar ++ lilyTime ++ lilyStem ++ lilyNote},
				{lilyBar ++ lilyTime ++ " \\once \\override Stem.color = #(x11-color \'grey" ++ lGrey.asString ++ ") " ++ lilyStem ++
					" \\once \\override NoteHead.color = #(x11-color \'grey" ++ lGrey.asString ++ ") " ++ lilyNote}));

			for(0, 5, {
				arg p; var grey;
				grey = if(sound == 2, {dGrey}, {lGrey});
				parts[p] = parts[p].add(if(string == p || (state == 0),
					{lilyBar ++ lilyTime ++ lilyStem ++ lilyNote},
					{lilyBar ++ lilyTime ++ " \\once \\override Stem.color = #(x11-color \'grey" ++ grey.asString ++ ") " ++ lilyStem ++
						" \\once \\override NoteHead.color = #(x11-color \'grey" ++ grey.asString ++ ") " ++ lilyNote}));
			});
		});
		lastState = state;
		lastDur = dur;
		n = n + 1;
	});

	lilyRepeat = "\\repeat unfold " ++ ((durSum-60)/5/12).trunc.asString ++ " { \\repeat unfold 59 { s16 \\noBreak } s16 \\break } ";
	lilyTime = "\\time 60/16 ";

	inFile = File(~dir +/+ "../lilypond/ostinato_and_interrupt_lilypond_score_template.ly", "r");
	inString = inFile.readAllString;
	inFile.close;

	outFile = File(~dir +/+ "../lilypond/ostinato_and_interrupt_lilypond_guitar_part.ly", "w");
	outString = "<< " ++ lilyRepeat ++ lilyTime ++
	   "{ \\override Staff.Rest #\'transparent = ##t " ++ notes.join ++ ' \\bar \"|.\" } >>';
	outFile.write(inString.replace("%<<music>>", outString).replace("piece = " ++ '\"part\"', "piece = " ++ '\"guitar/all\"'));
	outFile.close;

	outFile = File(~dir +/+ "../lilypond/ostinato_and_interrupt_lilypond_percussion_part.ly", "w");
	outString = "<< " ++ lilyRepeat ++ lilyTime ++
	    "{ \\override Staff.Rest #\'transparent = ##t " ++ perc.join ++ ' \\bar \"|.\" } >>';
	outFile.write(inString.replace("%<<music>>", outString).replace("piece = " ++ '\"part\"', "piece = " ++ '\"percussion\"'));
	outFile.close;

	for(0, 5, {
		arg p, staff;
		outFile = File(~dir +/+ "../lilypond/ostinato_and_interrupt_lilypond_ensemble_part_" ++ (6 - p).asString ++ ".ly", "w");
		staff = Array.fill(6, {|i| if(i == (5 - p), {"#f "}, {"(x11-color \'grey" ++ lGrey.asString ++ ") "})}).join;
		staff = "\\override Staff.StaffSymbol.stencil = #(color-staff-lines " ++ staff ++ ")";
		outString = "<< " ++ lilyRepeat ++ lilyTime ++
		    "{" ++ staff ++ " \\override Staff.Rest #\'transparent = ##t " ++ (parts[p]).join ++ ' \\bar \"|.\" } >>';
		outFile.write(inString.replace("%<<music>>", outString).replace(
			"piece = " ++ '\"part\"', "piece = " ++ '\"ensemble part ' ++ (6 - p).asString ++ '\"'));
		outFile.close;
	});
};
)

// uncomment below generate lilypond files without gui (requires resouces to exist)
/*(
~dir = thisProcess.nowExecutingPath.dirname;
~generateLilypond.value
)*/