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