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
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 !
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.
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.
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.
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
We found our own way through this with the team thanks to your answers. Thank you again for your time and patience !
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:
I create a snapshot which apply adhsr by its intensity. The intensity is controlled by a paramter āisPauseā. āisPauseā has a seek speed.
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.
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?
In the Pause method, I call Fmod setPaused(true) after x second. x second should match the seek speed of parameter āisPauseā
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.
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.