qambi
Version:
MIDI sequencer, loads MIDI files, can record and playback MIDI, uses WebMIDI and WebAudio
474 lines (400 loc) • 12.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.parseTimeEvents = parseTimeEvents;
exports.parseEvents = parseEvents;
exports.parseMIDINotes = parseMIDINotes;
exports.filterEvents = filterEvents;
var _util = require('./util');
var _midi_note = require('./midi_note');
var ppq = void 0,
bpm = void 0,
factor = void 0,
nominator = void 0,
denominator = void 0,
playbackSpeed = void 0,
bar = void 0,
beat = void 0,
sixteenth = void 0,
tick = void 0,
ticks = void 0,
millis = void 0,
millisPerTick = void 0,
secondsPerTick = void 0,
ticksPerBeat = void 0,
ticksPerBar = void 0,
ticksPerSixteenth = void 0,
numSixteenth = void 0,
diffTicks = void 0;
//previousEvent
function setTickDuration() {
secondsPerTick = 1 / playbackSpeed * 60 / bpm / ppq;
millisPerTick = secondsPerTick * 1000;
//console.log(millisPerTick, bpm, ppq, playbackSpeed, (ppq * millisPerTick));
//console.log(ppq);
}
function setTicksPerBeat() {
factor = 4 / denominator;
numSixteenth = factor * 4;
ticksPerBeat = ppq * factor;
ticksPerBar = ticksPerBeat * nominator;
ticksPerSixteenth = ppq / 4;
//console.log(denominator, factor, numSixteenth, ticksPerBeat, ticksPerBar, ticksPerSixteenth);
}
function updatePosition(event) {
var fast = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
diffTicks = event.ticks - ticks;
// if(diffTicks < 0){
// console.log(diffTicks, event.ticks, previousEvent.ticks, previousEvent.type)
// }
tick += diffTicks;
ticks = event.ticks;
//previousEvent = event
//console.log(diffTicks, millisPerTick);
millis += diffTicks * millisPerTick;
if (fast === false) {
while (tick >= ticksPerSixteenth) {
sixteenth++;
tick -= ticksPerSixteenth;
while (sixteenth > numSixteenth) {
sixteenth -= numSixteenth;
beat++;
while (beat > nominator) {
beat -= nominator;
bar++;
}
}
}
}
}
function parseTimeEvents(settings, timeEvents) {
var isPlaying = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
//console.log('parse time events')
var type = void 0;
var event = void 0;
ppq = settings.ppq;
bpm = settings.bpm;
nominator = settings.nominator;
denominator = settings.denominator;
playbackSpeed = settings.playbackSpeed;
bar = 1;
beat = 1;
sixteenth = 1;
tick = 0;
ticks = 0;
millis = 0;
setTickDuration();
setTicksPerBeat();
timeEvents.sort(function (a, b) {
return a.ticks <= b.ticks ? -1 : 1;
});
var e = 0;
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = timeEvents[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
event = _step.value;
//console.log(e++, event.ticks, event.type)
//event.song = song;
type = event.type;
updatePosition(event, isPlaying);
switch (type) {
case 0x51:
bpm = event.data1;
//console.log(event)
setTickDuration();
break;
case 0x58:
nominator = event.data1;
denominator = event.data2;
setTicksPerBeat();
break;
default:
continue;
}
//time data of time event is valid from (and included) the position of the time event
updateEvent(event, isPlaying);
//console.log(event.barsAsString);
}
//song.lastEventTmp = event;
//console.log(event);
//console.log(timeEvents);
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
}
//export function parseEvents(song, events){
function parseEvents(events) {
var isPlaying = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
//console.log('parseEvents')
var event = void 0;
var startEvent = 0;
var lastEventTick = 0;
var result = [];
tick = 0;
ticks = 0;
diffTicks = 0;
//let events = [].concat(evts, song._timeEvents);
var numEvents = events.length;
//console.log(events)
// noteoff comes before noteon
/*
events.sort(function(a, b){
return a.sortIndex - b.sortIndex;
})
*/
events.sort(function (a, b) {
if (a.ticks === b.ticks) {
// if(a.type === 128){
// return -1
// }else if(b.type === 128){
// return 1
// }
// short:
var r = a.type - b.type;
if (a.type === 176 && b.type === 144) {
r = -1;
}
return r;
}
return a.ticks - b.ticks;
});
event = events[0];
//console.log(event)
bpm = event.bpm;
factor = event.factor;
nominator = event.nominator;
denominator = event.denominator;
ticksPerBar = event.ticksPerBar;
ticksPerBeat = event.ticksPerBeat;
ticksPerSixteenth = event.ticksPerSixteenth;
numSixteenth = event.numSixteenth;
millisPerTick = event.millisPerTick;
secondsPerTick = event.secondsPerTick;
millis = event.millis;
bar = event.bar;
beat = event.beat;
sixteenth = event.sixteenth;
tick = event.tick;
for (var i = startEvent; i < numEvents; i++) {
event = events[i];
switch (event.type) {
case 0x51:
bpm = event.data1;
millis = event.millis;
millisPerTick = event.millisPerTick;
secondsPerTick = event.secondsPerTick;
diffTicks = event.ticks - ticks;
tick += diffTicks;
ticks = event.ticks;
//console.log(millisPerTick,event.millisPerTick);
//console.log(event);
break;
case 0x58:
factor = event.factor;
nominator = event.data1;
denominator = event.data2;
numSixteenth = event.numSixteenth;
ticksPerBar = event.ticksPerBar;
ticksPerBeat = event.ticksPerBeat;
ticksPerSixteenth = event.ticksPerSixteenth;
millis = event.millis;
diffTicks = event.ticks - ticks;
tick += diffTicks;
ticks = event.ticks;
//console.log(nominator,numSixteenth,ticksPerSixteenth);
//console.log(event);
break;
default:
//case 128:
//case 144:
updatePosition(event, isPlaying);
updateEvent(event, isPlaying);
/*
event.millis = millis
*/
result.push(event);
//console.log(event.bar)
// if(event.type === 176 && event.data1 === 64){
// console.log(event.data2, event.barsAsString)
// }
}
// if(i < 100 && (event.type === 81 || event.type === 144 || event.type === 128)){
// //console.log(i, ticks, diffTicks, millis, millisPerTick)
// console.log(event.type, event.millis, 'note', event.data1, 'velo', event.data2)
// }
lastEventTick = event.ticks;
}
parseMIDINotes(result);
return result;
//song.lastEventTmp = event;
}
function updateEvent(event) {
var fast = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
//console.log(bar, beat, ticks)
//console.log(event, bpm, millisPerTick, ticks, millis);
event.bpm = bpm;
event.nominator = nominator;
event.denominator = denominator;
event.ticksPerBar = ticksPerBar;
event.ticksPerBeat = ticksPerBeat;
event.ticksPerSixteenth = ticksPerSixteenth;
event.factor = factor;
event.numSixteenth = numSixteenth;
event.secondsPerTick = secondsPerTick;
event.millisPerTick = millisPerTick;
event.ticks = ticks;
event.millis = millis;
event.seconds = millis / 1000;
if (fast) {
return;
}
event.bar = bar;
event.beat = beat;
event.sixteenth = sixteenth;
event.tick = tick;
//event.barsAsString = (bar + 1) + ':' + (beat + 1) + ':' + (sixteenth + 1) + ':' + tick;
var tickAsString = tick === 0 ? '000' : tick < 10 ? '00' + tick : tick < 100 ? '0' + tick : tick;
event.barsAsString = bar + ':' + beat + ':' + sixteenth + ':' + tickAsString;
event.barsAsArray = [bar, beat, sixteenth, tick];
var timeData = (0, _util.getNiceTime)(millis);
event.hour = timeData.hour;
event.minute = timeData.minute;
event.second = timeData.second;
event.millisecond = timeData.millisecond;
event.timeAsString = timeData.timeAsString;
event.timeAsArray = timeData.timeAsArray;
// if(millis < 0){
// console.log(event)
// }
}
var midiNoteIndex = 0;
function parseMIDINotes(events) {
var notes = {};
var notesInTrack = void 0;
var n = 0;
//console.log(events)
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = events[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var event = _step2.value;
if (typeof event._part === 'undefined' || typeof event._track === 'undefined') {
console.log('no part and/or track set', event);
continue;
}
if (event.type === 144) {
notesInTrack = notes[event._track.id];
if (typeof notesInTrack === 'undefined') {
notesInTrack = notes[event._track.id] = {};
}
notesInTrack[event.data1] = event;
} else if (event.type === 128) {
notesInTrack = notes[event._track.id];
if (typeof notesInTrack === 'undefined') {
//console.info(n++, 'no corresponding noteon event found for event', event.id)
continue;
}
var noteOn = notesInTrack[event.data1];
var noteOff = event;
if (typeof noteOn === 'undefined') {
//console.info(n++, 'no noteon event for event', event.id)
delete notes[event._track.id][event.data1];
continue;
}
var note = new _midi_note.MIDINote(noteOn, noteOff);
note._track = noteOn._track;
note = null;
// let id = `MN_${midiNoteIndex++}_${new Date().getTime()}`
// noteOn.midiNoteId = id
// noteOn.off = noteOff.id
// noteOff.midiNoteId = id
// noteOff.on = noteOn.id
delete notes[event._track.id][event.data1];
}
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
Object.keys(notes).forEach(function (key) {
delete notes[key];
});
notes = {};
//console.log(notes, notesInTrack)
}
// not in use!
function filterEvents(events) {
var sustain = {};
var tmpResult = {};
var result = [];
var _iteratorNormalCompletion3 = true;
var _didIteratorError3 = false;
var _iteratorError3 = undefined;
try {
for (var _iterator3 = events[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
var event = _step3.value;
if (event.type === 176 && event.data1 === 64) {
if (event.data2 === 0) {
if (typeof sustain[event.trackId] === 'undefined') {
continue;
} else if (sustain[event.trackId] === event.ticks) {
delete tmpResult[event.ticks];
continue;
}
tmpResult[event.ticks] = event;
delete sustain[event.trackId];
} else if (event.data2 === 127) {
sustain[event.trackId] = event.ticks;
tmpResult[event.ticks] = event;
}
} else {
result.push(event);
}
}
} catch (err) {
_didIteratorError3 = true;
_iteratorError3 = err;
} finally {
try {
if (!_iteratorNormalCompletion3 && _iterator3.return) {
_iterator3.return();
}
} finally {
if (_didIteratorError3) {
throw _iteratorError3;
}
}
}
console.log(sustain);
Object.keys(tmpResult).forEach(function (key) {
var sustainEvent = tmpResult[key];
console.log(sustainEvent);
result.push(sustainEvent);
});
return result;
}