Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling interruptions in CoreAudio / iOS #325

Closed
jskuse opened this issue Jun 22, 2021 · 8 comments
Closed

Handling interruptions in CoreAudio / iOS #325

jskuse opened this issue Jun 22, 2021 · 8 comments

Comments

@jskuse
Copy link

jskuse commented Jun 22, 2021

In modern versions of iOS, incoming phone calls are displayed as a banner on top of apps rather than as a full screen UI forcing the current app into the background. We've noticed that this results in the app audio being interrupted while the app is still active, generating the notification AVAudioSessionInterruptionNotification and unless we stop the device when the interruptions starts and then restart at the end, the audio doesn't return.

In our version of miniaudio we've added this functionality to ma_router_change_handler since it's already perfectly set up to handle such a thing, and it's resolved the issue. But, of course it could also sit outside of miniaudio in the application code. I'd be happy to tidy up and submit a pull request, but I'm wondering if philosophically you regard handling this as within the scope of the library?

Ref: https://developer.apple.com/library/archive/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/HandlingAudioInterruptions/HandlingAudioInterruptions.html

@mackron
Copy link
Owner

mackron commented Jun 23, 2021

Yes, I'm absolutely supportive of adding support for this directly to miniaudio. For your use case, is it literally just a matter of calling ma_device_stop() followed later by a ma_device_start()? Is there any other management needing to be done?

Do you think it might also be useful to allow plugging in a callback for handling the interruptions in case the program wants to do something more specific?

@jskuse
Copy link
Author

jskuse commented Jun 27, 2021

Great! In our particular case (where audio is not critical to the function) it really is just as simple as just stopping and resuming the device, however for the majority of mobile apps I'd think you definitely would want a callback, both for interruptions and route changes (eg. if someone unplugs headphones an audio or video app would typically pause).

None of that is complex to implement so far as iOS is concerned, but it does beg some questions, eg. would those callbacks be implemented as part of the .coreaudio part of the context config, or as a general thing with the aim of supporting all platforms where applicable? To what extent could parameters informing the developer what type of device a route change is from or the nature of an interruption can be generalised cross-platfom? etc.

@mackron
Copy link
Owner

mackron commented Jun 27, 2021

Most likely I'd make the callbacks generic so that platforms like Android can make use of them. They'd just never get fired for platforms where it's not a real concept. If you do end up wanting to do a PR you can just make it specific to Core Audio as I start. I can just iterate on it later.

@mackron
Copy link
Owner

mackron commented Dec 28, 2021

Did you ever get around to finishing your implementation for this? I've added a new more general notification system to miniaudio to replace the old stop callback system. I've put a couple of placeholder event types called "interruption_began" and "interruption_ended" in anticipation for this. Basically, you register a callback and implement it like this:

void on_notification(const ma_device_notification* pNotification)
{
    MA_ASSERT(pNotification != NULL);
    
    switch (pNotification->type)
    {
        case ma_device_notification_type_started:
        {
            printf("Started\n");
        } break;

        case ma_device_notification_type_stopped:
        {
            printf("Stopped\n");
        } break;

        case ma_device_notification_type_rerouted:
        {
            printf("Rerouted\n");
        } break;

        case ma_device_notification_type_interruption_began:
        {
            printf("Interruption Began\n");
        } break;

        case ma_device_notification_type_interruption_ended:
        {
            printf("Interruption Ended\n");
        } break;

        default: break;
    }
}

I was thinking that in the case of iOS interruptions we'd just fire this notification callback from AVAudioSessionInterruptionNotification which would allow an application to handle the interruption however they'd like. Do you think that sounds reasonable?

@meshula
Copy link

meshula commented Dec 28, 2021

That looks reasonable to me - I would definitely make use of that. Perhaps accompanied by a bit of documentation with the OP notes for troubleshooting and resolving audio drops after the app is interrupted?

@mackron
Copy link
Owner

mackron commented Dec 29, 2021

I've done some initial work on integrating the new notification system with AVAudioSessionInterruptionNotification. It's in the dev branch. Unfortunately all I have available to me is the simulator and I'm not sure how to trigger the interruption. Is anyone able to give that a test before I release it?

Commit: afc0fc1

@jskuse
Copy link
Author

jskuse commented Dec 29, 2021

Hi David, thanks for the nudge! Yep, we've got an implementation which has been live for a few months now under heavy usage and seems to be holding up very well.

However I've noticed a handful crashes in the logs relating to interruptions which are on my todo list to look at in the new year. When I do that I'll see if I can bring miniaudio up to date and integrate everything and then see about doing a pull request.

@mackron
Copy link
Owner

mackron commented Jan 1, 2022

I've gone ahead and released this change (needed to get some other bug fixes out). I'm going to assume this is working, but if you find a bug with it later on we can treat it as a new issue. Thanks for pointing me in the right direction for how to handle this.

@mackron mackron closed this as completed Jan 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants