Skip to content

Instantly share code, notes, and snippets.

@Alexis-D
Created April 21, 2012 00:25
Show Gist options
  • Save Alexis-D/2432788 to your computer and use it in GitHub Desktop.
Save Alexis-D/2432788 to your computer and use it in GitHub Desktop.
compile.js
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