2014年11月10日月曜日

BLE MIDIのAndroid向けライブラリを作っています

iOS 8での新機能、MIDI over Bluetooth LEの最初のデバイス「mi.1」がindiegogoにて発表されていたので、早速投資して3つポチりました。


その後、ブツが届いたのはいいのですがファームウェアが導入されておらず、実際に使えるようになるまでにしばらく掛かりました。
製品版ではファームウェア書き込み済の状態で出荷しないとユーザが混乱しそうです。

まだmi.1が届いていないうちから、Android 4.3にて追加されたBluetooth LEのAPIを使ってMIDIっぽい通信をするライブラリを書いていました。
Appleが仕様を作るとして、極力既存のMIDIと互換を持たせたシンプルな形に実装するだろう、おそらくBluetooth LEにレガシMIDIのデータをそのまま垂れ流す程度のものだろう、などと想像しつつ先行して実装していました。
mi.1のファームウェアを更新した後、受信したデータをログに出したりしつつプロトコルを調整して、受信までは動作確認できました。

というわけで、まだ道半ばですが現状報告な感じで。

BLE MIDIのプロトコル(解析・検証中)

BLEデバイスの設定

BLEの受信データは1パケットあたり最長で20bytesです。これを連続して投げることでシリアル通信のようなことを実現できます。
BLEのCharacteristic(送受信に使われる通信路のようなもの)の種別はいくつかあるのですが、他のいくつかのシリアル通信系のBLEデバイスを参考にしたところ
  • BLEデバイス→Androidデバイス:Notify
  • Androidデバイス→BLEデバイス:Write without Response
となっていました。mi.1では、1つのChacteristicでこの2種類を兼ねているようです。

データの内訳

mi.1から受信されたデータを眺めると、先頭の2バイトはヘッダ情報のようでした。
ノートONの場合:
    0x80 0x80 0x90 0x24 0x7f ← この部分がMIDIのノートONメッセージ
という感じでした。

ノートオン・オフやプログラムチェンジなどの短いメッセージの場合、先頭2バイトは「0x80 0x80」で固定されているようでした。どういう時にこの部分の変化があるかは、いろいろテストしてみて検証していきます。
System Exclusiveなど長いデータの場合にデータがどう受信されるかも試せていません。
後日、サクっとデバッグ用デバイスを作ってテストしてみます。

作成したデバッグ用デバイス
ArduinoとSparkFunのMIDI Shieldを使って、

  1. MIDI ShieldでMIDIを送信
  2. Androidで受信したMIDIデータを解釈、同じ内容のデータを生成して返信
  3. MIDI Shieldで受信して、データが送ったものと一致することを確認する

というデバイスを作ってみました。MIDI ShieldはMIDI Outの中央のピンをGNDに接続して5Vが取れるように修正してあります。mi.1のケーブルがUSBのソケットと干渉して結構厳しいです。
やはりこういうツールは作ってみると便利で、いくつかバグがあったのを発見できました。

というかプロトコル仕様がどこかに公開されていれば、こんな苦労は必要ないのに

サンプルアプリ

USB MIDI Driver for Androidと同様のアプリを実装しました。
MIDI送受信と、ログ表示機能と、演奏機能が実装されています。
一通りの動作検証が終わったら、Google Playにて公開します。

ソースコード

最新版のコードをgithubに置いています。絶賛開発中のため、developブランチ上にあります。
https://github.com/kshoji/BLE-MIDI-for-Android/tree/develop

注意
現時点では、受信タイムラグが相当あってそのバラ付きもあるので、リアルタイム演奏できないクオリティです。
ラグの原因がAndroidライブラリ側なのかmi.1側なのかも切り分けできていません。
→その後、実際の楽器(電子ピアノ)で試してみたところ、わりとリアルタイムにイベントが飛んでいるようでした(2014/11/14追記)

ちなみに:Windows 8.1向けライブラリ

Windows 8.1の.NET FrameworkにもBluetooth LEのAPIがあって、そちら向けのライブラリ開発もしていたのですが、「データを連続して受信したときに受信イベントハンドラの呼ばれる順番がバラバラになる」という致命的な欠陥にぶつかったため、ライブラリ開発は頓挫しています。
Microsoft先生の次回作(Windows 10)に期待しています。
リポジトリはこちら。
https://github.com/kshoji/BLE-MIDI-for-.NET/tree/develop

今後の予定

以下のような機能追加・修正を予定しています。
  • MIDI送受信処理を全体的にテスト・デバッグします。
    • →mi.1が15バイト以上の長さのSysExを受け付けない(無視する)ようなので、そのテストができていません。それ以外の全てのMIDI機能はテストしてデバッグが完了しています(2014/11/13追記)。
    • mi.1→Android方向に高頻度にデータを送信すると、たまに情報抜けが起きています(2014/11/13追記)。
  • Android 5.0(Lollipop)で追加された新API、Bluetooth LE Peripheral機能を使って、AndroidデバイスがBLE MIDIデバイスをエミュレーションできるようにしていきます。
    • Preview版のLollipopを入れたら、Nexus 5もNexus 7もPeripheral非対応になったので頓挫しています。Issueには登録済で開発者も認識しているようなのでリリース版では使えるようになっている…かもしれません。 →Lollipop正式版がリリースされましたが、Nexus 5も7もPeripheralが使えませんでした(2014/11/13追記)。
  • Serviceとして使えないかを検証して、サンプルアプリを記述します。