|
|
|
(
|
|
|
|
~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;
|
|
|
|
(basePath +/+ "includes").mkdir;
|
|
|
|
|
|
|
|
scoreFile = File(basePath +/+ "cicc_score.ly".standardizePath,"w");
|
|
|
|
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]});
|
|
|
|
rest = if(p < rawMusicData.size, {(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]});
|
|
|
|
rest = if(p < rawMusicData.size, {(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;
|
|
|
|
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 noFullSystems;
|
|
|
|
|
|
|
|
//this causes a problem if a section is less than 10 half notes (4 measures)
|
|
|
|
if(remainder % 16 == 0, {
|
|
|
|
lineBreakString = lineBreakString ++ "\\repeat unfold 8 {s2 \\noBreak} \\break \n";
|
|
|
|
}, {
|
|
|
|
var noBeats;
|
|
|
|
noBeats = ((remainder + (64 - remainder).trunc(16)) / 8).asInteger;
|
|
|
|
lineBreakString = lineBreakString ++ "\\pseudoIndents 0 " ++
|
|
|
|
(21 * (8 - noBeats)) ++ " \\repeat unfold " ++ noBeats ++ " {s2 \\noBreak} \\break \n";
|
|
|
|
});
|
|
|
|
|
|
|
|
remainder = len - (64 - remainder).trunc(16);
|
|
|
|
|
|
|
|
noFullSystems = (remainder.trunc(64) / 64).asInteger;
|
|
|
|
if(noFullSystems > 0, {
|
|
|
|
(noFullSystems - 1).do({
|
|
|
|
lineBreakString = lineBreakString ++ "\\repeat unfold 8 {s2 \\noBreak} \\break \n";
|
|
|
|
});
|
|
|
|
if(remainder % 64 != 8, {
|
|
|
|
lineBreakString = lineBreakString ++ "\\repeat unfold 8 {s2 \\noBreak} \\break \n";
|
|
|
|
remainder = remainder - (noFullSystems * 64);
|
|
|
|
}, {
|
|
|
|
lineBreakString = lineBreakString ++ "\\pseudoIndents 0 42 \\repeat unfold 6 {s2 \\noBreak} \\break \n";
|
|
|
|
remainder = 24;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
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 \\markup {\\concat {\\smaller \\general-align #Y #DOWN \\note #\"2\" #1 \\normal-text \"";
|
|
|
|
lilyString = lilyString + "= approx. 80 (preferably faster towards 90 and no less than 70)\"}}";
|
|
|
|
if(p != 1, {lilyString = lilyString + "\\override Staff.TimeSignature #'stencil = ##f"});
|
|
|
|
lilyString = lilyString + "\\numericTimeSignature \\time 2/2\n";
|
|
|
|
|
|
|
|
lilyString = switch(p,
|
|
|
|
0, {lilyString + "\\clef \"treble_(8)\"\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 \\time 2/2\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[(((38.midicps * openStrings[group[0][0]]).cpsmidi + group[0][1]).round(1) % 12)];
|
|
|
|
lilyNote = lilyNote ++ lilyOcts[(((38.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)];
|
|
|
|
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 r4").clump(2).do({arg match;
|
|
|
|
lilyString = lilyString.replace(match[0][1], "r4 r1")});
|
|
|
|
|
|
|
|
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]
|
|
|
|
};
|
|
|
|
)
|