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.