2015年5月14日
Androidの10ms問題:Androidオーディオパスレイテンシ解説
本記事は、原著者の許諾のもとに翻訳・掲載しております。
ゲームやシンセサイザー、DAW(デジタルオーディオワークステーション)、インタラクティブなオーディオアプリ、バーチャル楽器アプリ、そして今注目のバーチャルリアリティアプリなど、低レイテンシのオーディオ機能に強く依存する多数のモバイルアプリは、全てAppleのプラットフォーム、App StoreとiOSデバイスで成功し、App StoreとiOS開発者に巨額の利益をもたらしています。こういったアプリはAndroidには ほぼ存在しません。
Androidの10ms問題 (ほとんど理解されておらず、多大な影響をもたらしうる非常に困難な技術的課題)のために、前述のような 利益を生み出すアプリがまともなパフォーマンスを発揮できない どころか、現時点ではAndroid上に公開すらされないのです。
スタートアップと開発者は、iOSでは成功しているアプリ( 10 ms以下のオーディオレイテンシを必要とする)をAndroidに移植、公開したがりません。オーディオパフォーマンスが低下し、批判的な口コミが広まって自分たちのプロとしての評価やブランドに傷がつくのを恐れるからです。
消費者は、iOSの売上データに載っているようなアプリをAndroidで買いたいと強く希望しているのに、それができずに損をしています。いわゆる”次の10億人”と呼ばれる”モバイルオンリー”の消費者たちを考慮に入れれば、この問題(機会)のスケールの重大さがわかるでしょう。
私たちはこの問題を解決したいのです。本解説では、Google Nexus 9による実際のレイテンシデータを使って、Androidの10ms問題の概観を簡単に説明します。
Androidの10ms問題とAndroidオーディオパスレイテンシがアプリ開発者とAndroid OEMに与える影響
音楽アプリはiOS App Storeの全ダウンロード数のたった3%を占めるのみですが、音楽アプリカテゴリは、ゲーム、ソーシャルネットワーキングに次いで3番目に高い収益を生み出しています。つまり、音楽アプリは低レイテンシを提供するApp Store/iOSデバイスのようなプラットフォームに効率よく利益をもたらしているということです。
[TABLE]
Androidでは話は別です。Google Play Storeでは、音楽カテゴリは収益ランキングのトップ5位にすら入らないのです。
圧倒的多数のAndroidデバイスは高過ぎるオーディオレイテンシに悩まされており、アプリ開発者はAndroidでは消費者の要求を満たすアプリを作れずにいます。
こうしてAndroidの10ms問題のために、GoogleとAndroidのアプリ開発者は数10億ドルをAppleとiOS開発者に譲るままになっているのです。
この解説では、往復のオーディオレイテンシは、単に1つのオーディオインプットが1つのモバイルデバイスに入力され、必要なプロセスを経た後、同じデバイスから出力されるまでの時間を指します。よくミュージシャンが言うように、人間は10ms以下のレイテンシを最も快く感じます。それよりもはるかに遅いと気持ちよく聞けないようです。
多くのAndroidアプリには100ms以上のオーディオアウトプットレイテンシ、200ms以上の往復(オーディオインプットからオーディオアウトプット)レイテンシがあります。アカデミー賞をとった映画『セッション』で言うなら、半拍遅れでビートを刻むドラマーのようなものです。
オーディオ関連のアプリが10msより高い往復オーディオレイテンシによって被る不便について、詳しい例を上げてみます。
- 楽器アプリ、オーディオ効果アプリ:Androidデバイスは他よりも半拍遅れるため、ミュージシャンたちはステージでアプリを使った合奏はできません。練習にすら使えません。
- DJはビートマッチングができません。ヘッドフォンで準備中に聞く信号が、観衆向けに流れるマスター信号よりもはるかに遅れるためです。ループロールやエコーなどの効果を与えるのも同様に困難です。
- ゲーム:爆発音や射撃音といったサウンド効果が数フレーム遅れて聞こえます。ゲームのオーディオはその時点でビジュアルからズレてしまい、粗悪なユーザエクスペリエンスのためにユーザはゲームに没入できません。
- SkypeなどのVOIPアプリ:対話する両ユーザが高レイテンシのAndroidフォンを使っていると、全体のオーディオレイテンシはネットワークレイテンシよりも高くなります。つまり、Android内にオーディオが流れるのに、大陸間でデータパケットを転送する以上に時間がかるのです。
- バーチャルリアリティ(VR):ビューワが首を回しても、オーディオがそれを”追いかける”のが非常に遅いため、3Dオーディオ体験は台無しです。Paul McCartneyのGoogle Cardboardアプリをチェックしてみてください。Googleは数10億ドルのVR市場をAppleに明け渡す寸前です。
テクノロジ業界のリーダー、アプリ開発者、技術者、プロダクトマネジャー、エクゼクティブ、ジャーナリスト、起業家、ミュージシャン、ゲーマー、そして投資家にAndroidの10ms問題の範囲と影響を教育、浸透させるために、いかなる利害も絡まない私たちSuperpoweredがこの解説を作りました。Androidオーディオの足かせ、ボトルネックになりうる全ての事項を容易に把握できるようにするためです。
目標は、Androidの10ms往復オーディオレイテンシへの挑戦のもとに集結し、協働すること、またそれ以上に、この問題をイノベーション、より良いユーザエクスペリエンスを生み出す機会に変え、Google Playの利用者、Android開発者、Android OEMと全Androidエコシステムに利益をもたらすことです。
オーディオレイテンシについて
デジタルオーディオレイテンシの測定には2つの有益な測定単位があります。
- ms(ミリ秒):1秒の1000分の1。レイテンシの多くはこの単位で測られ、このタイムスケールで発生します。
- サンプル(フレーム):オーディオストリームにおける、1点の不連続なデジタルの点(数字)。ソフトウェアが、音波のようなある連続した信号をサンプルのシーケンスに変換するのがサンプリングです。サンプルはオーディオチャネルの数とは無関係です。1個のチャネル信号にとって、1サンプルは1つの数字を意味します。2個のチャネル信号にとっての1サンプルは、2つの数字などです。
ここでは、オーディオ信号フローにおける全レイテンシを、ベストケースシナリオに照らして計算します。
- Androidのネイティブレイヤ(Android NDK)のオーディオは、Googleの推奨低レイテンシを使ってセットアップされています。残念なことに、AndroidアプリのほとんどはGoogleの推奨低レイテンシに準じていません。
- デバイス内蔵のAndroidは適切に設定されており、”Fast Mixer”パスをオーディオインプットとアウトプットの両方に使うことができます。最新のNexusモデルはさておき、メーカーの多くはAndroidがFast Mixerをサポートするように設定していないため、デバイス上の往復レイテンシは非常に高くなっています。各種人気Androidデバイスのレイテンシ計測データについては Superpoweredのモバイルオーディオ調査とレイテンシテストアプリ を見てください。
誰でも分かるAndroid 5.0 Lollipopオーディオパスレイテンシ解説
アナログオーディオインプット
内蔵マイクのプリアンプなど、さまざまなアナログコンポーネントが存在します。こういったアナログコンポーネントは今回の場合”ゼロレイテンシ”と考えて構いません。実際のレイテンシは一般に1ms以下だからです。
レイテンシ:0
アナログからデジタルへの変換(ADC)
オーディオチップは、入ってくるオーディオストリームをあらかじめ定義された間隔で計測し、その結果の全てを1つの数値に変換します。この間隔はサンプリングレートと呼ばれ、単位はHzです。 モバイルオーディオ調査とレイテンシテストアプリ は、Android、iOSデバイスに搭載されたほとんどのオーディオチップのネイティブサンプリングレートが48,000Hzであることを示しています。つまり、オーディオストリームは毎秒48,000回サンプリングされているということです。
ADCの実装には内部のオーバーサンプリングフィルタが含まれていることが多いため、ADCのステップをおおまかに1msレイテンシとして考えます。
オーディオストリームがデジタル化されたので、この点から先はオーディオストリームはデジタルオーディオになります。デジタルオーディオは1つ1つ伝わることは滅多になく、バッファやピリオドと呼ばれるかたまりで移動します。
レイテンシ:1ms
オーディオチップからオーディオドライバへのバス転送
オーディオチップにはいくつかの役目があります。ADCとDACを制御し、複数のインプット、アウトプット間を切り替えたり、ミックスしたり、ボリュームを適用させたりします。また、離散しているデジタルオーディオサンプルをバッファにグループ化し、これらバッファをオペレーティングシステムに転送したりもします。
オーディオチップは、USB、PCI、FireWireなどのバスでCPUに接続されます。各バスには、それぞれの内部バッファサイズとバッファカウント値に応じて、特有のレイテンシがあります。ここでのレイテンシ間は一般に、1ms(内部システムバス上のオーディオチップの場合)から6ms(基本的なUSBバス設定をしたUSBサウンドカードの場合)です。
レイテンシ:1~6ms
オーディオドライバ(ALSA、OSSなど)
オーディオドライバは、ほとんどの場合オーディオチップのネイティブサンプリングレート48,000Hzを使って、リングバッファに入ってくるオーディオを”バスバッファサイズ”ごとに受信します。
このリングバッファはバス転送ジッタ(”粗さ”)を滑らかにするのに不可欠な役割を果たしていて、バス転送バッファサイズをオペレーティングシステムのオーディオスタックのバッファサイズに”連結”します。リングバッファからのデータ消費はOSのオーディオスタックのバッファサイズの範囲内で行われるため、当然いくらかレイテンシが追加されます。
AndroidはLinuxの”上”で実行され、ほとんどのAndroidデバイスでは最も人気のあるLinuxオーディオドライバシステムALSA(Advanced Linux Sound Architecture)が使用されます。ALSAはリングバッファを次のように取り扱います。
- オーディオはリングバッファから”ピリオドサイズ”ごとに消費されます。
- リングバッファのサイズは”ピリオドサイズ”の倍数です。
例:
- ピリオドサイズ=480サンプル
- ピリオド数=2
- リングバッファのサイズは480×2=960サンプル。
- オーディオインプットは1つのピリオド(480サンプル)に受信され、一方オーディオスタックはその他のピリオド(480サンプル)を読み取り/処理します。
- レイテンシ=1ピリオド、480サンプル。48,000Hzで10msに等しくなります。
リングバッファ(960サンプル) | |
ピリオド(480サンプル) | ピリオド(480サンプル) |
共通のピリオド数は2ですが、それ以上になるシステムもあるかもしれません。
レイテンシ:1以上のピリオド
AndroidオーディオHardware Abstraction Layer(HAL)
HALはAndroidメディアサーバとLinuxオーディオドライバの間で仲介をします。HALはモバイルデバイスの製造者によって、”移植”Android上でそのデバイスに実装されます。
実装はオープンで、ベンダはどんな種類のHALコードでも自由に作成できます。あらかじめ定義された構造を使ってメディアサーバと通信します。メディアサーバはHALをロードし、サンプリングレート、バッファサイズまたはオーディオ効果のような任意の優先パラメータで、インプットまたはアウトプットのストリームを作成するよう要求します。
注意:HALは、パラメータに従って動作するかもしれませんし、しないかもしれませんが、メディアサーバはHALに”適応”しなければなりません。
一般的にHALは、ALSAオーディオドライバと通信するために使用されるtinyALSAに実装されます。ここにクローズドソースコードを記述して、重要だと思うオーディオ機能を実装するベンダもいます。
Androidソースリポジトリにある多くのオープンソースHAL実装のコードを分析したところ、おかしな設定と下手なコーディングのせいで、オーディオパスにかなりの量のレイテンシとCPU負荷が不必要に追加される癖がいくつか見つかりました。
うまくHALを実装してレイテンシが追加されないようにするべきです。
レイテンシ:0以上のサンプル
AudioFlinger
Androidメディアサーバは2つのサービスで構成されています。
- AudioPolicyサービスは、オーディオセッションと、マイクへのアクセス許可や割り込み通話のような許可処理を取り扱います。iOSのオーディオセッション処理によく似ています。
- AudioFlingerサービスはデジタルオーディオストリームを処理します。
AudioFlingerは、アプリケーションとオーディオドライバの間で仲介をするRecordThreadを作成します。基本的な仕事は以下のとおりです。
- Android HALを使ってドライバのリングバッファから次のインプットオーディオバッファを得ます。
- アプリケーションからネイティブサンプリングレートとは別のサンプリングレートを要求された場合に、バッファをサンプリングし直します。
- アプリケーションからネイティブピリオドサイズとは別のバッファサイズを要求された場合に、追加のバッファリングを行います。
AudioFlingerには”Fast Mixer”パスがあります。ただし、Androidがそのように設定されている場合です。ユーザアプリケーションがネイティブ(Android NDK)コードを使っていて、ネイティブハードウェアサンプリングレートとピリオドサイズでオーディオバッファキューをセットアップする場合、このステップで、サンプリングをし直したり、追加のバッファリングやミキシング(”MixerThread”)を行ったりすることはありません。
RecordThreadは”プッシュ”メソッドで動作し、オーディオドライバと厳密な同期を行いません。起動されて実行される時に”経験に基づく推測”を行おうとしますが、”プッシュ”メソッドはドロップアウトにもっと敏感な方法です。低レイテンシのシステムではいつも”プル”メソッドが使われ、オーディオドライバはオーディオチェーン全体にオーディオのインプット/アウトプットを”命令”します。Android OSの考案、設計、開発当初に、低レイテンシのオーディオが優先されていなかったのは明らかです。
レイテンシ:1ピリオド(ベストケースシナリオ)
バインダ
Androidの主要なプロセス間通信システムの共有メモリは、AudioFlingerとユーザアプリケーションの間でオーディオバッファを転送するのに使用されます。それはAndroidの心臓部で、Android内部の至るところに用いられます。
レイテンシ:0
AudioRecord
これはユーザアプリケーションのプロセスです。AudioRecordは、オーディオインプットのアプリケーション側を実装します。これは、OpenSL ESなどを経由してアクセス可能なクライアントライブラリの機能です。
AudioRecordは、AudioFlingerから新しいバッファを定期的に得るため、AudioFlingerで”プッシュ”と表現される概念を使いスレッドを実行します。これは、開発者が1つのバッファでのみ機能するように設定してある場合は、オーディオパスにレイテンシを加えません。
レイテンシ:0+サンプル
ユーザアプリケーション
ついにオーディオインプットは、折り返し地点となるユーザアプリケーションにたどり着きました。
スレッドのインプットとアウトプットは同じではないので、ユーザアプリケーションはスレッド間でリングバッファを実装しなくてはなりません。そのサイズは最低2ピリオド(オーディオインプットに1、オーディオアウトプットに1)ですが、アプリケーションがうまく書かれていないと、しばしば力ずくで処理を行い、CPUの限界を解決するためにより多くのピリオドを使います。
ここから、オーディオアウトプットに向かって今までと逆の経路をたどります。
レイテンシ:1ピリオド以上、一般的には2ピリオド弱(ベストケースシナリオ)
AudioTrack
AudioTrackはオーディオアウトプットのユーザアプリケーション側を実装します。これは、OpenSL ESなどを経由してアクセス可能なクライアントライブラリの機能です。AudioFlingerに次のオーディオバッファを送るためのスレッドを実行します。Android4.4.4以降は、AudioTrackは1つのバッファだけを使うように設定されているので、オーディオパスにレイテンシは加えません。
レイテンシ:0+サンプル
バインダ
オーディオインプットと同様。
レイテンシ:0
AudioFlinger
PlaybackThreadを作ります。これはオーディオインプットでRecordThreadと呼ばれるものと逆の働きをします。
レイテンシ:1ピリオド(ベストケースシナリオ)
AndroidオーディオHAL
オーディオインプットと同様。
レイテンシ:0以上のサンプル
オーディオドライバ(ALSA、OSSなど)
オーディオドライバのオーディオアウトプットは、オーディオインプットと同じ働きをし、リングバッファも使用します。
レイテンシ:1ピリオド以上
オーディオドライバからオーディオチップへのバス転送
オーディオインプットのバス転送と同様です。ここではレイテンシは1msから6msの間にあるのが普通です。
レイテンシ:1~6ms
デジタルからアナログへ変換(DAC)
ADCの逆であり、デジタルオーディオがこの時点でアナログに”変換”されます。ADCと同じ理由で、DACのレイテンシはおおまかに1msと仮定します。
レイテンシ:1ms
アナログオーディオアウトプット
DACのアウトプット信号はアナログオーディオになりますが、ヘッドフォンなど接続された機器を作動させるには、追加コンポーネントが必要です。アナログオーディオインプットと同様に、アナログのコンポーネントは”ゼロレイテンシ”とみなすことができます。
レイテンシ:0
Androidオーディオパスのレイテンシを図説
注釈:Google Nexus 9における、実際のレイテンシデータ
この画像を埋め込みたい場合は、以下のコードをコピーしてください。
Androidオーディオパスレイテンシのケーススタディ:Google Nexus 9の場合
これまで、Androidオーディオの往復レイテンシ計測テストで最も良い結果を出したのは、Google Nexus 9です。
ベストの結果はUSBサウンドカード、あるいはヘッドフォンのコネクタのマイクインプットやアウトプットと直接つながる特別なオーディオドングルを使った際の35msです。内蔵マイクロフォンアレイのノイズキャンセリング/フィードバック除去を無効にすることで、それにより生じる13msほどのレイテンシを防いでいます。
ですから、上にあるのと同じモデルを使い、Google Nexus 9におけるベストケースの往復オーディオレイテンシ35msを分析してみましょう。
コンポート | サンプル | Ms |
ADC | 1 | |
バス | 1 | |
ALSAオーディオドライバ | 256 | 5.3 |
Audio Flinger | 256 | 5.3 |
ユーザアプリケーションのリングバッファ | 512 | 10.6 |
Audio Flinger | 256 | 5.3 |
ALSAオーディオドライバ | 256 | 5.3 |
バス | 1 | |
DAC | 1 | |
合計: | 35.8 |
Google Nexus 9の往復レイテンシが35msになる理由
Superpoweredについて
私たちの使命は、メーカーの創造力と生産能力を向上させ、ビルダにはSuperpoweredのオーディオテクノロジがなければ不可能なものを大いに実体化してもらうことです。
そのために、私たちはテクノロジを作り上げ、Androidの10ms問題を解決するオーディオスタックを検討しています。
さしあたり、AndroidとiOS向けのSuperpowered Audio SDKは以下のようになります。
- クロスプラットフォーム:開発者はAndroid、iOS、OSXで同じコードを使用あるいは再利用できます。
- 超高速:モバイルデバイス上には、デスクトップ級の処理とプロのオーディオ品質を提供する最高のパフォーマンスを持つオーディオDSPがあります。CPU負荷が減ることでバッテリ寿命が改善し、全てのアプリケーションがスムーズになります。
- オーディオスタックの”プッシュ”、”プル”のどちらにも、またオフラインの処理にも効果的です。
- ゼロレイテンシ:Superpoweredの機能と処理はレイテンシを加えません。Superpowered Audio SDKを使って構築されたユーザアプリケーションは、iOS、Androidのあらゆるデバイスにおいて一番低いオーディオレイテンシで簡単に実行されます。
お読みいただき、ありがとうございました。
株式会社リクルート プロダクト統括本部 プロダクト開発統括室 グループマネジャー 株式会社ニジボックス デベロップメント室 室長 Node.js 日本ユーザーグループ代表
- Twitter: @yosuke_furukawa
- Github: yosuke-furukawa