piano/js/midi/io.js

167 lines
4.7 KiB
JavaScript

/*jshint es5: true, bitwise: true */
/*globals App */
/**
* io.js
*
* Handle communication with MIDI inputs and outputs
* Request navigator access to MIDI devices
*/
(function () {
'use strict';
/**
* Wrap around low-level MIDI output
*
* @param {native: MIDIOutput} Native MIDIOutput to wrap around
*/
function Output(native) {
this.native = native || {
send: function () {}
};
}
/**
* List of MIDI channel events
*/
Output.messages = {
noteOff: 0x80,
noteOn: 0x90,
noteAftertouch: 0xA0,
controller: 0xB0,
programChange: 0xC0,
channelAftertouch: 0xD0,
pitchBend: 0xE0
};
/**
* List of controller types
* (not complete)
*/
Output.controllers = {
modulationWheel: 1,
volume: 7,
pan: 10,
expression: 11,
sustainPedal: 64
};
Output.prototype.programChange = function (channel, program, delay) {
this.native.send([
Output.messages.programChange + channel,
program
], (delay || 0) * 1000);
};
Output.prototype.noteOn = function (channel, note, velocity, delay) {
this.native.send([
Output.messages.noteOn + channel,
note,
velocity
], (delay || 0) * 1000);
};
Output.prototype.noteOff = function (channel, note, delay) {
this.native.send([
Output.messages.noteOff + channel,
note,
0
], (delay || 0) * 1000);
};
Output.prototype.noteAftertouch = function (channel, note, amount, delay) {
this.native.send([
Output.messages.noteAftertouch + channel,
note,
amount
], (delay || 0) * 1000);
};
Output.prototype.controller = function (channel, type, value, delay) {
this.native.send([
Output.messages.controller + channel,
type,
value
], (delay || 0) * 1000);
};
Output.prototype.programChange = function (channel, program, delay) {
this.native.send([
Output.messages.programChange + channel,
program
], (delay || 0) * 1000);
};
Output.prototype.channelAftertouch = function (channel, amount, delay) {
this.native.send([
Output.messages.channelAftertouch + channel,
amount
], (delay || 0) * 1000);
};
Output.prototype.pitchBend = function (channel, value, delay) {
var lsb, msb;
value += 8192;
lsb = value & 127;
msb = value >> 7;
this.native.send([
Output.messages.pitchBend + channel,
lsb,
msb
], (delay || 0) * 1000);
};
/**
* Request MIDI access, select first available output
*
* @return Promise
*/
function connect() {
var promise;
promise = new window.Promise(function (resolve, reject) {
var ignoreAlert = "Si vous continuez, " +
"<em>aucun son ne sera émis ou reçu,</em> mais vous " +
"pourrez utiliser les autres fonctionnalités " +
"du logiciel.";
// by default, we use a no-op output
App.MIDI.output = new Output();
navigator.requestMIDIAccess().then(function (access) {
var outputs = access.outputs(),
output;
if (outputs && outputs.length) {
output = new Output(outputs[0]);
App.MIDI.output = output;
resolve(output);
} else {
reject(new Error(
"Aucun synthétiseur MIDI n'est disponible. Sur " +
"systèmes d'exploitation, un synthétiseur " +
"est disponible par défaut. S'il ce n'est pas " +
"votre cas, il faudra utiliser un logiciel " +
"tiers pour synthétiser les sons.<br /><br />" +
ignoreAlert
));
}
}).catch(function () {
reject(new Error(
"Impossible d'obtenir un accès aux contrôleurs " +
"MIDI, il est possible que votre système ne " +
"supporte pas la norme MIDI ou bien que " +
"vous ayez refusé l'accès à ces périphériques. " +
"<br /><br />" + ignoreAlert
));
});
});
return promise;
}
App.MIDI.connect = connect;
}());