MIDI over BLE を試してみる（CoreAudioKit）

本記事は [Bluetooth Low Energy Advent Calendar 2014](http://qiita.com/advent-calendar/2014/ble) の1日目の記事となります。


##MIDI over Bluetooth LE とは？

今までこうだったのが、

![midi_0_r1_c1.jpg](https://qiita-image-store.s3.amazonaws.com/0/3180/03796902-2a50-c6fc-2c9e-5d3d469ce205.jpeg)


MIDI over BLE によって、こうなります。

![midi_1_r1_c1.jpg](https://qiita-image-store.s3.amazonaws.com/0/3180/f25515cc-af88-a908-4f6f-4a068b187f39.jpeg)


どういうことかというと、**BLEを使ってワイヤレスでMIDIを送受信できる**、ということです。

接続してしまえば、**普通のMIDI機器と同等**に取り扱えます。


##CoreAudioKit

**iOS 8 で新規追加**されたフレームワーク。

iOS Dev Centerで "CoreAudioKit" で検索しても 「**No Documents Found**」と言われてしまう（2014年12月1日現在）、謎に包まれたフレームワークです。

![midi_2.jpg](https://qiita-image-store.s3.amazonaws.com/0/3180/37ecf30c-b4e8-5ca5-ec82-ba1b52ec1bf4.jpeg)


個々のクラス名で検索するとかろうじていくつかのドキュメントが引っかかってきますが、その中でちょっとでも全容把握に役立ちそうなのは「iOS 8.0 API Diffs」だけ。。


###CoreAudioKit の 全API

**クラスは4つしかない**ので、ここに「iOS 8.0 API Diffs」に載っていた全APIを載せておきます。


####CABTMIDICentralViewController.h

- CABTMIDICentralViewController

####CABTMIDILocalPeripheralViewController.h

- CABTMIDILocalPeripheralViewController

####CAInterAppAudioSwitcherView.h

- CAInterAppAudioSwitcherView
- -[CAInterAppAudioSwitcherView contentWidth]
- -[CAInterAppAudioSwitcherView setOutputAudioUnit:]
- CAInterAppAudioSwitcherView.showingAppNames

####CAInterAppAudioTransportView.h

- CAInterAppAudioTransportView
- CAInterAppAudioTransportView.connected
- CAInterAppAudioTransportView.currentTimeLabelFont
- CAInterAppAudioTransportView.enabled
- CAInterAppAudioTransportView.labelColor
- CAInterAppAudioTransportView.pauseButtonColor
- CAInterAppAudioTransportView.playButtonColor
- CAInterAppAudioTransportView.playing
- CAInterAppAudioTransportView.recordButtonColor
- CAInterAppAudioTransportView.recording
- CAInterAppAudioTransportView.rewindButtonColor
- -[CAInterAppAudioTransportView setOutputAudioUnit:]


##iOS側の実装

まず CoreAudioKit を import して、

```
@import CoreAudioKit;
```


CABTMIDICentralViewController, CABTMIDILocalPeripheralViewController というビューコントローラに遷移できるように実装しておきます。

```
- (IBAction)centralBtnTapped:(id)sender {
    
    CABTMIDICentralViewController *midiCentralCtr = [[CABTMIDICentralViewController alloc] init];
    [self.navigationController pushViewController:midiCentralCtr animated:YES];
}

- (IBAction)peripheralBtnTapped:(id)sender {

    CABTMIDILocalPeripheralViewController *midiPeripheralCtr = [[CABTMIDILocalPeripheralViewController alloc] init];
    [self.navigationController pushViewController:midiPeripheralCtr animated:YES];
}
```

どちらも UIViewController のサブクラスで、CABTMIDICentralViewController を使うとアプリはセントラル側としてふるまい、MIDI over BLE をサポートしているペリフェラルデバイスをスキャン、接続することができるようになります。

また CABTMIDILocalPeripheralViewController を使うと、アプリは **ペリフェラル側としてふるまい、サービスをアドバタイズ** します（＝MIDI over BLE をサポートしているセントラルデバイスによって発見・接続できるようになる）。

どちらも**パブリックなプロパティ・メソッドは持っていません**。


とりあえずコードは以上。


##Mac側の準備

###MIDI Studio の起動

`/Applications/Utilities` フォルダに、「Audio MIDI 設定.app」というアプリがあるので、起動します。

メニューの、[ウィンドウ] > [MIDI スタジオを表示] から MIDI スタジオを起動します。

###スキャン／アドバタイズの開始

Bluetooth の設定アイコンをダブルクリックすると、

![midistudio0.jpg](https://qiita-image-store.s3.amazonaws.com/0/3180/55b1ca33-3761-8e67-3fa1-79c127ba7bd1.jpeg)


Bluetooth設定ウィンドウが表示されます。

![midistudio1.jpg](https://qiita-image-store.s3.amazonaws.com/0/3180/91114a9c-aef4-3028-27e7-554064bd5516.jpeg)


スキャンは自動的に開始されています。ペリフェラルとしてアドバタイズする場合は、「アドバタイズ」ボタンをクリックします。

![midistudio2.jpg](https://qiita-image-store.s3.amazonaws.com/0/3180/ee44dc39-a9bd-f49f-8f95-8d0e595a941d.jpeg)

アドバタイズを開始すると、ボタン名が「アドバタイズを停止」に変わります。


##接続する：iOS（セントラル）→ Mac（ペリフェラル）

Mac側でアドバタイズを開始し、iOS 側で CABTMIDICentralViewController を表示すると、次のようにペリフェラルである Mac がリストに出てきます。

![midi_3.jpg](https://qiita-image-store.s3.amazonaws.com/0/3180/2977f15b-90b7-71c7-eb2e-369f8dfedc28.jpeg)


「i」ボタンをタップすると次のような画面に遷移し、

![midi_4.jpg](https://qiita-image-store.s3.amazonaws.com/0/3180/b40a9b47-40e0-fc17-6b4a-b2280cd8aec3.jpeg)


ConnectのスイッチをOnにすると・・・**繋がらない**・・・

コンソールには

```
Connecting to peripheral with UUID XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX ...
```

と出て、接続を試みてはいるのですが、しばらくするとスイッチが自動的にoffの方に戻ります・・・**どなたか接続できない原因／接続方法などわかる方、ご教示いただけますと幸いです**・・・！


##接続する：Mac（セントラル）→ iOS（ペリフェラル）

iOS側で CABTMIDILocalPeripheralViewController を立ち上げると、次のような画面になります。

![midi_5.jpg](https://qiita-image-store.s3.amazonaws.com/0/3180/a0438052-07f3-d908-effe-ce9d1a0cb439.jpeg)


「Advertise MIDI Service」セルにあるスイッチをオンにすると、アドバタイズが開始されます。

その後 Mac側のMIDIスタジオの画面を見ると、アドバタイズ開始したiOSデバイスが発見されています。

![midistudio3.jpg](https://qiita-image-store.s3.amazonaws.com/0/3180/4d0e0a79-457e-82a0-c8a1-565df1a8d9c7.jpeg)


ここで「接続」ボタンをクリックすると、iOSデバイス側では CABTMIDILocalPeripheralViewController での STATUS の表示が「Connected to {セントラル名}. Advertising disabled.」に変わり、Mac側では、MIDIスタジオにペリフェラルのアイコンが追加されます。


![midistudio4.jpg](https://qiita-image-store.s3.amazonaws.com/0/3180/024c3726-3cac-8740-3c51-99d0fa92898e.jpeg)


この状態で、MIDIデータ出力ポートを選べるMacアプリからMIDIを送信し、

![midi_mac.jpg](https://qiita-image-store.s3.amazonaws.com/0/3180/3cd46983-eba0-0c95-5d71-e537d0247225.jpeg)


iOS側ではMIDIを受け取れるアプリで受信すると、

![midi_ios.jpg](https://qiita-image-store.s3.amazonaws.com/0/3180/5864e263-0b57-bee4-3f0e-af0791ab2ec2.jpeg)

上記のようにMIDIがワイヤレスで受け取れていることが確認できます。


###（追記）

本記事では別アプリを使用しましたが、下記で紹介されているアプリが MIDI over BLE を試すのによさそう。（まだ試してない）

- [Free App Brings MIDI Over Bluetooth LE To iOS Music Apps](http://www.synthtopia.com/content/2014/10/03/free-app-brings-midi-over-bluetooth-le-to-ios-music-apps/)


##参考資料

- WWDC 2014 - 501 What's new in Core Audio
- [Technical Q&A QA1831 - Adding Bluetooth LE MIDI Support](https://developer.apple.com/library/ios/qa/qa1831/_index.html)