JavaScriptだけでMIDIで遊べる！最高に乱暴なWeb MIDI API利用方法

# JavaScriptだけでMIDIで遊べる！最高に乱暴なWeb MIDI API利用方法

[Web MIDI API / Web Audio APIを使ったハッカソンイベント「Web Music ハッカソン #3」](http://googledevjp.blogspot.jp/2014/08/web-music-3.html)が近づいていますので、ここでWeb MIDI APIの使い方を振り返ってみましょう。

はじめに断っておきますが、これは **乱暴者による乱暴者向けの記事**です。
**最低限の手間で、Web MIDI APIに対応してる気分を味わう** までを目指します。

> [2015/02/08 追記]
> さらに手間をかけたくないという超絶手抜きな人（ワシです）向けに、[アホみたいなラッパー(poormidi.js)](https://github.com/tadfmac/poormidi)作りました。
>
> - [使い方](http://qiita.com/tadfmac/items/d93d82599eefeb8f0044)
>
> 良かったら使ってみてください。

ちゃんと勉強したい方は、下記リンクを見てください。

## ちゃんと勉強したい方向けリンク集

### [Web MIDI API (W3C)](http://www.w3.org/TR/webmidi/)

Web MIDI APIの仕様はW3Cで策定中です。（2014年8月25日現在、Working Draft版です）

### [Web MIDI API (日本語訳)](http://g200kg.github.io/web-midi-api-ja/)

[shinyagaitoさん](http://www.g200kg.com/)によるWeb MIDI API仕様の日本語訳です。

### [Code Labs](https://github.com/ryoyakawai/WebMusicDevelopersJP/tree/master/codeLabs)

@ryoyakawaiさんによるWeb Audio APIとWeb MIDI APIのチュートリアルです。

## Chromeで動かそう

それでははじめましょう。

Web MIDI APIが動くブラウザは、2014年8月25日現在Chromeだけですが、今回は、[Polyfill](https://github.com/cwilso/WebMIDIAPIShim)を使わず、Chromeしか動かなくていーやー。な乱暴な感じで行きます。

ブラウザ差分考えなくていいからいいよね！？w

### Chromeの Web MIDI API機能を有効にするための設定

対応してる風なChromeですが、まだ試験運用のようで、Web MIDI API機能はデフォルトでは無効になっているようです。
ブラウザのアドレスバーから、`chrome://flags`と入力して設定画面を呼び出して、`midi` で検索を行い、「Web MIDI API を有効にする」欄をチェックして有効にしてください。（Chromeの再起動が必要）

また、MIDI機器を繋いだ後も、ブラウザの再起動が必要です。

## MIDIを有効にする。`requestMIDIAccess()` 

はじめに。

Web MIDI APIを使うには、最初に`navigator.requestMIDIAccess()`を呼び出して、Web MIDIを有効にします。

```js
navigator.requestMIDIAccess().then(onMIDISuccess,onMIDIFailure);
```

`.then()`の第1パラメータに、MIDI使える時に呼び出されるCallback関数を、第2パラメータにエラー時のCallback関数を指定しましょう。

## 成功を祈りつつ。`onMIDISuccess()` (Chrome v39以降用に書き換え)

続けて、MIDI有効に出来た時に呼び出される`onMIDISuccess()`を書いてみます。

```js
var midi = null;
var inputs = [];
var outputs = [];

function onMIDISuccess(m){
  midi = m;
  var it = midi.inputs.values();
  for(var o = it.next(); !o.done; o = it.next()){
    inputs.push(o.value);
  }
  var ot = midi.outputs.values();
  for(var o = ot.next(); !o.done; o = ot.next()){
    outputs.push(o.value);
  }

  for(var cnt=0;cnt < inputs.length;cnt++){
    inputs[cnt].onmidimessage = onMIDIEvent;
  }
}
```

乱暴者らしく、どのポートに来ても全部同じ処理ですw
さらに、`onMIDIFailure()`の方は空っぽですw

```js
function onMIDIFailure(msg){
  console.log("onMIDIFailure()呼ばれただと？:"+msg);
}
```

こんな感じで良いはずです。（適当w）

## onmidimessageに登録する関数を書く。

もう少しです。続けてMIDI信号を受け取った時の処理を書きましょう。
先ほど`inputs[cnt].onmidimessage`に指定した`onMIDIEvent()`です。

```js
function onMIDIEvent(e){
  if(e.data[2] != 0){ 
    // なにかをうけとったときの処理
  }
}
```

これは、**乱暴者らしさを強調する** 恐ろしく手抜きな処理です！w

**たぶんNote ONと Note OFFしか来ないからVelocityが0以外だったらNoteONと見なして処理しよう。**
という作戦です。

こんなんじゃヤダ！という正常な人は、[g200kgさんのDTM技術情報>1.MIDIメッセージ一覧](http://www.g200kg.com/jp/docs/tech/midi.html)でも見て、ちゃんと書きましょう。

## 送信にも対応する

最後に、MIDI送信にも対応しましょう。
もちろん **乱暴さ** を最後まで徹底したいので、**1コ目の機器決め打ちで適当なノートONを送りつける** という処理にします。

```js
function sendMIDINoteOn(note){
  if(outputs.length > 0){
    outputs[0].send([0x90,note,0x7f]);
  }
}
```

出来ました！

これを、`<button>`タグとかの`onClick`とかで呼び出せば、MIDI機器が鳴ってくれます！

しかし、ここでも **超乱暴な仕掛** けが。
ノートOFFが無いので、多くの機器では **鳴りっぱなし** になるはずです。
もちろん、乱暴者は、**機器側の電源を切る** などの乱暴な対応で乗り切ってください。

## 完成。（Chrome v39対応）

> ※以下のコードは、Chrome v39.0以降用に書き換えています。(2014/11/09)

```js
navigator.requestMIDIAccess().then(onMIDISuccess,onMIDIFailure);

var midi = null;
var inputs = [];
var outputs = [];

function onMIDISuccess(m){
  midi = m;
  var it = midi.inputs.values();
  for(var o = it.next(); !o.done; o = it.next()){
    inputs.push(o.value);
  }
  var ot = midi.outputs.values();
  for(var o = ot.next(); !o.done; o = ot.next()){
    outputs.push(o.value);
  }

  for(var cnt=0;cnt < inputs.length;cnt++){
    inputs[cnt].onmidimessage = onMIDIEvent;
  }
}

function onMIDIFailure(msg){
  console.log("onMIDIFailure()呼ばれただと？:"+msg);
}

function onMIDIEvent(e){
  if(e.data[2] != 0){
    // なにかをうけとったときの処理
  }
}

function sendMIDINoteOn(note){
  if(outputs.length > 0){
    outputs[0].send([0x90,note,0x7f]);
  }
}
```

簡単！w

## まとめ

乱暴者にもWeb MIDI APIなら使えるよ！

こんな感じで。
[ち〜んタイマー](http://mz4u.net/timer/)

> **2022/11/02更新**
> もともとの記事に記載していた「フィジカルWebアプリち〜ん」の運用が停止したため、「ち〜んタイマー」にリンクを置き換えました。
> 「ち〜んタイマー」は、ベルを鳴らすMIDIデバイス「ち〜ん」がつながってれば、タイムアップ時にMIDIデバイスのベルが鳴り、つながっていなくても、Web Audioでベルの音が鳴る「ある意味拡張現実（AAR）」アプリです。