Skip to content

Instantly share code, notes, and snippets.

@RyanJ93
Created March 6, 2015 19:26
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RyanJ93/8c0d78323ab13787ea51 to your computer and use it in GitHub Desktop.
Save RyanJ93/8c0d78323ab13787ea51 to your computer and use it in GitHub Desktop.
Simple web MIDI API example
<html>
<head>
<style type="text/css">
.text{
font-family:"Trebuchet MS", Arial, Helvetica, sans-serif;
font-size:16px;
}
.title{
font-family:"Trebuchet MS", Arial, Helvetica, sans-serif;
font-size:24px;
}
.bold{
font-weight:bold;
}
</style>
<script type="text/javascript">
var waveForm = 'sine';
var globalVolume = 0;
var midi = null;
var devices = new Array();
var dev = null;
var oscillator = null;
var gain = null;
var context = null;
var instances = new Array();
function getFrequency(value){
return (Math.pow(2, ( ( parseInt(value) - 69 ) / 12 )) * 440);
}
function getVelocity(value){
return ( ( value * 100 ) / 127 );
}
window.AudioContext = window.AudioContext||window.webkitAudioContext;
try{
window.AudioContext = window.AudioContext || window.webkitAudioContext;
context = new AudioContext();
}catch(e){
console.log(e);
alert('Web Audio API is not supported in this browser');
}
try{
navigator.requestMIDIAccess().then(_event_success, function(){
console.log("ERR");
});
}catch(ex){
console.log(ex);
alert("NOT SUPPORTED");
}
function _event_success(access){
midi = access;
inputs = midi.inputs;
iterator = inputs.values();
var i = 0;
while((data = iterator.next()).done === false){
if ( data.value.type.toLowerCase() == 'input' ){
devices[i] = {
dev: data.value,
name: data.value.name,
manufacturer: data.value.manufacturer,
version: data.value.version
};
addDevice(data.value.name, i);
i++;
}
}
changeDevice(0);
return true;
}
function addDevice(name, id){
var wrapper = document.getElementById('devices');
var element = document.createElement('option');
element.text = name;
element.setAttribute('value', parseInt(id));
wrapper.appendChild(element);
return true;
}
function changeDevice(id){
if ( id == null ){
var element = document.getElementById('devices');
id = element.options[element.selectedIndex].value;
}
try{
dev.removeEventListener("midimessage", handleMIDIMessage);
}catch(ex){}
dev = devices[id].dev;
instances = new Array();
dev.addEventListener("midimessage", handleMIDIMessage);
document.getElementById('dev-name').textContent = devices[id].name;
document.getElementById('dev-manufacturer').textContent = devices[id].manufacturer;
document.getElementById('dev-version').textContent = devices[id].version;
return true;
}
function handleMIDIMessage(event){
try{
if ( typeof(instances[event.data[1]]) == 'undefined' || instances[event.data[1]] == null ){
instances[event.data[1]] = {
oscillator: context.createOscillator(),
gain: context.createGain(),
data: event.data
}
instances[event.data[1]].oscillator.type = waveForm;
instances[event.data[1]].oscillator.frequency.value = getFrequency(event.data[1]);
instances[event.data[1]].gain.gain.value = ( getVelocity(event.data[2]) - globalVolume );
console.log(( getVelocity(event.data[2]) - globalVolume ));
instances[event.data[1]].oscillator.connect(instances[event.data[1]].gain);
instances[event.data[1]].gain.connect(context.destination);
instances[event.data[1]].oscillator.start();
}else{
if ( event.data[2] <= 0 ){
instances[event.data[1]].oscillator.stop();
instances[event.data[1]] = null;
}else{
}
}
}catch(ex){
console.log(ex);
}
return true;
}
function changeWaveForm(){
var element = document.getElementById('waveform');
waveForm = element.options[element.selectedIndex].value;
newRendering();
return true;
}
function changeVolume(){
globalVolume = document.getElementById('volume').value;
newRendering();
return true;
}
function newRendering(){
var buffer = null;
try{
instances.forEach(function(entry){
if ( typeof(entry) != 'undefined' && entry != null ){
try{
entry.oscillator.stop();
}catch(ex){}
buffer = entry.data;
entry = null;
entry = {
oscillator: context.createOscillator(),
gain: context.createGain(),
data: buffer
}
entry.oscillator.type = waveForm;
entry.oscillator.frequency.value = getFrequency(buffer[1]);
entry.gain.gain.value = getVelocity(buffer[2]) - globalVolume;
entry.oscillator.connect(instances[buffer[1]].gain);
entry.gain.connect(context.destination);
entry.oscillator.start();
}
});
}catch(ex){
console.log(ex);
}
return true;
}
</script>
</head>
<body>
<h1 class="title">Basic web Audio API & web MIDI API example</h1>
<br />
<table cellpadding="0" cellspacing="0">
<tr>
<td align="left" valign="middle" width="200">
<span class="text">Found devices:</span>
</td>
<td align="left" valign="middle">
<select id="devices" onChange="changeDevice(null);"></select>
</td>
</tr>
<tr>
<td align="left" valign="middle" width="200">
<span class="text">Actual device:</span>
</td>
<td align="left" valign="middle">
<span class="text bold" id="dev-name"></span>&nbsp;<span class="text">manufactured by</span>&nbsp;<span class="text bold" id="dev-manufacturer"></span>&nbsp;<span class="text bold">version:</span>&nbsp;<span class="text bold" id="dev-version"></span>
</td>
</tr>
<tr>
<td align="left" valign="middle" width="200">
<span class="text">General volume:</span>
</td>
<td align="left" valign="middle">
<input type="range" min="0" max="100" value="0" onChange="changeVolume();" id="volume" />
</td>
</tr>
<tr>
<td align="left" valign="middle" width="200">
<span class="text">Wave form:</span>
</td>
<td align="left" valign="middle">
<select id="waveform" onChange="changeWaveForm();">
<option value="sine" selected>Sine</option>
<option value="square">Square</option>
<option value="sawtooth">Sawtooth</option>
<option value="triangle">Triangle</option>
</select>
</td>
</tr>
</table>
<br /><br /><br />
<span class="text">Note: For use the MIDI APIs you must use Google Chrome Canary and activate the experimental flag on <pre>chrome://flags</pre></span>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment