(
~transcribe = {arg data, durMult, subName, drawAmps = false;

	data.do({arg seq, p;
		fork {var basePath, cond, pattern, ampFilePath, ampSampleRate, ampBuf, amps,
			lilyFile, lastVal, curTime = 0, lilyString = "";

			basePath = ~dir +/+ ".." +/+ "score" +/+ "transform_" ++ ~transform.join ++ "_score" +/+ "lilypond";

			// writes the template files for the master score and parts
			if(File.exists(basePath).not, {arg template, writeTemplate;
				writeTemplate = {arg template, part; var fileAppend, scoreType, systemsPerPage, lileFile, formattedTemplate;
					fileAppend = switch(part, nil, {"master_score"}, 6, {"part_hl6"}, 5, {"part_hl5"}, 4, {"part_hl4"});
					scoreType = switch(part, nil, {"master score"}, 6, {"part - hl 6"}, 5, {"part - hl 5"}, 4, {"part - hl 4"});
					lilyFile = File(basePath +/+ "a_lot_of_tiles_trivial_scan_transform_" ++ ~transform.join
						++ "_" ++ fileAppend ++ ".ly".standardizePath,"w");
					formattedTemplate = template.replace("~~score_type~~", scoreType);
					if(part != nil, {formattedTemplate = formattedTemplate
						.replace("systems-per-page = 4", "systems-per-page = 8");
						[4, 5, 6].difference([part]).do({arg p; formattedTemplate = formattedTemplate
							.replace("%~~hl" ++ p ++ "-start~~", "%{~~hl" ++ p.asString ++ "~~")
							.replace("%~~hl" ++ p.asString ++ "-end~~", "%}")});
						if(part != 6, {formattedTemplate = formattedTemplate
							.replace("unfold 33", "unfold 17").replace("unfold 3", "unfold 7")})});
					lilyFile.write(formattedTemplate);
					lilyFile.close};

				File.mkdir(basePath);
				File.mkdir(basePath +/+ "includes");
				File.mkdir(basePath +/+ ".." +/+ "pdf");
				template = File.readAllString(~dir +/+ ".." +/+ "score" +/+ "score_template"
					+/+ "a_lot_of_tiles_trivial_scan_score_template.ly".standardizePath);
				template = template.replace("~~transform~~", ~transform.join);

				writeTemplate.value(template, nil);
				writeTemplate.value(template, 6);
				writeTemplate.value(template, 5);
				writeTemplate.value(template, 4);
			});

			cond = Condition.new;

			// generate pattern and get amplitude values for hl6
			pattern = Pmono(\lamp, \dur, ~dur * durMult, \amp, Pseq(seq));
			if(drawAmps, {
				ampFilePath = basePath +/+ "amp_curve_tmp_hl_6_harm_" ++ (1 + (p * 4)).asString() ++ ".wav";
				pattern.render(ampFilePath, ~dur * durMult * seq.size, action: {cond.unhang}); cond.hang;
				ampSampleRate = SoundFile(ampFilePath).sampleRate;
				Buffer.readChannel(s, ampFilePath, channels: [0], action: {arg ampBuf;
					ampBuf.loadToFloatArray(action: {arg array; amps = array; cond.unhang})}); cond.hang});

			lilyFile = if(data.size > 1, {lilyFile = subName ++ "_harm_" ++ (1 + (p * 4)).asString()}, {subName});
			lilyFile = File(basePath +/+ "includes" +/+ "a_lot_of_tiles_trivial_scan_" ++ lilyFile ++ ".ly".standardizePath,"w");

			// main transcribe code which groups data into beats and creates lilypond code accordingly
			lastVal = nil;
			seq.collect({arg v; durMult.collect({v})}).flat.clump(4).do({arg beat, i;
				beat.separate({arg a, b; a != b}).do({arg group; var noteLength, target = 0, colors = "", lilyNote;
					noteLength = group.size;
					lilyNote = switch(noteLength, 1, {"b'16 "}, 2, {"b'8 "}, 3, {"b'8. "}, 4, {"b'4 "});

					// lilypond directives to draw amplitude gradients for hl6
					if(drawAmps, {
						colors = amps[((ampSampleRate * curTime).asInteger)..((ampSampleRate * (curTime + (noteLength / 8))).asInteger)];
						target = colors[0];
						colors = 1 - (colors.resamp0(noteLength * 50));
						colors = colors.collect({arg color; color.round(0.0001).asString});
						colors = "\\override Glissando.details.colors = #'" ++ "(" ++ colors.join(" ") ++ ") "});

					// 0 or 1 above every note based on data
					if(drawAmps.not, {lilyNote = lilyNote ++ "^" ++ group[0].asString ++ " "});

					// ties notes
					lilyString = lilyString ++ if(group[0] == lastVal, {"~ "}, {""});
					lilyString = lilyString ++ if((curTime % 2 == 0), {"|"}, {""});
					lilyString = lilyString ++ colors ++ lilyNote;
					lilyString = lilyString ++ if(drawAmps && (group[0] != lastVal),
						{"-\\tweak Y-offset #-5.5 _" ++ (target.trunc(0.1) * 10).asInteger.asString}, {""});
					lilyString = lilyString ++ if(drawAmps, {"\n"}, {""});

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

			// consolidates tied quarters for hl4 and hl5
			if(drawAmps.not, {
				lilyString.findRegexp("b'4 \\^(0|1) ~ b'4 \\^(0|1) ~ b'4 \\^(0|1) ~ b'4 \\^(0|1)").clump(5).do(
					{arg match; lilyString = lilyString.replace(match[0][1], "b'1 ^" ++ match[1][1])});
				lilyString.findRegexp("b'4 \\^(0|1) ~ b'4 \\^(0|1) ~ b'4 \\^(0|1)").clump(4).do(
					{arg match; lilyString = lilyString.replace(match[0][1], "b'2. ^" ++ match[1][1])});
				lilyString.findRegexp("b'4 \\^(0|1) ~ b'4 \\^(0|1)").clump(3).do(
					{arg match; lilyString = lilyString.replace(match[0][1], "b'2 ^" ++ match[1][1])});
				lilyString.findRegexp("~ \\|b'(1|2.|2|4) \\^(0|1)").clump(3).do(
					{arg match; lilyString = lilyString.replace(match[0][1], "~ |b'" ++ match[1][1])})});

			// prettify
			lilyString = lilyString.replace("|", "\n|\n");
			lilyString = lilyString.replace("\n~ ", " ~\n");

			// consolidates tied quarters for hl6 (very tricky)
			if(drawAmps, {var replaceFirst, tmp;
				replaceFirst = { arg string, find, replace = "", offset = 0;
					var index, out = "", array = string, findSize = max(find.size, 1);
					index = array.find(find, offset: offset);
					out = out ++ array.keep(index) ++ replace;
					array = array.drop(index + findSize);
					out ++ array};

				tmp = lilyString;
				lilyString.split($|).do({arg bar; var beats, groups, offset = 0;
					beats = bar.split($\n);
					groups = beats.separate({arg a, b; (a.contains("b'4") && a.contains("~") && b.contains("b'4")).not });
					groups.do({arg group;
						if(group.size > 1, {
							var ampList, noteLength, tweak, tie, replace, find;
							ampList = group.collect({arg note; note[(note.find("(") + 1)..(note.find(")") - 1)]}).join(" ");
							noteLength = switch(group.size, 2, {"2 "}, 3, {"2. "}, 4, {"1 "});
							tweak = if(group[0].contains("tweak"), {group[0][(group[0].find("-\\tweak"))..(group[0].find("#-5.5") + 8)]}, {""});
							tie = if(group.last.contains("~"), {"~ "}, {" "});
							replace = "\\override Glissando.details.colors = #'(" ++ ampList ++ ") b'" ++ noteLength ++ tweak ++ tie;
							find = group.join("\n");
							tmp = replaceFirst.value(tmp, find, replace, offset)});
						offset = lilyString.find("|", offset: offset)})});
				lilyString = tmp});


			// final lilypond directives and write files
			if(drawAmps, {
				lilyString = "\\override Glissando.stencil = #my-gliss \\addGliss { \\override Glissando.details.thickness = 1.15 " ++ lilyString ++ " }"});
			lilyString = "{ " ++ lilyString ++ " \\bar \"|.\" \\stopStaff \\hide b'1}";
			lilyFile.write(lilyString);
			lilyFile.close;

			// this deletes the tmp files and creates the pdfs on the last call.
			if(drawAmps, {
				File.delete(ampFilePath);
				if(p == 3, {
					"which lilypond".unixCmd({ arg res1, pid1;
						if(res1 == 0, {
							PathName(basePath).files.do({arg path;
								("lilypond -o " ++ basePath +/+ ".." +/+ "pdf " ++ path.fullPath).unixCmd({ arg res2, pid2;
									if(res2 != 0, {{var win, text;
										win = Window.new.front;
										text = StaticText(win, Rect(10, 10, 300, 200));
										text.string = "Something went wrong creating the pdfs, \n" ++
										"but the lilypond files likely generated just fine"}.defer});
									[\done, res2, pid2].postln})})}, {{var win, text;
							win = Window.new.front;
							text = StaticText(win, Rect(10, 10, 300, 200));
							text.string = "Something went wrong creating the pdfs. \nLikely Lilypond is not installed, \n" ++
							"but the Lilypond files probably generated just fine."}.defer});
						[\done, res1, pid1].postln})})})}});
};
)