Transitions latency when changing parameter

I’ve checked with our API development team, and they’ve informed me that this isn’t a bug.

FMOD Studio schedules instruments to start playing a little ahead of when they actually play. This behavior is necessary for content to be scheduled with to-the-sample accuracy. The playback position’s location, on the other hand, indicates the content that is actually currently playing.

This can be seen in your video: If you look closely, you’ll see that the multi instrument at the destination marker lights up a moment before the playback position arrives. This lighting up indicates that it has been scheduled to start playback. The instrument doesn’t actually start producing output until a few moments later, when the playback position arrives at the destination marker.

1 Like

Thank you Joseph. So does this mean that it is not possible to use parameters play a sound, without getting a delay?

I hope there’s a workaround for this, as I put up many things in my game to play like this :crossed_fingers:

There will always be some latency between calling setParameter and the instrument starting to play, as it is physically impossible for a consequence and its cause to be simultaneous. Usually this delay isn’t significant enough to cause problems, as it’s small enough that an end user won’t notice it.

That said, if it’s important to your project to reduce this delay, there are ways to do so, but each way has its own limitations. What behavior are you trying to achieve in-game, and why is having low latency on a parameter value change important for that behavior? If you give us more information about what you want, we’ll be better positioned to suggest solutions.

Alright, thanks for helping me out Joseph!

Here’s an example of when I get a problem with the latency:
I’m working on a soccer game, where my music event starts playing a looping drone when the level starts. I have a parameter called “FirestBallTouch” that is set to 1.0 when a player touches the ball.
This parameter starts a drum loop, but that does not feel very good, when there’s a latency.

Another example is my “KickBall” event. The event starts playing a charge sound. I have a parameter called “KickBallAfterCharge” and one called “LostBallDuringCharge”. The first one play a kick sound and the second one play a silly “swuup sound”. Again these does not feel good with latency.

In both scenarios I’m using a transition region to move the playhead whenever the parameter is set to one. Of course I could play new events from my code instead, but that seems much more messy, as I would then have to stop one event and start another one. And using one event also makes it possible to use transition timelines :slight_smile:

Thanks again

Further investigation has revealed a latency issue that was missed when we were making the latency fixes for FMOD Studio 2.00.00. This issue results in approximately 20 milliseconds of additional latency when making a parameter value change compared to starting a new event. We’re still investigating the cause of this bug, but will include a fix in an upcoming release of FMOD Studio.

Until this bug is fixed, stopping one event and starting another may be your best option for reducing latency.

That sounds great Joseph - hope I will be able to bring that to GamesCom in August :slight_smile:

Can you say if this will be fixed both for 1.10.13 and 2.00.00?

Both 1.10.13 and 2.00.00 have already been released, and will not change; the fix will be included in future patch releases, not existing ones. Perhaps 1.10.14 and 2.00.02, or 1.10.15 and 2.00.03, or some other future releases.

In any case, we’re still investigating this bug, and have not yet identified its cause. As such, there’s no way for us to estimate how long it will take to fix at this time.

Alright thank you Joseph – I’ll keep my fingers crossed :slight_smile:

Can you tell if this has been fixed in the recent 1.10.15 or 2.00.03 update? Finger crossed that I don’t have to make workaround for this before showcasing our game at GamesCom :grimacing:

Those versions do not include a fix for the 20 ms latency issue. Given that GamesCom is imminent, I recommend pursuing that workaround.

Hi Joseph!
What is the cause of the 20 ms latency issue?


I’m experiencing a similar issue with my music system, where the transitions don’t trigger correctly if I don’t manually insert some latency by either waiting for about 5 frames or waiting for 30 ms.

Here’s how my event is set up:

I have several songs in nested events, inside the main “musicController”-event.
All the songs can be accessed through the “00 Selection Loop” by switching the “Song”-parameter to their appropriate indexes (setup as integers: 01, 02, 03, etc).
All songs can go back to the “00 Selection Loop” by switching the “Song”-parameter to 0.

This means that in order to go from Song 02 to Song 04, FMOD would have to do like this:

Song 02 → 00 Selection Loop → Song 04


I’ve implemented this solution in Unity by doing the following in a Coroutine:

Frame 0
CurrentParameterValue == 2f
SetParameter to 0f
yield/wait 1 frame (for Fmod to to switch to the Selection Loop)

Frame 1
CurrentParameterValue == 0f
SetParameter to 4f
CurrentParameterValue == 4f


When I print the parameter value during each stage of the process (Before switching, In-Between Switching, After Switching), the parameter values I get back from the API are correct, and the music/audio is most times also correct.
But the bug I’m encountering is that sometimes the actual audio of the event is stuck on the first song. Ie. the switch to the “00 Selection Loop” never happens.

My workaround so far for this is to yield/wait for 5(!) frames or wait for 30 ms (as described above) between Frame 0 and Frame 1. When I do that, the music switches correctly, at least so far as my testing has proven.

But, doing that is pretty hacky.


So my question is:

Since this game is going to be released on several platforms (PS4, XBONE, Switch, PC, etc), which approach should I use?

  • Waiting for an arbitrary amount of frames (which could differ on the different platforms)?
  • Or should I rather wait for a set amount of time (which may or may not correspond to the same amount of frames on different devices)?

Regards,

Pablo Sorribes Bernhard
contact@pablosorribes.com
pablosorribes.com

Hi Paalo

We’ve been able to reproduce this issue in a simple example and what I believe is happening when the audio gets stuck on a song is that the calls to set the controlling parameter’s value to zero and then the new song index are landing in the same (asynchronous) FMOD Studio update. API commands are processed at the start of our update, followed by scheduling logic. When two commands to set a parameter’s value are processed in the same update they will both be evaluated before we perform scheduling, so in this case the scheduler never sees the parameter value of zero and never triggers the transition from the playing song to the selection loop, therefore it won’t transition to the new song.

I’ll log a bug for this, in the meantime the best way for you to workaround the issue is to call Studio::System::flushCommands after you’ve set the song parameter to 0 and before you set it to the new song index. This will force the set parameter command to be evaluated, setting the parameter value to 0, and the scheduling logic to be performed, triggering the transition to the selection loop.

Cheers
Derek

1 Like

Hi Derek,

Would the workaround calling Studio::System::flushCommands after haveing changed a parameter generally be a good workaround for avoiding the latency the transitioning using parameters bug?

Cheers,
Nikolaj

EDIT:
I summarized my bug, the solution and my results in a separate thread:


Hi Derek!
Sorry for the late response, I wanted to make sure that the workaround was effective.

We have now tested the game with the workaround you suggested and it worked for us. So far we haven’t been able to reproduce the issue, neither on PC nor Nintendo Switch. So thanks a lot, I was on the edge of considering to remake the entire music/ambience system.


Some notes for other devs with similar issues:
The biggest challenge was to find/make a valid FMOD::Studio::System-object which was properly initialised. The solution for that was to use the one provided on the FMODUnity.RuntimeManager.

So the final code snipped that did the trick looks like this:
FMODUnity.RuntimeManager.StudioSystem.flushCommands();


