UNPKG

qambi

Version:

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

181 lines (153 loc) 5.77 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.Instrument = undefined; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _init_audio = require('./init_audio'); var _eventlistener = require('./eventlistener'); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Instrument = exports.Instrument = function () { function Instrument() { _classCallCheck(this, Instrument); this.scheduledSamples = new Map(); this.sustainedSamples = []; this.sustainPedalDown = false; this.output = null; } // mandatory _createClass(Instrument, [{ key: 'connect', value: function connect(output) { this.output = output; } // mandatory }, { key: 'disconnect', value: function disconnect() { this.output = null; } // mandatory }, { key: 'processMIDIEvent', value: function processMIDIEvent(event) { var _this = this; var time = event.time / 1000; var sample = void 0; if (isNaN(time)) { // this shouldn't happen console.error('invalid time value'); return; //time = context.currentTime } if (time === 0) { // this shouldn't happen -> external MIDI keyboards console.error('should not happen'); time = _init_audio.context.currentTime; } if (event.type === 144) { //console.log(144, ':', time, context.currentTime, event.millis) sample = this.createSample(event); this.scheduledSamples.set(event.midiNoteId, sample); //console.log(sample) sample.output.connect(this.output); sample.start(time); //console.log('scheduling', event.id, event.midiNoteId) //console.log('start', event.midiNoteId) } else if (event.type === 128) { //console.log(128, ':', time, context.currentTime, event.millis) sample = this.scheduledSamples.get(event.midiNoteId); if (typeof sample === 'undefined') { //console.info('sample not found for event', event.id, ' midiNote', event.midiNoteId, event) return; } // we don't want that the sustain pedal prevents the an event to unscheduled if (this.sustainPedalDown === true) { //console.log(event.midiNoteId) this.sustainedSamples.push(event.midiNoteId); } else { sample.stop(time, function () { // console.log('stop', time, event.midiNoteId) sample.output.disconnect(); _this.scheduledSamples.delete(event.midiNoteId); }); //sample.stop(time) } } else if (event.type === 176) { // sustain pedal if (event.data1 === 64) { if (event.data2 === 127) { this.sustainPedalDown = true; ///* (0, _eventlistener.dispatchEvent)({ type: 'sustainpedal', data: 'down' }); //*/ //console.log('sustain pedal down') } else if (event.data2 === 0) { this.sustainPedalDown = false; this.sustainedSamples.forEach(function (midiNoteId) { sample = _this.scheduledSamples.get(midiNoteId); if (sample) { //sample.stop(time) sample.stop(time, function () { //console.log('stop', midiNoteId) sample.output.disconnect(); _this.scheduledSamples.delete(midiNoteId); }); } }); //console.log('sustain pedal up', this.sustainedSamples) this.sustainedSamples = []; ///* (0, _eventlistener.dispatchEvent)({ type: 'sustainpedal', data: 'up' }); //*/ //this.stopSustain(time); } // panning } else if (event.data1 === 10) { // panning is *not* exactly timed -> not possible (yet) with WebAudio //console.log(data2, remap(data2, 0, 127, -1, 1)); //track.setPanning(remap(data2, 0, 127, -1, 1)); // volume } else if (event.data1 === 7) { // to be implemented } } } // mandatory }, { key: 'allNotesOff', value: function allNotesOff() { this.sustainedSamples = []; if (this.sustainPedalDown === true) { (0, _eventlistener.dispatchEvent)({ type: 'sustainpedal', data: 'up' }); } this.sustainPedalDown = false; this.scheduledSamples.forEach(function (sample) { sample.stop(_init_audio.context.currentTime); sample.output.disconnect(); }); this.scheduledSamples.clear(); } // mandatory }, { key: 'unschedule', value: function unschedule(midiEvent) { var sample = this.scheduledSamples.get(midiEvent.midiNoteId); if (sample) { sample.stop(_init_audio.context.currentTime); sample.output.disconnect(); this.scheduledSamples.delete(midiEvent.midiNoteId); } } }]); return Instrument; }();