The iPhone and iPod touch devices are audio devices, but actually they dont have awesome audio hardware and most of the audio processing is actually done in software.
Playing Sound Effects inefficient way:
There are many ways to play sound effects on the iPhone, but OpenAL provides the most optimized method for playing multiple channels of sound effects.
In OpenAL a sound effect is stored in buffer and then played when needed.The format of this buffer is critical, because you dont want the CPU to have to do any extra work converting the hundreds and thousands of samples every second from the buffers format to Core Audio's native format[Core Audio File Format(CAFF)].
You should never have some of your sounds to be 22kHz and some 44.1kHz.They must all be the exact same frequency, bit depth, and format, and the must be mono.Even having just one oddball effect can destroy the audio pipeline and cause serious performance issues.
Note : The most optimal format for your CAFF files is 16bit at 44.1kHz since this is native format for the device.
You can even use 16/22kHz to reduce burdon on RAM.In this case what core auido does is mixes all of your effects together into a single 16/22kHz buffer and then make a single pass to convert the data to the device's native 16/44.1 format(which requires a little extra CPU processing).
Using afconvert command line tool(in terminal app):
To generate a 16-bit/44.1kHz CAFF file, enter following:
afconvert -f caff -d LEI16 {INPUT PATH} {OUTPUT PATH}
To generate a 16bit/22kHz file enter following:
afconvert -f caff -d LEI16@22050 {INPUT PATH} {OUTPUT PATH}
There three fundamental objects in OpenAL:
- Buffers : A buffer can be filled with audio data, and can then be attached to a source.
- Sources : A source can be positioned and played.
- Listener : Listener determines how the source is heard,by its position and orientation relative to the Listener object.
Creating 3D audio world in OpenAL:
Create a number of sources and buffers and a single listener object and then updating the positions and orientations of the sources and listener dynamically can present a convincing 3D audio world.
Initializing OpenAL:
At least one device has to be opened. Within that device at least one context will be created. Within that context, one listener object is implied, and a multitude of source objects can be created.Each source can have one or more buffer objects attached to it.
STEPS:
- Open a device.
- Open the context of that device,make it current context.
- Create buffers and put some data into it.
- Create source and attach buffer to source.
- Play the source.
- Create a AudioFileID using AudioFileOpenURL.
- Get the audio file size using AudioFileGetProperty.
- Using AudioFileID which we have created in step one finally read bytes using method AudioFileReadBytes.
Note : At runtime you can update source and listener properties to create a 3D audio world.
Method that are used for playing sound effects with OpenAL:
alcOpenDevice : This takes a string as input.which is either the name of a valid OpenAL rendering device, or NULL to request the default device.
ALCdevice *alcOpenDevice(
const ALCchar *devicename
);
alcCreateContext : function creates the context with specified device
ALCcontext * alcCreateContext(
ALCdevice *device,
ALCint* attrlist
);
device : a pointer to a device
attrlist : a pointer to a set of attributes
ALC_FREQUENCY
ALC_MONO_SOURCES
ALC_REFRESH
ALC_STEREO_SOURCES
ALC_SYNC
alGenBuffers : this is used to generate the number of buffers desired.
void alGenBuffers(
ALsizei n,
ALuint *buffers
);
alBufferData : fills the buffers with audio data.
void alBufferData(
ALuint buffer,
ALenum format,
const ALvoid *data,
ALsizei size,
ALsizei freq
);
buffer : buffer name to be filled with data.
format : format type from among the following: AL_FORMAT_MONO8, AL_FORMAT_MONO16, AL_FORMAT_STEREO8, AL_FORMAT_STEREO16.
data : pointer to the audio data.
size : size of the audio data in bytes.
freq. : the frequrnce of the audio data.
alGenSource: generates the number of sources desired.
alSourcei : This function sets an integer property of a source.
void alSourcei(
ALuint source,
ALenum param,
ALint value
);
source : source name whose attribute is being set.
param : the name of the attribute to set: AL_SOURCE_RELATIVE, AL_CONE_INNER_ANGLE,AL_CONE_OUTER_ANGLE,AL_LOOPING,AL_BUFFER,AL_SOURCE_STATE.
value : the value to set the attribute to.
alSourcePlay : plays the buffer using source.
alGetListenerfv, alListener3f, alSourcei, alGetSource3f : these are the methods that allows you to updated Source and listener properties dynamically.
AudioFileReadBytes : Reads bytes of audio data from an audio file.
OSStatus AudioFileReadBytes{
AudioFileID inAudioFile,
Boolean inUseCache,
SInt64 inStartingByte,
UInt32* ioNumBytes,
void* outBuffer
};
inAudioFile : The audio file whose bytes of data you want to read.
inUseCache : decides read or write data caching.
inStartingByte : the byte offset of the audio data you want to be returned.
inNumBytes : on input, a pointer to the number of bytes to read.On output, a pointer to the number of bytes actually read.
outBuffer : a pointer to user-allocated memory large enough for the requested bytes.
AudioFileOpenURL : Open an existing audio file specified by a URL.
OSStatus AudioFileOpenURL(
CFURLRef inFileRef,
SInt8 inPermissions,
AudioFileTypeID inFileTypeHint,
AudioFileID * outAudioFile
);
inFileRef : The URL of an existing audio file.
inPermissions : The read-write permissions you want to assign to the file(kAudioFileReadPermission, kAudioFileWritePermission, kAudioFileReadWritePermission).
inFileTypeHint : Use this to hint to indicated the file type,otherwise, pass 0.
outAudioFile : A pointer to the newly opened audio file.
AudioFileGetProperty:
Gets the value of an audio file property.
OSStatus AudioFileGetProperty(
AudioFileID inAudioFile,
AudioFilePropertyID inPropertyID,
UInt32 *ioDataSize,
void *outPropertyData
);
inAudioFile : The audio file you want to obtain a property value from.
inPropertyID : The property whose value you want.\
ioDataSize : On input, the size of the buffer passed in the outPropertyData parameter. On output, the number of bytes written to the buffer.
outPropertyData : On output, the value of the property specified in the inPropertyID parameter.