AVAudioPlayer: Keeping device speakers active between plays

I'm using an AVAudio player instance to play a user interface "click" sound when the user presses a button in my game.


When playing through my iPad's built in speakers I've found that the sound fails to play the first time if there has been a delay of more than 3 seconds since the last play. Subsequent plays do work as long as they are within 3 seconds. Everything works fine through the headphones, and also If I play background music continuously then the UI click sound works everytime. Also if I play music continuously at 0.0001 volume (effectively silent) then the click sound works....


So it seems that the iPad speaker is being aggressively switched off if it is inactive for about 3 seconds. Because my UI click sound is very short the speakers don't wake up quickly enough to play the sound.


Is there anyway to make this deactivation less agressive? I assume it helps save battery so I'm reluctant to just play a silent background track to workaround this, but 3 seconds is just a bit too aggressive and makes the app feel broken... Is there a way to do this without resorting to silent background tracks?


Thanks.

Why not just have an audible background music track? That would avoid the whole issue…


You might also find this other thread helpful: https://forums.developer.apple.com/message/70456

I just looked into AVAudioPlayer and found this: (header file)

/* transport control */
/* methods that return BOOL return YES on success and NO on failure. */
- (BOOL)prepareToPlay; /* get ready to play the sound. happens automatically on play. */


and this: (class reference)

Calling this method preloads buffers and acquires the audio hardware needed for playback, which minimizes the lag between calling the

play
method and the start of sound output.

Calling the

stop
method, or allowing a sound to finish playing, undoes this setup.


Try calling -prepareToPlay on your sound when the interface is loaded; that might keep the speakers from shutting off.

Thanks bob133, (Sorry for not responding sooner, I was expecting an email if anyone responded to my post but I failed to set that preference in the new forums!)


Anyway, I do have a background audio track, but give the player the option to switch it off which is when this problem arises.


I've got a lot of code already that calls the prepareToPlay method, I actually keep a queue of "ready to play" players preloaded so there is always one ready. I think this problem is just down to the time it takes to wake the hardware. I actually do hear the very last part of my audio sample a lot of the time, so instead of a "click" I get a "whoosh" sound that I guess is the decay at the end of the sample.


I might try to add a few microseconds to the start of the sample to see if that helps, it may not be noticeable to the user, or perhaps I could add 6 or 7 seconds of silence to the end of the sample to keep the speakers awake for longer after each sound but not on all the time.


Thanks for your suggestions.


* Also just tested this with the iOS keyboard click sounds and they also fail to play after a 3 seconds etc. So perhaps there is no official way to get round this.

You're welcome. Sorry I couldn't help 🙂.


Your idea to attempt to reproduce the issue with the iOS keyboard was a good one—it proves that it's definitely a bug with the system. Here's the link for the Bug Reporter: bugreport.apple.com

Thanks

Having the audio hardware ready to play a sound immediately (with minimum possible latency) is likely exactly same as just playing continuous silent audio. Both require leaving audio hardware (speaker amplifier, etc.) powered up, and with the OS driver already running (thus not needing setup or (re)initialization time). Filling the audio callback buffer with zeros for silence likely adds an non-measurable extra CPU or power load to any game loop.


If you don't want to play continuous audio, you could try playing a very short (near) silent click at least every 2.9 seconds (or other experimentally determined interval) between louder game sounds.

AVAudioPlayer: Keeping device speakers active between plays
 
 
Q