Created
April 21, 2012 00:25
-
-
Save Alexis-D/2432788 to your computer and use it in GitHub Desktop.
compile.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var clone = function (o) { | |
// return a copy of o. | |
// http://stackoverflow.com/questions/728360/copying-an-object-in-javascript | |
if(null === o || 'object' !== typeof o) { | |
return o; | |
} | |
var copy = o.constructor(); | |
for(var attr in o) { | |
if(o.hasOwnProperty(attr)) { | |
copy[attr] = o[attr]; | |
} | |
} | |
return copy; | |
}, | |
compile = function (musexpr) { | |
// convert a MUS 'AST' to a NOTE program | |
var endTime = function (start, musexpr) { | |
// return the end time of a MUS program | |
// given the start time | |
switch(musexpr.tag) { | |
case 'note': | |
case 'rest': | |
return start + musexpr.dur; | |
case 'seq': | |
return endTime(start, musexpr.left) + endTime(start, musexpr.right); | |
case 'par': | |
return Math.max(endTime(start, musexpr.left), endTime(start, musexpr.right)); | |
case 'section': | |
return endTime(musexpr.section); | |
default: | |
// wtf? | |
} | |
}, | |
convertPitch = function (pitch) { | |
// convert scientific notation to midi numbers for pitches | |
var pitchLetter = pitch[0].toLowerCase(), | |
octave = parseInt(pitch[1], 10), | |
conversion = { | |
'c': 0, | |
'd': 2, | |
'e': 4, | |
'f': 5, | |
'g': 7, | |
'a': 9, | |
'b': 11 | |
}; | |
return 12 + 12 * octave + conversion[pitchLetter]; | |
}, | |
compile = function (musexpr, start) { | |
// compile a MUS expression starting at start | |
if(musexpr.tag === 'note' || musexpr.tag === 'rest') { | |
// do not modify original muse expression | |
musexpr = clone(musexpr); | |
if(musexpr.tag === 'note') { | |
musexpr.pitch = convertPitch(musexpr.pitch); | |
} | |
musexpr.start = start; | |
return [musexpr]; | |
} | |
else if(musexpr.tag === 'repeat') { | |
var notes = compile(musexpr.section, start), | |
duration = endTime(0, musexpr.section), | |
res = []; | |
for(var i = 0; i < musexpr.count; ++i) { | |
res = res.concat(notes); | |
// fix start times | |
for(var j = 0, l = notes.length; j < l; ++j) { | |
var note = notes[j], | |
newNote = clone(note); | |
newNote.start += duration; | |
notes[j] = newNote; | |
} | |
} | |
return res; | |
} | |
// seq or par | |
var left = compile(musexpr.left, start), | |
rightStart = musexpr.tag === 'seq' ? endTime(start, musexpr.left) : start, | |
right = compile(musexpr.right, rightStart); | |
return left.concat(right); | |
}; | |
return compile(musexpr, 0); | |
}; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment