webMIDI
var context = null;
// the Web Audio "context" object
var midiAccess = null;
// the MIDIAccess object.
var oscillator = null;
// the single oscillator
var envelope = null;
// the envelope for the single oscillator
var attack = 0.05;
// attack speed
var release = 0.05;
// release speed
var portamento = 0.05;
// portamento/glide speed
var activeNotes = [];
// the stack of actively-pressed keys
document.addEventListener('load', function() {
// patch up prefixes
document.AudioContext = window.AudioContext || window.webkitAudioContext;
context = new AudioContext();
if (navigator.requestMIDIAccess)
navigator.requestMIDIAccess().then(onMIDIInit, onMIDIReject);
else
alert("No MIDI support present in your browser. You're gonna have a bad time.")
// set up the basic oscillator chain, muted to begin with.
oscillator = context.createOscillator();
oscillator.frequency.setValueAtTime(110, 0);
envelope = context.createGain();
oscillator.connect(envelope);
envelope.connect(context.destination);
envelope.gain.value = 0.0;
// Mute the sound
oscillator.start(0);
// Go ahead and start up the oscillator
});
function onMIDIInit(midi) {
midiAccess = midi;
var haveAtLeastOneDevice = false;
var inputs = midiAccess.inputs.values();
for (var input = inputs.next(); input && !input.done; input = inputs.next()) {
input.value.onmidimessage = MIDIMessageEventHandler;
haveAtLeastOneDevice = true;
}
if (!haveAtLeastOneDevice)
alert("No MIDI input devices present. You're gonna have a bad time.");
}
function onMIDIReject(err) {
alert("The MIDI system failed to start. You're gonna have a bad time.");
}
function MIDIMessageEventHandler(event) {
// Mask off the lower nibble (MIDI channel, which we don't care about)
switch (event.data[0] & 0xf0) {
case 0x90:
if (event.data[2] != 0) {
// if velocity != 0, this is a note-on message
noteOn(event.data[1]);
return;
}
// if velocity == 0, fall thru: it's a note-off. MIDI's weird, y'all.
case 0x80:
noteOff(event.data[1]);
return;
}
}
function frequencyFromNoteNumber(note) {
return 440 * Math.pow(2, (note - 69) / 12);
}
function noteOn(noteNumber) {
activeNotes.push(noteNumber);
oscillator.frequency.cancelScheduledValues(0);
oscillator.frequency.setTargetAtTime(frequencyFromNoteNumber(noteNumber), 0, portamento);
envelope.gain.cancelScheduledValues(0);
envelope.gain.setTargetAtTime(1.0, 0, attack);
}
function noteOff(noteNumber) {
var position = activeNotes.indexOf(noteNumber);
if (position != -1) {
activeNotes.splice(position, 1);
}
if (activeNotes.length == 0) {
// shut off the envelope
envelope.gain.cancelScheduledValues(0);
envelope.gain.setTargetAtTime(0.0, 0, release);
} else {
oscillator.frequency.cancelScheduledValues(0);
oscillator.frequency.setTargetAtTime(frequencyFromNoteNumber(activeNotes[activeNotes.length - 1]), 0, portamento);
}
}
This Gist was automatically created by Carbide, a free online programming environment.