/* -------------------------------------------- MIDI.Plugin : 0.3 : 11/20/2012 -------------------------------------------- https://github.com/mudcube/MIDI.js -------------------------------------------- MIDI.WebAudioAPI MIDI.Flash MIDI.HTML5 MIDI.GeneralMIDI MIDI.channels MIDI.keyToNote MIDI.noteToKey -------------------------------------------- setMute? getInstruments? ------------------------------------- */ if (typeof (MIDI) === "undefined") var MIDI = {}; if (typeof (MIDI.Plugin) === "undefined") MIDI.Plugin = {}; (function() { "use strict"; /* -------------------------------------------- Web Audio API - OGG or MPEG Soundbank -------------------------------------------- https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html -------------------------------------------- */ if (typeof (MIDI.WebAudioAPI) === "undefined") MIDI.WebAudioAPI = {}; if (window.AudioContext || window.webkitAudioContext) (function () { var AudioContext = window.AudioContext || window.webkitAudioContext; var root = MIDI.WebAudioAPI; var ctx; var sources = {}; var masterVolume = 1; var audioBuffers = {}; var audioLoader = function (instrument, urlList, index, bufferList, callback) { var synth = MIDI.GeneralMIDI.byName[instrument]; var instrumentId = synth.number; var url = urlList[index]; 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 (n) { masterVolume = n; }; 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); /// var gainNode = ctx.createGainNode(); var value = -0.5 + (velocity / 100) * 2; var minus = (1 - masterVolume) * 2; gainNode.connect(ctx.destination); gainNode.gain.value = Math.max(-1, value - minus); source.connect(gainNode); source.noteOn(delay || 0); return source; }; 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; }; // FIX: needs some way to fade out smoothly.. // POSSIBLE FIX: fade out smoothly using gain and ramping to value root.noteOff = function (channel, note, delay) { delay = delay || 0; var source = sources[channel + "" + note]; if (!source) return; source.gain.linearRampToValueAtTime(1, delay); source.gain.linearRampToValueAtTime(0, delay + 0.75); source.noteOff(delay + 0.75); return source; }; 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.connect = function (callback) { MIDI.lang = 'WebAudioAPI'; 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.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) 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