Oboeを使い始めてハマった罠まとめ
Androidで低遅延(?)の音声処理を実現するために、Googleが提供している音声ライブラリ「Oboe」を使い始めました。
一見するとシンプルに扱えるように見えますが、実際に実装・長時間運用してみると、端末ごとの挙動の違いやライブラリ内部の仕様で思わぬトラブルに遭遇しました。ここでは特に印象的だった「ハマりどころ」をまとめます。
1. LowLatencyモードでの録音音量低下(主にSamsung端末)
- 現象
- Samsung端末(例: Galaxy S8)で
PerformanceMode::LowLatencyを指定すると、録音音量が極端に小さくなる
- Samsung端末(例: Galaxy S8)で
- 回避策
-
inputStream->setPerformanceMode(oboe::PerformanceMode::None)を指定すると改善する
-
- 参考リンク
2. プリセットによる音声前処理の影響
- 現象
-
InputPresetのVOICE_COMMUNICATIONとVOICE_RECOGNITIONなど、プリセットによって録音音量や音質が変わる
-
- 背景
- Xperia端末で
/vendor/etc/audio_effects.xmlを確認したところ、以下のようにプリセットごとに異なる前処理(AEC, NS, ZNR, DNNR)が割り当てられていた
<preprocess> <stream type="voice_communication"> <apply effect="aec"/> <apply effect="ns"/> </stream> <stream type="mic"> <apply effect="ZNR"/> <apply effect="DNNR"/> </stream> <stream type="camcorder"> <apply effect="ZNR"/> <apply effect="DNNR"/> </stream> </preprocess> - Xperia端末で
- ポイント
-
VOICE_COMMUNICATION→ Acoustic Echo Canceller (AEC) + Noise Suppressor (NS) -
MIC/CAMCORDER→ Zoom/Wind Noise Reduction - これにより、録音レベルや音質が端末・プリセット依存で変わる
-
- 参考リンク
3. CAMCORDERプリセットの罠(Xperiaなど)
- 現象
-
Xperia端末などでAAUDIO_INPUT_PRESET_CAMCORDERを使う問題点- 録音がノイズ化することがある
- 無音になることがある
- (OpenSL ESと比べて、新しい端末での動作が基本大丈夫だが、古い端末では不安定かも)
-
- 回避策
-
VOICE_COMMUNICATIONを使う - また、
Xperia XZ3ではLowLatencyモードを指定すると録音が正常に動作するようにはなる
-
- 参考リンク
4. 長時間稼働での問題
- 現象
- 長時間連続で録音・処理を続けると、音声処理が停止またはクラッシュする
- 原因
- サンプリングレート48kHzで稼働し続けると、システム内部の
int32カウンタが約12時間20分でオーバーフローする -
audioserverが転けた可能性もある
- サンプリングレート48kHzで稼働し続けると、システム内部の
- 回避策
- 定期的に音声ストリームを再起動する
- 音声データを監視し、異常があれば再起動する
- 参考リンク
5. 出力デバイス変更で発生するDisconnect問題
- 現象
- Oboeで
AAudioを使う場合、イヤホンの抜き差しによってストリームが「切断(Disconnected)」状態になるはず -
Android 9 (P)や初期のAndroid 10 (Q)では、DisconnectイベントがAAudioに届かない不具合がある - 出力デバイスの切り替えが失敗し、音が出なくなる
- Oboeで
- 回避策
- Java側で
AudioDeviceCallback()を使い、デバイス変更を検知してストリームを再作成する
- Java側で
- 詳しい情報