WebMidiApiとは
W3Cで策定しているブラウザでMidiを操作できるプロトコルです。
以前はChromeのみの対応でしたがEDGE、FireFoxも対応となりました。またPC/MAC/Androidのブラウザで動きます。
おそらくアップル側の意向と思われますがIOS(iphone)はまだ対応しておりません。
IOSでWebMidiApiに対応するには Web MIDI Browser
で試してみてください。
各種ブラウザ対応の確認はこちらの Can I Useのサイトよりご確認ください。

おもにIEですが他のブラウザでも動くようにするにはWebMIDIAPIShimより「WebMIDIAPI.min.js」を読込ます,そしてJazzPlugInをインストールします。
システムエクスクルーシブ(sysex)を扱う場合、SSLのサーバーが必要になります。
下記コードではsysex:true部分がSysExのON設定です。SysExを使わない場合はfalseで非SSLサーバーで問題ありません。ちなみにローカルならどちらも使えます。
シンプルなWebMidiApiの実装
JavaScriptでシンプルなWebMidiApiを作ります。WebMidiApiの実験室様を参考にさせていただきました。機能としてはポートon/off表示、INPUT_MIDIデータ表示、textのMIDI_OUTPUT出力です
現状でWebMidiApiを作るときはChromeとIEだけに特化すればよいのですが、2つのブラウザ間だけでも少々問題があり、他、気になったところは以下になります。
1,IEで'\n'で改行すると無効になりましたので'br'にしました。
2.Web Midi Apiのport.idでinput,outputを表示させていたのですがIEで文字化けのような表示となりましたのでport.idの使用をやめました。
3.対応しないブラウザで開いたときchromeで開くようにアラートを出します。
4.ネットからの読込 <script src='http://cwilso.github.com/WebMIDIAPIShim/build/WebMIDIAPI.min.js'></script>
にすると反応しませんでした。ローカルにおいて読み込むと反応しました。
5.jazzPluginの作者様はjazz.jsに移行しているようで、ブラウザの独自搭載を待つよりないのかなというところです。
以下JavaScript付きhtmコードになります。
WebMidiApiのメインコードは、わずかなコードで動きます。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-127064675-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-127064675-1');
</script>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width">
<title>Basic Web Midi Api | BooleanEffect</title>
<link rel="canonical" href="https://booleaneffect.info/wmi.htm">
<meta name="Description" content="Basic WebMidiApi Sample OnLine PortON/OFF,Input,Output:: Only works in Chrome browser " />
<meta name="Keywords" content="Port,On,Off,Midi,midi,web midi api,input,output,WebMIDIAPI,Boolean.Effect" />
<!--Spcial Thanks cwilso/WebMIDIAPIShim -->
<!--WebMIDIAPIShimの読み込み<script src='http://cwilso.github.com/WebMIDIAPIShim/build/WebMIDIAPI.min.js'></script>エラー -->
<script src="js/WebMIDIAPI.min.js"></script>
<script>
/*WebMidiAPI 部分*/
var inputs=[], outputs=[], Pins=[], pinStatus=[], m=null;
var input, output;
/*SysEx許可 SSL接続が必要 orローカルでも可*/
window.onload=function(){
if(navigator.requestMIDIAccess) navigator.requestMIDIAccess({sysex:true}).then(onMIDIsuccess, onMIDIfailure);
else console.log("No MIDI support present in your browser.");
}
function $(id){ return document.getElementById(id); }
function onMIDIfailure(){
console.error('No access to your midi devices.');
alert('This Program only works in Chrome');
}
function onMIDIsuccess(midi){
m=midi;
var iIterator = midi.inputs.values();
for(var o=iIterator.next(); !o.done; o=iIterator.next()) inputs.push(o.value);
for(var i=0; i<inputs.length; i++) $("select1").appendChild(new Option(inputs[i].name),i+1);/*input*/
if(inputs.length!=0)document.getElementById('select1').selectedIndex=1;
if(inputs.length!=0)inputDeviceSelect();
var oIterator = midi.outputs.values();
for(var o=oIterator.next(); !o.done; o=oIterator.next()) outputs.push(o.value);
for(var i=0; i<outputs.length; i++) $("select2").appendChild(new Option(outputs[i].name),i+1);/*output*/
if(outputs.length!=0)document.getElementById('select2').selectedIndex=1;
if(outputs.length!=0)outputDeviceSelect();
}
/*MIDIポート確認*/
function inputDeviceSelect(){
inputs.forEach(function(port){
port.close();
})
var port=inputs[$("select1").selectedIndex-1];
if(port){
port.onmidimessage=onMIDIMessage;
port.open();
input=inputs[$("select1").selectedIndex-1];
}
readinput();
}
/*ポートの表示*/
function readinput(){
document.getElementById("log").innerHTML =""
/*時間を入れないと直前の値となる*/
function hogeinput(){
inputs.forEach(function(port){
console.log(port.id,port.name,port.state, port.connection );
document.getElementById("log").innerHTML = document.getElementById("log").innerHTML + "input: " + port.name +": " + port.connection + "<br>";
});
clearTimeout(setinput);
}
var setinput = setTimeout(hogeinput, 200);
}
function outputDeviceSelect(){
outputs.forEach(function(port){
port.close();
})
var port=outputs[$("select2").selectedIndex-1];
if(port) port.open();
output=outputs[$("select2").selectedIndex-1];
readoutput();
}
function readoutput(){
/*時間を入れないと直前の値となる*/
function hogeout(){
outputs.forEach(function(port){
console.log(port.id,port.name,port.state, port.connection );
document.getElementById("log").innerHTML = document.getElementById("log").innerHTML + "output: " + port.name +": " + port.connection +"<br>" ;
});
clearTimeout(setout);
}
var setout = setTimeout(hogeout, 200);
}
function onMIDIMessage( event ) {
var str=null;
var i,k;
/*IEで\n改行できないため<br>にした*/
/*アクティブセンシングよけ*/
if( event.data[0] == 0xFE ) return;
if( event.data.length>1) {
document.getElementById("log").innerHTML += " 0x" +( "00" + event.data[0].toString(16) + ":" ).slice( -3 );
for(i=1; i<event.data.length; i++){
document.getElementById("log").innerHTML +=" 0x" + ( "00" + event.data[i].toString(16) + ":" ).slice( -3 );
if(i%7==0){
document.getElementById("log").innerHTML +="<br>";
}
}
}
str =" __Data_Length=" +event.data.length+ ":"+ "<br>";
document.getElementById("log").innerHTML += str;
var obj = document.getElementById("log");
obj.scrollTop = obj.scrollHeight;
}
/*SendMIDI*/
function sendmidi(){
var midievent=document.getElementById("out").innerHTML;
var len=midievent.length;
var str;
if(len==0) return;
var sysex=Array(1000);
var j=0;
for(var i=0; i<len; i++){
str="0x";
str+=midievent.substr(i,2);
sysex[j]=parseInt(str);
i+=2;
j++;
}
sysex.length=j;
output.send(sysex);
}
</script>
<style>
html,body{
height: 100%;
margin:15px;
}
#log{
border: 1px solid #999;
overflow: auto;
width:100%;
max-width: 430px;
height: 40%;
}
#out{
border: 1px solid #999;
width:100%;
max-width: 430px;
height: 20%;
overflow:auto;
}
</style>
</head>
<body>
<h2>Basic_Web_Midi_Api</h2>
<p style="color:red;"> Only works in Chrome Browser</p>
<div id ="inp" style="inline;">
<p style="display:inline; margin-right:13px;">INPUT :</p>
<label for="select1" class="select-1">
<select class="ids" id="select1" onChange="inputDeviceSelect(this);">
<option value="0">No Device
</select>
</label>
</div>
<p style="display:inline">OUTPUT:</p>
<label for="select2" class="select-1">
<select class="ids" id="select2" onChange="outputDeviceSelect(this);">
<option value="0">No Device
</select>
</label>
<br><br>
<div id="log">Input</div>
<button onclick=readinput(),readoutput()>OpenClose check</button>
<br><br>
<div id ="out" contenteditable="true">C0 00</div>
<button onclick=sendmidi()>SendMidi</button>
<br><br>
<hr>
<a href="wmiinfo.htm" class="menu--link" title="WebMidiApiInfo">WebMidiApiInfo</a>
<div align=right>BooleanEffect</div>
</body>
</html>
参考リンク Spcial thanks
WebMidiApiの実験室Web Midi APIのテスト
メインのコードは上記を参考にしました。
WebMIDIAPIShimJazz-Soft.net