2012年12月20日木曜日

Second Web MIDI API Working Draft のサンプルコード レビュー

Web Music Developers JPのアドベントカレンダーの記事です。(12月20日)

追記:Web MIDI APIの仕様は日に日に更新されています。2013年1月8日の段階で既にこの説明の説明からは変更されていますのでご注意ください。

前回は「Second Web MIDI API Working Draftのレビュー」を行いました。今回はWeb MIDI APIのWorkingDraft 第二版の末尾にあるサンプルコードのレビューを行います。とてもシンプルで分かりやすいサンプルコードになっていてとても参考になると思います。

ではさっそくレビューにはいります。

MIDI機器を取得
MIDI機器を扱う為の準備。
 1.| var midi = null;  // global MIDIAccess object
 2.|
 3.| function onMIDISuccess( midiAccess ) {
 4.|  console.log( "MIDI ready!" );
 5.|  midi = midiAccess;  // store in the global 
 6.| }
 7.|
 8.| function onMIDIFailure(msg) {
 9.|   console.log( "Failed to get MIDI access - " + msg );
10.| }
11.|
12.| navigator.getMIDIAccess( onMIDISuccess, onMIDIFailure );
getMIDIAccessメソッド成功時のcallback関数をonMIDISuccess[3-6行目]とする。onMIDISuccessでGlobal変数midi[1行目]にインターフェイスMIDIAccessを代入[5行目]。getMIDIAccessメソッドがエラーとなった場合のcallback関数としてonMIDIFailure[8-9行目]をと指定。

MIDI機器のリストアップ
MIDI入力元、出力先を指定する為にリストアップ。
 1.| function enumerateInputsAndOutputs( midiAccess ) {
 2.|  var inputs = midiAccess.enumerateInputs();
 3.|  var outputs = midiAccess.enumerateOutputs();
 4.|  var i;
 5.|
 6.|  for (i=0; i<inputs.length; i++) {
 7.|   console.log(inputs[i]);
 8.|  }
 9.|
10.|  for (i=0; i<outputs.length; i++) {
11.|   console.log(outputs[i]);
12.|  }
13.| }
インターフェイスMIDIAccessのメソッドenumerateInputs[2行目]/enumerateOutputs[3行目]を実行してMIDI機器のリストを取得して入力機器、出力機器を別々にconsole.logでデバッガのWebコンソールに出力[入力機器:6-8行目、出力機器:10-12行目]

MIDIの入力信号を処理
受け取ったMIDI信号を処理。
 1.| function onMIDIMessage( event ) {
 2.|   var str = "MIDI message received at timestamp " + event.timestamp + "[" +
   |                event.data.length + " bytes]: ";
 3.|   for (var i=0; i<event.data.length; i++)
 4.|     str += "0x" + event.data[i].toString(16) + " ";
 5.|   console.log( str );
 6.| }
 7.| 
 8.| function startLoggingMIDIInput( midiAccess, indexOfPort ) {
 9.|   var input = midiAccess.getInput( indexOfPort );
10.|   input.onmessage = onMIDIMessage;
11.| }
インターフェイスMIDIAccessのメソッドgetInputで入力機器を指定して取得[9行目]し、MIDIメッセージを受信した場合のcallback関数(onmessage)をonMIDIMessageに指定[10行目]
関数onMIDIessageは、MIDI入力を16進数変換してconsole.logでデバッガのWebコンソールに出力。

MIDIの出力ポートからMIDI信号を出力
MIDI信号を送信。
 1.| function sendMiddleC( midiAccess, indexOfPort ) {
 2.|   var output = midiAccess.getOutput( indexOfPort );
 3.|   output.send( [0x90, 60, 0x7f] );
   |    // note on, middle C, full velocity - omitting the timestamp means send immediately.
 4.|   output.send( [0x80, 60, 0x40], window.performance.now() + 1000.0 );
   |    // note off, middle C, release velocity = 64, 
   |    // timestamp = now + 1000ms.
 5.| }
インターフェイスMIDIAccessのメソッドgetOutputで出力機器を指定して取得[2行目]し、即座(timestampなし)に[90 60 7f]を実行するようMIDIメッセージを送信[3行目]、次に1000ms後に[80 60 40]が実行されるようMIDIメッセージを送信[4行目]
# [90 60 7f]:「MIDIポート1のC4を127の音量で発音する」というMIDIメッセージ
# [80 60 40]:「MIDIポート1のC4を64の速度(機器によって異なる)で発音を停止する」というMIDIメッセージ
RunningStatusの送信は許可されていません。

MIDIの入力機器から受信したMIDIメッセージを出力機器へ送信するLoopback
 1.| var midi = null;  // global MIDIAccess object
 2.| var output = null;
 3.| 
 4.| function echoMIDIMessage( event ) {
 5.|   if (output)
 6.|     output.send( event.data, event.timestamp );
 7.| }
 8.| 
 9.| function onMIDISuccess( midiAccess ) {
10.|   console.log( "MIDI ready!" );
11.|   try { 
12.|     var input = midiAccess.getInput( 0 );
13.|     output = midiAccess.getOutput( 0 );
14.|     input.onmessage = echoMIDIMessage;
15.|   }
16.|   catch (e) {
17.|     console.log("Exception! Couldn't get i/o ports." + e );
18.|   }
19.| }
20.| 
21.| function onMIDIFailure(msg) {
22.|   console.log( "Failed to get MIDI access - " + msg );
23.| }
24.| 
25.| navigator.getMIDIAccess( onMIDISuccess, onMIDIFailure ); 
インターフェイスMIDIAccessを代入するGlobal変数midiを初期化[1行目]。
インターフェイスMIDIAccessのメソッドgetOutputで取得するインターフェイスMIDIOutputを代入するGlobal変数outputを初期化[2行目]。
getMIDIAccessメソッド成功時のcallback関数をonMIDISuccess[9-19行目]とする[25行目]。
onMIDISuccessでは、getInputで先頭ににリストアップされた入力機器を取得[12行目]、getOutputで先頭ににリストアップされた出力機器取得[13行目]MIDIメッセージを受信した場合のcallback関数としてechoMIDIMessageを指定[14行目]
echoMIDIMessageでは、選択した入力機器から受信したMIDIメッセージをそのまま選択した出力機器へ送信[6行目]。

というのがサンプルコードになります。
これでかなりイメージが湧くかな、と思います。

そして、Web MIDI APIの編集者の1人であるChris Wilsonさんが公開くださっているプラグインを使ったエミュレーションライブラリ(Polyfill)を実際に使って簡単なMIDI INのみのデモを作ってみましのた!!動作にはUSB-MIDIキーボードとJazz SoftのJazz-Pluginのインストールが必須となります。こんなに簡単にUSB-MIDI機器がブラウザにつながってしまう世の中になるのか〜、って思うとワクワクしちゃいます!

デモはこちらです!

それでは次回Web Music Developers JPのAdventCalenderの最終日は、MIDI OUTなデモが作成できたらな〜、と考えています!(作成できなかった場合、すみません。。。)