Examples on handling iOS AVAudioSession notifications?


#1

I get really confused on how to handle AVAudioSession notifications to satisfy the expectation of FMOD Studio on iOS.

I had a look at common_platform.mm found in the examples provided with Fmod Studio API. I find it listens to many AVAudioSession notifications, but all of them are simply printing logs without doing anything real. Even for AVAudioSessionInterruptionNotification where it calls gSuspendCallback, I find gSuspendCallback is not set anywhere. Does that mean I’m NOT expected to do anything with these notifications?

In contrast, the documentation explicitly says I should (or might? ) call mixerSuspend and mixerResume for addObserverForName:AVAudioSessionInterruptionNotification. I cannot find any call to these two functions in example code.

So should I call anything into FMOD for AVAudioSession notifications? Especially, how should I properly handle AVAudioSessionInterruptionNotification, AVAudioSessionRouteChangeNotification and AVAudioSessionMediaServicesWereResetNotification? Do I need to suspend or resume or reset anything of FMOD?

Is there example code that actually handles those notifications?

Thanks,


#2

The callback code in the common files are more for our own internal testing.

You will NEED to use mixerSuspend & mixerResume when handling interruptions, otherwise you will run into problems as FMOD will not be allowed to run in the background.

While these are not used in any of our examples, the code in the documentation you linked is the best place to start.


#3

First of all, I think if it’s called “examples” all the code included in it should be “examples” that we’re supposed to learn from, considering this is a closed-source software.

Second, the documentation of mixerSuspend says “All internal state will be maintained”, which I think it’s not true. When mixer suspends, the timeline playhead does not move forward. As a result, if the gameplay code keep playing sound, all of them will be stuck in memory and never finishes, and eventually run out of memory.

We considered adding a check around the PlaySound() function provided to gameplay code like if (mixerSuspended) then play else do nothing. But I realized it is also wrong: If I add this check, and if a BGM music is supposed to play on level load, and if the AVAudioSession is interrupted during level load, then the music never plays even when the session restores.

You must be already aware that it’s not only going to background that leads to the interrupted state, but also a phone call can hold the interrupted state for a long time even when the app is in the foreground. And we want to allow players to play during a phone call without running out of memory by all queued but not played sound.

So the situation is more complicated than just call mixerSuspend() on interruption begin and mixerResume() on interruption end. So it’ll be super helpful to have some actual example code that is not for internal testing.


#4

Thank you for the feedback, we are currently in the process of going over our examples and documentation.

MixerSuspend maintains the internal state by keeping everything alive in memory, any calls made to FMOD during this time will be added to the queue and be processed once MixerResume is called.
Because of this, MixerSuspend should be used when the game is in a paused state.

To play sounds in the background, you will need to configure the AudioSession to handle this:
https://developer.apple.com/library/archive/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/AudioSessionBasics/AudioSessionBasics.html