-
-
Notifications
You must be signed in to change notification settings - Fork 367
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
Android rerouting fix #920
Conversation
…th after toggling devices. The legacy path (AudioStreamLegacy) has been proven to cause sudden disconnections with no callbacks being called, resulting in no audio. Also, when reading default device, we give the AAUDIO_PERFORMANCE_MODE_LOW_LATENCY hint, allowing for non-legacy path.
…nd fails to start. Re-routing (again) solves this very rare error.
Commit b8cffea is interesting. You can try it yourself. I finally found a way to reproduce this rare case.
Now that the bluetooth device got disconnected, we have to re-route again. There is no need to post the job, so I intend to optimize this a bit. |
…e times. If some BlueTooth device goes nuts and toggles connection state back and forth, we bail out.
Any chance you can merge this in a couple of days or so? We are eager to try it out in github/orx. |
…hread (re-routing) and never re-opened.
Thanks a lot for all your work on this. Just giving this a review now. A few things:
|
Sure. As long as I can disable that buffer logic using some public API. Can you perhaps add your suggestions to this PR, so I can try it out? As for the buffer workaround, I'm quite sure it is broken. It fights with some weird "divide by 2" logic in AAudio internals and it is (mathematically) guaranteed to fail. Maybe I'll find time, this weekend, to explain this in detail. Regarding 2, I added those for completeness. Didn't realize those functions had these constraints. Not needed for the PR at least. |
Yeah what I was thinking was a variable like |
This change makes it so that setBufferCapacityInFrames() and setFramesPerDataCallback() can be opted-in if explicitly requested in the device config. This also adds back enableCompatibilityWorkarounds in order to prevent anyone's build from breaking when updating. This will be removed again in the 0.12 branch.
This commit removes the calls to ma_device__set_state() and replaces them with a call to ma_device_stop() which is the intended way for backends to change the state of the device. In addition, this comes with the added effect of firing the stop callback when a reroute fails.
I've made some changes of my own. Summary of my changes:
This could probably do with some additional testing just to be double sure I haven't broken anything with these changes. I'm actually wondering if I should add another device state called |
Cool! Now I remember why I didn't call See the assert I added. I guard for |
I added the same guard to |
I saw those guards now. Should work as it is. Will verify that the new code works, later tonight. |
I verified the latest tweaks in my two apps. No issues 👍 |
Thanks for testing. Merged. |
Cool! When is the next release planned? |
Well I've been saying "soon" for about the last 9 months or so... But I am for real wanting to get this out within the next few weeks. Maybe next weekend, no promises. |
Fix for #913.
History
In our game engine, orx, we switched to
miniaudio
in late 2021. Ever since then, we observed a rare, intermittent problem onAndroid
where audio would disappear (and never come back). Usually, it would happen when resuming a game after a few days. Then, in 2024, we found out that the issue is more likely to occur when taking a ride with the car 😆. It just happens that the car has a bluetooth audio device...During these years, I have tried multiple devices, all running the latest
Android
version (API level30
up to35
). Just to name a few:What is the common denominator here? Re-routing!
Symptoms
When re-routing, volume is usually lowered when returning back to the original device (this too is an important clue). Sometimes though, the audio is completely gone. In
logcat
we get a hint of what happened:And you get this error for both
AAudio
andOpenSL
. Thus, these two APIs overlap somehow. As it turns out,AAudio
has two paths;mmap
andlegacy
, where the former is more performant. When re-routing, ourAAudio
integration seems to choose the legacy path. This indicates that it fails to pick themmap
path for some reason. That's odd!Now, if we enforce the
mmap
path by callingAAudio_setMMapPolicy(AAUDIO_POLICY_ALWAYS)
, re-routing always fails at this line:Error is
AAUDIO_ERROR_OUT_OF_RANGE
due to the buffer size logic in AudioStreamInternal.cpp(295).Clearly, re-routing does not work for
mmap
enabled devices. Makes no sense!The fix
It turns out that there are fragments in the code that aim to handle this very issue.
Indeed, removing the workaround fixes the problem! Re-routing now maintains the
mmap
path, avoiding the less stablelegacy
path. Also, when reading information about the default device viama_open_stream_basic__aaudio
we now setAAUDIO_PERFORMANCE_MODE_LOW_LATENCY
, allowing for themmap
path. This likely reduces the "path confusion" insideAAudio
. Ideally, I would like to have the same logic as inma_create_and_configure_AAudioStreamBuilder__aaudio
but this is the best I can come up with when there is noma_device_config
to consider.Final notes
You might want to re-iterate the removal of
enableCompatibilityWorkarounds
. However, since I have struggled with this issue since 2021 I'm quite confident that the "compatibility workarounds" were added at a time whenAAudio
still had some growing pains. My take is that the workarounds are no longer needed.