From c9af7bb67bfefc3f37b4cdd4a066a29138f202b3 Mon Sep 17 00:00:00 2001 From: piernov Date: Thu, 13 Mar 2014 16:48:55 +0100 Subject: Importation du projet --- Processing-js/libs/js/MIDI/Plugin.js | 623 +++++++++++++++++++++++++++++++++++ 1 file changed, 623 insertions(+) create mode 100644 Processing-js/libs/js/MIDI/Plugin.js (limited to 'Processing-js/libs/js/MIDI/Plugin.js') diff --git a/Processing-js/libs/js/MIDI/Plugin.js b/Processing-js/libs/js/MIDI/Plugin.js new file mode 100644 index 0000000..7647f96 --- /dev/null +++ b/Processing-js/libs/js/MIDI/Plugin.js @@ -0,0 +1,623 @@ +/* + -------------------------------------------- + MIDI.Plugin : 0.3.2 : 2013/01/26 + -------------------------------------------- + https://github.com/mudcube/MIDI.js + -------------------------------------------- + Inspired by javax.sound.midi (albeit a super simple version): + http://docs.oracle.com/javase/6/docs/api/javax/sound/midi/package-summary.html + -------------------------------------------- + Technologies: + MIDI.WebMIDI + MIDI.WebAudio + MIDI.Flash + MIDI.AudioTag + -------------------------------------------- + Helpers: + MIDI.GeneralMIDI + MIDI.channels + MIDI.keyToNote + MIDI.noteToKey +*/ + +if (typeof (MIDI) === "undefined") var MIDI = {}; + +(function() { "use strict"; + +var setPlugin = function(root) { + MIDI.api = root.api; + MIDI.setVolume = root.setVolume; + MIDI.programChange = root.programChange; + MIDI.noteOn = root.noteOn; + MIDI.noteOff = root.noteOff; + MIDI.chordOn = root.chordOn; + MIDI.chordOff = root.chordOff; + MIDI.stopAllNotes = root.stopAllNotes; + MIDI.getInput = root.getInput; + MIDI.getOutputs = root.getOutputs; +}; + +/* + -------------------------------------------- + Web MIDI API - Native Soundbank + -------------------------------------------- + https://dvcs.w3.org/hg/audio/raw-file/tip/midi/specification.html + -------------------------------------------- +*/ + +(function () { + var plugin = null; + var output = null; + var channels = []; + var root = MIDI.WebMIDI = { + api: "webmidi" + }; + root.setVolume = function (channel, volume) { // set channel volume + output.send([0xB0 + channel, 0x07, volume]); + }; + + root.programChange = function (channel, program) { // change channel instrument + output.send([0xC0 + channel, program]); + }; + + root.noteOn = function (channel, note, velocity, delay) { + output.send([0x90 + channel, note, velocity], delay * 1000); + }; + + root.noteOff = function (channel, note, delay) { + output.send([0x80 + channel, note, 0], delay * 1000); + }; + + root.chordOn = function (channel, chord, velocity, delay) { + for (var n = 0; n < chord.length; n ++) { + var note = chord[n]; + output.send([0x90 + channel, note, velocity], delay * 1000); + } + }; + + root.chordOff = function (channel, chord, delay) { + for (var n = 0; n < chord.length; n ++) { + var note = chord[n]; + output.send([0x80 + channel, note, 0], delay * 1000); + } + }; + + root.stopAllNotes = function () { + for (var channel = 0; channel < 16; channel ++) { + output.send([0xB0 + channel, 0x7B, 0]); + } + }; + + root.getInput = function () { + return plugin.getInputs(); + }; + + root.getOutputs = function () { + return plugin.getOutputs(); + }; + + root.connect = function (conf) { + setPlugin(root); + navigator.requestMIDIAccess().then(function (access) { + plugin = access; + output = plugin.outputs()[0]; + if (conf.callback) conf.callback(); + }, function (err) { // well at least we tried! + if (window.AudioContext || window.webkitAudioContext) { // Chrome + conf.api = "webaudio"; + } else if (window.Audio) { // Firefox + conf.api = "audiotag"; + } else { // Internet Explorer + conf.api = "flash"; + } + MIDI.loadPlugin(conf); + }); + }; +})(); + +/* + -------------------------------------------- + Web Audio API - OGG or MPEG Soundbank + -------------------------------------------- + https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html + -------------------------------------------- +*/ + +if (window.AudioContext || window.webkitAudioContext) (function () { + + var AudioContext = window.AudioContext || window.webkitAudioContext; + var root = MIDI.WebAudio = { + api: "webaudio" + }; + var ctx; + var sources = {}; + var masterVolume = 127; + var audioBuffers = {}; + var audioLoader = function (instrument, urlList, index, bufferList, callback) { + var synth = MIDI.GeneralMIDI.byName[instrument]; + var instrumentId = synth.number; + var url = urlList[index]; + if (!MIDI.Soundfont[instrument][url]) { // missing soundfont + return callback(instrument); + } + var base64 = MIDI.Soundfont[instrument][url].split(",")[1]; + var buffer = Base64Binary.decodeArrayBuffer(base64); + ctx.decodeAudioData(buffer, function (buffer) { + var msg = url; + while (msg.length < 3) msg += " "; + if (typeof (MIDI.loader) !== "undefined") { + MIDI.loader.update(null, synth.instrument + "
Processing: " + (index / 87 * 100 >> 0) + "%
" + msg); + } + buffer.id = url; + bufferList[index] = buffer; + // + if (bufferList.length === urlList.length) { + while (bufferList.length) { + buffer = bufferList.pop(); + if (!buffer) continue; + var nodeId = MIDI.keyToNote[buffer.id]; + audioBuffers[instrumentId + "" + nodeId] = buffer; + } + callback(instrument); + } + }); + }; + + root.setVolume = function (channel, volume) { + masterVolume = volume; + }; + + root.programChange = function (channel, program) { + MIDI.channels[channel].instrument = program; + }; + + root.noteOn = function (channel, note, velocity, delay) { + /// check whether the note exists + if (!MIDI.channels[channel]) return; + var instrument = MIDI.channels[channel].instrument; + if (!audioBuffers[instrument + "" + note]) return; + /// convert relative delay to absolute delay + if (delay < ctx.currentTime) delay += ctx.currentTime; + /// crate audio buffer + var source = ctx.createBufferSource(); + sources[channel + "" + note] = source; + source.buffer = audioBuffers[instrument + "" + note]; + source.connect(ctx.destination); + /// + if (ctx.createGain) { // firefox + source.gainNode = ctx.createGain(); + } else { // chrome + source.gainNode = ctx.createGainNode(); + } + var value = (velocity / 127) * (masterVolume / 127) * 2 - 1; + source.gainNode.connect(ctx.destination); + source.gainNode.gain.value = Math.max(-1, value); + source.connect(source.gainNode); + if (source.noteOn) { // old api + source.noteOn(delay || 0); + } else { // new api + source.start(delay || 0); + } + return source; + }; + + root.noteOff = function (channel, note, delay) { + delay = delay || 0; + if (delay < ctx.currentTime) delay += ctx.currentTime; + var source = sources[channel + "" + note]; + if (!source) return; + if (source.gainNode) { + // @Miranet: "the values of 0.2 and 0.3 could ofcourse be used as + // a 'release' parameter for ADSR like time settings." + // add { "metadata": { release: 0.3 } } to soundfont files + var gain = source.gainNode.gain; + gain.linearRampToValueAtTime(gain.value, delay); + gain.linearRampToValueAtTime(-1, delay + 0.2); + } + if (source.noteOff) { // old api + source.noteOff(delay + 0.3); + } else { + source.stop(delay + 0.3); + } + /// + delete sources[channel + "" + note]; + }; + + root.chordOn = function (channel, chord, velocity, delay) { + var ret = {}, note; + for (var n = 0, length = chord.length; n < length; n++) { + ret[note = chord[n]] = root.noteOn(channel, note, velocity, delay); + } + return ret; + }; + + root.chordOff = function (channel, chord, delay) { + var ret = {}, note; + for (var n = 0, length = chord.length; n < length; n++) { + ret[note = chord[n]] = root.noteOff(channel, note, delay); + } + return ret; + }; + + root.stopAllNotes = function () { + for (var source in sources) { + var delay = 0; + if (delay < ctx.currentTime) delay += ctx.currentTime; + // @Miranet: "the values of 0.2 and 0.3 could ofcourse be used as + // a 'release' parameter for ADSR like time settings." + // add { "metadata": { release: 0.3 } } to soundfont files + sources[source].gain.linearRampToValueAtTime(1, delay); + sources[source].gain.linearRampToValueAtTime(0, delay + 0.2); + sources[source].noteOff(delay + 0.3); + delete sources[source]; + } + }; + + root.connect = function (conf) { + setPlugin(root); + // + MIDI.Player.ctx = ctx = new AudioContext(); + /// + var urlList = []; + var keyToNote = MIDI.keyToNote; + for (var key in keyToNote) urlList.push(key); + var bufferList = []; + var pending = {}; + var oncomplete = function(instrument) { + delete pending[instrument]; + for (var key in pending) break; + if (!key) conf.callback(); + }; + for (var instrument in MIDI.Soundfont) { + pending[instrument] = true; + for (var i = 0; i < urlList.length; i++) { + audioLoader(instrument, urlList, i, bufferList, oncomplete); + } + } + }; +})(); + +/* + -------------------------------------------- + AudioTag