How to use DSP Clock to get a more accurate GetTimelinePosition()?

Through browsing through the forums, I have seen that GetTimelinePosition() is not accurate and a possible more accurate solution is using DSPClock which I can get through:

eventInstance.getChannelGroup(out FMOD.ChannelGroup channelGroup);
channelGroup.getDSPClock(out ulong DSPClock, out ulong parent);

However I can’t wrap my head on how I’ll be able to get the current time through that as the number is large.

I read from here: Get Playback Time . That you will need to compare it to a value retrieved earlier in time (i.e. when the event instance was started. So I tried retrieving the DPS clock when my event started then retrieved it in update minus the initial but the number still doesn’t resemble time.

Can anyone help me with an example code on how to do it right? For my use case I’ll need to retrieve the current time of the event in the update loop. Haven’t seen actual code snippet on how to properly use it. Thanks in advance!

1 Like

getDSPClock returns the time in samples, so to get seconds you need to divide it by your sample rate. It should just be something like:

eventInstance.getChannelGroup(out FMOD.ChannelGroup channelGroup);
channelGroup.getDSPClock(out ulong DSPClock, out ulong parent);
FMODUnity.RuntimeManager.CoreSystem.getSoftwareFormat(out int samplerate, out SPEAKERMODE speakermode, out int numrawspeakers);
float timeSeconds = DSPClock / (float)samplerate;

Here’s my solution for an event instance that is going to be paused in runtime:
Using DSP Clock needs cached values so i minimalized caching as much as possible.
A more accurate solution would be using the eventInstance.setCallback method. That way the channelgroup is valid and you can get the DSP Clock IN the pinpoint accuracy of event.

private void UpdateSongEmitterDSPClockStart()
{
    RuntimeManager.CoreSystem.getSoftwareFormat(out int sampleRate, out _, out _);
    EventInstance instance = m_SongEmitterRef.EventInstance;

    if (m_SongEmitterDSPClockStart == 0) // ChannelGroup invalid in STARTING state. So in the next frame, without caching the playback state, you will gather the DSP clock when the song started again.
    {
        instance.getChannelGroup(out ChannelGroup channelGroup);
        instance.getTimelinePosition(out int timelinePositionInMilliseconds);
        channelGroup.getDSPClock(out ulong DSPClock, out _);
        ulong timelinePositionInSeconds = ((ulong)timelinePositionInMilliseconds / 1000);
        ulong timelineDSPClock = timelinePositionInSeconds * (ulong)sampleRate;
        m_SongEmitterDSPClockStart = (DSPClock - timelineDSPClock);
    }

    instance.getPlaybackState(out PLAYBACK_STATE playbackState);
    switch (playbackState)
    {
        case PLAYBACK_STATE.STARTING:
        case PLAYBACK_STATE.STOPPED:
        {
            m_SongEmitterDSPClockStart = 0;
        }
        break;
    }
}

private float GetSongEmitterTimelinePositionInSeconds()
{
    RuntimeManager.CoreSystem.getSoftwareFormat(out int sampleRate, out _, out _);
    EventInstance instance = m_SongEmitterRef.EventInstance;
    instance.getChannelGroup(out ChannelGroup channelGroup);
    channelGroup.getDSPClock(out ulong DSPClock, out _);
    UpdateSongEmitterDSPClockStart(); // This method should be removed and be called before this method.

    return (DSPClock - m_SongEmitterDSPClockStart) / (float)sampleRate;
}
1 Like