CRI ADXで音源の再生時間、再生終了時間を取得する

ADXは音声の再生中にミリ秒単位の再生時刻を取得できます。
再生時刻の取得についてはGetTimeメソッドとGetTimeSyncedWithAudioメソッドがあり、再生終了時刻はCriAtomEx.CueInfoのlengthプロパティで取得できます。

とりあえず以下のクラスを作って、適当なGameObjectにアタッチしてください。
キューシートは「TimeTest」という名前で追加済みであるものとします。

using CriWare;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;

public class TimeTestClass : MonoBehaviour  
{
    private CriAtomExPlayer _player;
    private CriAtomExPlayback _playback;
    private CriAtomExAcb _exAcb;
    private string _cueSheetName = "TimeTest";

    void Start()  
    {
        StartCoroutine(CreatePlayer());  
    }

    public IEnumerator CreatePlayer()
    {
        _player = new CriAtomExPlayer(true);
        _playback = player.Prepare();

        _exAcb = CriAtom.GetCueSheet(_cueSheetName).acb;
        // CRI Assets/CRI Addressablesを使っている場合は上記の行をコメントアウトして、
        // 以下をコメントを外して使う。【Addressablesのパス】は事前に登録しておいたものにすること
        //var handle = Addressables.LoadAssetAsync<CriAtomAcbAsset>("【Addressablesのパス】");
        //var acbAsset = handle.WaitForCompletion();
        //_exAcb = acbAsset.Handle;

        // 再生準備完了待ち
        while (_playback.GetStatus() != CriAtomExPlayback.Status.Playing)
        {
            yield return null;
        }
    }
}

このクラスに色々なメソッドを付けてみて確認します。

目次

再生時間の取得

TimeTestClassに以下のメソッドを追加してください。

    void Update()  
    {
        Debug.Log("GetTime:" + GetTime());
        Debug.Log("GetTimeSyncedWithAudio:" + GetTimeSyncedWithAudio());
    }

    public long GetTime()
    {
        return _criAtomExPlayback.GetTime();
    }

    public long GetTimeSyncedWithAudio()
    {
        return _criAtomExPlayback.GetTimeSyncedWithAudio();
    }

これで音源の再生時間がデバッグログに毎フレーム出力されます。

GetTimeとGetTimeSyncedWithAudioの違い
2分7秒ほどの楽曲を2分ほど再生した様子。GetTimeよりもGetTimeSyncedWithAudioの方が正確な時間を表している
2行目のGetAudioSourceLengthについては後述

基本的にはGetTimeを使用しますが、GetTimeSyncedWithAudioは処理速度を犠牲に正確な時間を取得できるので、リズムゲーム等、楽曲とゲーム内時間を同期する必要があるゲームでは後者を使用します。
用途次第で使う方を決めてください。
ちなみにGetTimeSyncedWithAudioを使わない場合は、new CriAtomExPlayer();で引数にtrueを指定せずにCriAtomExPlayerのインスタンスを作った方が処理負荷を抑えられます

GetTimeについて
GetTimeのグラフ
中級編05 音声の再生時刻を取得する(通常取得・再生済みサンプル数編) - CRIWARE for Gamesより
GetTimeSyncedWithAudioのグラフ
GetTimeSyncedWithAudioのグラフ
中級編06 音声の再生時刻を取得する(音声同期タイマ編) - CRIWARE for Gamesより

CriAtomExPlayer.GetTimeとCriAtomExPlayback.GetTimeの違い

GetTimeSyncedWithAudioはCriAtomExPlaybackにしかないのですが、GetTimeはCriAtomExPlayer版とCriAtomExPlayback版があります。
結論から言うと、CriAtomExPlayback版を使いましょう。つまり上記のコードでOKです。

CriAtomExPlayerのドキュメントにはこう記されています。

同一プレーヤで複数の音声を再生し、本関数を実行した場合、本関数は "最後に"再生した音声の時刻を返します。
複数の音声に対して再生時刻をチェックする必要がある場合には、 再生する音声の数分だけプレーヤを作成するか、または CriWare.CriAtomExPlayback::GetTime 関数をご利用ください。

CRIWARE Unity Plugin Manual: CriAtomExPlayer クラス

対して、CriAtomExPlaybackのドキュメントはこちら。

CriWare.CriAtomExPlayer::GetTime 関数と異なり、本関数は再生中の音声ごとに時刻を 取得可能ですが、再生終了時刻を取ることができません。

CRIWARE Unity Plugin Manual: CriAtomExPlayback 構造体

基本的にはCriAtomExPlayback版でOKです。
「再生終了時刻を取ることができません」というのは、再生終了後に再生時間が-1になってしまうことを指しています。

CriAtomExPlayerとCriAtomExPlaybackのGetTimeの違い
GetTimeがCriAtomExPlayback版、GetTime2がCriAtomExPlayer版。楽曲の再生が終わった後に取得した様子
GetAudioSourceLengthについては後述

再生終了時刻は後述の方法で別途取得できます。
CriAtomExPlaybackを使えないシチュエーションでのみ、CriAtomExPlayer版を使うといいでしょう。

再生終了時間の取得

TimeTestClassに以下のメソッドを追加してください。
※Updateメソッドは上書きしてください

    void Update()  
    {
        Debug.Log("GetAudioSourceLength:" + GetAudioSourceLength());
        Debug.Log("GetTime:" + GetTime());
        Debug.Log("GetTimeSyncedWithAudio:" + GetTimeSyncedWithAudio());
    }

    public long GetAudioSourceLength()
    {
        CriAtomEx.CueInfo cueInfo;
        // CueInfoが読み込めなかった場合は暫定で-1を返す
        if (!_exAcb.GetCueInfo(_cueSheetName, out cueInfo))
            return -1;

        return cueInfo.length;
    }

単位はGetTimeやGetTimeSyncedWithAudioと同じミリ秒です。
1秒ちょうどのSEなら1000、2分ちょうどの楽曲なら60秒*2*1000=120000が返ってきます。

実はこれがこの記事を書こうと思ったきっかけで、ドキュメントを色々読んで実装にこぎつけました。
コードに起こしちゃえば簡単なんですけどね。
再生終了時間を知りたいことって結構あると思うんですが、意外と使わないんでしょうか……?

戻り値の型について

ADXから取得できる再生時刻・再生終了時刻は、戻り値の型がlongになっています。
しかし実際のところはint(32bit)の精度しかありません。

戻り値の型は long ですが、現状、32bit以上の精度はありません。
再生時刻を元に制御を行う場合、約24日で再生時刻が異常になる点に注意が必要です。
( 2147483647 ミリ秒を超えた時点で、再生時刻がオーバーフローし、負値になります。)

CRIWARE Unity Plugin Manual: CriAtomExPlayback 構造体

つまり、int型にキャストしても情報の欠損がないということです。
long型よりもint型の方が扱いやすいでしょうし、キャストして使ってしまいましょう。

いずれは64bit精度に対応するのかもしれませんが、24日以上の再生を行う用途って限られますよね。
24時間稼働しているオンラインゲームとかだと問題になることがあるのかな?
ADX自体はゲーム以外にも使えますし、24時間投影の街頭ビジョンとか?

  • URLをコピーしました!
目次