123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- var clone = function (o) {
- if (typeof o != 'object') return (o);
- if (o == null) return (o);
- var ret = (typeof o.length == 'number') ? [] : {};
- for (var key in o) ret[key] = clone(o[key]);
- return ret;
- };
- function Replayer(midiFile, timeWarp, eventProcessor, bpm) {
- var trackStates = [];
- var beatsPerMinute = bpm ? bpm : 120;
- var bpmOverride = bpm ? true : false;
- var ticksPerBeat = midiFile.header.ticksPerBeat;
-
- for (var i = 0; i < midiFile.tracks.length; i++) {
- trackStates[i] = {
- 'nextEventIndex': 0,
- 'ticksToNextEvent': (
- midiFile.tracks[i].length ?
- midiFile.tracks[i][0].deltaTime :
- null
- )
- };
- }
- var nextEventInfo;
- var samplesToNextEvent = 0;
-
- function getNextEvent() {
- var ticksToNextEvent = null;
- var nextEventTrack = null;
- var nextEventIndex = null;
-
- for (var i = 0; i < trackStates.length; i++) {
- if (
- trackStates[i].ticksToNextEvent != null
- && (ticksToNextEvent == null || trackStates[i].ticksToNextEvent < ticksToNextEvent)
- ) {
- ticksToNextEvent = trackStates[i].ticksToNextEvent;
- nextEventTrack = i;
- nextEventIndex = trackStates[i].nextEventIndex;
- }
- }
- if (nextEventTrack != null) {
- /* consume event from that track */
- var nextEvent = midiFile.tracks[nextEventTrack][nextEventIndex];
- if (midiFile.tracks[nextEventTrack][nextEventIndex + 1]) {
- trackStates[nextEventTrack].ticksToNextEvent += midiFile.tracks[nextEventTrack][nextEventIndex + 1].deltaTime;
- } else {
- trackStates[nextEventTrack].ticksToNextEvent = null;
- }
- trackStates[nextEventTrack].nextEventIndex += 1;
- /* advance timings on all tracks by ticksToNextEvent */
- for (var i = 0; i < trackStates.length; i++) {
- if (trackStates[i].ticksToNextEvent != null) {
- trackStates[i].ticksToNextEvent -= ticksToNextEvent
- }
- }
- return {
- "ticksToEvent": ticksToNextEvent,
- "event": nextEvent,
- "track": nextEventTrack
- }
- } else {
- return null;
- }
- };
- //
- var midiEvent;
- var temporal = [];
- //
- function processEvents() {
- function processNext() {
- if (!bpmOverride && midiEvent.event.type == "meta" && midiEvent.event.subtype == "setTempo" ) {
- // tempo change events can occur anywhere in the middle and affect events that follow
- beatsPerMinute = 60000000 / midiEvent.event.microsecondsPerBeat;
- }
- ///
- var beatsToGenerate = 0;
- var secondsToGenerate = 0;
- if (midiEvent.ticksToEvent > 0) {
- beatsToGenerate = midiEvent.ticksToEvent / ticksPerBeat;
- secondsToGenerate = beatsToGenerate / (beatsPerMinute / 60);
- }
- ///
- var time = (secondsToGenerate * 1000 * timeWarp) || 0;
- temporal.push([ midiEvent, time]);
- midiEvent = getNextEvent();
- };
- ///
- if (midiEvent = getNextEvent()) {
- while(midiEvent) processNext(true);
- }
- };
- processEvents();
- return {
- "getData": function() {
- return clone(temporal);
- }
- };
- };
|