オーディオレイテンシーの話 - oxxxideoxxxide.org/lt/tsubu_2015_9_26_oxxxide.pdf ·...
TRANSCRIPT
オーディオレイテンシーの話
つ部2015/9/26LT大会
自己紹介
twitter: @oxxxide
web: http:oxxxide.org
7年ほどSE/プログラマとして普通のSIerに勤務。去年の6月ごろ退職。
Java周りのWebシステムとか触ってました(Tomcat、Apache、MySQL等)
現在はフリーランスプログラマー(無職)
※C/C++、C#、Javascript、VBAとかも使えます。
OXXXIDE
作ったアプリ
全部音関連のアプリです 買ってね!
随時案件・お仕事募集中です!お気軽にお声がけください
シンセサイザーとかです
https://www.youtube.com/watch?v=kF_E-9VkxLI
https://www.youtube.com/watch?v=wiB5Q2cz3pE
ユーザーさんが動画をアップしてくれました
オーディオレイテンシーとは
● ユーザーが操作が行ってからスピーカーから音が鳴るまでの時間
● 一般的に10ms(0.01秒)以下であればプロの演奏でも支障が無い
とされている。
● 個人的には楽器演奏には30msがギリギリ許容レベル。
● 格ゲーでいえば1フレームが16.7ms(60fpsの場合)
Android端末はiPhone/iPadと比べ、極端にオーディオレイテンシが大きい場合が多い
● iOSデバイスが概ね10ms以内に抑えられているのに対し、Androidデバイスは最短のNexus9ですら48ms
● このリストは往復の値なので実際のレイテンシは半分程度です。
● Nexus端末の片道レイテンシは概ね18~40ms程度でAndroidの中では比較的優秀(たぶん)
● Androidでは300msを超える端末も珍しくない
出典: http://superpowered.com/latency/
オーディオレイテンシーが大きい事により発生する問題
● 楽器アプリ
○ 操作からワンテンポ遅れて発音するため、まともに演奏できない
● エフェクターアプリ(ボイスチェンジャー・ボコーダー等)
○ 同様の理由で演奏には使えない。
○ ボイスチャット等でもラグが発生しユーザビリティが悪化
● 音ゲー
○ グラフィックとBGMにラグが生じる。
○ タッチから音が鳴るまでにラグが生じ、プレイが困難になる。
スクフェス・デレステ等ではスコア(楽譜)の表示にディレイを加え、BGMとグラフィックを同期させているようです(たぶん)
理不尽なレビュー
何故iOS端末に比べて遅いのか?
● iOS端末がソフト・ハード共に最適化され、低レイテンシに抑えられている一方、
Androidはサウンドチップ・サウンドドライバー・HALの実装は開発ベンダーに依存
している。(ベンダー独自の高音質化機能の追加等も更にレイテンシ増加に拍車を
かけている。)
○ Googleもこの問題を認識しており、Nexus端末は比較的低レイテンシです。
● Android OSそのものの問題
○ LinuxではALSAやOSS等のカーネルコンポーネントそのものを叩く事ができる
が、AndroidはAudioFlingerというAndroid独自のオーディオ機能を統括する
プロセスへ一旦バッファが投げられる。
○ アプリケーションフレームワークでストリーミングモードを経由する場合、仮想
マシン層とNative層でメモリの共有をしないため、本来不要なスレッドの同期、
メモリコピー等の処理が必要になり、消費リソースが増大。
アプリケーション(Dalvik/ART層)からネイティブ層のフレームワーク、HALを経由しオーディオドライバへデータが渡されるまでの処理が冗長すぎる
Androidのオーディオレイテンシが酷い主な原因
※LinuxではALSA/OSS等のカーネルコンポーネントを直接叩けるため、レイテンシはそれほど問題になっていない
仮想マシン層(Dalvik/ART)
※HALやサウンドドライバの実装はベンダーに任されているので、 アプリ開発者はこのレイヤに手を加える事はできません。
AndroidSDKのストリーミングモードでのバッファリングによるレイテンシ(理論値)を実際に計算してみる
Xperia M dualでの結果
9216/48000=0.192秒(192ms)のバッファサイズが必要→まともな楽器アプリを作成する事は事実上不可能
Androidのオーディオレイテンシは
普通にSDKで実装すると
かなり酷い事になることがわかりました。
そこでAndroid NDKの出番です
VM層のバッファメモリを確保する必要がなくなり、直接Native層のAudioFlingerへバッファをキューする事が可能に
Android2.3からAndroid NDKから直接操作できるオーディオAPI群が正式にサポート
OPEN OpenSL|ES
Androidアプリにおいてオーディオレイテンシを抑える為の最低限の手段
1. オーディオストリーミングの実装にJavaコードは使わない
2. オーディオストリーミング処理はAndroidNDK・OpenSL|ESで実装する
3. OpenSL|ESのバッファサイズは256sample(64*4)程度以下に抑えて設定
4. 端末のオーディオドライバのネイティブサンプリングレートを使用する
○ ネイティブサンプリングレート以外の Streamがバインドされた場合、 AudioFlinger内でネイティ
ブサンプリングレートへのリサンプリング処理が行われ、その分無駄なリソースが消費される)
※AudioFlinger、HAL、サウンドドライバはベンダーと機種の実装に依存しており、 上記の対策を施しても理想的なレイテンシを得られる保証はありません。
OpenSL|ESはC言語をオブジェクト指向っぽく書いてたりして初学者にとってはやや難解ですので、下記ソリューションを使う手もあります
libpdhttps://github.com/libpd/pd-for-androidPdのライブラリ群をAndroidで使えるようにしたやつ。中ではOpenSL|ESを叩いているがOpenSL|ESの複雑怪奇なAPIは隠蔽されているので比較的お手軽
superpoweredhttp://superpowered.com/よく知りませんがガチっぽいです
Samsung Professional Audio SDKhttp://developer.samsung.com/galaxy#professional-audioとても高機能ですが GALAXYでしか使えないので微妙です
その他のAndroid用オーディオソリューション
エクストリームな解決策
❏ 改造OSをビルドして端末に焼く❏ CyanogenModの派生OSではAudioFlingerへのバインドをALSAにポート
するバージョン等が存在するようです。(未確認)❏ PULSE AUDIOで重鈍なAudioFlingerを置き換える動きがあるようです。
http://arunraghavan.net/2012/01/pulseaudio-vs-audioflinger-fight/
❏ 自前でハードウェアを開発する❏ USBデバイスを経由すればOSの様々なしがらみから解放される!
❏ USB -> USART -> mbed(arduino等も可) -> SPI -> DAC -> スピーカー
❏ 少しお金がかかる❏ それなりのハードウェアの知識が必須❏ 当然自分の設計に準拠したアプリしか動かない
❏ ハードウェアを量産し販売すればビジネスチャンス?
自前でオーディオインターフェースを作ろうとした結果
mbed LPC1114FN28とUSB/USART変換チップ、DAC等を買ってみた
そして
SSOPチップ(DAC)のはんだ付けで挫折
ご静聴ありがとうございました