What happens if I don't handle audio interruptions? - iphone

Is it possible to still play sound / music even if audio has been interrupted, or more precisely: even if MyInterruptionListener got called from the OS with the interruption state kAudioSessionBeginInterruption ?
Yeah I know that's not good idea to do. But want to know anyways.

By the time you get an interrupt message, the audio resources you've been using have been shut down.
For AVAudioPlayer, playback will be stopped until you start it again.
For OpenAL, your context will be invalid. All OpenAL commands will fail with an error until you clear the current context and set it to current again.
For Audio Units, your graph will be in an invalid state. No sound will be played until you set the graph inactive and then active.
I don't know what would happen if you tried to start your audio resources again upon getting an interrupt start message, but at the very least you'd get rejected in the app store if the reviewers ever discovered this behavior.

Related

How to get a callback from AVQueuePlayer/AVPlayerItem when network become active (and is ready to play)?

I have a AVQueuePlayer based audio streaming player that needs to run in the background. The player needs to continue running until it finishes playing all the list. Of course it is going to have to pause if the network connection becomes bad, but it should automatically resume when the network connection comes back.
For this, I am monitoring
AVPlayerItem.status
AVPlayerItem.playbackLikelyToKeepUp
AVPlayer.currentItem
AVPlayer.status
AVPlayer.error
using KVO. For example, if the network connection recovers from temporary error, I expect currentAVPlayerItem.status becomes AVPlayerStatusItemReadyToPlay, which will be reported to my player and I can issue [AVQueuePlayer play] at that point.
This mechanism (logic) seems to work some cases, but quite frequently in offline environment, AVPlayerItem.status becomes AVPlayerItemStatusFailed, which item AVQueuePlayer seems to skip automatically. As a result, the queue will end up being empty and no callback can be received from AVPlayerItem.
I was hoping that some property in AVPlayer will change when network connection goes bad/recovers, but nothing seems to change (status, error etc).
Obviously I can monitor Reachability, but that doesn't work when the app is running in the background.
How can I know when the network comes back up and AVQueuePlayer is playable again in this situation?
I may be just being a novice around this area. If anybody can give me a general idea how he/she achieves continuous AVQueuePlayer playing experience without being completely stopped by temporary network connection issues, that would be an awesome help as well!
You can monitor AVPlayerItemPlaybackStalledNotification to know when the item finished playing its buffer but not the entire file:
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(AVPlayerItemPlaybackStalledNotification:)
name:AVPlayerItemPlaybackStalledNotification object:playerItem];
Once there's enough buffer to continue, you should get a notification sent to playbackLikelyToKeepUp which it sounds like you're already monitoring.

Mic and Speaker Feedback

I have an iPad application (a tuner) that uses Core Audio Audio Units. It reads the signal from the mic and processes it. It does NOT echo the sound to the speaker.
Unfortunately, at different times, the signal actually feedbacks and comes out of the speaker - loud and sort of phasey. I haven't made any connection from the mic to the speaker - but it creates the illusion that the mic is somehow "on". It isn't a direct signal - it is chopped up and requires you to make somewhat loud noises before it will happen.
I'm concerned this is related to overloading the cpu or something. I don't think the callback is getting behind. If I put debug statements into the callback, they seem to stop when I turn off the Audio Unit ... which brings up another oddity. At certain times, even when the Audio Unit has been stopped, the feedback continues to occur from the mic to the speaker so that the app has to be shutdown and removed from the background processing queue before the incessant noise stops.
Oddly, this doesn't happen every time and to every tester but it does occur often enough to create a stir.
If your RemoteIO callbacks are too slow and/or your app crashes and stops handling the audio callbacks, the RemoteIO audio buffers may get recycled, which may cause some of your old play buffers, or perhaps even record buffers, to end up repeated or repeating in the underflowed audio channel. One way to test this is to comment out all your processing code (and debug prints, which can also be too slow) inside your callbacks and see if this fixes your "feedback" problem.
Try to do only simple buffer copies and/or other low-overhead fast processing in both your RemoteIO record and play callbacks. Do not process data inside the Remote callback, instead handshake, schedule or queue the work to be done later outside the callback.
If your app can somehow detect that it can't keep up, it should stop the RemoteIO audio unit (AudioOutputUnitStop).
Also try zero-ing the data each record buffer after you are done with it before exiting each record callback. There have been reports that this may help fix a bug in some very old versions of iPhoneOS.

AVAudioPlayer interrupting playback with audioPlayerDecodeErrorDidOccur, with NSOSStatusErrorDomain -50

