Sound on iOS: Best Practices

Daniel Sperl on June 21, 2010

The latest Sparrow version finally brought support for audio playback. We designed the classes in a way that you don't have to care about the file format; no matter what kind of sound you play, you use the same code.

However, because of the hardware limitations of the iPhone family, there are some guidelines you should follow for best performance. This post summarizes the most important points and shows you how to apply them.

Compressed vs. uncompressed Audio

Behind the scenes, Sparrow uses two libraries to play sound: OpenAL and AVAudioPlayer.

  • OpenAL is a very fast audio library that is available on a huge number of platforms and is primarily used for games. Its downside is that it does not support any compressed file formats.
  • AVAudioPlayer is part of the iPhone SDK. While not blazingly fast, it supports a wide range of file formats, including compressed formats like aifc or mp3.

When Sparrow loads an audio file, it automatically chooses the optimal backend for playback. In either case, you receive SPSound and SPSoundChannel objects. Thus, forget about these internals right away - all you have to know is when to use which format.

SPSound *sound;

// uncompressed => OpenAL
sound = [SPSound soundWithContentsOfFile:@"sound.caf"];  
// compressed => AVAudioPlayer
sound = [SPSound soundWithContentsOfFile:@"sound.aifc"]; 

Which format should I use?

The short answer: Use CAFF (uncompressed) for short sound effects and AIFF IMA4 (compressed) for music. This is also the recommendation from Apple.

  • CAFF (Core Audio File Format) is, in a nutshell, the iPhone's native audio file format for uncompressed sounds.
  • AIFF (Audio Interchange File Format) with IMA4 gets you about 4:1 compression on audio files. It is supported natively by the iPhone. One other advantage of this format is that it loops seamlessly - most other compressed audio files are problematic in this regard.

Compared to others, those formats have the lowest impact on the CPU. If you use them as described above, you get the best of both worlds: sound effects will play fast and without delay. Background music, being compressed, keeps the application size small; it will be streamed into memory, saving precious RAM.

Another tip in relation to the file format: most players use the internal speakers of the iPhone (iPod/iPad). You will agree that they do not provide quite the best acoustic quality. Thus, you can safely use low bitrates and mono sounds. This will reduce the CPU impact even more, reserving more resources for smooth rendering of the visuals.

How do I convert my files into the correct formats?

Thankfully, Apple provides a very useful little command line tool with the iPhone SDK: "afconvert". If you have installed the SDK, it will already be available to you. Here are examples of the most useful calls:

# creates sound.caf (little endian, 16 bit)
afconvert -f caff -d LEI16 sound.wav

# creates sound.caf (little endian, 16 bit, 22kHz)
afconvert -f caff -d LEI16@22050 sound.wav

# creates sound.caf (little endian, 16 bit, MONO)
afconvert -f caff -d LEI16 -c 1 sound.wav

# creates sound.aifc (IMA4 compression)
afconvert -f AIFC -d ima4 sound.wav

# creates sound.aifc (IMA4 compression, MONO)
afconvert -f AIFC -d ima4 -c 1 sound.wav 

If you want to convert all audio files in a directory at once, you could create a shell script like this:

#!/bin/bash

for i in *.wav; do
  afconvert -f caff -d LEI16 $i
done

# move new files to project directory
mv *.caf ~/my_project_path/sounds/  

Save this script into the file "convert_sounds.sh", copy it into your sound directory, and make it executable:

# allow script to be executed
chmod u+x convert_sounds.sh  

# Later, to execute it, just call
./convert_sounds.sh

Conclusion

If you keep these best practices in mind, you will be able to add sound to your game in no time. If you have any questions, don't hesitate to post them below or in the forum. Good luck!