If anyone’s interested, here’s the code for the entire Coroutine which handles the switch of music/ambience:

	/// <summary>
	/// Simplifies the Fmod-event by allowing the timeline to jump back to zero for a frame, 
	/// then jump to the desired song/ambience.
	/// <para></para>
	/// Also checks if the desired music/ambience is the same as the current one. In that case, it will do nothing.
	/// </summary>
	private IEnumerator SwitchAudioCoroutine(int desiredMusicSong, int desiredAmbienceType)
	{
		//The "_Fmod"-class just contains a bunch of variables with public readonly strings 
		//to avoid someone doing a typo somewhere, and propagate name-changes from one centralized place.
		//So the values are:
		//_Fmod.Params.song == "song"
		//_Fmod.Params.variation == "variation"

        //Just making sure that the value doesn't get truncated (ie. float 0.9 → int 0, which is not the desired result).
		int currentMusicParamValue = Mathf.RoundToInt(AudioManager.Instance.GetParameterValue(musicController, _Fmod.Params.song));
		int currentAmbienceParamValue = Mathf.RoundToInt(AudioManager.Instance.GetParameterValue(ambController, _Fmod.Params.variation));

        //Only go to selection loop if we actually are changing the desired music/ambience
		if (currentMusicParamValue != desiredMusicSong)
		{
			musicController.SetParameter(_Fmod.Params.song, 0);
		}
		if (currentAmbienceParamValue != desiredAmbienceType)
		{
			ambController.SetParameter(_Fmod.Params.variation, 0);
		}

        //Wait a frame for the parameter change to take effect.
		yield return null;

        // HACK: Fmod has latency when switching with parameters and transition regions (https://qa.fmod.com/t/transitions-latency-when-changing-parameter/14383/28)
        // Therefore we flush the fmod thread, so that all the polled commands will be executed first, before continuing Fmod's internal (asynchronous) update.
        // This makes it *actually* register the last frame's parameter change (ie. setting it to 0, triggering a transition to the "selection loop"), 
        // before changing the parameter to the desired music/ambience.
        FMODUnity.RuntimeManager.StudioSystem.flushCommands();

        //Set the music/ambience to the desired values.
        musicController.SetParameter(_Fmod.Params.song, desiredMusicSong);
		ambController.SetParameter(_Fmod.Params.variation, desiredAmbienceType);
	}

Also, to get the parameter value, here’s the code for that:

public float GetParameterValue(FMODUnity.StudioEventEmitter eventEmitter, string parameterName)
	{
		FMOD.Studio.ParameterInstance parameterInstance;
		float paramValue;

		eventEmitter.EventInstance.getParameter(parameterName, out parameterInstance);
		parameterInstance.getValue(out paramValue);

		return paramValue;
	}

Hi deHaan

It might be worth trying out but I wouldn’t expect too much. There is potential to reduce some latency between your code calling the FMOD API to set a parameter value and FMOD processing the command, but I think most of the latency you are experiencing is probably scheduling delay which can’t be worked around.

Any chance this got fixed in 1.10.16? :pray: We’re gettting closer to release date, and I would love those transitions to be snappier :slight_smile:

Or in 1.10.17? I don’t see any revision history for those updates :slight_smile:

1 Like

So, we’re soon about to release our game, and still have the latency issue, which kind of sucks :frowning: Are there any workarounds? (It is a soccer game, and I want the music to go to a marker right when the players touch the ball during the 2nd half of the game…)

Just to make things clear, the observed transition latency is not something we are addressing as a bug, so there is no easy fix to wait for. Allow me a moment to explain the latency you’re seeing.

When something is put on the timeline, we evaluate ahead of time to ensure playback is sample accurate and smooth. If streams are used anywhere, this will add latency because we need to ensure they are buffered up ready for playback. So my first tip is don’t use streams anywhere in an event to reduce its latency. This latency is called scheduling delay.

Secondly, FMOD internally updates every 20ms unless you change this setting via FMOD_STUDIO_ADVANCEDSETTINGS. To ensure no gaps in timeline playback we schedule double that time in advance, so 40ms. When you have a condition on the timeline it is evaluated ahead of time, this is probably the latency you are seeing. To reduce this latency you can change the Studio update rate to 10ms, halving the latency. This latency is called scheduling lookahead.

If there is a particular EventInstance where you want to override these settings take a look at EventInstance::setProperty with FMOD_STUDIO_EVENT_PROPERTY_SCHEDULE_DELAY and FMOD_STUDIO_EVENT_PROPERTY_SCHEDULE_LOOKAHEAD. Use these with care though, as I mentioned above setting too small could cause sample inaccuracy.

If the above doesn’t help you may need to consider engineering the Event differently.

Hmm. I seem to be having a similar issue, but it seems to depend on where my playhead is. It’s almost like sometimes it waits for the instrument to finish as if it has some kind of async setting on it. Screen capture provided that shows my transition happening correctly first, and incorrectly the second time. Thank you for your time.

~Cameron

EDIT 01: I should note before it is asked, that 2nd track is set to async, but the problem persists when async is toggled off.

EDIT 02: Seems to work now. I had an unused LFO modulator on the parameter, and once I removed it my problem went away.