(
~transcribe = {arg scoreData, seed;
	var rawMusicData, timeSigData, sectionData, dir, basePath, scoreFile, maxSize, lineBreakString, openStrings, musicData;

	rawMusicData = scoreData[0];
	timeSigData = scoreData[1];
	sectionData = scoreData[2];

	basePath = ~dir +/+ ".." +/+ "lilypond" +/+ "seed_" ++ seed;
	basePath.mkdir;

	scoreFile = File(basePath +/+ "cicc_score.ly".standardizePath,"w");
	//File.readAllString(basePath +/+ ".." +/+ "templates" +/+ "cicc_score_template.ly").postln;
	scoreFile.write(File.readAllString(basePath +/+ ".." +/+ "templates" +/+ "cicc_score_template.ly").replace("seed: xxx", "seed: " ++ seed));
	scoreFile.close;
	scoreFile = File(basePath +/+ "cicc_pseudoindents_def.ly".standardizePath,"w");
	scoreFile.write(File.readAllString(basePath +/+ ".." +/+ "templates" +/+ "cicc_pseudoindents_def.ly"));
	scoreFile.close;

	openStrings = [1/1, 3/2, 2/1, 5/2, 35/12, 7/2];

	maxSize = 0;
	musicData = rawMusicData.collect({arg partData, p;
		var res;
		res = partData.collect({arg item, i;
			var note, rest;
			switch(p,
				0, {
					var string, fret, dur, sus;
					string = item[0];
					fret = item[1];
					dur = item[2];
					sus = item[3];
					note = sus.collect({[string, fret, i]});
				},
				1, {
					var freq, dur, sus;
					freq = item[0];
					dur = item[1];
					sus = item[2];
					note = sus.collect({[freq, i]});
					if(p < rawMusicData.size, {rest = (dur - sus).collect({[-1, i]})}, {[]});
				},
				2, {
					var freq1, freq2, dur, sus;
					freq1 = item[0];
					freq2 = item[1];
					dur = item[2];
					sus = 4;
					note = sus.collect({[[freq1, freq2 - freq1], i]});
					if(p < rawMusicData.size, {rest = (dur - sus).collect({[-1, i]})}, {[]});
				}
			);
			note ++ rest
		}).flatten;
		if(res.size > maxSize, {maxSize = res.size});
		res
	});


	musicData = musicData.collect({arg partData, p;
		var lastSectionSize, lastSectionSizeTrunc, finalSectionSize, ext;
		partData[(partData.size - 10)..];
		lastSectionSize = (maxSize - sectionData.last[0]);
		lastSectionSizeTrunc = lastSectionSize.trunc(16);
		finalSectionSize = if(lastSectionSize != lastSectionSizeTrunc, {lastSectionSizeTrunc + 16}, {lastSectionSize});
		ext = finalSectionSize - lastSectionSize;
		partData.extend((maxSize + ext), if(p == 0, {partData.last}, {[-1, partData.last[1]]}))
	});

	lineBreakString = "";
	sectionData.slice(nil, 0).add(musicData[0].size).differentiate.drop(1).clump(4).do({arg section;
		var remainder, endSec;
		remainder = 0;

		section.do({arg len, index;
			var measuresInFirst;
			if(remainder % 16 == 0, {
				lineBreakString = lineBreakString ++ "\\repeat unfold 8 {s2 \\noBreak} \\break \n";
			}, {
				lineBreakString = lineBreakString ++ "\\pseudoIndents 0 21 \\repeat unfold 7 {s2 \\noBreak} \\break \n";
			});

			remainder = len - (((64 - remainder) / 16).asInteger * 16);

			((remainder / 64) - 1).asInteger.do({
				lineBreakString = lineBreakString ++ "\\repeat unfold 8 {s2 \\noBreak} \\break \n";
			});

			remainder = remainder - (((remainder / 64) - 1).asInteger * 64);

			if(remainder % 16 == 0, {
				lineBreakString = lineBreakString ++ "\\repeat unfold 8 {s2 \\noBreak} \\break \n";
				remainder = remainder % 64;
			}, {
				if(remainder > 72, {
					lineBreakString = lineBreakString ++ "\\repeat unfold 8 {s2 \\noBreak} \\break \n";
					remainder = remainder - 64;
				}, {
					lineBreakString = lineBreakString ++ "\\pseudoIndents 0 42 \\repeat unfold 6 {s2 \\noBreak} \\break \n";
					remainder = 24;
				});
			});
			remainder
		});

		if(remainder > 0, {
			lineBreakString = lineBreakString ++ "\\pseudoIndents 0 " ++
			(21 * (8 - (remainder / 8).asInteger)) ++ " \\repeat unfold " ++ (remainder / 8).asInteger ++ " {s2 \\noBreak} \\break \n";
		});
	});


	musicData.do({arg part, p;
		var amps, harm, modi, timeSigIndex, sectionCount, sectionIndex, subSectionIndex, curTimeSig,
		lilyFile, lilyString, voices, lastVal, lilyNotes, lilyOcts, lilyGString, isHarmonic, measureCount,
		lilyNote, lilyDur, lilyRest, lilyBeatingMark, curTime = 0, noteTuples, markupSuffixes;

		//create file
		lilyFile = switch(p,
			0, {File(basePath +/+ "includes" +/+ "cicc_guitar.ly".standardizePath,"w")},
			1, {File(basePath +/+ "includes" +/+ "cicc_high.ly".standardizePath,"w")},
			2, {File(basePath +/+ "includes" +/+ "cicc_low.ly".standardizePath,"w")}
		);

		//start lilypond directives
		lilyString = "";

		lastVal = nil;

		//start voice
		lilyString = lilyString ++ "\n{ ";
		lilyString = lilyString ++ "\n\\set Score.markFormatter = #format-mark-box-numbers ";

		lilyString = lilyString + "\\tempo 2 = 90\n";
		if(p != 1, {lilyString = lilyString + "\\override Staff.TimeSignature #'stencil = ##f"});
		//lilyString = lilyString + "\\numericTimeSignature \\time 4/4\n \\mark \\default \n";
		lilyString = lilyString + "\\numericTimeSignature \\time 2/2\n";

		lilyString = switch(p,
			0, {lilyString + "\\clef treble\n"},
			1, {lilyString + "\\clef \"treble^(8)\"\n"},
			2, {lilyString + "\\clef \"bass_(8)\"\n"}
		);

		lilyNotes = ["c", "cis", "d", "dis","e", "f", "fis", "g", "gis", "a", "ais", "b"];
		lilyOcts = [",,", ",", "", "'", "''", "'''", "''''"];

		timeSigIndex = 0;
		sectionCount = 0;
		sectionIndex = 1;
		subSectionIndex = 1;
		curTimeSig = 4;
		measureCount = 0;
		part.clump(4).do({arg beat, i;
			var gSum = 0;

			beat.separate({arg a, b; ((a[0] != -1) || (b[0] != -1)) && (a != b)}).do({arg group, g; var noteLength, target = 0;
				noteLength = group.size;
				gSum = gSum + noteLength;

				//add ties
				lilyString = lilyString ++ if((p != 2) && (group[0] == lastVal) && (group[0][0] != -1), {"~ "}, {""});
				//add barcheck count
				lilyString = lilyString ++ if((curTime % curTimeSig == 0) && (i != 0), {measureCount = measureCount + 1; "| "}, {""});

				if((i == (sectionData[sectionCount][0] / 4)) && (g == 0),{
					var barType, pageBreak;
					barType = switch(sectionData[sectionCount][1],
						0, {"\"||\""},
						1, {"\".|\""},
						-1, {"\"|.\" \\set Score.currentBarNumber = #1 "});
					pageBreak = switch(sectionData[sectionCount][1], 0, {""}, 1, {""}, -1, {measureCount = 0; "\n\\pageBreak \n"});
					isHarmonic = switch(sectionData[sectionCount][1], 0, {false}, 1, {true}, -1, {false});
					lilyString = lilyString + " \\bar " ++  barType ++
					" \\mark \\markup { \\bold \\box " ++ sectionIndex ++ "." ++ subSectionIndex ++ " }" ++ pageBreak;
					if(sectionCount < (sectionData.size - 1), {sectionCount = sectionCount + 1});
					switch(sectionData[sectionCount][1],
						0, {subSectionIndex = subSectionIndex + 1},
						1, {subSectionIndex = subSectionIndex + 1},
						-1, {sectionIndex = sectionIndex + 1; subSectionIndex = 1})
				});

				if((i == (timeSigData[timeSigIndex][0] / 4)) && (g == 0),{
					timeSigData[timeSigIndex][0];
					curTimeSig = timeSigData[timeSigIndex][1];
					if(curTimeSig % 2 == 0, {
						lilyString = lilyString + "\n\\time " ++ (curTimeSig / 2).asInteger.asString ++ "/2\n";
					}, {
						lilyString = lilyString + "\n\\time " ++ curTimeSig.asString ++ "/4\n";
					});
					if(timeSigIndex < (timeSigData.size - 1), {timeSigIndex = timeSigIndex + 1});
					curTime = 0;
				});

				switch(p,
					0, {
						lilyNote = lilyNotes[(((62.midicps * openStrings[group[0][0]]).cpsmidi + group[0][1]).round(1) % 12)];// * 2];
						lilyNote = lilyNote ++ lilyOcts[(((62.midicps * openStrings[group[0][0]]).cpsmidi + group[0][1]).round(1) / 12).asInteger - 2];
					},
					1, {
						if(group[0][0] != -1, {
							lilyNote = lilyNotes[((group[0][0].cpsmidi).round(1) % 12)];// * 2];
							lilyNote = lilyNote ++ lilyOcts[(((group[0][0]).cpsmidi).round(1) / 12).asInteger - 2];
						},{lilyNote = "r"});
					},
					2, {
						if(group[0][0] != -1, {
							lilyNote = lilyNotes[((group[0][0][0].cpsmidi).round(1) % 12)];// * 2];
							lilyNote = lilyNote ++ lilyOcts[(((group[0][0][0]).cpsmidi).round(1) / 12).asInteger - 2];
							lilyBeatingMark = "^ \\markup{ " ++ group[0][0][1].round(0.1) ++ " } ";
						},{lilyNote = "r"});
					}
				);

				//duration
				lilyDur = switch(noteLength, 1, {"16 "}, 2, {"8 "}, 3, {"8. "}, 4, {"4 "});
				//append rest directive
				lilyRest = "";
				lilyGString = if(((group[0] != lastVal) && (p == 0)), {
					var stringString, fretString;
					stringString = ["VI ", "V ", "IV ", "III ", "II ", "I "][group[0][0]];
					fretString = group[0][1].asString;
					if(isHarmonic, {fretString = "\\musicglyph \"noteheads.s0harmonic\""});
					"_\\markup{\\concat{ " ++ stringString ++ " \\super " ++ fretString ++ "}} "
				}, {""});

				if((p != 2) || (lilyNote == "r"), {
					lilyString = lilyString ++ lilyNote ++ lilyDur ++ lilyGString;
				}, {
					lilyString = lilyString ++ " <<{ " ++ lilyNote ++ lilyDur ++
					" \\laissezVibrer " ++ lilyBeatingMark ++ " }\\\\ {\\new Voice { \\voiceTwo " ++
					lilyNote ++ lilyDur ++ " \\laissezVibrer }}>> \\oneVoice " ++ lilyGString;
				});

				//beam group
				if((p != 2) && (g == 0) && (noteLength != 4), {lilyString = lilyString ++ " [ "});
				if((p != 2) && (gSum == 4) && (noteLength != 4), {lilyString = lilyString ++ " ] "});

				lastVal = group[0];
				curTime = curTime + (noteLength / 4);
			});
		});

		//end voice
		lilyString = lilyString ++ " ] \\bar \"|.\" } \n";


		noteTuples = [lilyNotes, lilyOcts].allTuples.collect({arg val; val.join}).join("|");

		markupSuffixes = ["VI ", "V ", "IV ", "III ", "II ", "I "].collect({arg stringString;
			(["\\\\musicglyph \\\"noteheads.s0harmonic\\\""] ++ (0..14)).collect({arg fret;
				"_\\\\markup{\\\\concat{ " ++ stringString ++ " \\\\super " ++ fret.asString ++ "}}"})}).flatten.join("|");

		lilyString.findRegexp(
			"(" ++ noteTuples ++ ")4 (" ++ markupSuffixes ++ ") ~ " ++
			"(" ++ noteTuples ++ ")4 ~ (" ++ noteTuples ++ ")4 ~ (" ++
			noteTuples ++ ")4 ~ (" ++ noteTuples ++ ")4 ~ (" ++ noteTuples ++ ")4"
		).clump(8).do({arg match;
			lilyString = lilyString.replace(match[0][1], match[1][1] ++ "1. " ++ match[2][1])});

		lilyString.findRegexp(
			"(" ++ noteTuples ++ ")4 (" ++ markupSuffixes ++ ") ~ (" ++ noteTuples ++ ")4 ~ (" ++ noteTuples ++ ")4 ~ (" ++ noteTuples ++ ")4"
		).clump(6).do({arg match;
			lilyString = lilyString.replace(match[0][1], match[1][1] ++ "1 " ++ match[2][1])});

		lilyString.findRegexp(
			"(" ++ noteTuples ++ ")4 (" ++ markupSuffixes ++ ") ~ (" ++ noteTuples ++ ")4 ~ (" ++ noteTuples ++ ")4"
		).clump(5).do({arg match;
			lilyString = lilyString.replace(match[0][1], match[1][1] ++ "2. " ++ match[2][1])});

		lilyString.findRegexp("(" ++ noteTuples ++ ")4 (" ++ markupSuffixes ++ ") ~ (" ++ noteTuples ++ ")4").clump(4).do({arg match;
			lilyString = lilyString.replace(match[0][1], match[1][1] ++ "2 " ++ match[2][1])});


		//consolidate notes
		lilyString.findRegexp(
			"(" ++ noteTuples ++ ")4 ~ (" ++ noteTuples ++ ")4 ~ (" ++
			noteTuples ++ ")4 ~ (" ++ noteTuples ++ ")4 ~ (" ++ noteTuples ++ ")4 ~ (" ++ noteTuples ++ ")4"
		).clump(7).do({arg match;
			lilyString = lilyString.replace(match[0][1], match[1][1] ++ "1.")});

		lilyString.findRegexp(
			"(" ++ noteTuples ++ ")4 ~ (" ++ noteTuples ++ ")4 ~ (" ++ noteTuples ++ ")4 ~ (" ++ noteTuples ++ ")4"
		).clump(5).do({arg match;
			lilyString = lilyString.replace(match[0][1], match[1][1] ++ "1")});

		lilyString.findRegexp("(" ++ noteTuples ++ ")4 ~ (" ++ noteTuples ++ ")4 ~ (" ++ noteTuples ++ ")4").clump(4).do({arg match;
			lilyString = lilyString.replace(match[0][1], match[1][1] ++ "2.")});

		lilyString.findRegexp("(" ++ noteTuples ++ ")4 ~ (" ++ noteTuples ++ ")4").clump(3).do({arg match;
			lilyString = lilyString.replace(match[0][1], match[1][1] ++ "2")});


		//consolidate rests
		lilyString.findRegexp("r4 r4 r4 r4 r4 r4").clump(2).do({arg match;
			lilyString = lilyString.replace(match[0][1], "R1*3/2")});

		lilyString.findRegexp("r4 r4 r4 r4").clump(2).do({arg match;
			lilyString = lilyString.replace(match[0][1], "r1")});

		lilyString.findRegexp("r4 r4 r4").clump(2).do({arg match;
			lilyString = lilyString.replace(match[0][1], "r2.")});

		lilyString.findRegexp("r4 r4").clump(2).do({arg match;
			lilyString = lilyString.replace(match[0][1], "r2")});


		lilyString.findRegexp("\\| r1").clump(2).do({arg match;
			lilyString = lilyString.replace(match[0][1], "| R1")});

		lilyString.findRegexp("4\nr1").clump(2).do({arg match;
			lilyString = lilyString.replace(match[0][1], "2\n R1")});

		//write file
		lilyFile.write("{\n" ++ lineBreakString ++ "}\n" ++ lilyString);
		lilyFile.close;
	});
};

~genScoreData = {arg guitarSeq, accompLowSeq, accompHighSeq, timeSigInsSeq, sectionSeq;
	var stringSeq, fretSeq, durSeq,
	partData, timeSigData, sectionData;
	stringSeq = guitarSeq.slice(nil, 0);
	fretSeq = guitarSeq.slice(nil, 1);
	durSeq = guitarSeq.slice(nil, 2);
	partData = [
		[stringSeq, fretSeq, durSeq, durSeq].flop,
		accompHighSeq,
		accompLowSeq
	];
	timeSigData = timeSigInsSeq;
	sectionData = sectionSeq;
	[partData, timeSigData, sectionData]
};
)