Skip to content

Instantly share code, notes, and snippets.

@rudle
Created May 1, 2016 23:07
Show Gist options
  • Save rudle/1007b15e84d70423fb59675182d3c4e0 to your computer and use it in GitHub Desktop.
Save rudle/1007b15e84d70423fb59675182d3c4e0 to your computer and use it in GitHub Desktop.
var ChordSpeller = {
chord: {}, // this represents the cord the user is holding down. map[string] -> int
chordView: null, // cached chord view
self: this,
init: function() {
console.log("requesting MIDI access");
if (navigator.requestMIDIAccess) {
navigator.requestMIDIAccess({
sysex: false
}).then(ChordSpeller.onMIDISuccess, ChordSpeller.onMIDIFailure);
} else {
alert("No MIDI support in your browser.");
}
return;
},
onMIDIMessage: function(event) {
console.log(event.data)
switch (event.data[0] & 0xf0) {
case 0x90:
if (event.data[2]!=0) { // if velocity != 0, this is a note-on message
ChordSpeller.noteOn(event.data[1]);
return;
}
// if velocity == 0, fall thru: it's a note-off. MIDI's weird, y'all.
case 0x80:
ChordSpeller.noteOff(event.data[1]);
return;
}
},
onMIDIFailure: function(error) {
// when we get a failed response, run this code
console.log("No access to MIDI devices or your browser doesn't support WebMIDI API. Please use WebMIDIAPIShim " + error);
},
// midi functions
onMIDISuccess: function(midiAccess) {
midi = midiAccess;
var inputs = midi.inputs.values();
// loop over all available inputs and listen for any MIDI input
for (var input = inputs.next(); input && !input.done; input = inputs.next()) {
// each time there is a midi message call the onMIDIMessage function
console.log("detected input: " + input.value.manufacturer + " " + input.value.name);
input.value.onmidimessage = ChordSpeller.onMIDIMessage;
}
},
noteNumberToLetter: function(noteNumber, bias) {
if (bias === null){
bias = "#";
}
switch (noteNumber % 12) {
case 0:
return "C"+bias;
break;
case 1:
return "C#"+bias;
break;
case 2:
return "D"+bias;
break;
case 3:
return "D#"+bias;
break;
case 4:
return "E"+bias;
break;
case 5:
return "F"+bias;
break;
case 6:
return "F#"+bias;
break;
case 7:
return "G"+bias;
break;
case 8:
return "G#"+bias;
break;
case 9:
return "A"+bias;
break;
case 10:
return "A#"+bias;
break;
case 11:
return "B"+bias;
break;
default:
console.log("math is broken");
break;
}
},
MIDIMessageEventHandler: function (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;
}
},
renderChord: function() {
console.log(ChordSpeller.chord)
if (this.chordView === null) {
this.chordView = document.getElementById('chord');
}
this.chordView.innerHTML = Object.keys(this.chord).join(" ");
},
addToChord: function(noteNumber) {
name = ChordSpeller.noteNumberToLetter(noteNumber);
ChordSpeller.chord[name] = true; // TODO store velocity instead
ChordSpeller.renderChord();
},
removeFromChord: function(noteNumber) {
name = ChordSpeller.noteNumberToLetter(noteNumber);
delete ChordSpeller.chord[name];
ChordSpeller.renderChord();
},
noteOn: function(noteNumber) {
return this.addToChord(noteNumber);
},
noteOff: function(noteNumber) {
return this.removeFromChord(noteNumber);
},
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment