// Copyright (c) 2014-2016 Walter Bender
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the The GNU Affero General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 3 of the License, or (at your option) any later version.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA
|
|
|
|
// This header is prepended to the Lilypond output.
|
|
const LILYPONDHEADER = '\\version "2.18.2"\n\n% ****************************************************************\n% \n% WHAT IS THIS? -- This is a LilyPond file generated from Music\n% Blocks software (Read about it at www.musicblocks.net).\n% \n% DOWNLOAD LILYPOND -- In order to create notation with this file,\n% you will need to download and install LilyPond software onto your\n% computer (http://lilypond.org/download.html). Frescobaldi\n% software is also handy for editing LilyPond files\n% (http://frescobaldi.org/download).\n% \n% LILYPOND INSTRUCTIONS -- For instructions on how to further\n% manipulate musical notation using LilyPond software, please\n% read the Introduction (http://lilypond.org/text-input.html) and\n% the Manual\n% (http://lilypond.org/doc/v2.18/Documentation/learning/index.html).\n% \n% GLOSSARY -- A glossary with helpful examples may be found here\n% (http://www.lilypond.org/doc/v2.19/Documentation/music-glossary/).\n% \n% MUTOPIA -- You may also benefit from studying scores from the\n% Mutopia Project website, which has freely sharable music notation\n% generated with LilyPond (http://www.mutopiaproject.org/).\n% \n% LILYBIN -- You can explore your Lilypond output in a web browser at\n% (http://lilybin.com/).\n% \n% COMMENTS -- Some of the code below is commented out. You can\n% enable it by deleting the % that precedes the text or, in the\n% case of a commented section, deleting the %{ and %} that surrounds\n% the section.\n% \n% ****************************************************************\n\n% Please add your own name, the title of your musical creation,\n% and the intended copyright below.\n% The copyright is great for sharing (and re-sharing)!\n% Read more about it here (http://creativecommons.org/licenses/by-sa/4.0/).\n% Of course, you can use any copyright you like -- you made it!\n\\header {\n dedication = \\markup {\n \\abs-fontsize #8 \\sans "Made with LilyPond and Music Blocks" \\with-url #"http://walterbender.github.io/musicblocks/" {\n \\abs-fontsize #8 \\sans "(http://walterbender.github.io/musicblocks/)"\n }\n }\n title = "My Music Blocks Creation"\n% subtitle = "Subtitle"\n% instrument = "Instrument"\n composer = "Mr. Mouse"\n% arranger = "Arranger"\n copyright = "Mr. Mouse (c) 2015 -- CC-BY-SA"\n tagline = "Made from Music Blocks v.0.9"\n footer = \\markup {\n \\with-url #"http://walterbender.github.io/musicblocks/" "Made with Music Blocks Software v.0.9." Engraved on \\simple #(strftime "%Y-%m-%d" (localtime (current-time)))\n }\n currentYear = \\markup {\n \\simple #(strftime "%Y" (localtime (current-time)))\n }\n copyTag = " free to distribute, modify, and perform"\n copyType = \\markup {\n \\with-url #"http://creativecommons.org/licenses/by-sa/3.0/" "Creative Commons Attribution ShareAlike 3.0 (Unported) License "\n }\n copyright = \\markup {\n \\override #\'(baseline-skip . 0 ) \\right-column {\n \\sans \\bold \\with-url #"http://musicblocks.net" {\n \\abs-fontsize #9 "Music " \\concat {\n \\abs-fontsize #12 \\with-color #white \\char ##x01C0 \\abs-fontsize #9 "Blocks "\n }\n }\n }\n \\override #\'(baseline-skip . 0 ) \\center-column {\n \\abs-fontsize #11.9 \\with-color #grey \\bold {\n \\char ##x01C0 \\char ##x01C0\n }\n }\n \\override #\'(baseline-skip . 0 ) \\column {\n \\abs-fontsize #8 \\sans \\concat {\n " Typeset using " \\with-url #"http://www.lilypond.org" "LilyPond software " \\char ##x00A9 " " \\currentYear " by " \\composer " " \\char ##x2014 " " \\footer\n }\n \\concat {\n \\concat {\n \\abs-fontsize #8 \\sans {\n " " \\copyType \\char ##x2014 \\copyTag\n }\n }\n \\abs-fontsize #13 \\with-color #white \\char ##x01C0\n }\n }\n }\n tagline = ##f\n}\n\n% To change the meter make adjustments in the following section.\n% You must also delete the % before \\meter everywhere it appears below.\nmeter = {\n \\time 3/4\n \\key c \\minor\n \\numericTimeSignature\n \\partial 4 \n \\tempo "Andante" 4=90\n}\n\n';
|
|
|
|
//.TRANS Animal names used in Lilypond output
|
|
const RODENTS = [_('mouse'), _('brown rat'), _('mole'), _('chipmunk'), _('red squirrel'), _('guinea pig'), _('capybara'), _('coypu'), _('black rat'), _('grey squirrel'), _('flying squirrel'), _('bat')];
|
|
const RODENTSEN = ['mouse', 'brown rat', 'mole', 'chipmunk', 'red squirrel', 'guinea pig', 'capybara', 'coypu', 'black rat', 'grey squirrel', 'flying squirrel', 'bat'];
|
|
//.TRANS Abbreviations for names used in Lilypind output, e.g., m for mouse
|
|
const RODENTSSHORT = [_('m'), _('br'), _('ml'), _('ch'), _('rs'), _('gp'), _('cb'), _('cp'), _('bk'), _('gs'), _('fs'), _('bt')];
|
|
const RODENTSSHORTEN = ['m', 'br', 'ml', 'ch', 'rs', 'gp', 'cb', 'cp', 'bk', 'gs', 'fs', 'bt'];
|
|
const LYNOTE = 0;
|
|
const LYDURATION = 1;
|
|
const LYDOTCOUNT = 2;
|
|
const LYTUPLETVALUE = 3;
|
|
const LYROUNDDOWN = 4;
|
|
const LYINSIDECHORD = 5;
|
|
const LYSTACCATO = 6;
|
|
const CLEFS = ['treble', 'bass', 'bass_8', 'percussion'];
|
|
|
|
|
|
getLilypondHeader = function () {
|
|
return LILYPONDHEADER;
|
|
}
|
|
|
|
|
|
updateLilypondNotation = function (logo, note, duration, turtle, insideChord) {
|
|
var obj = durationToNoteValue(duration);
|
|
if (!(turtle in logo.lilypondStaging)) {
|
|
logo.lilypondStaging[turtle] = [];
|
|
}
|
|
|
|
if (logo.turtles.turtleList[turtle].drum) {
|
|
note = "c'";
|
|
}
|
|
|
|
logo.lilypondStaging[turtle].push([note, obj[0], obj[1], obj[2], obj[3], insideChord, logo.staccato[turtle].length > 0 && last(logo.staccato[turtle]) > 0]);
|
|
};
|
|
|
|
|
|
processLilypondNotes = function (logo, turtle) {
|
|
// obj = [instructions] or
|
|
// obj = [note, duration, dotCount, tupletValue, roundDown, insideChord, staccato, tie]
|
|
|
|
logo.lilypondNotes[turtle] = '';
|
|
|
|
function __toLilynote (note) {
|
|
// Lilypond notes use is for sharp, es for flat,
|
|
// , and ' for shifts in octave.
|
|
// Also, notes must be lowercase.
|
|
// And the octave bounday is at C, not A.
|
|
|
|
// Convert frequencies here.
|
|
if (typeof(note) === 'number') {
|
|
var pitchObj = frequencyToPitch(note);
|
|
note = pitchObj[0] + pitchObj[1];
|
|
}
|
|
|
|
return note.replace(/♯/g, 'is').replace(/♭/g, 'es').replace(/10/g, "''''''''").replace(/1/g, ',,').replace(/2/g, ',').replace(/3/g, '').replace(/4/g, "'").replace(/5/g, "''").replace(/6/g, "'''").replace(/7/g, "''''").replace(/8/g, "''''''").replace(/9/g, "'''''''").toLowerCase();
|
|
};
|
|
|
|
var counter = 0;
|
|
var queueSlur = false;
|
|
var articulation = false;
|
|
var targetDuration = 0;
|
|
var tupletDuration = 0;
|
|
for (var i = 0; i < logo.lilypondStaging[turtle].length; i++) {
|
|
obj = logo.lilypondStaging[turtle][i];
|
|
if (typeof(obj) === 'string') {
|
|
if (obj === 'break') {
|
|
if (i > 0) {
|
|
logo.lilypondNotes[turtle] += '\n';
|
|
}
|
|
counter = 0;
|
|
} else {
|
|
if (obj === '(') {
|
|
// The ( is added after the first note.
|
|
queueSlur = true;
|
|
} else if (obj === 'begin articulation') {
|
|
articulation = true;
|
|
} else if (obj === 'end articulation') {
|
|
articulation = false;
|
|
} else {
|
|
logo.lilypondNotes[turtle] += obj;
|
|
}
|
|
}
|
|
} else {
|
|
if (counter % 8 === 0 && counter > 0) {
|
|
logo.lilypondNotes[turtle] += '\n';
|
|
}
|
|
counter += 1;
|
|
|
|
var note = __toLilynote(obj[LYNOTE]);
|
|
var incompleteTuplet = 0; // An incomplete tuplet
|
|
|
|
// If it is a tuplet, look ahead to see if it is complete.
|
|
// While you are at it, add up the durations.
|
|
if (obj[LYTUPLETVALUE] != null) {
|
|
targetDuration = (1 / logo.lilypondStaging[turtle][i][LYDURATION]);
|
|
tupletDuration = (1 / logo.lilypondStaging[turtle][i][LYROUNDDOWN]);
|
|
var j = 1;
|
|
var k = 1;
|
|
while (k < obj[LYTUPLETVALUE]) {
|
|
if (i + j >= logo.lilypondStaging[turtle].length) {
|
|
incompleteTuplet = j;
|
|
break;
|
|
}
|
|
|
|
if (logo.lilypondStaging[turtle][i + j][LYINSIDECHORD] > 0 && logo.lilypondStaging[turtle][i + j][LYINSIDECHORD] === logo.lilypondStaging[turtle][i + j - 1][LYINSIDECHORD]) {
|
|
// In a chord, so jump to next note.
|
|
j++;
|
|
} else if (logo.lilypondStaging[turtle][i + j][LYTUPLETVALUE] !== obj[LYTUPLETVALUE]) {
|
|
incompleteTuplet = j;
|
|
break;
|
|
} else {
|
|
targetDuration += (1 / logo.lilypondStaging[turtle][i + j][LYDURATION]);
|
|
tupletDuration += (1 / logo.lilypondStaging[turtle][i + j][LYROUNDDOWN]);
|
|
j++; // Jump to next note.
|
|
k++; // Increment notes in tuplet.
|
|
}
|
|
}
|
|
}
|
|
|
|
function __processTuplet(logo, turtle, i, count) {
|
|
var j = 0;
|
|
var k = 0;
|
|
|
|
while (k < count) {
|
|
var tupletDuration = 2 * logo.lilypondStaging[turtle][i + j][LYDURATION];
|
|
// Are we in a chord?
|
|
if (logo.lilypondStaging[turtle][i + j][LYINSIDECHORD] > 0) {
|
|
// Is logo the first note in the chord?
|
|
if ((i === 0 && j === 0) || logo.lilypondStaging[turtle][i + j - 1][LYINSIDECHORD] !== logo.lilypondStaging[turtle][i + j][LYINSIDECHORD]) {
|
|
logo.lilypondNotes[turtle] += '<';
|
|
}
|
|
|
|
logo.lilypondNotes[turtle] += __toLilynote(logo.lilypondStaging[turtle][i + j][LYNOTE]);
|
|
if (obj[LYSTACCATO]) {
|
|
logo.lilypondNotes[turtle] += '\\staccato';
|
|
}
|
|
|
|
logo.lilypondNotes[turtle] += ' ';
|
|
|
|
// Is logo the last note in the chord?
|
|
if (i + j === logo.lilypondStaging[turtle].length - 1 || logo.lilypondStaging[turtle][i + j + 1][LYINSIDECHORD] !== logo.lilypondStaging[turtle][i + j][LYINSIDECHORD]) {
|
|
logo.lilypondNotes[turtle] += '>' + logo.lilypondStaging[turtle][i + j + 1][LYROUNDDOWN] + ' ';
|
|
k++; // Increment notes in tuplet.
|
|
}
|
|
j++;
|
|
} else {
|
|
logo.lilypondNotes[turtle] += __toLilynote(logo.lilypondStaging[turtle][i + j][LYNOTE]) + logo.lilypondStaging[turtle][i + j][LYROUNDDOWN];
|
|
if (obj[LYSTACCATO]) {
|
|
logo.lilypondNotes[turtle] += '\\staccato';
|
|
}
|
|
|
|
logo.lilypondNotes[turtle] += ' ';
|
|
j++; // Jump to next note.
|
|
k++; // Increment notes in tuplet.
|
|
}
|
|
}
|
|
|
|
// Workaround to a Lilypond "feature": if a slur
|
|
// ends on a tuplet, the closing ) must be inside
|
|
// the closing } of the tuplet.
|
|
if (i + j - 1 < logo.lilypondStaging[turtle].length - 1) {
|
|
var nextObj = logo.lilypondStaging[turtle][i + j];
|
|
if (typeof(nextObj) === 'string' && nextObj === ')') {
|
|
logo.lilypondNotes[turtle] += ')} ';
|
|
i += 1;
|
|
} else {
|
|
logo.lilypondNotes[turtle] += '} ';
|
|
}
|
|
} else {
|
|
logo.lilypondNotes[turtle] += '} ';
|
|
}
|
|
|
|
return j;
|
|
};
|
|
|
|
if (obj[LYTUPLETVALUE] > 0) {
|
|
// lilypond tuplets look like logo: \tuplet 3/2 { f8 g a }
|
|
// multiplier = tupletDuration / targetDuration
|
|
// e.g., (3/8) / (1/4) = (3/8) * 4 = 12/8 = 3/2
|
|
// There may be chords embedded.
|
|
|
|
if (incompleteTuplet === 0) {
|
|
var tupletFraction = toFraction(tupletDuration / targetDuration);
|
|
logo.lilypondNotes[turtle] += '\\tuplet ' + tupletFraction[0] + '/' + tupletFraction[1] + ' { ';
|
|
|
|
i += __processTuplet(logo, turtle, i, obj[LYTUPLETVALUE]) - 1;
|
|
} else {
|
|
var tupletFraction = toFraction(obj[LYTUPLETVALUE] / incompleteTuplet);
|
|
logo.lilypondNotes[turtle] += '\\tuplet ' + tupletFraction[0] + '/' + tupletFraction[1] + ' { ';
|
|
|
|
i += __processTuplet(logo, turtle, i, incompleteTuplet) - 1;
|
|
}
|
|
|
|
targetDuration = 0;
|
|
tupletDuration = 0;
|
|
} else {
|
|
if (obj[LYINSIDECHORD] > 0) {
|
|
// Is logo the first note in the chord?
|
|
if (i === 0 || logo.lilypondStaging[turtle][i - 1][LYINSIDECHORD] !== obj[LYINSIDECHORD]) {
|
|
// Open the chord.
|
|
logo.lilypondNotes[turtle] += '<';
|
|
}
|
|
|
|
logo.lilypondNotes[turtle] += (note);
|
|
|
|
// Is logo the last note in the chord?
|
|
if (i === logo.lilypondStaging[turtle].length - 1 || logo.lilypondStaging[turtle][i + 1][LYINSIDECHORD] !== obj[LYINSIDECHORD]) {
|
|
// Close the chord and add note duration.
|
|
logo.lilypondNotes[turtle] += '>';
|
|
logo.lilypondNotes[turtle] += obj[LYDURATION];
|
|
for (var d = 0; d < obj[LYDOTCOUNT]; d++) {
|
|
logo.lilypondNotes[turtle] += '.';
|
|
}
|
|
|
|
if (articulation) {
|
|
logo.lilypondNotes[turtle] += '->';
|
|
}
|
|
|
|
logo.lilypondNotes[turtle] += ' ';
|
|
}
|
|
} else {
|
|
logo.lilypondNotes[turtle] += (note + obj[LYDURATION]);
|
|
for (var d = 0; d < obj[LYDOTCOUNT]; d++) {
|
|
logo.lilypondNotes[turtle] += '.';
|
|
}
|
|
|
|
if (articulation) {
|
|
logo.lilypondNotes[turtle] += '->';
|
|
}
|
|
}
|
|
|
|
if (obj[LYSTACCATO]) {
|
|
logo.lilypondNotes[turtle] += '\\staccato';
|
|
}
|
|
|
|
targetDuration = 0;
|
|
tupletDuration = 0;
|
|
}
|
|
|
|
logo.lilypondNotes[turtle] += ' ';
|
|
|
|
if (queueSlur) {
|
|
queueSlur = false;
|
|
logo.lilypondNotes[turtle] += '(';
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
lilypondLineBreak = function(logo, turtle) {
|
|
if (logo.lilypondStaging[turtle] == undefined) {
|
|
logo.lilypondStaging[turtle] = [];
|
|
}
|
|
|
|
logo.lilypondStaging[turtle].push('break');
|
|
};
|
|
|
|
|
|
lilypondBeginArticulation = function(logo, turtle) {
|
|
if (logo.lilypondStaging[turtle] == undefined) {
|
|
logo.lilypondStaging[turtle] = [];
|
|
}
|
|
|
|
logo.lilypondStaging[turtle].push('begin articulation');
|
|
};
|
|
|
|
|
|
lilypondEndArticulation = function(logo, turtle) {
|
|
logo.lilypondStaging[turtle].push('end articulation');
|
|
};
|
|
|
|
|
|
lilypondBeginCrescendo = function(logo, turtle, factor) {
|
|
if (logo.lilypondStaging[turtle] == undefined) {
|
|
logo.lilypondStaging[turtle] = [];
|
|
}
|
|
|
|
if (factor > 0) {
|
|
logo.lilypondStaging[turtle].push('\\< ');
|
|
} else {
|
|
logo.lilypondStaging[turtle].push('\\> ');
|
|
}
|
|
};
|
|
|
|
|
|
lilypondEndCrescendo = function(logo, turtle) {
|
|
logo.lilypondStaging[turtle].push('\\! ');
|
|
};
|
|
|
|
|
|
lilypondBeginSlur = function(logo, turtle) {
|
|
if (logo.lilypondStaging[turtle] == undefined) {
|
|
logo.lilypondStaging[turtle] = [];
|
|
}
|
|
|
|
logo.lilypondStaging[turtle].push('(');
|
|
};
|
|
|
|
|
|
lilypondEndSlur = function(logo, turtle) {
|
|
logo.lilypondStaging[turtle].push(') ');
|
|
};
|
|
|
|
|
|
lilypondInsertTie = function(logo, turtle) {
|
|
if (logo.lilypondStaging[turtle] == undefined) {
|
|
logo.lilypondStaging[turtle] = [];
|
|
}
|
|
|
|
logo.lilypondStaging[turtle].push('~');
|
|
};
|
|
|
|
|
|
lilypondRemoveTie = function(logo, turtle) {
|
|
logo.lilypondStaging[turtle].pop();
|
|
};
|
|
|
|
|
|
saveLilypondOutput = function(logo, saveName) {
|
|
var turtleCount = 0;
|
|
var clef = [];
|
|
for (var t in logo.lilypondStaging) {
|
|
turtleCount += 1;
|
|
}
|
|
console.log('saving as lilypond: ' + turtleCount);
|
|
|
|
logo.lilypondOutput += '% You can change the MIDI instruments below to anything on logo list:\n% (http://lilypond.org/doc/v2.18/documentation/notation/midi-instruments)\n\n';
|
|
|
|
var c = 0;
|
|
for (var t in logo.lilypondStaging) {
|
|
if (logo.lilypondStaging[t].length > 0) {
|
|
var octaveTotal = 0;
|
|
var noteCount = 0;
|
|
for (var i = 0; i < logo.lilypondStaging[t].length; i++) {
|
|
obj = logo.lilypondStaging[t][i];
|
|
if (typeof(obj) === 'object') {
|
|
if (obj[0].length < 2) {
|
|
// Test for rests
|
|
} else {
|
|
if (typeof(obj[0]) === 'string') {
|
|
octaveTotal += Number(obj[0].substr(-1));
|
|
} else {
|
|
var pitchObj = frequencyToPitch(obj[0]);
|
|
octaveTotal += pitchObj[1];
|
|
}
|
|
noteCount += 1;
|
|
}
|
|
}
|
|
}
|
|
if (logo.turtles.turtleList[t].drum) {
|
|
clef.push('percussion');
|
|
} else if (noteCount > 0) {
|
|
// console.log(t + ': ' + octaveTotal + ' ' + noteCount);
|
|
switch (Math.floor(octaveTotal / noteCount)) {
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
clef.push('bass_8');
|
|
break;
|
|
case 3:
|
|
clef.push('bass');
|
|
break;
|
|
default:
|
|
clef.push('treble');
|
|
break;
|
|
}
|
|
} else {
|
|
clef.push('treble');
|
|
}
|
|
|
|
processLilypondNotes(logo, t);
|
|
|
|
var instrumentName = logo.turtles.turtleList[t].name;
|
|
if (instrumentName === _('start') || instrumentName === _('start drum')) {
|
|
instrumentName = RODENTS[t % 12];
|
|
} else if (instrumentName === t.toString()) {
|
|
instrumentName = RODENTS[t % 12];
|
|
}
|
|
|
|
if (instrumentName === "") {
|
|
instrumentName = RODENTSEN[t % 12];
|
|
}
|
|
|
|
instrumentName = instrumentName.replace(/ /g, '_');
|
|
|
|
logo.lilypondOutput += instrumentName + ' = {\n';
|
|
logo.lilypondOutput += '% \\meter\n';
|
|
logo.lilypondOutput += logo.lilypondNotes[t];
|
|
|
|
// Add bar to last turtle's output.
|
|
if (c === turtleCount - 1) {
|
|
logo.lilypondOutput += ' \\bar "|."'
|
|
}
|
|
logo.lilypondOutput += '\n}\n\n';
|
|
|
|
var shortInstrumentName = RODENTSSHORT[t % 12];
|
|
|
|
if (shortInstrumentName === "") {
|
|
shortInstrumentName = RODENTSSHORTEN[t % 12];
|
|
}
|
|
|
|
logo.lilypondOutput += instrumentName.replace(/ /g, '_') + 'Voice = ';
|
|
if (logo.turtles.turtleList[t].drum) {
|
|
logo.lilypondOutput += '\\new DrumStaff \\with {\n';
|
|
// logo.lilypondOutput += ' \\drummode {\n hihat4 hh bassdrum bd\n }\n';
|
|
} else {
|
|
logo.lilypondOutput += '\\new Staff \\with {\n';
|
|
}
|
|
logo.lilypondOutput += ' \\clef "' + last(clef) + '"\n';
|
|
logo.lilypondOutput += ' instrumentName = "' + instrumentName + '"\n';
|
|
logo.lilypondOutput += ' shortInstrumentName = "' + shortInstrumentName + '"\n';
|
|
logo.lilypondOutput += ' midiInstrument = "acoustic grand"\n';
|
|
// Automatic note splitting
|
|
logo.lilypondOutput += '\n \\remove "Note_heads_engraver"\n \\consists "Completion_heads_engraver"\n \\remove "Rest_engraver"\n \\consists "Completion_rest_engraver"\n'
|
|
|
|
logo.lilypondOutput += '} { \\clef "' + last(clef) + '" \\' + instrumentName.replace(/ /g, '_') + ' }\n\n';
|
|
}
|
|
c += 1;
|
|
}
|
|
|
|
// Begin the SCORE section.
|
|
logo.lilypondOutput += '\n\\score {\n';
|
|
logo.lilypondOutput += ' <<\n';
|
|
|
|
// Sort the staffs, treble on top, bass_8 on the bottom.
|
|
for (var c = 0; c < CLEFS.length; c++) {
|
|
var i = 0;
|
|
for (var t in logo.lilypondNotes) {
|
|
if (clef[i] === CLEFS[c]) {
|
|
if (logo.lilypondStaging[t].length > 0) {
|
|
var instrumentName = logo.turtles.turtleList[t].name;
|
|
if (instrumentName === _('start') || instrumentName === _('start drum')) {
|
|
instrumentName = RODENTS[t % 12];
|
|
} else if (instrumentName === t.toString()) {
|
|
instrumentName = RODENTS[t % 12];
|
|
}
|
|
instrumentName = instrumentName.replace(/ /g, '_');
|
|
logo.lilypondOutput += ' \\' + instrumentName + 'Voice\n';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add GUITAR TAB in comments.
|
|
logo.lilypondOutput += '\n\n% GUITAR TAB SECTION\n% Delete the %{ and %} below to include guitar tablature output.\n%{\n \\new TabStaff = "guitar tab" \n <<\n \\clef moderntab\n';
|
|
for (var c = 0; c < CLEFS.length; c++) {
|
|
var i = 0;
|
|
for (var t in logo.lilypondNotes) {
|
|
if (clef[i] === CLEFS[c]) {
|
|
if (logo.lilypondStaging[t].length > 0) {
|
|
var instrumentName = logo.turtles.turtleList[t].name;
|
|
if (instrumentName === _('start') || instrumentName === _('start drum')) {
|
|
instrumentName = RODENTS[t % 12]
|
|
} else if (instrumentName === t.toString()) {
|
|
instrumentName = RODENTS[t % 12];
|
|
}
|
|
instrumentName = instrumentName.replace(/ /g, '_');
|
|
logo.lilypondOutput += ' \\context TabVoice = "'+ instrumentName + '" \\' + instrumentName.replace(/ /g, '_') + '\n';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Close the SCORE sections.
|
|
logo.lilypondOutput += ' >>\n%}\n';
|
|
logo.lilypondOutput += '\n >>\n \\layout {}\n\n';
|
|
|
|
// Add MIDI OUTPUT in comments.
|
|
logo.lilypondOutput += '% MIDI SECTION\n% Delete the %{ and %} below to include MIDI output.\n%{\n\\midi {\n \\tempo 4=90\n}\n%}\n\n}\n\n';
|
|
|
|
// ADD TURTLE BLOCKS CODE HERE
|
|
logo.lilypondOutput += '% MUSIC BLOCKS CODE\n';
|
|
logo.lilypondOutput += '% Below is the code for the Music Blocks project that generated logo Lilypond file.\n%{\n\n';
|
|
// prepareExport() returns json-encoded project data.
|
|
var projectData = prepareExport();
|
|
logo.lilypondOutput += projectData.replace(/]],/g, ']],\n');
|
|
logo.lilypondOutput += '\n%}\n\n';
|
|
|
|
doSaveLilypond(logo, saveName);
|
|
};
|