2017年5月6日土曜日

Android 7.0の音ズレ問題

スクフェス、デレステ、ガルパなどの音ゲー関連がAndroid7.0で軒並み音ズレが酷いという情報をチラホラ聞きます(参照)。

どの程度酷いのかは未確認。
というより、Androidで音ゲーやるのがそもそも間違っている気がします。
後述しますが、Androidの場合OSの仕様レベルでそもそも音ゲーに耐えられないシロモノなので。(私も音楽系のアプリをAndroidで出していてそこそこ高評価を頂いてますが、低評価が付く原因の9割以上はOS仕様上どうにもできない部分の話しだったりします)

とりあえず、対策方法としては(root化が必要ですが)BuildPropのaudio_hal.period_sizeを調整すると治る場合があるとか(参照)言われています。この値は何ぞや?と思ってAndroidのソースコードを見てみたところ、恐らくこの辺ですね。要するにストリームアウトするバッファサイズに関係するパラメタらしい。

つまり、どういうことか。

例えば、ストリームアウトするバッファ・サイズが100msだった場合、オーディオ出力をする指令を出してから実際に音声が鳴る = HALから低レベルオーディオAPI(最近のAndroidなら多分ALSA)に波形データが渡るまでの間に平均50ms(0〜100ms)のラグが発生するという具合です。

そして、恐らくAndroid 7.0でこのデフォルト値が大きくなったため、遅延が酷くなって音ゲーが全滅してしまった感じでしょう。(それ以外にも色々と複合的な要因がありそうな気がしていますが)
何故、大きくしたのかですが、これは多分何らかのトレードオフかと思います。バッファ・サイズを大きくすると、遅延が大きくなるというデメリットがある反面、CPUの専有期間を短くできることで、例えば「音がプツプツする」といった事象発生を緩和することができます。(つまり、Android 7.0で別のところで処理能力を回したいから、音のリアルタイム性を犠牲にしてCPUリソースを確保したものと推測しています)

Androidのオーディオシステムの仕組みを解説した分かり易い図があったので貼っておきます。
Android 5.0 Lollipop Audio Path Latency
Learn more about Android's 10 Millisecond Problem

ALSA(一部のAndroidはALSAじゃないけど)は、Advanced Linux Sound ArchitectureというLinuxのオーディオHALです。
以前はOSS(Open Sound System)が主流でしたが、割と最近ALSAに変わりました。

ALSAは従来(OSS)と比べて高機能になりましたが、その分、遅延もそこそこあります(上図だと5.3msだとか)。Androidのオーディオ関係がクソな原因のひとつが、ALSAという割と高機能なHALの上に更にAudioFlingerというAndroid独自のHALを載っけていることです。

カツラの上にカツラを被る大御所俳優みたいな感じですね。
この設計は流石に拙すぎるので、Googleほどの技術力があればここら辺は将来的にしっかり治してくるだろう・・・と思っていた時期もありました。

以前のLinuxで主流だったOSSの場合だとそれなりに(AudioFlingerの)存在意義はありました。OSSというのはかなりシンプルなオーディオHALで、特定のスペシャルデバイスファイルに対してパルス符号を入出力するとD/A,A/D変換するというものです。シンプル故にその上に別途HALを作ってオーディオパスを多重化するような実装が必要だから、AudioFlignerにはそれなりに存在意義があったと理解できるかと思います。

しかし、ALSAは高度化されておりそれを直に使っても問題無いので、現在のAudioFlingerは無駄に遅延時間を長くするだけの邪魔な存在でしかなくて、しかし、その上位層がAudioFlingerベッタリになっているから直せない(正確には直せないこともないが直すのが大変=コストが掛かるが、Googleの人は恐らくそれほどオーディオ関係のことを重要視していないから予算が取れない)という感じだろうと推測しています。

ちなみに、ココら辺の設計がダメダメになったのがAndroid 4.xあたりで、3メジャーバージョンも上がった7.xでもそのダメダメなクソ仕様を引きずり続けている感じです。たぶん、もう治らないんじゃないかと思います。私は5.0の時に抜本的な対策がされなかったことから、「もうAndroidは(少なくともオーディオ系統は)ダメだ」と確信しました(だからプライベートのスマホはiPhoneに乗り換えた)が、今回のAndroid7.0で音ゲーが全滅したケースで、やはり私の確信は正しかったんだなと確認できました。このままだと、将来的にはもっと酷くなるんだろうけど、流石にその前には何とかしてくるかもしれません。(何ともならないかもしれません)