Edited at

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

More than 3 years have passed since last update.


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

Web MIDI API / Web Audio APIを使ったハッカソンイベント「Web Music ハッカソン #3」が近づいていますので、ここでWeb MIDI APIの使い方を振り返ってみましょう。

はじめに断っておきますが、これは 乱暴者による乱暴者向けの記事です。

最低限の手間で、Web MIDI APIに対応してる気分を味わう までを目指します。


[2015/02/08 追記]

さらに手間をかけたくないという超絶手抜きな人(ワシです)向けに、アホみたいなラッパー(poormidi.js)作りました。

良かったら使ってみてください。


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


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


Web MIDI API (W3C)

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


Web MIDI API (日本語訳)

shinyagaitoさんによるWeb MIDI API仕様の日本語訳です。


Code Labs

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


Chromeで動かそう

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

Web MIDI APIが動くブラウザは、2014年8月25日現在Chromeだけですが、今回は、Polyfillを使わず、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を有効にします。

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

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


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

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

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

function onMIDIFailure(msg){

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

こんな感じで良いはずです。(適当w)


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

もう少しです。続けてMIDI信号を受け取った時の処理を書きましょう。

先ほどinputs[cnt].onmidimessageに指定したonMIDIEvent()です。

function onMIDIEvent(e){

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

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

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

という作戦です。

こんなんじゃヤダ!という正常な人は、g200kgさんのDTM技術情報>1.MIDIメッセージ一覧でも見て、ちゃんと書きましょう。


送信にも対応する

最後に、MIDI送信にも対応しましょう。

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

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)


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なら使えるよ!

こんな感じで。

ち〜ん