ObjectAL
|
iOS Audio development, minus the headache.
Version 2.2
Copyright 2009-2013 Karl Stenerud
Released under the Apache License v2.0
ObjectAL for iPhone is designed to be a simpler, more intuitive interface to OpenAL and AVAudioPlayer. There are four main parts to ObjectAL for iPhone:
ObjectAL follows the same basic principles as the OpenAL API by Creative Labs.
Note: While OpenAL allows for multiple devices and contexts, in practice you'll only use one device and one context when using OpenAL under iOS.
Further information regarding the more advanced features of OpenAL (such as distance models) are available via the OpenAL Documentation at Creative Labs.
In particular, read up on the various property values for sources and listeners (such as Doppler Shift) in the OpenAL Programmer's Guide, and distance models in section 3 of the OpenAL Specification.
To add ObjectAL to your project, do the following:
Copy ObjectAL/ObjectAL from this project into your project. You can simply drag it into the "Groups & Files" section in xcode if you like (be sure to select "Copy items into destination group's folder").
Alternatively, you can build ObjectAL as a static library (as it's configured to do in the ObjectAL demo project).
Add the following frameworks to your project:
Note: The demos in this project use Cocos2d, a very nice 2d game engine. However, ObjectAL doesn't require it. You can just as easily use ObjectAL in your Cocoa app or anything you wish.
Note #2: You do NOT have to provide a link to the Apache license from within your application. Simply including a copy of the license in your project is sufficient.
By installing the ObjectAL documentation into XCode's Developer Documentation system, you gain the ability to look up ObjectAL classes and methods just like you'd look up Apple classes and methods. You can install the ObjectAL documentation into XCode's Developer Documentation system by doing the following:
ObjectALConfig.h contains configuration defines that will affect at a high level how ObjectAL behaves. Look inside ObjectALConfig.h to see what can be configured, and what each configuration value does.
The recommended values are fine for most users, but Cocos2D users may want to set OBJECTAL_CFG_USE_COCOS2D_ACTIONS so that the audio actions (such as fade) use the Cocos2D action manager.
The audio formats officially supported by Apple are defined here.
OALAudioTrack supports all hardware and software decoded formats.
OpenAL officially supports 8 or 16 bit PCM data only. However, Apple's implementation only seems to work with 16 bit data.
The effects preloading/playing methods in OALSimpleAudio and the buffer loading methods in OpenALManager can load any audio file that can be software decoded. However, there is a cost incurred at load time converting to a native OpenAL format. To avoid this, convert all of your samples to a CAFF container with 16-bit little endian integer PCM format and the same sample rate as "mixerOutputFrequency" in OpenALManager (by default, 44100Hz). Note, however, that uncompressed files can get quite large.
Convert to iOS native uncompressed format using Apple's "afconvert" command line tool:
Alternatively, if sound file load time is not an issue for you, you can lower your app footprint size (for over-the-air app download) by using a compressed format.
Convert to AAC compressed format with CAFF container using Apple's "afconvert" command line tool:
OpenAL (ALSource, or effects in OALSimpleAudio) and AVAudioPlayer (OALAudioTrack, or background audio in OALSimpleAudio) are playback technologies built for different purposes. OpenAL is designed for game-style short sound effects that have no playback delay. AVAudioPlayer is designed for music playback. You can of course mix and match as you please.
OpenAL | AVAudioPlayer | |
Playback Delay | None | Small delay if not preloaded |
Format on Disk | Any software decodable format | Any software decodable format, or any hardware format if using hardware |
Decoding | During load | During playback |
Memory Use | Entire file loaded and decompressed into memory | File streamed realtime (very low memory use) |
Max Simult. Sources | 32 | As many as the CPU can handle |
Playback Performance | Good | Excellent with 1 track (if using hardware). Good with 2 tracks. Not so good with more (each non-hardware track taxes the CPU significantly, especially if the files are compressed). |
Looped Playback | Yes (on or off) | Yes (specify number of loops or -1 = forever) |
Panning | Yes (mono files only) | Yes (iOS 4.0+ only) |
Positional Audio | Yes (mono files only) | No |
Modify Pitch | Yes | No |
Audio Power Metering | No | Yes |
By far, the easiest component to use is OALSimpleAudio. You sacrifice some power for ease-of-use, but for many projects it is more than sufficient. You can also use your own instances of OALAudioTrack, ALSource, ALBuffer and such alongside of OALSimpleAudio if you want (just be sure to set OALSimpleAudio's reservedSources to less than 32 if you want to make your own instances of ALSource).
Here is a code example using purely OALSimpleAudio:
The OpenAL objects and OALAudioTrack offer you much more power at the cost of complexity. Here's the same thing as above, done using OpenAL components and OALAudioTrack:
The demo scenes in this distribution have been crafted to demonstrate common uses of this library. Try them out and go through the code to see how it's done. I've done my best to keep the code readable. Really!
You can try out the demos by building and running the OALDemo target for iOS or OSX.
The current demos are:
Certain versions of iOS have bugs or quirks, requiring workarounds. ObjectAL tries to handle most of these automatically, but there are cases that require specific handling by the developer. These are:
In iOS 3.x, MPMoviePlayerController doesn't play nice, and takes over the audio session when you play a video. In order to mitigate this, you must manually suspend OpenAL, play the video, and then manually unsuspend once video playback finishes:
On iOS 4.0, MPMusicPlayerController sends an interrupt when it begins playback, but doesn't send a corresponding "end interrupt" when it ends. To work around this, force an "end interrupt" after starting playback:
As you've likely heard time and time again, the simulator is no substitute for the real thing. The simulator is buggy. It can run faster or slower than a real device. It fails system calls that a real device doesn't. It shows graphics glitches that a real device doesn't. Sounds stop working, clicks and static, dogs and cats living together, etc, etc. When things look wrong, try it on a real device before bugging people.
The simulator does not support setting audio modes, so setting allowIpod or honorSilentSwitch in OALAudioSession will have no effect in the simulator.
From time to time, the simulator can get confused, and start spitting out spurious errors. When this happens, check on a real device to make sure it's not just a simulator issue. Usually quitting and restarting the simulator will fix it, but sometimes you may have to reboot your machine as well.
The simulator is notoriously finicky when it comes to audio playback. Any number of programs you've installed on your mac can cause the simulator to stop playing bg music, or effects, or both!
Some things to check when sound stops working: