Sound on iOS: Best Practices

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!

12 Comments

Xcode Templates

It has already been announced in the forum, but I wanted to add that information here, too. Our friend Ronald from sodeso.nl has spared no efforts and has created great Xcode templates for project and file creation.

The templates can be found here along with the explanation on how to use them. They were already updated for Sparrow 0.8, so Audio support is already baked in.

Ronald is currently also working on a tutorial on how to create a game using the Sparrow Framework, so check back on his page in the future!

0 Comments

Sparrow 0.8 has landed!

Finally, the download to Sparrow v0.8 is available. Thanks for your patience, everybody!

I will use this post to describe the most important changes since the last release. However, I also recommend that you have a look at the updated demo project (which is part of the download) to see those features in action.

Audio Support

By far the most highly anticipated feature of this new release is, of course, support for hassle-free audio. I think we found a nice, easy-to-use solution to this. If you’re in a hurry, this one-liner will play audio in any format known to the iPhone:

[[SPSound soundWithContentsOfFile:@"sound.aif"] play];

(Don’t worry, the auto release pool won’t touch this sound until it’s done playing.) Of course, this is not all of it. In normal circumstances, you will use the following two classes to add sound to your game:

  • SPSound
  • SPSoundChannel

These two classes act in analogy to the ‘SPTexture’ and ‘SPImage’ classes. ‘SPSound’ contains the data, and ‘SPSoundChannel’ controls its playback. So, if you need a sound multiple times, the ‘SPSound’ will be in memory just once, while several ‘SPSoundChannel’s will play it back multiple times. Here is a real-life example:

SPSound *sound = [SPSound soundWithContentsOfFile:@"sound.caf"];
SPSoundChannel *channel = [sound createChannel];

[channel play];
[channel pause];
[channel stop];
[channel addEventListener:@selector(onSoundCompleted:)
         atObject:self
         forType:SP_EVENT_TYPE_SOUND_COMPLETED];

That should speak for itself. Behind the scenes, the SPSound class will choose the appropriate technology for playback: uncompressed files will use OpenAL, compressed sound will be handled by Apple’s AVAudioPlayer. You don’t have to care. Besides, your sounds will automatically be paused when the application is disrupted (e.g. by a phone call), and will continue playback where they stopped.

In the next blog post, we will show you which audio formats should be used for best performance, and how you can easily convert your files into these formats.

SPMovieClip

Sparrow now contains a very lightweight movie class: SPMovieClip. You can imagine this class as an SPImage with changing textures. (As it extends SPImage, it is really just that.)

// load frames from atlas
SPTextureAtlas *atlas = [SPTextureAtlas
                         atlasWithContentsOfFile:@"atlas.xml"];
SPTexture *texture0 = [atlas textureByName:@"frame0"];
SPTexture *texture1 = [atlas textureByName:@"frame1"];
SPTexture *texture2 = [atlas textureByName:@"frame2"];

// create movie clip
SPMovieClip *movie = [[SPMovieClip alloc]
                      initWithFrame:frame0 fps:10];
[movie addFrame:texture1];
[movie addFrame:texture2];

// add sounds to certain frames
SPSound *sound = [SPSound soundWithContentsOfFile:@"sound.caf"];
[movie setSound:[sound createChannel] atIndex:0];

// important: add clip to juggler
[self.stage.juggler add:movie]

This will display all the frames in sequence with the specified frame rate. There is more to this class — a detailed description will be part of one of our next blog posts.

New Transition functions

Your tweens can now animate stuff in all important transition styles, like “bounce” or “elastic”.

Other Changes

Here are a few other minor changes:

  • SPJuggler now supports the handy method ‘removeTweensWithTarget:’
  • SPDisplayObjectContainer now supports the method ‘removeAllChildren’
  • The rotation property has changed a little bit: angles are now clamped between -180 and +180 degrees (before, it was 0-360 degrees). This should make most common rotation tweens easier.
  • Flickering at application start was removed
  • The stage property is now accessible in the REMOVED_FROM_STAGE event
  • Many other bugfixes and some performance improvements

Feedback wanted!

We did our best to test the stability of the new release — but, of course, we might have missed something. So if you have any problems with the new release, don’t hesitate to post it in the forum, and we will do our best to help you out. The documentation will be updated within the next days!

I hope you like the new feathers of Sparrow 0.8! Have fun!

P.S.: One more thing — you will have to add the following frameworks to your game project, as they are needed for the audio classes: “OpenAL.framework”, “AVFoundation.framework” and “AudioToolbox.framework”.

4 Comments