/*
--------------------------------------------
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 = (velocity / 100) * masterVolume * 2 - 1;
gainNode.connect(ctx.destination);
gainNode.gain.value = Math.max(-1, value);
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