UNPKG

qambi

Version:

MIDI sequencer, loads MIDI files, can record and playback MIDI, uses WebMIDI and WebAudio

474 lines (400 loc) 12.3 kB
'use strict'; 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; }