Pausing an event smoothly

Hi everyone,
I made some searches on this forum but I sadly cannot get my head around this problem, so I hope I will not stir a pot that has already been stirred too much :slight_smile:

I am a composer, I am currently using FMOD to put music in a game, and we are currently designing the way sounds get paused when pausing the game. I am not a developer though so my knowledges are limited to basic functions, so please excuse me if some stuff I say are a bit unprecise or ingenuous.

To be clear, what we want is basically pausing the music so it doesnā€™t goes out of sync with the gameplay, since some music is synced with actions in the game.

I am already aware of the different ways to pause an event (the ā€œsetPausedā€ method and the ā€œget/setTimelinePosition with event stopping and starting again in betweenā€ method) but neither are really satisfying for the following reasons :

  • setPaused pauses the music (yes) but does it abruptly without any fade out, even creating clicks sometimes which is unpleasant. Same goes when unpausing the game. We are using this method for now but is not satisfactory for the aformentioned reasons, and basically it would be perfect if it could trigger a fade-in/fade-out ;

  • get/setTimelinePosition is not satisfactory either since we are already using an ADSR enveloppe for when the game transitions from the end of a level to the next one, and the release is quite long (3-4 seconds), which is not compatible with a pause state (a 100ms fade out should be enough for our needs). I am also unsure of what happens with the different parameters used during playback in this case.

I was thinking of another solution but I am not sure it is possible : to call a fadeout/fadein on the corresponding event from the code specifically for the setPaused state, and maybe add a setTimelinePosition before setPaused being set untrue to counterbalance the time lost during fadeout.

What do you think we can do ?

As a suggestion for the future of FMOD, I think having different ADSR behaviors for the pause state and the stopped state in FMOD would be super useful. Iā€™d go even further as to say that having different ADSR behaviors even inside the two categories would be super useful since an event can be paused or stopped for a lot of different reasons gameplay-wise, but also artistically-wise.

Thank you in advance for your answers, and have a great day !

Louis

3 Likes

Interesting question! I also would want a solution for that! :smiley:

Isnā€™t it possible to trigger a snapshot which fades out the master bus, just before setting the pause?

Youā€™re right that setPaused canā€™t trigger a fade-out. This is actually a requirement of certain operating systems, and so not something weā€™re likely to change.

However, it should be possible to impose a fade-out on your music just before using setPaused through a variety of methods.
For example, as Alcibiade suggested, you could create a snapshot with an AHDSR modulator on its intensity, and have it set the volume of the group bus into which your music event is routed. Because this is a separate AHDSR modulator to the one used in your event, you would be able to set its attack and release periods to be different than those one used by the AHDSR modulator in your music event.

Iā€™m afraid I donā€™t understand what you mean by this question.

Hi everyone, and thank you for your answers !

Joseph, my concern was the following, sorry for not being clear about it : if we play an event that uses parameters (which may be used to trigger transitions, automations, etc), does getTimelinePosition
keeps in memory the states of these parameters if we kill the event after and on the other hand, does setTimelinePosition sets the aformentioned parameters to the values that they had when we used the getTimelinePosition ?

An example. For a friend. Totally not from the game I am working on. :smiley:

I have this event with a music progression throughout a level. It is made of various loops and we make the players navigate from a loop to another (through transition regions and such) depending on the zones they trigger, using a parameter called MusicPosition.

So for example we are at the hangar, which is supposed to be a zone in which you have been through various boxes that end up setting the MusicPosition parameter up to 4. If we use getTimelinePosition during pause (implying killing the event in between if I understood it correctly), will the MusicPosition parameter get back to 4 when we unpause the game and use setTimelinePosition ?

In other words, does get/setTimelinePosition store only the Timeline position or does it store also the different parameters values at the moment the getTimelinePosition is used ?

Let me know if this is still unclear. Have a great day !

Parameters has nothing to do with timeline position, so no. But why would you kill an event after having paused it? Unless ā€œkillā€ means ā€œpauseā€?..

