iOS AudioSession vs mixer

Hello! We encountered a problem with iOS AudioSession using FMOD.

You provide a guide on handling sessions, but I checked your iOS examples, and since version 2.02.23, they no longer follow that guide. The difference is that in newer versions, there are no mixerSuspend/mixerResume calls when the application moves to the background/foreground or when an audio session begins/ends an interruption.

I tested the simple_event example in different versions, and here are the results:

  • Version 2.02.23 and later (including 2.03.05):
    You can start sound by pressing B, then switch to the background (sound stops) and return to the foreground (sound continues playing) — which works fine. However, if you receive an incoming call or alarm and then dismiss it, the sound freezes. The application continues updating as usual (including the mixer), but no sound plays. Additionally, you cannot start any other sounds after that.
    I uploaded the video 20305.mp4 to my profile for reference. iOS version was 17.6.1
  • Version 2.02.22:
    In this version, mixerSuspend/mixerResume calls are present. However, sometimes an “interruption began” event is triggered when the application returns to the foreground, causing a mixerSuspend call and making the sound freeze. Unlike newer versions, if you switch to the background and then return to the foreground, the sound resumes playing.
    You can check video 20222.mp4 and the log file 20222log.rtf for details. iOS version was 13.5.1, it much more difficult to catch it on newer version but it’s possible.

So my question is: What is the proper way to handle iOS audio sessions, application suspensions, and activations?

Hi,

There were some changes to how FMOD handles interruptions and suspend/resume 2.02.23/ 2.03.02, which would explain the differences you’re observing between the versions you noted. It’s likely that the platform-specific docs weren’t updated to follow. I’ll take a look at your uploaded videos, our docs, and the expected behavior, and get back to you on this soon.

Thanks for the videos and log clearly demonstrating what you’re talking about.

To succinctly answer your question: the iOS platform specific docs are correct.

To expand on this: as part of the changes I noted with 2.02.23, our docs now state that “it is now the responsibility of the developer to interact with the AudioSession APIs native to this platform”. Essentially, we expect users to implement mixerSuspend/mixerResume calls themselves. This could be done in a few ways:

  • A pointer to the FMOD system object coreSystem can be passed to the iOS platform .mm code to call mixerSuspend/mixerResume, like it is in the docs
  • A pointer to a C++ function that calls mixerSuspend/mixerResume can be passed to the to the iOS platform .mm, similar to how FMOD for Unity handles this

However, the FMOD Engine examples are required to remain platform-agnostic, so the code example listed in the docs isn’t present - this is the discrepancy you’ve noted.

Personally, I do find it strange that the FMOD Engine example code doesn’t handle the suspend/resume calls, or doesn’t communicate the expectation that the user do so in some way. I’ve passed this along to the development team for further consideration.

Apple documentation offers specific techniques for handling Audio Session interruptions, and none of them suggest manually stopping sounds. The Audio Session handles this automatically for you. However, as you can see from your latest examples, FMOD does not handle such interruptions correctly—it stops playing entirely instead.

On the other hand, we can call mixerSuspend/mixerResume when necessary to help the FMOD engine handle such interruptions, but you need to provide an example of how to do it properly.

As previously stated, this is intentional in order to have the code remain platform-agnostic. I do think this should be changed though, and I have flagged some improvements with the development team.

The example in our documentation demonstrates how to do this. To get it to work with the FMOD Engine examples, you need to do the following:

  • Place the mixerSuspend/mixerResume calls in the documentation example in the same addObserverForName calls in common_platform.mm
  • Pass a pointer to your core FMOD system to Common_Init() as the extraDriverData argument
  • In Common_Init(), cast extraDriverData back to FMOD_SYSTEM* and store it as coreSystem so it can be called from within common_platform.mm

The example in our documentation demonstrates how to do this.

Such way is implemented in FMOD examples version 2.02.22 and earlier. Initially I’ve also uploaded the video with the work of this example, you can check it (20222.mp4 and 20222log.rtf). It also doesn’t work properly. The problem is here:
There is no guarantee that a begin interruption will have a corresponding end interruption
But your docs and examples expects session calls in pairs.

So there is no problem of passing fmod system object to the right place or call mixerSuspend/mixerResume in the way as documentation says, there problem is that such way is also doesn’t work.