Core Bluetooth / BLEで音声データをやりとりする

#はじめに

以前書いた２つの記事でわかったことは、 **BLEは少量データ／低頻度での用途に特化することで省電力を実現した規格なので、音声データをやり取りするような用途にはそもそも向かない** 、ということでした。

- [Core Bluetoothのプロファイルについて調べたことのまとめ](http://d.hatena.ne.jp/shu223/20140109/1389216052)
- [iOSのCore Bluetooth / BLEの通信速度](http://d.hatena.ne.jp/shu223/20140110/1389292125:title:bookmark)

ただ、<b>MFiなし、WiFiもなしでデバイスとiOSアプリを無線通信させたい</b>場合、iOSの現状の公開APIで可能な範囲ではやはりCoreBluetooth/BLE一択になってくるので、どうにかならないものかと。


そんなわけで、いろいろと調べたり聞いてみたり試行錯誤してみたことを書いておきます。


**（2015.8追記）この記事は古く、書いた当時はBLEについての知識も乏しかったので内容には多分に誤りが混じっている可能性があります。**

#Bluetooth4.0イヤホンはどうやって音声データを流してるのか

疑問だったのは、自分がいま使ってるイヤホンは、Bluetooth4.0であることでした。


<div class="amazlet-box" style="margin-bottom:0px;"><div class="amazlet-image" style="float:left;margin:0px 12px 1px 0px;"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/B0093QUS2W/22301-22/ref=nosim/" name="amazletlink" target="_blank"><img src="http://ecx.images-amazon.com/images/I/31cnWsuurnL._SL160_.jpg" alt="Logitec Bluetooth ステレオヘッドホン カナルタイプ 高音質aptX/AAC対応 SpecialEdition ブラック LBT-AVHP06SEBK" style="border: none;" /></a></div><div class="amazlet-info" style="line-height:120%; margin-bottom: 10px"><div class="amazlet-name" style="margin-bottom:10px;line-height:120%"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/B0093QUS2W/22301-22/ref=nosim/" name="amazletlink" target="_blank">Logitec Bluetooth ステレオヘッドホン カナルタイプ 高音質aptX/AAC対応 SpecialEdition ブラック LBT-AVHP06SEBK</a><div class="amazlet-powered-date" style="font-size:80%;margin-top:5px;line-height:120%">posted with <a href="http://www.amazlet.com/" title="amazlet" target="_blank">amazlet</a> at 14.01.29</div></div><div class="amazlet-detail">ロジテック (2012-11-05)<br />売り上げランキング: 3,022<br /></div><div class="amazlet-sub-info" style="float: left;"><div class="amazlet-link" style="margin-top: 5px"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/B0093QUS2W/22301-22/ref=nosim/" name="amazletlink" target="_blank">Amazon.co.jpで詳細を見る</a></div></div></div><div class="amazlet-footer" style="clear: left"></div></div>


自分は Bluetooth4.0 = BLE だと思っていたので、何でBLEで音楽聴けてるんだろう？と。ビットレートをそこまで落としてる感じもしないし。


##識者の方々に聞いてみた

というわけで、Facebookの[WF-BTLE](https://www.facebook.com/groups/563064710384459/)グループで、次のような質問をしました。


> BLEのプロファイルについてよくわからない点があるので、質問させてください。

> BLEは『少量のデータを低頻度でやりとりする用途に、ハードウェアの低コスト化と、コイン型電池で1～2年間の連続動作ができる超低消費電力に特化』（[こちらの記事](http://reinforce-lab.github.io/blog/2013/09/19/blebook-ch3-corebluetooth/)より引用）した規格であると認識しています。

> なので、BLEのGATTベースのプロファイルは、Heart Rateや、Battery Serviceなど、少量データ・低頻度で済む用途のものが[定義されている](https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx)し、GATTの規格自体も大きいデータを流しっぱなしにするようにはなっていない（アトリビュートのvalueは512バイトまで）と。

> ただよくわからないのが、世の中には[Bluetooth4.0用のヘッドセットなども出ている](http://buffalo.jp/products/catalog/supply/multimedia/headset/bluetooth/bshsbe23/)点です。

> 上記ヘッドセットのページにはプロファイルにHFPを使用しているようなことが書いてあります。 **私の認識ではBLE機器ではGATTベースのプロファイルしか使えず、HFPなどは3.0以前の従来規格でしか使用できない、というものなのですが、そんなことないのでしょうか？もしくは、フレームレートを抑える等の工夫をしてGATTの規格内でHFP相当の通信ができるようにしている、ということなのでしょうか？**

> 見当違いのことを言ってるかもしれませんが、識者のみなさま、ご教示いただけると幸いです。

> ちなみにこの質問をする意図としては、iOSのCoreBluetoothで、デバイスと音声データのやり取りをしたい（音質は5kbpsぐらいまで落とせる）、というものになります。BLEはそもそもそういう用途の規格ではないとは思いますが、MFiなし、WiFiもなしでデバイスとiOSアプリを無線通信させたい場合、やはりCoreBluetooth/BLE一択になってくるので。。


そして、回答をいくつかいただきました。（掲載許可は得ていないので）原文を載せるのは避け、要約すると、

- <b>Bluetooth4.0は、3.0までの技術に、Low Energyの技術を統合したもの。なので、3までの技術も使える</b>
-- 両方に対応したものをデュアルモードと呼ぶ
- ただ、<b>Core Bluetoothでは、Low Energyの部分しか制御できない</b>
- BLEを音声通信的なものに利用するのは、あり。CoreAudioでBluetothのヘッドセットへルート切り替えが、最近はできるようになったはず。
- 参考リンク
 - [Bluetooth Low Energy(BLE)についての概要 #2](http://www.cloudcluster.cloudysunny14.org/show_materials?id=ahBzfm9uY2xvdWRjbHVzdGVyciULEg9NYXRlcmlhbHNUaGVtZXMY-VUMCxIITWVudGlvbnMY6QcM)
 - [Bluetooth LEの解説本、第1章 - Reinforce-Lab.’s Blog](http://reinforce-lab.github.io/blog/2013/07/26/blebook-ch1/)

という明快な回答をいただきました。


なるほど、まず大前提として、「Bluetooth 4.0 = BLE」というのが大きな勘違いでした。


「デュアルモード」というのは知ってましたが、それは3.0にも対応している、という意味だと思っていて、4.0の仕様が3.0の仕様も含んでいる、ということだとは知りませんでした。


で、音楽を聴けるヘッドセットやイヤホンは、3.0までの技術を使っていて、それはMFiなしで使えるCoreBluetoothでは制御できないと。


また「Bluetoothを扱いたければCoreBluetoothだ！」とばかり思っていたので、オーディオのルート切り替えは盲点でした。


##オーディオセッションによるBluetoothデバイスへのルート切り替え

そういえば、ルート切り替えの定義でBluetoothなんちゃらっての見たことあるな、というのはなんとなく記憶にあったので、改めて見てみると、

````
kAudioSessionInputRoute_BluetoothHFP
kAudioSessionOutputRoute_BluetoothHFP
kAudioSessionOutputRoute_BluetoothA2DP
````

というのがありました。


これができれば、HFPプロファイルに対応したデバイスから音声データを受け取ってそのままAudio Unitとかで波形処理できるので、なかなか良さそうです。 **iOS7からdeprecated** になってましたが。。


#Core Bluetoothでどうにかしてみる

上述したようにオーディオセッションでルートを切り替えることで音声データのやりとりができそう、とわかったものの、デバイス側がいまのところGATTベースのプロファイルにしか対応してないので、結局Core Bluetoothでどうにかすることにしました。


**※ペリフェラル側でS/N比などをみて音声データを切って送信する前提です。**


##ペリフェラル側

````
- (void)peripheralManager:(CBPeripheralManager *)peripheral
    didReceiveReadRequest:(CBATTRequest *)request
{
    // 音声バッファの続きを渡す
    request.value = [self soundDataFromCurrentIndex];
    
    [peripheral respondToRequest:request
                      withResult:CBATTErrorSuccess];
}
````


上記コード内で呼んでいる soundDataFromCurrentIndex というメソッドでは128バイトずつ音声バッファのデータを渡すようにしています。


##セントラル側

````
- (void)                 peripheral:(CBPeripheral *)peripheral
    didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
                              error:(NSError *)error
{
    NSData *data = characteristic.value;
    NSUInteger bytes = data.length;

    [self.receivedData appendData:data];
        
    // 次のデータを読み込む
    if (bytes >= kMaxBytes) {

        [cbPeripheral readValueForCharacteristic:self.characteristic];
    }
    // 受信完了
    else {
        
        // receivedDataに対して処理を行う
    }
}
````


全部読み終わるまでreadし続ける、という（とくにTips要素もない）普通の処理です。


#試してみた結果

上記方法で試しに 15kB の wavデータ（16bit, 16kHz）を送ってみると、20秒ちょいかかりました。[先日計測した速度](http://d.hatena.ne.jp/shu223/20140110/1389292125)とだいたい同じぐらいなので妥当そうですが、送ったのは再生時間が1秒にも満たないデータなので、 **リアルタイムにはほど遠い** レベルです。


5kbpsぐらいの通信速度である程度リアルタイムに送るには、1秒当たり600バイトぐらいに収める必要があるので、ビットレートを落とすだけじゃなく、いったんaacとかの圧縮フォーマットにエンコードして送る必要がありそうです。


#関連記事

- [Bluetooth Low Energy (BLE) のサービス／キャラクタリクスの構成例一覧](http://d.hatena.ne.jp/shu223/20140129/1391035286)
- [Reading long characteristic values using CoreBluetooth](http://stackoverflow.com/questions/19280429/reading-long-characteristic-values-using-corebluetooth)
- [iOS のオーディオ／サウンド処理について学べる書籍10冊＋α](http://d.hatena.ne.jp/shu223/20121125/1353877706)
- [Bluetooth 4.0 および Bluetooth Low Energy (BLE) に関する技術情報のまとめ](http://d.hatena.ne.jp/shu223/20140128/1391063947)