I suspect you have not understood getTimelinePosition correctly - or perhaps I have not understood what you mean by ā€œkill.ā€ getTimelinePosition retrieves the value of an event instancesā€™s timeline in milliseconds so that you can know which part of that timeline is currently playing (or would be playing if the event was unpaused). This has no effect on the playback or behavior of the event instance, regardless of whether that event is paused. It definitely does not kill, stop, release, steal, virtualize, or otherwise end the event instance.

setTimelinePosition also does not kill, stop, release, steal, or virtualize the event instance. Instead, it sets the value of the event instanceā€™s timeline parameter. As I mentioned above, if the event is paused when this function is called, the new value will not be applied until the event is unpaused.

Because of this point of confusion, I canā€™t be sure I understand what youā€™re asking - but I can think of a few possibilities, which the following dot points should address:

  • A paused event instanceā€™s parameter values do not change when or while it is paused. If you set an event instanceā€™s parameter values (including its timeline value) while it is paused, it accepts the new parameter values and remembers them, but does not actually apply them until the event is unpaused. When a paused event instance is unpaused, those new parameter values are applied at that moment, as if they had been set the instant after the instance was unpaused. (If a parameter is set multiple times while an event instance is paused, only the most recent value will be applied when it is unpaused.)
  • Stopping an event instance resets its timeline to 00:00.000 and has no effect on its other parameter values. If you set an event instanceā€™s parameter values while it is stopped, the changes will take place immediately. Local parameters set while an event is stopped will not respect their seek speed properties.
  • Stopping an event instance and releasing it clears away the event instance, along with its parameter values.
  • Newly created event instances have new local parameter values, unrelated to those of other event instances. These values are based on the initial values of their respective parameters by default, though they can of course be set by a variety of means.
  • Virtualized event instances maintain their parameter values and update them as if the instance was not virtualized, allowing the event to resume as if it had been non-virtual the whole time when it is subsequently unvirtualized.
  • Event instances that are stolen by stealing behaviors other than ā€œvirtualizeā€ are stopped, as described above.

Thank you for your answer !

I did not explain the ā€œkillā€ thing in the first place so I indeed took a shortcut that lacked some context.

In short, I read somewhere (probably on this forum) about someone who wished to pause the music while the game was in pause. This person was explaining that in the end they were using getTimelinePosition, then stop the event in order to use the ADSR curve (in my mind stop=kill), then use setTimelinePosition and then play the event from the point it stopped. Thatā€™s why I had all those questions about ā€œwhat happens to the parameters valuesā€ when we stop the event, but it was clear in my mind that set/getTimelinePosition had no effect on playback or behaviors. Sorry for the messy questions !

I now understand (and I probably wouldā€™ve a little sooner if I had thinked about it for maybe 10 more minutes) that there is indeed no need to kill any event to do what we want to do :slight_smile:

We found our own way through this with the team thanks to your answers. Thank you again for your time and patience !

Have a great day.

Sry guys, a reply from 2025šŸ˜‚

We are also facing such problem. I kind of understand the idea which Alcibiade suggested, but wonder how to implement it both in program and fmod.

My approach is here:

  1. I create a snapshot which apply adhsr by its intensity. The intensity is controlled by a paramter ā€œisPauseā€. ā€œisPauseā€ has a seek speed.
  2. On the coding side, I have a method ā€œPauseā€. It set the parameter ā€œisPauseā€ to 1 and let the seek speed do the job of fading out. And I should call the FMOD method setPaused(true) at some point.
  3. To unpause the track, I can implement a method called ā€œUnpauseā€. It set the parameter ā€œisPauseā€ to 0, and call setPaused(false)

Here comes the problem, I still need to call the FMOD setPaused(true) right? But at which point?

  1. In the Pause method, I call Fmod setPaused(true) after x second. x second should match the seek speed of parameter ā€œisPauseā€
  2. Is there any way that fmod can call setPaused() instead. I mean, since we already have the paramter seek speed, I prefer not to add another ā€œx secondā€ in my code.

Hope Iā€™ve made it clear. Thanks.

As of the time of writing (March of 2025), there is no way to create an event or other element of an FMOD Studio project that automatically calls setPaused() on an event instance after a specific period of time. (If there was such a way, it would likely be a type of command instrument.) You will therefore have to create this behavior in your gameā€™s code.

Thanks for reply. Hence we will try to call the pause manually in out code.