Arduinoを使ってWeb MIDI APIから制御可能なUSB MIDIデバイスを自作する（MIDIUSB編）

Web MIDI APIで楽器やMIDIコンと連携するWebアプリが作れるようになりました。
しかし、そうなってくると、Webアプリと連携する「自作」MIDIデバイスも作りたくなるものですね（強引）

今回は、[MIDIUSB](https://github.com/arduino-libraries/MIDIUSB)を使ってUSB MIDIデバイスを作ってみようと思います。

> Web Audio APIや Web MIDI APIの記事じゃなくてごめんなさい。。。

# おさらい。いろんなArduinoでのUSB MIDIデバイス自作環境

[MIDIUSB](https://github.com/arduino-libraries/MIDIUSB)の話に入る前に、ArduinoでUSB MIDIデバイスを自作する方法についておさらいしてみましょう。

1. Arduino UNO R3
2. Arduino Leonardo / Arduino Micro / Sparkfun Pro Micro など
3. Arduino Zero (arduino.cc) / Arduino M0 Pro (arduino.org) など
4. 番外編 mi:muz

> なんか変なのが混ざってますがw 気にしないw

## 1. Arduino UNO R3 と [MocoLUFA](https://github.com/kuwatay/mocolufa)、[Arduino MIDI Library](http://playground.arduino.cc/Main/MIDILibrary)

Arduinoで一番有名なArduino UNO。
このボードはATmega328PとATmega16u2という2つのMCが搭載されています。(R3の場合)

Arduinoを USB MIDIデバイスにするには、下記手順で行います。

1. [Arduino MIDI Library](http://playground.arduino.cc/Main/MIDILibrary)というシリアルMIDIに対応させるためのライブラリを使ってArduinoのスケッチをATmega328P側に書き込む
2. [MocoLUFA](https://github.com/kuwatay/mocolufa)というUSB MIDIとシリアルMIDIを変換するファームウエアを、ATmega16u2側に書き込む。
3. MIDIモードで起動（ATmega16u2のISPピンのジャンパーで選択）

Arduino UNOでは今回書く[MIDIUSB](https://github.com/arduino-libraries/MIDIUSB)は利用できません。

上記方法でUSB MIDIデバイスを作りましょう。

参考：

- [Arduino Moco LUFA](https://webmusicdevelopers.appspot.com/codelabs/arduino-mocolufa/index.html?ja-jp)
- [Arduino UNOで作る一番簡単なMIDI音源](http://qiita.com/tadfmac/items/443207986039f48c578a)

## 2. Arduino Leonardo互換ボード と [rkistner/arcore](https://github.com/rkistner/arcore)

ATmega32u4が搭載されたArduino Leonardoとその互換ボードたち。

- [Arduino Micro](https://www.arduino.cc/en/Main/ArduinoBoardMicro)
- [Sparkfun Pro Micro](https://www.sparkfun.com/products/12640)
- [よくわからん互換風ボード](http://www.ebay.com/itm/321822531477)

これらのボードには、ATmega32u4が搭載されています。このMC、USBペリフェラルに対応しているため、UNOのようにシリアル変換を行う必要がありません。

Arduino Leonardoと互換ボード向けのUSB MIDI対応環境として、[rkistner/arcore](https://github.com/rkistner/arcore)があります。

参考：

- [Arduino Leonardo/MicroでもMIDI使いたい。](http://qiita.com/tadfmac/items/d685dae3e46d570386c3)

[rkistner/arcore](https://github.com/rkistner/arcore)は、arduinoのcoreに直接USB-MIDI機能を追加するもので、ライブラリとは違った形でMIDIの機能を組み込むことができます。
しかし、この環境。更新が止まっているため、新しいIDEやボードへの対応が気がかりです。

新しい環境では今回紹介する[MIDIUSB](https://github.com/arduino-libraries/MIDIUSB)を使った方が良いかもしれません。

## 3. Arduino Zero / Arduino M0 Pro (Arduino.org) など

ATSAMD21が搭載されたARM Cortex M0版のArduinoです。
こちらもUSBペリフェラルに対応しているため、直接USB MIDIデバイス化することができます。

今回紹介する[MIDIUSB](https://github.com/arduino-libraries/MIDIUSB)が対応しているようですが、残念ながら **ボードを持っていない！** ので今回検証はできません。

> 検証してくれる方募集中〜！

## 4. 番外編 [mi:muz](https://github.com/tadfmac/mi-muz)

[mi:muz](https://github.com/tadfmac/mi-muz)は、[V-USB](https://www.obdev.at/products/vusb/index.html)などOSSの資産を生かして私が開発しているMIDIデバイス開発環境です。
OSSでハード設計情報、Arduino向けライブラリ、サンプルスケッチ等を公開しています。

ATtinyなどUSBペリフェラルを持たない安価なMCでMIDIデバイスを作ることができますが、USB MIDIデバイス作成環境としてみた場合には、PCとの相性問題や、USBハブを経由して接続すると認識しなくなる等、ソフトウエアでUSBに対応しているが故の制約も多い環境です。

## 5. 番外編 Arduino Pro miniとか、nanoとか

Arduino Pro miniやnanoなど、ATmega328のみ搭載したArduinoは、USBペリフェラルがありません。
一応、前述の[V-USB](https://www.obdev.at/products/vusb/index.html)などを使って頑張ればUSB MIDIに対応可能です。でも少しハードルが高い。

これらのボードの場合、あえてUSBではなく[Arduino MIDI Library](http://playground.arduino.cc/Main/MIDILibrary)を使ったシリアルMIDIデバイスを作るのが良いとおもいます。

5DINケーブルで繋ぐデバイスを制作されたい方はこちらで良いと思います。

## 各環境の特徴まとめ

一応、これまでの内容をまとめてみました。
今からArduinoを買ってMIDI Device作ってみよう！という方は参考にしてみてください。

|No.|環境|対応ボード|特徴|
|:---:|:----|:---|:---|
|1|MocoLUFA + Arduino MIDI Library|Arduino UNO R3|USB-MIDIとメインプログラム部分でMCが分離しているため安定性抜群。またSysEx等MIDIの多くの機能に対応している。一方でArduino UNOにしか対応しないので、小さなデバイスが作れないのが難点|
|2|arcore|Arduino Leonardoと互換ボード|Arduino MicroやSparkfun Pro Micro等小さなボードに適用できるのがメリット。ただしCoreを追加する形式のためArduino IDEのUpdateに追従するのが難しい。Updateが止まっており最新環境での対応に不安が残る|
|3|MIDIUSB|Arduino Leonardoと互換ボード、Arduino ZERO, M0等|最新のATSAMD21搭載ボードにも対応しており、Arduinoの標準ライブラリの位置づけで更新されている。ただし、UNO等では使えない|
|4|mi:muz|ATtinyx4,x5,x41,ATmega8等|USB MIDIだけでなく I2C上のMIDI伝送にも1ライブラリで対応しているが、実質mi:muzボードでしか使えない。また、USB3.0やUSBハブでの動作が不安定なのも×|

基本的には、UNOを買ったら 1. それ以外の方は 3. でいいんじゃないか？と思っています。

# MIDIUSBライブラリを使ってみる

それでは、Arduinoの[MIDIUSB](https://github.com/arduino-libraries/MIDIUSB)ライブラリを使ってみることにします。

## 用意するもの

- PC (今回はMac前提で書きます。) Arduino IDEが動作するもの。インターネット接続環境
- Arduino Leonardo互換機 私はSparkfun Pro Microの互換機で試してみます。
- PCとArduinoを接続するUSBケーブル（※充電ケーブルだと通信できないので注意!）

## 導入

[Arduino IDE](https://www.arduino.cc/en/Main/Software)をダウンロード、インストールしてください。今回は Arduino 1.6.13を使いました。

つぎに、`https://github.com/arduino-libraries/MIDIUSB` からライブラリをダウンロードしてください。

zipファイルを解凍して、`MIDIUSB`というフォルダ名にリネームします。

`MIDIUSB`はArduinoライブラリですので、下記いずれかの方法で導入可能です。

1. ドキュメント配下のlibrariesフォルダに`MIDIUSB`を入れる

    `~/Documents/Arduino/libraries` に入れます。

2. Arduino.app配下のlibrariesフォルダに`MIDIUSB`を入れる

    `/Applications/Arduino.app/Contents/Java/libraries/` に入れます。

複数のArduino.appを入れている場合、全てのArduino.appでライブラリを有効にするには、上記1.の入れ方が良いです。
一方で、特定のArduino.appだけで使いたい場合には、2. の入れ方にしましょう。

フォルダのコピーが終わったら一度Arduino IDEを再起動してください。

## exampleを確認

Arduinoへのライブラリの導入が成功していれば、File>Examplesの中に`MIDIUSB`が追加されています。

![example.png](https://qiita-image-store.s3.amazonaws.com/0/31758/ffbda95e-f790-ff58-fa9b-c8fe5b948cd1.png)

exampleの何かを実行してもいいのですが、ここではMIDI Note ON/OFFでLチカするサンプルを実行してみましょう。

```midiusb_test.ino
#include "MIDIUSB.h"

#define LED_PIN 2 // Pro Micro用。Leonardoなら 13

void setup() {
  pinMode(LED_PIN,OUTPUT);
}

void loop() {
  midiEventPacket_t midievent;
  midievent = MidiUSB.read();
  if(midievent.header != 0){
    if((midievent.byte1 & 0xf0)== 0x90){
      if(midievent.byte3 != 0){
        digitalWrite(LED_PIN,HIGH);
      }else{
        digitalWrite(LED_PIN,LOW);
      }
    }else if((midievent.byte1 & 0xf0)== 0x80){
      digitalWrite(LED_PIN,LOW);
    }
  }
}
```

このスケッチをArduinoに書き込みましょう。まずは、ボードを選ぶところから。

Tools>Board から、Arduinoボードを選んでください。

私は今回Arduino Leonardoだ！と言い張るSparkfun Pro Microの互換ボードを利用していますので、下記のように表示されました。

![board.png](https://qiita-image-store.s3.amazonaws.com/0/31758/1fb35916-988b-1ddb-fbef-9e90d049300e.png)

次に、ポートも選びます。

![port1.png](https://qiita-image-store.s3.amazonaws.com/0/31758/b6fb04d1-8fe0-7196-9b3f-f166dbc8810b.png)

これで書き込み準備ができました。
Arduino IDEの`→`ボタンを押して書き込みましょう。

![write.png](https://qiita-image-store.s3.amazonaws.com/0/31758/acdbb63a-0014-1ec3-ccb0-ab35809a34bf.png)

書き込みがうまくいくと、下記のように表示が変わります。
USB MIDIデバイスのできあがりです！

![port2.png](https://qiita-image-store.s3.amazonaws.com/0/31758/681aeb87-290e-0a9e-164b-5a0a1602af63.png)

# ブラウザからテスト

さて、なんとかLチカMIDIデバイスが出来ましたので、最後にブラウザからテストしてみましょう。
Web MIDI APIを手抜きして使う[poormidi.js](https://github.com/tadfmac/poormidi)を利用します。

`poormidi.js`と、下記`index.html`をlocalhost配下の同じディレクトリに置いてください。
(Webサーバーをlocalhostに立てておいてください)

```index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>MIDIUSB Test (Lチカ)</title>
<style>
  button{font-size:32px;width:200px;height:100px;}
</style>
<script src="poormidi.js"></script>
<script>
var midi = new poormidi();
var interval = null;
var onOff = 0;
function startBlink(){
  if(interval){
    clearInterval(interval);
    interval=null;
  }
  interval = setInterval(function(){
    onOff ^= 1;
    if(onOff){
      midi.sendNoteOn(40,100);
    }else{
      midi.sendNoteOff(40);
    }
  },1000);
}
function stopBlink(){
  if(interval){
    clearInterval(interval);
    interval=null;
  }
  midi.sendNoteOff(40);
}
</script>
</head>
<body>
<h1>MIDI経由でLチカ</h1>
<button id="start" onclick="startBlink()">start</button>
<button id="stop" onclick="stopBlink()">stop</button>
</body>
</html>
```

さきほどのMIDI経由Lチカスケッチを書き込んだArduinoをPCのUSBに繋いでから、Web MIDI APIに対応したChromeかOperaから上記`index.html`を開きます。

ボタンが2つだけのアホみたいなページが表示されますw

ここで、`start`をクリック後、Arduino側がLチカしたら成功です！
単なるLチカですが、MIDI経由でのLチカです。

めちゃくちゃシンプルなMIDIデバイスの完成ですw

# まとめ

- Arduino Leonardo互換のArduinoでは[MIDIUSB](https://github.com/arduino-libraries/MIDIUSB)を使って簡単にMIDIデバイスがつくれます
- Web MIDI APIからMIDIデバイスのテストが簡単にできます


それでは、よいクリスマスを！