In very specific, but reproducible cases, I'm getting audioPlayerDecodeErrorDidOccur:error: with the following NSError:
Error Domain=NSOSStatusErrorDomain Code=-50 "The operation couldn’t be completed. (OSStatus error -50.)"
This occurs in a game that also uses OpenAL; we're playing sounds using OpenAL, but attempting to leverage hardware AAC decoding. However, the occurence of the above does not appear linked to anything we do in OpenAL.
This happens about 2-3 seconds after we perform scene (game mode) switching -- but only with certain combinations of from-and-to scenes. It is even stranger since we do nothing important audio related on these events. I've verified that we do nothing with AVAudioPlayer, but it doesn't seem that anything important is done with OpenAL either.
I've tried to resolve this by releasing the AVAudioPlayer, and replacing it with another one that references the same file, uses the same volume and resumes from the same time in the file. However, after a few seconds, this player also throws the aforementioned error. Switching to a new song, on the other hand, creates a fully functional player, that does not have any problems.
My question is: what does error -50 mean in this context, or how would you go about figuring out what it means?
(If it means anything, the game must run at minimum on iOS 3.1.2).
We have tried disabling OpenAL part of the code; it did not help.
Audio library code is publicly available at http://libxal.svn.sf.net/svnroot/libxal/trunk/
We managed to mess up something on the C++ level. This probably caused memory corruption in AVAudioPlayer without actually crashing the game, and behaving the same on the Simulator and the device. We fixed this and the AVAudioPlayer now works.

running an NSTimer in the background of a multitasking iPhone app to turn location service on/off

i am attempting to make an app that records an accurate location every 10 minutes.
the problem with this is that when running is best mode, the battery drains really quickly.
i would like a timer to turn of the location service, have didUpdateToLocation get a good location, turn of location service and then wait for the timer again.
i have tried a million things- but my NSTimer always gets frozen when put in background mode.
interestingly, didUpdateFromLocation can turn location service off, and if you use significantChangeUpdate you can use didUpdateToLocation to turn location service back on when the user passes a triangulation boundry- and record locations to coredata-
so in theory the only thing stopping me getting this thing running is an NSTimer in a thread that doesnt get frozen, ever.
i read some documents that said you CAN do simple things in the background beyond VOIP, location, audio. does anyone have any experience getting a thread running that doesnt get frozen? i know everyone thinks it can't be done- from my research it is possible, but i just cant figure it out.
advice based on any experience getting a thread running in the background beyond VOIP, Audio, location would be much appreciated
thanks guys, dave-
The answer to this question has an alternative hack where you use re-use the applicationDidEnterBackground event to loop back on itself, each time re-starting a thread where you can do some work
iPhone - Backgrounding to poll for events

NSTimer callbacks while iPhone application is inactive

This question seems to be the essence of several others on this forum. I believe that it is possible for the active iPhone application to continue running, and specifically, to continue receiving timer call-backs, after it has entered the inactive state (either through the idle timer kicking in the screen lock, or through the user pressing the hardware lock button).
The documentation specifically says that while an application is inactive, it is executing, but not dispatching incoming events (I'm not giving a link because I'm jumpy about NDA - should I relax about that? Is this whole post a breach? sigh).
Also, two answers by user "Ambr Str" directly state that it is possible to continue receiving timer call-backs, and he supplies a snip of code to achieve it (I can't link to this because I'm a new user, sorry - search for the question: "What happens to an iPhone app when iPhone goes into stand-by mode?" to find his answer).
I've tried to create my call-backs as he suggests, but once my application becomes inactive, the call-backs cease firing.
I've just noticed that while the iPhone is plugged in, if the application becomes inactive (due to idle time out or me pressing the sleep button), call-backs do continue to occur - perhaps I should get my users to carry a battery pack with them ;-)
There is a good answer to this question on Apple's forums. Search for "Timer" and "Eskimo" (the helpful chap who provides the answers).
In brief, shortly after the application becomes inactive, the phone really does go to sleep. The only way to prevent this is to be playing some audio (or for some audio to be playing in a background application). While audio is playing the phone will not sleep, and your application continues to be run.
It is suggested that playing stay awake audio is a hack, and that you shouldn't do it if at all possible. I think in my application (which performs audio playback interspersed with silent periods), the approach is valid, if not ideal!
I have an app. which includes an embedded webserver. I'm planning to offer an option of disabling auto-sleep IFF the server is turned on, AND the device is on power. So you might consider checking the batteryState property of UIDevice. So if batteryState != UIDeviceBatteryStateUnplugged, go ahead and disable idle timer. (note: the docs say that UIDeviceBatteryStateUnknown will be returned when in simulator.)
You'll also want to listen for UIDeviceBatteryStateUnplugged notifications and set batteryMonitoringEnabled appropriately.