Command instrument activates ahead of playback cursor during loop?

So I’m trying to recreate a cd player semi randomly glitching on a track and the solution I have is to use tiny loop regions coupled with command instruments to pick a number at random and then decrement it per loop, allowing the loop to break out when the count hits 0:

image

This kinda works except I can see that the parameter is decrementing ahead of the playback cursor. For example if I fix the loop count to anything below 4 then the count hits 0 before the cursor even reaches the end of the loop region once. Obviously an easy fix is to set the minimum value of that parameter to 4, which is all good, but it’d be great to know if there is a less hacky way to do this?

Also, what I really wanted was to have these little loop glitches occur randomly at any point, as opposed to just where I’ve put the loop regions. I can’t think of a way to do this though, there’s no way to arbitrarily push the playback cursor back a fixed amount is there?

Thanks for bringing this issue to our attention! This appears to be a bug, so I’ve added it to our bug tracker. It’ll be fixed in an upcoming release of FMOD Studio.

In the mean time, I’m afraid you’ll have to use the workaround you have already discovered.

You can use Studio::EventInstance::getTimelinePosition to get the currentposition of the timeline, and Studio::EventInstance::setTimelinePosition to set it to a new value. If you use these two API calls in your game’s code, in combination with a simple mathematical operation, you should be able to decrement the timeline of an event instance by an amount of your choosing at any time.

Thanks for getting back to me about this. I was trying to keep the solution in FMOD if at all possible but actually an externally scripted solution seems pretty straightforward. I’ll have a play around with it and see what I can do. If I do this with a streaming file will that create issues with latency if I’m rapidly changing the timeline position over and over? Or will a chunk of that event stay in memory even after the timeline has moved past it?

These API calls are both part of the FMOD engine.

A stream works by continually loading each piece of the asset to be played into a memory buffer only moments before it plays, then immediately unloading it once it has played. Unexpectedly moving the playback position therefore renders the content already loaded into the buffer invalid, and necessitates loading new content from the playback position’s new location in real time. In such a case, latency is unavoidable.

Oops I meant within FMOD Studio :man_facepalming:

Thanks for clarifying how streaming works, it’s really useful to get that context. I’ll keep everything in memory then!

Ok so I’ve got this solution implemented in Csharp and it mostly works great, the only issue is that when doing loops by repeatedly jumping timeline position there are often quite audible clicks/pops. If I recreate the exact same scenario with a loop region in Studio then there are no pops at all. I’m guessing this is because behind the scenes Studio is doing mini crossfades when it loops? Is there an easy way to recreate this using API calls?

Thanks for all your help by the way!

The FMOD Studio System is supposed to do do short fadeouts when stopping sounds via those API calls, so I’m not sure why it’s no doing so in your situation. Are you able to send us a profiler session that exhibits the issue?

Sure, I’ve uploaded it here: WeTransfer - Send Large Files & Share Photos Online - Up to 2GB Free

I noticed afterwards I’d incorrectly set 5.1 instead of stereo, but i tested again in stereo and got the same results.

This is the code I’m using to make the timeline jumps:

 private IEnumerator Skipper(int SkipNumber, int TimelineJumpPosition, int TimeSkipAmount)
    {
        while (SkipNumber > 0)
        {

            Player.setTimelinePosition(TimelineJumpPosition);
  
            SkipNumber--;
            yield return new WaitForSeconds((float)TimeSkipAmount / 1000);
        }

        IsSkipping = false;
    }

I have reproduced the issue here, and it looks like the pops are occurring because the event is set to instantaneous scheduling mode. FMOD Studio sets this scheduling mode automatically when an event has only one sound in it, because it reduces latency when starting the event. However, it does mean that when setting the timeline position, the fadeouts on sounds that are being stopped don’t get set up properly.

We are still evaluating options to fix this issue, but for now you should be able to work around it by calling eventInstance.setProperty(FMOD.Studio.EVENT_PROPERTY.SCHEDULE_DELAY, bufferlength * 2), where bufferlength comes from the FMOD.System.getDSPBufferSize() function (usually 1024).