-
Notifications
You must be signed in to change notification settings - Fork 91
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
Audio glitches when screen is not being touched #47
Comments
Apparently, glitchy audio playback has been a long-standing issue on Android, due to a variety of causes, probably, and with many different solutions offered: https://code.google.com/p/android/issues/detail?id=22763 Assuming, on the other hand, that your issue is something we can fix, I wonder if requesting audio focus would address this: http://android-developers.blogspot.com/2013/08/respecting-audio-focus.html The AudioWrapper class does attempt to raise the audio thread priority, but apparently that does not keep the audio device focused and alert. Eyeballing the code, it looks fairly straightforward to request audio focus on start and abandon focus on stop: @nettoyeurny Comments? |
We should definitely do something about audio focus. A few thoughts off the top of my head:
|
I'm happy to find this thread, was searching for days now for this issue. I ported my "Gamelan Gender" from iOS to android using libPd, as there is no AUSampler like framework in android. Everything is fine so far, except on a nexus 6 on marshmallow, when the sequencer is running and there's no user input, the sound starts to crackle and gets distorted, that stops as soon I tap the screen or move a finger on the screen. Tried to implement the focus-thing to no avail, despite get granted focus, the crackling resists. |
@okramis Thanks, this is a crucial bit of information. Now that I've thought about this some more, and given okramis's post, I believe that handling audio focus is not unlike handling phone state (e.g., for the purpose of pausing playback when a phone call comes in). It's useful to have, and a complete audio app should probably pay attention to it, but it's not a core responsibility of pd-for-android and doesn't require access to the internals of core classes such as PdAudio or PdService. My current take is to file this under "nice to have", and to add a decorator for PdService to the utils package if we want to provide support for this. We might even combine this with the handling of phone state (or would this be redundant --- maybe we lose audio focus when the phone rings?), and have developers interact with it through a simplified listener interface, say AudioInterruptionListener, with methods like OnAudioInterrupted(boolean canDuck) and OnAudioContinued(). |
Since it seems that for both @rpattabi as well as @okramis touching the screen resulted in better audio performance, I thought it's worth mentioning that faking touch events and disabling the screen saver is apparently a hack that JUCE for Android uses to achieve better audio performance: |
I was hoping that audio focus would solve this issue. I agree that would be 'nice to have' now since that is not solving this serious issue. Other than the work around of artificial tapping on the screen (not sure how to do, need to look at how JUCE did it), is there anything pd-for-android do to address this? This is clearly pd-for-android's responsibility since it should never let the app to lose audio thread priority. |
@rpattabi I agree, it should be fixed in pd-for-android. It might not so easy, as I think the issue lies somewhere in the aggressive power management of the nexus devices. I tried the artificial tapping - it is tapping - but unfortunately it does not help. It must have to do with the sensors becoming active, as I also can just rotate the device (portrait - landscape) to stop the crackling. |
@okramis thanks for the information about artificial tapping not helping. In my case, the problem is addressed by updating the pd patch, by drastically reducing the amount of processing during the playback. |
I did some more tests on more devices. The only device with the issue is a Motorola Nexus 6 on android 6.x. I put the PdService in a thread raised process priority to THREAD_PRIORITY_URGENT_AUDIO, tried to simplify the pd patch as much as possible - no change. No activity on ui-sensors, the distortion starts after ~3 secs, also when the player runs in background. Touch on screen or change orientation not important in what app, the distortion stops... So I'm giving up, hope there'll be not to many devices out, showing this issue. |
Android Audio team recognized this problem in last week's google I/O. You know what they recommend? Fake touches! Check this out: https://youtu.be/F2ZDp-eNrh4?t=9m0s |
I found ripples in some UI elements using the API they suggested. So I used different API to do the same which doesn't impact the UI, provided you have a view that is just kept for this purpose (typically a text view that doesn't have to react to touch events). Here is my code: https://gist.github.com/rpattabi/5252d38eb470e11bd4d0e8bb29f239bc Please let me know how it works for you. |
@rpattabi thanks a lot for sharing! I did some tests with the API from the video and indeed it solves the crackles. The only problem, this can't run in background (my app can play in background), so you have to watch out for visibility changes. I'll have a look at your class when there's some more spare time. |
@rpattabi had a look at your class, unfortunately it won't work in my app, looks similar to my own attempt. I provided a TextView just for this purpose and the timer is firing, but crackling persists. Do I have to set some special properties on the TextView to have it working? |
@okramis thanks for taking a look at my code. I was not sure it is working since I don't have audio glitches on my devices. But I thought this implementation is an improvement than what they recommended (which caused ripples in my app). Apparently I was incorrect. Android system seems to understand that my implementation's fake touches are not from real user. So instrumentation is the way to go. I wonder how you could avoid ripples due to fake touches with their suggestion. |
Android audio team talked about ideas to avoid glitches at Google I/O 17. See #66 for details. |
One advice from the Google I/O video was to use nop (no operation) assembly calls in the callback to keep the CPU busy, so it would not introduce scaling. Someone knows how to do that? |
No idea about no-op assembly calls. Hope someone can answer. I would just like to add that it is now possible to request for sustaining performance from android N and above.
It shall be requested after activity is visible to the user, possibly like
More info: Sustained Performance Mode Update:
|
@rpattabi Thanks. That will only help for N+, of course, but good to know. There seems to be a workaround in the opensl callback function by keeping the CPU busy there, but how to do it is beyond me at this point. I have hacked PdBase and PdAudio to force it to use AudioTrack. That actually worked quite well, and none of these issues arised. It would be nice to be able to choose between opensl and audiotrack, but it seems that requires changes to PdBase, and the native libraries would have to be loaded from some init method instead of from a static initializer. PS: Yeah, I changed my username. |
@funkyfourier I found that superpoweredSdk provided SuperpoweredCPU class that exposes a way to enable sustained performance mode. It used the no-op assembly calls which you mentioned. Unlike android's inbuilt sustainPerformanceMode, this allows sustaining performance irrespective of whether activity window is in foreground or not. Unfortunately SuperpoweredCPU source is not public. So not sure what else they implemented in addition to no-ops. I haven't tried it myself, it is just what I learned. |
@rpattabi Hi. That sounds interesting. However, as you point out, we do not have access to the source code. I have been thinking that the way to go here is to use Google's oboe library rather than opensl_stream. It provides a simple API which is implemented on OpenSL ES or AAudio depending on what is available. It would be reasonable to assume that they have solved the CPU migration issues in oboe. Once oboe matures a little bit more I might take a stab at it. |
It would be interesting to watch oboe. Probably, we can make pd-for-android depend on oboe (after it matures) instead of opensl? I don't know. But I really would like pd-for-android is kept up-to-date on these aspects. |
Has anyone made any progress on this? I'm using opensles, but background audio is choppy and slows down. The "fake touch" solution isn't working for me. |
Google's oboe tries to ensure that our app uses fast track. Integrating oboe with libpd will eliminate the need for us having to do anything special. More info libpd/libpd#284. |
When I try to play a steady frequency, after few seconds there are noticeable breaks in the audio, even while screen is still on.
Interestingly, when I keep tapping on the screen, there are no breaks in the audio.
I tested this with couple of Nexus 4 devices with Lollipop (stock android and CyanogenMod). On the other hand, I don't get this problem in emulator.
I was assuming pd-for-android would retain audio thread priority for the app.
By the way, there is no problem with simpler patches. My patch involved some reasonably heavy calculation, getting rid of this part from the patch avoided this problem. As I mentioned, even if that calculation part is kept and the screen kept tapped, no problem of audio breaks.
I am using v1.0.0, native sampling rate, 2 output channels, 1 input channel, and PdService.
The text was updated successfully, but these errors were encountered: