1. atsushieno

    Posted

    atsushieno
Changes in title
+12-07 Oboe
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,39 @@
+https://adventar.org/calendars/3353 7日目のエントリーです。
+
+## Oboeとは
+
+OboeはC++環境向けのAndroidプラットフォーム向けのオーディオAPIです。
+
+Androidでは、API Level 9 (Gingerbread) の時にネイティブのオーディオAPIレイヤーとしてOpenSL ESの実装が追加され、API Level 26(Oero)の時に低レイテンシーオーディオ処理をサポートするための新しくAAudio APIが追加されています。OboeはAAudio APIが利用可能な時にはAAudioを利用し、それ以外の時はOpenSL ESを利用する実装になっています。環境に応じて最適なバックエンドを選択する共通APIということになります。
+
+なお、OboeはAPI Level 27以降にのみ含まれている部分のAAudio APIに依存しており、OboeがAAudioを利用する条件はAPI Level 27以降のみとなっています)。また、OpenSL ESドライバー実装も、サポートされているのはオーディオ設定まわりのAPIが追加されたAndroid 16(Jellybeanのひとつ)以降のみです。
+
+Oboeのことを「低レイテンシーに対応したAPI」と紹介しているものがあるとしたら、それはほぼ間違いなくAAudioのことを指しています。Android 8.0以前では無関係な話です。
+
+Oboeの機能は、概ねAAudio APIが提供するものと同様です。OpenSL ESにはAAudioには無いオプション設定がいくつかあるのですが、Android NDKに含まれるOpenSLESの実装ではサポートされていなかったものが多く、実質的にOpenSL ESを選択しなければならないような場面はほとんど無いでしょう。
+
+Oboeは10月にバージョン1.0として正式版が公開され、GoogleのAndroid developers blogでも紹介されている程度には本気度と完成度が高いので、安心して使えると思います。(cmakeのビルドスクリプトではstaticでしかビルドできなかったりしますが…!)
+
+https://android-developers.googleblog.com/2018/10/introducing-oboe-c-library-for-low.html
+
+## シンプルなAPI
+
+OboeはOpenSL ESに比べて極めてシンプルで使いやすいAPI設計になっています。具体例として、わたしがfluidsynth(これについてはまた別の日に書きます)でOpenSL ESを使用しているコードとOboeを使用しているコードを比較してみてください。というか、OpenSL ES APIの「どうしてこうなった」感…([VST3と似たような回りくどさ](https://qiita.com/hotwatermorning/items/7f1049a7222aa59a425c)ですね)
+
+- OpenSL ES: https://github.com/atsushieno/fluidsynth-fork/blob/e78021fad11e839570d134eebae2f2ecf6435b51/src/drivers/fluid_opensles.c#L142
+- Oboe: https://github.com/atsushieno/fluidsynth-fork/blob/8f7c0e4c69e2c881c23d9fc48ae87c288d84b2c4/src/drivers/fluid_oboe.cpp#L159
+ - これはC++だから、というわけではありません。わたしがoboe-cというC APIを作って実装を書いた時のコードもまだまだ簡単なので、参考として挙げておきます: https://github.com/atsushieno/fluidsynth-fork/blob/e78021fad11e839570d134eebae2f2ecf6435b51/src/drivers/fluid_oboe.c#L128
+
+## Oboe(あるいはAAudio)の特徴的なオプション
+
+AAudioおよびOboeによって新しく登場したAndroidネイティブオーディオのオプションとしては、次の2つが挙げられます。
+
+(1) 共有モード: オーディオI/Oを排他的に獲得するか否かを指定します。Exclusiveで接続していると、他のアプリケーションから割り込まれたりはしなくなります。結果的にミキサーをひとつ経由しなくなる分レイテンシーが下がりますが、システム等によって割り込まれたりなどしてオーディオ接続が切断される可能性が高まるようです。早目の解放が想定されています。Sharedで接続しているとミキサーをひとつ経由するのでその分遅くなります。以下は公式サイトのドキュメントにある図です。
+
+![image.png](https://qiita-image-store.s3.amazonaws.com/0/18593/171f239f-5eb6-e84a-90a2-f007971b326e.png)
+
+![image.png](https://qiita-image-store.s3.amazonaws.com/0/18593/1fc24528-36f5-277f-ea1e-d49c38bbf340.png)
+
+(2) パフォーマンスモード: LowLatencyモードとPowerSavingモードがあります。前者の低レイテンシーモードでは、バッファサイズを抑えることで、アプリケーションに対するオーディオデータ要求コールバックの頻度が上がり、オーディオの遅延は小さくなることが期待されます。逆にPowerSavingモードでは、コールバックの頻度が下がる分、バッテリーを過剰に使用しなくなります。デフォルトではその折衷的なNoneになっています。
+
+これらをアプリケーションに合わせてうまく調整することで、最善のエクスペリエンスが期待できるでしょう。