コガネブログ

平日更新を目標にUnityやC#、Visual Studioなどのゲーム開発アレコレを書いていきます

【GTMF2015】「「音声再生遅延推測機能」正式リリース! ズレない!待たせない!快適なスマホゲームを実現する技術紹介」メモ

CRIWAREとは

  • CRIのミドルウェア群の総称
    • CRI ADX2
      • オーディオ統合ソリューション
    • CRI Sofdec2
    • ファイルマジックPRO
      • ファイル読み込み
      • 圧縮/パッキング
      • ネットワーク対応

モバイル環境での利用形態

ADX2の概要

ADX2の基本コンセプト

  • プログラマとサウンドデザイナの分業
    • パラメータ制御や再生タイミング、発音数制御などは、データ側に設定
    • プログラム側は単純な再生制御だけでOK

CRI独自の音声コーデック

種類 説明
ADX 高音質・低負荷な1/4圧縮
HCA MP3/AAC同等の高音質・高圧縮
HCA-MX HCAと同じ圧縮率・高音質だが、複数最世辞に非常に低負荷

イントロ付きループ

  • 途切れず、綺麗にループするBGM
    • ループポイント付き波形の圧縮・再生に対応
    • イントロ付きループBGMをプログラムの工夫なしで実現

Android音ズレ対策

音ズレが気になる演出

  • リズムゲーム
    • 音楽に合わせてタップ操作
  • 音楽に合わせた、演出の切り替え
    • 音楽に合わせて、照明が変化するライブシーンなど
  • ユーザーの操作に合わせた音でも…
    • スワイプに合わせて、SEの音階が上がっていくような演出とか
  • 口パクにこだわっても…
    • ボイスに合わせて口パクをしっかり描画

Androidの何が問題か?

  • サウンド再生レイテンシと、その端末差
    1. 再生のきっかけ
      • ユーザーのタッチ操作
      • 自動イベントシーンで指定の時間になった
      • etc.
    2. プログラムによる再生指示
    3. スピーカーからの発音
      • 2と3の間にかかる時間が「再生レイテンシ」
      • Androidの場合
        • 遅い
        • 機種によって差が激しい
        • 遅いと200msec以上

絵と音のズレ

  • 音ズレ問題をもう少し分解すると
    1. 鳴っている音の時刻を正しく取れるか?
    2. 再生指示から音が鳴るまでのレイテンシ
    3. 絵と音の同期は崩れないか?
      • のちほど補足説明
  • ADX2での対策方法
    1. 鳴っている音の時刻を正しく取れるか?
      • 「サウンド再生遅延推測機能」で音ズレを調べて、描画のタイミングを調整する(遅らせる)
    2. 再生指示から音が鳴るまでのレイテンシ
      • 低レイテンシ再生モードを使用して、音を鳴らす
      • ネイティブサウンドレンダラ指定でボイスプールを作成する

新機能(今月リリース予定)

  • サウンド再生遅延推測機能
    • 2015年2月にβ版としてADX2 SDKに搭載
    • 今月、正式機能としてリリース予定(関数仕様が刷新される)
    • アプリが、ADX再生時刻に推測結果を加味して描画タイミングを自動調整できるようになる
    • Android端末ごとの個別調整が不要になる
    • ※CRIなりの推測値のため、100%正しいとは保証できない、あくまでもタイミング調整の参考値として扱うこと

遅延推測機能

  • アプリでの利用例(リズムゲームの場合)
    • 初回起動時
      • ADX2で推測値を取得
      • タイミング調整の値として遅延推測の値を保存
    • 2回目以降の起動
      • タイミング調整値の読み込み
      • (起動のたびに調整値が勝手に変わらないように)
    • (ノートの表示時刻+タイミング調整値)>音声の時刻
    • この条件を満たしたらノート表示=絵を遅らせる
    • ※ユーザーによるタイイング調整オプションは実装すること。推測値はタイミング調整の初期値として使うことをお勧めする
  • ADX2遅延推測の仕組み(概要)
    • 基本的な仕組みは単純
      • 以下の要素を考慮しながら、ADX2時刻とのズレを計算
        • ADX2出力バッファのデータ消費
        • Androidのサウンドバッファ(OpenSLES)のデータ消費
        • 再生指示を出したタイミング
      • 結果のゆらぎを異常系も考慮して、最終的な推測値を作る
  • 補正がうまくいかないケースもある
    • 端末差を考慮した推測方法ではないので、推測がうまくいかない端末もあるのではないかと考えている
    • XPERIAのxLAUDなど、端末側でサウンド最終段に特殊処理が入るような場合は怪しい
    • (今回試したら、xLAUDが有効でも大丈夫だった)

低レイテンシ再生

  • ADX2の低レイテンシ再生モードについて
    • Android版ADX2は、音ごとに2つの再生モードが指定できる
      • 通常再生モード(ASR)
        • ADX側で全ての音をミキシングして、1つの音として出力
        • 最終段が1音なのでAndroidの端末毎の影響を受けにくい
        • 複数トラックの同期保証やDSPエフェクトなどが利用可能
      • 低レイテンシ再生モード(NSR
        • 1つの音をAndroidの1音として直接出力する
        • たくさん鳴らすと端末によって処理落ちしたりするので注意
        • HCA-MXコーデックが使えないなど制限も多い
  • 低レイテンシ再生モードの使いどころ
    • リズムゲームのタップ音や、スワイプ操作に合わせた音など
    • リズムゲームの場合、連打されると処理落ちが発生する可能性もあるので注意
    • 問題が出た場合は、発音数制御などの調整を検討すること
    • ※ADX2の遅延推測結果は、低レイテンシ再生の時刻には適用できません(再生時刻との同期が必要なものは通常再生すること)

絵と音の同期

  • 絵と音の同期は崩れないか?
    • 再生開始の遅延時間が分かったとしても、再生途中で(外部要因によって)絵と音の同期が崩れる可能性がある
    • 例えば...
      • ユーザ操作によるポーズON/OFF
      • アプリのサスペンド/レジューム
      • プッシュ通知や電話着信
      • スクリーンショットの撮影
      • アプリの処理落ちや、データ不足などによる音途切れ
  • 時刻精度と滑らかさ
    • この問題はADX2がまだ弱いところ
    • リズムゲーム開発で困るので、改善検討中
    • ADX2の再生時刻系1:GetTimeReal
      • 滑らかに時刻が増加するが、ポーズ連打で音とズレが発生
    • ADX2の再生時刻系2:GetNumPlayedSamples
      • 音と大きくはずれないが、精度が粗く時刻が少しゆらぐ

参考情報

  • Android側サウンドバッファの再生位置について
    • 最初からOpenSLESのGetPositionを使えばいいのでは?
      • 試してみると...
      • 更新粒度に端末差が大きい
      • 再生位置が動き始めるまでの時刻にゆらぎがある
      • データ供給不足が起きると、再生位置がリセットされる?
      • など、扱いに注意が必要