midi everything!
hacking web midi to do silly stuff
by gregor
HTML
<div class="wrapper block">
<div id="test-controls" class="centered">
<label>bend
<input type="range" min="0" max="127" value="64" id="bend-control" />
</label>
<label>mod
<input type="range" min="0" max="127" value="0" id="mod-control" />
</label>
<label></label>
<label>fader
<!-- <input type="range" min="0" max="127" value="0" id="fader-control" /> -->
<input type="range" min="0" max="127" value="127" id="fader-control" />
</label>
</div>
</div>
<div class="fake-height"></div>
CSS
body {
margin: 0;
padding: 0;
font: bold 12px/3 sans-serif;
letter-spacing: 1.5px;
color: #999;
/* default state */
/* opacity: 0; */
/*
background-image: url('http://subtlepatterns.com/patterns/crissXcross.png');
background-image: url('http://subtlepatterns2015.subtlepatterns.netdna-cdn.com/patterns/footer_lodyas.png');
*/
background-image: url('http://subtlepatterns2015.subtlepatterns.netdna-cdn.com/patterns/sativa.png');
}
.wrapper {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.fake-height {
width: 1px;
height: 10000px;
}
#test-controls {}
#test-controls label,
#test-controls input {
width: 50px;
height: 100px;
margin: 0;
padding: 0;
}
#test-controls label {
float: left;
text-align: center;
}
#bend-control,
#mod-control,
#fader-control {
-webkit-appearance: slider-vertical;
writing-mode: bt-lr;
}
.block {
text-align: center;
white-space: nowrap;
}
.block:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
margin-right: -0.25em;
}
.centered {
display: inline-block;
vertical-align: middle;
white-space: normal;
}
JavaScript
var log = console.log.bind(console),
testControlsEl = document.getElementById('test-controls'),
bendControlEl = document.getElementById('bend-control'),
modControlEl = document.getElementById('mod-control'),
faderControlEl = document.getElementById('fader-control');
var midi, bendIntervalId;
var data, cmd, channel, type, note, velocity;
var tickScrollDistance = 10;
// element binding
bendControlEl.addEventListener('input', function(e) {
onBend(bendControlEl.value);
});
modControlEl.addEventListener('input', function(e) {
onMod(modControlEl.value);
});
faderControlEl.addEventListener('input', function(e) {
onFader(faderControlEl.value);
});
// simulate the physical control:
// jump to middle position when leaving mouse button on the bend slider
document.addEventListener('mouseup', function(e) {
if (e.target === bendControlEl) {
onBend(bendControlEl.value = 64);
}
})
// request MIDI access
if (navigator.requestMIDIAccess) {
navigator.requestMIDIAccess({
sysex: false
}).then(onMIDISuccess, onMIDIFailure);
} else {
alert("No MIDI support in your browser.");
}
// midi functions
function onMIDISuccess(midiAccess) {
midi = midiAccess;
var inputs = midi.inputs.values();
for (var input = inputs.next(); input && !input.done; input = inputs.next()) {
input.value.onmidimessage = onMIDIMessage;
}
midi.onstatechange = onStateChange;
}
function onMIDIMessage(event) {
data = event.data,
cmd = data[0] >> 4,
channel = data[0] & 0xf,
type = data[0] & 0xf0, // channel agnostic message type. Thanks, Phil Burk.
note = data[1],
velocity = data[2];
switch (type) {
case 144: // note on
switch (note) {
case 48: // C-4
midiMessageDecorator(onKeyC4, null, velocity);
break;
}
break;
case 128: // note off
break;
case 224: // pitch bend
midiMessageDecorator(onBend, bendControlEl, velocity);
break;
case 176: // faders, knobs,...