CRI ADX2(Unity)
中級編05 音声の再生時刻を取得する(通常取得・再生済みサンプル数編)

音楽ゲームはもちろんのこと、BGMの再生時刻に合わせた演出など、ゲームを作るうえで再生中の曲の時刻を取得したいシーンは様々存在すると思われます。
そこで本編では、音声の再生時刻の取得方法について紹介をしたいと思います。

音声再生時刻の取得方法

CRIWAREプラグインにおいて、音声の再生時刻を取得する方法は以下の3通り存在します。
これらの方法にはそれぞれ利点と欠点が存在します。

方法 利点 欠点
通常の再生時刻(ミリ秒) 取得が楽 厳密には「再生時刻」ではない
再生済みサンプル数 出力される音と合っている 滑らかに増えない、時刻への変換が必要
音声同期タイマを使用した再生時刻 出力される音と合っている 初期化が必要、使い方に注意が必要

それでは各方法について詳しく見ていきましょう。

[Don't Destroy On Load]チェックボックスは有効に

[Don't Destroy On Load]チェックが無効な場合は、シーン切り替えを行った際にライブラリの終了処理を行います。 ほとんどの場合、シーンごとにライブラリを初期化する必要はありません。
また、シーン切り替え前後で変わらずライブラリ機能が使えるので、シーンを跨いでもBGMを鳴らしっぱなしにできるなど、演出面でも便利にご利用いただけます。

通常の再生時刻

CriAtomExPlayer.GetTimeおよびCriAtomExPlayback.GetTimeで再生時刻を取得できます。

上記関数は「再生開始後からの経過時間」を取得します。
そのため、何らかの要因で再生音が途切れた場合でも、 再生時刻のカウントアップが進みます。

もっともシンプルな再生時刻取得サンプルコードは以下のような形で書くことができます。
同一プレーヤで複数の音声を再生し、本関数を実行した場合、本関数は最後に再生した音声の時刻を返すため注意が必要です。

/* AtomExPlayerの生成 */
CriAtomExPlayer atomExPlayer = new CriAtomExPlayer();
atomExPlayer.SetCue("Cue1");
atomExPlayer.Start();

...中略

private void Update(){
    /* AtomExplayerの再生時刻の取得 */
    long playerGetTimems = atomExPlayer.GetTime();
}

複数の音声の再生時刻を取得したい場合はプレーヤを複数用意してそれぞれの時刻を取得も可能ですが、UnitySDK初級編02 音の止め方で行った再生音オブジェクトに対して時刻を取得することでプレーヤを一つのみにすることも可能です。

/* AtomExPlayerの生成 */
CriAtomExPlayer atomExPlayer = new CriAtomExPlayer();

/* キュー毎に再生音オブジェクトをキープする */
atomExPlayer.SetCue("Cue1");
CriAtomExPlayback playback1 = atomExPlayer.Start();
atomExPlayer.SetCue("Cue2");
CriAtomExPlayback playback2 = atomExPlayer.Start();

...中略

private void Update(){
    /* それぞれの再生時刻の取得 */
    long playback1Time = playback1.GetTime();
    long playback2Time = playback2.GetTime();
}

再生済みサンプル数

CriAtomExPlayback.GetNumPlayedSamplesで再生済みサンプル数とサンプリングレートを取得することができます。
通常の再生時刻の取得に比べ、実際に実機で消費されたサンプル数を取得できるので、波形データと映像のより厳密な同期を行うことが可能です。
しかし、取得できる値はサンプル数のため、取得後時刻に変換する必要があります。

/* 再生済みサンプル数を取得 */
long numsamples;
int samplingrate;
playback.GetNumPlayedSamples(out numsamples, out samplingrate);

/* 時刻に変換(ミリ秒) */
float playbackTime = numsamples / (float)samplingrate * 1000.0f;

それでは紹介した方法で取得した値を図にプロットしてみます。(AtomConfig.ServerFrequency : 30Hz)

時間経過と共にAPIから取得した時刻も増加していますが、ガタガタとしていますね。
これは、2つの時刻が別スレッドで行われる音声処理(Atomサーバー処理)で更新されるためです。
サーバー処理周波数を(わざと)30fpsに設定したため、60fpsのメインスレッドで時刻を取得すると、毎フレーム時刻が更新されるとは限らないのです。

次の記事では、より滑らかな再生時刻を取得できるCriAtomExPlayback.GetTimeSyncedWithAudioについてご紹介します。

author:我妻