By deans ~ June 5th, 2009. Filed under: Resources.
Almost everything covered in this post is available in Apple’s excellent developer documentation, but many of us don’t seem to have the patience to “go to the source,” so I’ll try to extract some of the choice bits out here.
One of the questions that I’ve faced myself, and that I’ve now tried to answer many times for others, is, “Which method should I use to play sounds for my app?”
Here’s the overview, right from Apple’s Getting Started with Audio & Video document:
Playing Audio and Invoking Vibration
Depending on your needs, you play audio in iPhone OS using System Sound Services, the AVAudioPlayer class, Audio Queue Services, OpenAL, or the I/O audio unit.
- To play alerts and user-interface sound effects, or to invoke vibration, use System Audio Services. This technology can play .caf, .wav, and .aif files containing sounds with durations of 30 seconds or less. Refer to “Using Sound in iPhone OS” in iPhone Application Programming Guide and to System Sound Services Reference.
- To play sounds of any duration, to play multiple sounds simultaneously [dgs- see comments on this below], or to play sounds with level control, use the AVAudioPlayer class. This technology can play any audio format supported in iPhone OS including MP3, AAC, ALAC (Apple Lossless), IMA4, linear PCM, and others. See iPhone Application Programming Guide and AVAudioPlayer Class Reference.
- To play sounds with precise control—such as for synchronization—or to play audio captured from an Internet stream, use Audio Queue Services. See Audio Queue Services Programming Guide and Audio Queue Services Reference. For sample code, see SpeakHere.
- To play positional audio, especially if your application is a game, use OpenAL, an open source technology documented at http://openal.org. See OpenAL FAQ for iPhone OS for important information on using this technology in iPhone OS. For sample code, see oalTouch.
- To play sounds with lowest I/O latency, or to provide simultaneous audio input and output, use the I/O audio unit. See the aurioTouch sample.
Some details that are left out of this overview, including:
Compressed Formats on the iPhone — The bottom line here is that the higher level frameworks on the iPhone will only play one highly compressed sound at a time. This is due to limitations in the processing available to decompress sounds in the audio pipeline. You might be able to get around this by implementing your own decoder and feeding the resulting uncompressed audio to either OpenAL, or AudioQueue, but that’s beyond my interests at this point. Apple’s statement above regarding AVAudioPlayer could be a bit misleading, because AVAudioPlayer will not play multiple MP3 sounds simultaneously. Here’s the section from Coding How-Tos: Audio and Video:
The following limitations pertain for simultaneous sounds in iPhone OS, depending on the audio data format:
- AAC, MP3, and ALAC (Apple Lossless) audio: no simultaneous playback; one sound at a time.
Can I Play an MP3 with SystemAlerts? — No. SystemAudioServices only plays sounds in linear PCM or IMA4 (IMA/ADPCM) format, packaged as a .caf, .aif, or .wav file. AVAudioPlayer, on the other hand, supports the playback of any audio format available in the iPhone OS. This is documented in the iPhone Application Programming Guide: Multimedia Support
Why not just stick with AVAudioPlayer? — AVAudioPlayer is fine, if you don’t need positional audio and if you’re not worried about some significant delays in starting up each player. This latter bit can be especially important if you’re trying to fire off sounds in a tight loop, or if you need to synchronize effects in a multi-threaded environment.
What I you recommend? — Use SystemAudioServices if your sounds are short and available in the proper formats. It’s by far the simplest player and, within its constraints, it pretty much handles everything for you. Use AVAudioPlayer for operations like playing songs or recorded speech. Unfortunately, Apple doesn’t sanction SoundEngine anymore, but I’ve become a big fan of using SoundEngine on top of OpenAL for games. This combination hides some of the complexities of OpenAL while still giving you access to most of the standard stuff. Also, it’s easy to extend SoundEngine to get at pretty much any OpenAL functionality you need. We downloaded the source for SoundEngine from the Oolong site, but it might be a bit easier to grab it directly from coocos2d.
A final word. With pretty much everything beyond SystemAudioServices, you’ll want to seriously consider managing the Audio Session yourself. As always, Apple provides excellent documentation. Even Apple encourages you to take care of this detail:
Each iPhone OS application gets an audio session object, usually called an audio session. This object comes with some default behavior that you can use to get started in development. Except for certain special cases, however, the default behavior is unsuitable for a shipping application.
You don’t need to instantiate an AudioSession object. The iPhone OS provides every app with a singleton AudioSession when the app launches. However, you do have to initialize the AudioSession. You may also need to set properties, and you’ll probably want to Activate/Deactivate the session.