mackron / miniaudio

Audio playback and capture library written in C, in a single source file.
https://miniaud.io
Other
4.07k stars 361 forks source link

[COREAUDIO] On iOS, audio doesn't come back after interruption #400

Closed alexandrebeaudet closed 2 years ago

alexandrebeaudet commented 2 years ago

On iOS 15.2, iPhone 11, using miniaudio-0.11.2 through 0.11.4

We've tried to update to latest miniaudio version to benefit from the integrated audio interrupt handling features but it doesn't work as expected. The interruption_began is detected when audio goes off, but after interruption_ended, the audio doesn't come back :/

Before this feature, we were using a patch that we made, catching the interrupt began/ended events and recreate the whole ma_device ourselves.

While trying to find the reason the audio didn't came back, we've seen the ma_device_stop__coreaudio waiting ad vitam at line 33325 (ma_event_wait(&pDevice->coreaudio.stopEvent);). The ma_event_wait__posix blocks on pthread_cond_wait((pthread_cond_t*)&pEvent->cond, (pthread_mutex_t*)&pEvent->lock); (line 15573)

Here's miniaudio debug output fwiw :

INFO: [Core Audio] Interruption: AVAudioSessionInterruptionTypeBegan
INFO: [Core Audio] Route Changed: AVAudioSessionRouteChangeReasonCategoryChange
DEBUG: [Core Audio] Changing Route. inputNumberChannels=2; outputNumberOfChannels=2
INFO: [Core Audio] Route Changed: AVAudioSessionRouteChangeReasonCategoryChange
DEBUG: [Core Audio] Changing Route. inputNumberChannels=2; outputNumberOfChannels=2
INFO: [Core Audio] Route Changed: AVAudioSessionRouteChangeReasonCategoryChange
DEBUG: [Core Audio] Changing Route. inputNumberChannels=2; outputNumberOfChannels=2
INFO: [Core Audio] Interruption: AVAudioSessionInterruptionTypeEnded

If you need more info we'd be glad to help Thank you :)

mackron commented 2 years ago

Thanks for the report. I'll get to this one ASAP and report back. Is this 100% reproducible? Just to understand your scenario better, are you doing ma_device_stop() in interruption_began and ma_device_start() in interruption_ended?

alexandrebeaudet commented 2 years ago

Hmm there's two things ; up until now, we were flipping a flag, that would be read in an other thread, that would in turn call ma_device_stop then ma_device_start, but just on the interruption_ended. Since interruption_began already means no-audio is out, we didn't do anything there.

We've tried the start/stop in reaction to interruption notifications received from miniaudio, and also doing absolutely nothing and expecting miniaudio to handle rerouting on its own :)

mackron commented 2 years ago

So you're calling stop() and then start() in interruption_ended, and it's in that stop() call that it's getting stuck?

As a side note, I'm thinking it might be best to have miniaudio stop the device itself in interruption_begin so it's always in the correct state.

alexandrebeaudet commented 2 years ago

Yes ! Just not directly in the miniaudio notification callback.

it might be best to have miniaudio stop the device itself in interruption_begin

That would be great !

mackron commented 2 years ago

Are you able to give the dev branch a try? I've made two changes:

alexandrebeaudet commented 2 years ago

I'll check that asap :)

alexandrebeaudet commented 2 years ago

It works ! It's great because we no longer have to listen to interruptions at all now :) Thanks !

mackron commented 2 years ago

Great. Thanks a lot for the fast turnaround on checking that. I'll get this released soon, hopefully this weekend.

mackron commented 2 years ago

This has been released. Thanks for the report and testing. Closing.