Unscaled equivalent of Audiosettings.dsptime?


I have a following problem: I have a progressive music system in Unity that tracks the point where loops should change with Audiosettings.dsptime. It works great. However, I implemented a feature which keeps the music playing when the game is paused (with lower volume and a lowpass filter), but this obviously messes the timing system up.

I tried to track time with a unscaled deltatime -based timer on Update, and it works for some time, but after some dozen seconds or minutes it gets messed up. The point in which it messes up seems random, and I haven't been able to point out anything specific that would cause it.

    private void Update()
        if (unscaledTimer > goalTime - .2f) PlayTimedProgressiveLevelClip();
        unscaledTimer += Time.unscaledDeltaTime;
    void PlayTimedProgressiveLevelClip()
        AudioClip clipToPlay = currentLoopClips[0];
        if (currentLoopClips.Count != 1) while (earlierClip == clipToPlay) clipToPlay = currentLoopClips[Random.Range(0, currentLoopClips.Count)];
        earlierClip = clipToPlay;

        if (audioSource2Next == true)
            SoundManager.Instance.musicSounds2.clip = clipToPlay;
            SoundManager.Instance.musicSounds.clip = clipToPlay;
        clipDuration = (double)clipToPlay.samples / clipToPlay.frequency;
        goalTime += clipDuration - lvlMusicAudioTailTime;
        audioSource2Next = !audioSource2Next;

Any ideas?

I believe the slippage you're experiencing is due to the precision of Time.unscaledDeltaTime. Although it is conceptually right to use that, you should probably use AudioSettings.dspTime for all your time sensitive calculations.

In your code, I would suggest you get rid of unscaledTimer and simply compare goalTime to AudioSettings.dspTime everywhere. That should make it more consistent by keeping the highest precision in that context, and might fix your issue.

Thanks for the reply! However in my case that is not the solution, since I have audiolistener on pause during the pauses. But I managed to find an ok workaround for it. I just start a coroutine which waits for the duration of the clip currently playing, after which it starts playing the next one. It's not as precise but works well enough.

1 Like