Tone.js/utils/MidiToScore.js

82 lines
2.3 KiB
JavaScript
Raw Normal View History

/**
* Pass in a MIDI File as the command line argument to this Node.js
* script and it will output a js file in the same directory.
*
* @example
* node MidiToScore.js mySong.mid
*/
2014-09-09 04:24:34 +00:00
var midiFileParser = require("midi-file-parser");
var fs = require("fs");
var file = fs.readFileSync(process.argv[2], "binary");
var midi = midiFileParser(file);
var output = {};
var tempo = 120;
var ticksPerBeat = midi.header.ticksPerBeat;
var timeSignature = [4, 4];
var microsecondsPerBeat = 60000000 / tempo;
//parse the tracks
for (var i = 0; i < midi.tracks.length; i++) {
var data = midi.tracks[i];
var trackName = "track"+i;
var trackNotes = [];
var currentTime = 0;
for (var j = 0; j < data.length; j++) {
//meta tag stuff
var evnt = data[j];
if (evnt.type === "meta"){
if (evnt.subtype === "timeSignature"){
timeSignature[0] = evnt.numerator;
timeSignature[1] = evnt.denominator;
} else if (evnt.subtype === "setTempo"){
tempo = 60000000 / evnt.microsecondsPerBeat;
microsecondsPerBeat = evnt.microsecondsPerBeat;
} else if (evnt.subtype === "trackName"){
trackName = evnt.text;
}
} else {
if (evnt.subtype === "noteOn" || evnt.subtype === "noteOff"){
currentTime += evnt.deltaTime;
var time = deltaTimeToMeter(currentTime);
var note = midiToNote(evnt.noteNumber);
var velocity = evnt.velocity / 127;
if (evnt.subtype === "noteOff"){
velocity = 0;
}
trackNotes.push([time, note, velocity.toFixed(2)]);
}
}
}
output[trackName] = trackNotes;
}
output.tempo = tempo;
output.timeSignature = timeSignature;
//write it to the output file
fs.writeFileSync(process.argv[2]+".js", JSON.stringify(output));
function deltaTimeToMeter(deltaTime){
var timeSigValue = timeSignature[0] / (timeSignature[1] / 4);
// return deltaTime;
var quarters = deltaTime / ticksPerBeat;
var measures = Math.floor(quarters / timeSigValue);
var sixteenths = (quarters % 1) * 4;
quarters = Math.floor(quarters) % timeSigValue;
var progress = [measures, quarters, sixteenths];
return progress.join(":");
}
function midiToNote(noteNum){
var noteIndexToNote = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
var octave = Math.floor(noteNum / 12) - 2;
var note = noteNum % 12;
return noteIndexToNote[note] + octave;
}