3
OpenAL
oalTouch Application
12
2010-2
iPhone Application Index
1. oalTouch
2. oalTouch Classes & Resources
3. oalTouch Application Class
4. oalTouch
5. Initialize Audio Session, Sound Source, Buffer, OpenAL
6. Start & Stop Sound
7. Sound Source & Listener Position, Listener Rotation
8. Dealloc
iPhone Application oalTouch
Sound Start/Stop
Background Music on/off
on/off Listener
Sound Source
iPhone Application
oalTouch Classes & Resources
MyOpenALSupport : OpenAL task
oalPlayback : OpenAL audio playback
oalSpatialView : view oalTouchAppDelegate :
main
OpenAL
avTouch Application oalTouch Application
MyOpenALSupport oalTouchAppDelegate
oalSpatialView
oalPlayback
• oalTouch Application 4
• oalTouchAppDelegate
- Delegate
- View oalSpatialView view , Sound oalPlayback playback
• oalSpatialView
- Touch Event
• oalPlayback
- , 3D
• MyOpenALSupport
- oalPlayback OpenAL
avTouch Classes & Resources oalTouch
View
Contents Touch Event
• oalTouch Application 6
Sound Sound
/
,
oalSpatialView -(id)initWithCoder -(void)awakeFromNib -(void)observeValueForKeyPath -(void)initializeContents -(void)layoutContents
oalSpatialView -(void)touchPoint -(void)touchesBegan -(void)touchesMoved -(void)touchesEnded
oalPlayback
void interruptionListener void RouteChangeListener -(id)init
-(void)checkForMusic -(void)initBuffer -(void)initSound -(void)initOpenAL
oalPlayback -(void)checkForMusic -(IBAction)toggleMusic -(void)startSound -(void)stopSound
oalPlayback -(void)dealloc -(void)teardownOpenAL oalSpatialView -(void)dealloc oalAppDelegate -(void)dealloc oalPlayback
-(CGPoind)sourcePos -(void)setSourcePos -(CGPoind)listenerPos -(void)setListenerPos -(CGFloat)listenerRotation -(void)setListenerRotation oalTouchAppDelegate
-(IBAction)playpause
• oalTouch Application oalPlayback .
avTouch Classes & Resources 1.
view : oalSpatialView oalTouchAppDelegate
initWithCoder oalSpatialView
•
initializeContents
awakeFromNib
checkForMusic oalPlayback
layoutContents
observeValueForKeyPath
touchesBegan touchPoint
touchesMoved touchesEnded
playback : oalPlayback
listenerPos
sourcePos
listenerPos sourcePos
Initialize Audio Session,
Sound Source, buffer, OpenAL
avTouch Classes & Resources
1. /
! ! // Start with our sound source slightly in front of the listener ;
! ! sourcePos = CGPointMake(0., -70.);
! !
! ! // Put the listener in the center of the stage ;
! ! listenerPos = CGPointMake(0., 0.);
! !
! ! // Listener looking straight ahead ;
! ! listenerRotation = 0.;
1.
• oalPlayback::init
OSStatus result = AudioSessionInitialize(NULL, NULL, interruptionListener, self);
2.
(1) (interruptionListener)
• oalPlayback::init
AudioSessionInitialize
Initializes an iOS application’s audio session object.
inRunLoop The run loop that the interruption listener callback should be run on. Pass NULL to use the main run loop.
inRunLoopMode The mode for the run loop that the interruption listener function will run on. Passing NULL is equivalent to passing kCFRunLoopDefaultMode.
inInterruptionListener
The interruption listener callback function. The application’s audio session object invokes the callback when the session is interrupted and (if the application is still running) when the interruption ends.
inClientData Data that you would like to be passed to your interruption listener callback.
OSStatus AudioSessionInitialize (
CFRunLoopRef inRunLoop, CFStringRef inRunLoopMode,
AudioSessionInterruptionListener inInterruptionListener, void *inClientData
);
avTouch Classes & Resources 2.
! oalPlayback* THIS = (oalPlayback*)inClientData;
! if (inInterruptionState == kAudioSessionBeginInterruption)
! {
! ! ! alcMakeContextCurrent(NULL);! !
! ! ! if ([THIS isPlaying]) {
! ! ! ! THIS.wasInterrupted = YES;
! ! ! }
! }
! else if (inInterruptionState == kAudioSessionEndInterruption)
! {
! ! OSStatus result = AudioSessionSetActive(true);
! ! if (result) NSLog(@"Error setting audio session active! %d\n", result);
! ! alcMakeContextCurrent(THIS->context);
! ! if (THIS.wasInterrupted)
! ! {
! ! ! [THIS startSound];! ! !
! ! ! THIS.wasInterrupted = NO;
! ! }
! }
(2)
- Context NULL wasInterrupted YES .
- Context wasInterrupted NO .
• oalPlayback::interruptionListener
alcMakeContextCurrent
makes a specified context the current context.
ALCboolean alcMakeContextCurrent(
ALCcontext *context );
context a pointer to the new context
avTouch Classes & Resources 2.
// if there is other audio playing, we don't want to play the background music UInt32 size = sizeof(iPodIsPlaying);
result = AudioSessionGetProperty(kAudioSessionProperty_OtherAudioIsPlaying, &size, &iPodIsPlaying);
if (result) NSLog(@"Error getting other audio playing property! %d", result);
// if the iPod is playing, use the ambient category to mix with it
// otherwise, use solo ambient to get the hardware for playing the app background track
UInt32 category = (iPodIsPlaying) ? kAudioSessionCategory_AmbientSound : kAudioSessionCategory_SoloAmbientSound;
(3) iPod
• oalPlayback::init
result = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(category), &category);
if (result) NSLog(@"Error setting audio session category! %d\n", result);
result = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, RouteChangeListener, self);
if (result) NSLog(@"Couldn't add listener: %d", result);
result = AudioSessionSetActive(true);
if (result) NSLog(@"Error setting audio session active! %d\n", result);
(4) , ,
• oalPlayback::init
AudioSessionGetProperty
inID The identifier for the audio session property that you want to get the value of.
ioDataSize On input, the memory size for the outData parameter.
On output, the actual size of the property value.
outData On output, the value of the specified audio session property.
Gets the value of a specified audio session property.
OSStatus AudioSessionGetProperty ( AudioSessionPropertyID inID, UInt32 *ioDataSize, void *outData );
AudioSessionSetProperty
inID The identifier for the audio session property that you want to set the value of.
inDataSize The size, in bytes, of the value in the inData parameter.
inData The value that you are applying to the specified audio session property.
Sets the value of a specified audio session property.
OSStatus AudioSessionSetProperty ( AudioSessionPropertyID inID, UInt32 inDataSize, const void *inData );
AudioSessionAddPropertyListener
inID The identifier for the audio session property whose value changes you want to listen for.
inProc The name of your property listener callback function.
inClientData Data that you would like to be passed to your property listener callback.
Adds a property listener callback function to your application’s audio session object.
OSStatus AudioSessionAddPropertyListener ( AudioSessionPropertyID inID, AudioSessionPropertyListener inProc, void *inClientData );
AudioSessionSetActive
active Pass true to activate your application’s audio session, or false to deactivate it.
Actives or deactivates your application’s audio session.
OSStatus AudioSessionSetActive ( Boolean active
);
avTouch Classes & Resources 2.
CFDictionaryRef dict = (CFDictionaryRef)inData;
!
CFStringRef oldRoute = CFDictionaryGetValue(dict, CFSTR(kAudioSession_AudioRouteChangeKey_OldRoute));
!
UInt32 size = sizeof(CFStringRef);
!
CFStringRef newRoute;
OSStatus result = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &size, &newRoute);
NSLog(@"result: %d Route changed from %@ to %@", result, oldRoute, newRoute);
(5)
• oalPlayback::RouteChangeListener
bgURL = [[NSURL alloc] initFileURLWithPath: [[NSBundle mainBundle]
pathForResource:@"background" ofType:@"m4a"]];
bgPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:bgURL error:nil];!
! ! ! !
wasInterrupted = NO;
(6)
• oalPlayback::init
[self initOpenAL];
(7) OpenAL
• oalPlayback::init
CFDictionaryGetValue
theDict The dictionary examine.
Returns the value associated with a given key.
const void * CFDictionaryGetValue ( CFDictionaryRef theDict, const void *key
);
avTouch Classes & Resources 1.
view : oalSpatialView oalTouchAppDelegate
initWithCoder oalSpatialView
•
initializeContents
awakeFromNib
checkForMusic oalPlayback
layoutContents
observeValueForKeyPath
touchesBegan touchPoint
touchesMoved touchesEnded
playback : oalPlayback listenerPos
sourcePos
listenerPos sourcePos
init
interruptionListener routeChangeListener
avTouch Classes & Resources 3. OpenAL
! // Pass NULL to specify the system’s default output device
! device = alcOpenDevice(NULL);
1. OpenAL
• oalPlayback::initOpenAL
! if (device != NULL)
! {
! ! // Create a new OpenAL Context
! ! // The new context will render to the OpenAL Device just created
! ! context = alcCreateContext(device, 0);
! ! if (context != NULL)
! ! {
! ! ! // Make the new context the Current OpenAL Context
! ! ! alcMakeContextCurrent(context);
! ! !
! ! ! // Create some OpenAL Buffer Objects
! ! ! alGenBuffers(1, &buffer);
! ! ! if((error = alGetError()) != AL_NO_ERROR) {
! ! ! ! NSLog(@"Error Generating Buffers: %x", error);
! ! ! ! exit(1);
! ! ! }
! ! !
! ! ! // Create some OpenAL Source Objects
! ! ! alGenSources(1, &source);
! ! ! if(alGetError() != AL_NO_ERROR)
! ! ! {
! ! ! ! NSLog(@"Error generating sources! %x\n", error);
! ! ! ! exit(1);
! ! ! }
! ! !
! ! }
! }
// clear any errors
! alGetError();
2. OpenAL , ,
• oalPlayback::initOpenAL
alcOpenDevice
devicename a null-terminated string describing a device
opens a device by name.
ALCdevice *alcOpenDevice(
const ALCchar *devicename );
alcCreateContext
creates a context using a 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
alcMakeContextCurrent
makes a specified context the current context.
context a pointer to the new context ALCboolean alcMakeContextCurrent(
ALCcontext *context );
alGenBuffers
generates one or more buffers, which contain audio data.
void alGenBuffers(
ALsizei n, ALuint *buffers );
n the number of buffers to be generated
buffers pointer to an array of ALuint values which will store the names of new buffers
alGetError
returns the current error state and then clears the error state.
ALenum alGetError(ALvoid);
alGenSources
generates one or more sources.
n the number of sources to be generated
sources pointer to an array of ALuint values which will store the names of new sources void alGenSources(
ALsizei n, ALuint *sources );
avTouch Classes & Resources 4.
! [self initBuffer];!
1. initBuffer
• oalPlayback::initOpenAL
NSBundle*!! bundle = [NSBundle mainBundle];
!
// get some audio data from a wave file
CFURLRef fileURL = (CFURLRef)[[NSURL fileURLWithPath:[bundle pathForResource:@"sound" ofType:@"caf"]] retain];
!
if (fileURL) {!
! data = MyGetOpenALAudioData(fileURL, &size, &format, &freq);
! CFRelease(fileURL);
! !
! if((error = alGetError()) != AL_NO_ERROR) {
! ! NSLog(@"error loading sound: %x\n", error);
! ! exit(1);
! }
! !
! // use the static buffer data API
! alBufferDataStaticProc(buffer, format, data, size, freq);
! !
! if((error = alGetError()) != AL_NO_ERROR) {
! ! NSLog(@"error attaching audio to buffer: %x\n", error);
! }! !
} else
! NSLog(@"Could not find file!\n");
}
2.
• oalPlayback::initBuffer
avTouch Classes & Resources 4.
void* MyGetOpenALAudioData(CFURLRef inFileURL, ALsizei *outDataSize, ALenum *outDataFormat, ALsizei*!outSampleRate)
{! OSStatus!! ! ! ! ! err = noErr;!
! SInt64! ! ! ! ! ! ! theFileLengthInFrames = 0;
! AudioStreamBasicDescription! ! theFileFormat;
! UInt32! ! ! ! ! ! ! thePropertySize = sizeof(theFileFormat);
! ExtAudioFileRef! ! ! ! ! extRef = NULL;
! void*! ! ! ! ! ! ! theData = NULL;
! AudioStreamBasicDescription! ! theOutputFormat;
. . . }
3. OpenAL
- , , (channel count, sample rate...)
-
- -
• MyOpenALSupport::MyGetOpenALAudioData
avTouch Classes & Resources 4.
ALvoid alBufferDataStaticProc(const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq) {
! static! alBufferDataStaticProcPtr! proc = NULL;
if (proc == NULL) {
proc = (alBufferDataStaticProcPtr) alcGetProcAddress(NULL, (const ALCchar*) "alBufferDataStatic");
} if (proc)
proc(bid, format, data, size, freq);
!
return;
}
4. API
• MyOpenALSupport::alBufferDataStaticProc
alcGetProcAddress
retrieves the address of a specified context extension function.
device a pointer to the device to be queried for the function
funcName a null-terminated string describing the function void * alcGetProcAddress(
ALCdevice *device, const ALCchar *funcName );
avTouch Classes & Resources 5.
! [self initSource];
1. initSource
• oalPlayback::initOpenAL
! // Turn Looping ON
! alSourcei(source, AL_LOOPING, AL_TRUE);
!! // Set Source Position
! float sourcePosAL[] = {sourcePos.x, kDefaultDistance, sourcePos.y};
! alSourcefv(source, AL_POSITION, sourcePosAL);
!
! // Set Source Reference Distance
! alSourcef(source, AL_REFERENCE_DISTANCE, 50.0f);
!
! // attach OpenAL Buffer to OpenAL Source
! alSourcei(source, AL_BUFFER, buffer);
!! if((error = alGetError()) != AL_NO_ERROR) {
! ! NSLog(@"Error attaching buffer to source: %x\n", error);
! ! exit(1);
2. OpenAL OpenAL
• oalPlayback::initSource
alSourcei
sets an integer property of a source.
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 void alSourcei(
ALuint source, ALenum param, ALint value );
alSourcefv
sets a floating point-vector property of a source.
source source name whose attribute is being set
param
the name of the attribute being set:
AL_POSITION AL_VELOCITY AL_DIRECTION
value a pointer to the vector to set the attribute to void alSourcefv(
ALuint source, ALenum param, ALfloat *values );
alSourcef
alSourcef
sets a floating point property of a source.
source source name whose attribute is being set
param
the name of the attribute being set:
AL_PITCH AL_GAIN AL_MIN_GAIN AL_MAX_GAIN AL_MAX_DISTANCE AL_ROLLOFF_FACTOR AL_CONE_OUTER_GAIN AL_CONE_INNER_ANGLE AL_CONE_OUTER_ANGLE AL_REFERENCE_DISTANCE
value a pointer to the vector to set the attribute to void alSourcef(
ALuint source, ALenum param, ALfloat value );
avTouch Classes & Resources 1.
view : oalSpatialView oalTouchAppDelegate
initWithCoder oalSpatialView
•
initializeContents
awakeFromNib
checkForMusic oalPlayback
layoutContents
observeValueForKeyPath
touchesBegan touchPoint
touchesMoved touchesEnded
playback : oalPlayback listenerPos
sourcePos
listenerPos
sourcePos
init
interruptionListener routeChangeListener
initOpenAL initBuffer MyOpenALSupport.c
MyGetOpenALAudioData
alBufferDataStaticProc
initSource
Start & Stop
Sound
avTouch Classes & Resources 1.
! // Toggle the playback
!! if (playback.isPlaying) [playback stopSound];
! else [playback startSound];
! sender.selected = playback.isPlaying;
1. /
-
• oalTouchAppDelegate::playPause
! ALenum error;
!
! NSLog(@"Start!\n");
! // Begin playing our source file
! alSourcePlay(source);
! if((error = alGetError()) != AL_NO_ERROR) {
! ! NSLog(@"error starting source: %x\n", error);
! } else {
! ! // Mark our state as playing (the view looks at this)
! ! self.isPlaying = YES;
! }
2. OpenAL
• oalPlayback::startSound
alSourcePlay
source the name of the source to be played
plays a source.
void alSourcePlay(
ALuint source );
avTouch Classes & Resources 2.
! // Toggle the playback
!! if (playback.isPlaying) [playback stopSound];
! else [playback startSound];
! sender.selected = playback.isPlaying;
1. /
-
• oalTouchAppDelegate::playPause
! ALenum error;
!
! NSLog(@"Stop!!\n");
! // Stop playing our source file
! alSourceStop(source);
! if((error = alGetError()) != AL_NO_ERROR) {
! ! NSLog(@"error stopping source: %x\n", error);
! } else {
! ! // Mark our state as not playing (the view looks at this)
! ! self.isPlaying = NO;
! }
2. OpenAL
• oalPlayback::stopSound
alSourceStop
source the name of the source to be stopped
stops a source.
void alSourceStop(
ALuint source );
avTouch Classes & Resources 1.
view : oalSpatialView oalTouchAppDelegate
initWithCoder oalSpatialView
•
initializeContents
awakeFromNib
checkForMusic oalPlayback
layoutContents
observeValueForKeyPath
touchesBegan touchPoint
touchesMoved touchesEnded
playback : oalPlayback listenerPos
sourcePos
listenerPos
sourcePos
init
interruptionListener routeChangeListener
initOpenAL initBuffer MyOpenALSupport.c
MyGetOpenALAudioData
alBufferDataStaticProc
initSource playPause Play/Pause
startSound startSound /
Sound Source & Listener Position,
Listener Rotation
avTouch Classes & Resources 1. Sound Source
- (CGPoint)sourcePos {
! return sourcePos;
}
1. CGpoint
• oalPlayback::sourcePos
- (void)setSourcePos:(CGPoint)SOURCEPOS {
! sourcePos = SOURCEPOS;
! float sourcePosAL[] = {sourcePos.x, kDefaultDistance, sourcePos.y};
! // Move our audio source coordinates
! alSourcefv(source, AL_POSITION, sourcePosAL);
}
2.
• oalPlayback::setSourcePos
avTouch Classes & Resources 2. Listener
- (CGPoint)listenerPos {! return listenerPos;
}
1. CGpoint
• oalPlayback::sourcePos
- (void)setListenerPos:(CGPoint)LISTENERPOS {! listenerPos = LISTENERPOS;
! float listenerPosAL[] = {listenerPos.x, 0., listenerPos.y};
! // Move our listener coordinates
! alListenerfv(AL_POSITION, listenerPosAL);
}
2.
• oalPlayback::setListenerPos
alListenerfv
sets a floating point-vector property of the listener.
param
the name of the attribute to be set:
AL_POSITION AL_VELOCITY AL_ORIENTATION
values pointer to floating point-vector values void alListenerfv(
ALenum param, ALfloat *values );
avTouch Classes & Resources 3. Listener
- (CGFloat)listenerRotation {! return listenerRotation;
}
1. CGpoint
• oalPlayback::setListenerPos
- (void)setListenerRotation:(CGFloat)radians {! listenerRotation = radians;
! float ori[] = {cos(radians + M_PI_2), sin(radians + M_PI_2), 0., 0., 0., 1.};
! // Set our listener orientation (rotation)
! alListenerfv(AL_ORIENTATION, ori);
}
2.
• oalPlayback::setListenerRotation
avTouch Classes & Resources 1.
view : oalSpatialView oalTouchAppDelegate
initWithCoder oalSpatialView
•
initializeContents
awakeFromNib
checkForMusic oalPlayback
layoutContents
observeValueForKeyPath
touchesBegan touchPoint
touchesMoved touchesEnded
playback : oalPlayback listenerPos
sourcePos
listenerPos
sourcePos
init
interruptionListener routeChangeListener
initOpenAL initBuffer MyOpenALSupport.c
MyGetOpenALAudioData
alBufferDataStaticProc
initSource playPause Play/Pause
startSound startSound /
setListenerPos
setSourcePos setListenerRotation listenerRotation
Dealloc
avTouch Classes & Resources 1. oalSpatialView
- (void)dealloc {
! [playback removeObserver:self forKeyPath:@"sourcePos"];
! [playback removeObserver:self forKeyPath:@"isPlaying"];
! [playback removeObserver:self forKeyPath:@"listenerPos"];
! [playback removeObserver:self forKeyPath:@"listenerRotation"];
!
! CGImageRelease(_speaker_off);
! CGImageRelease(_speaker_on);
!
! [super dealloc];
}
1.
• oalSpatialView::dealloc
avTouch Classes & Resources 2. oalPlayback
- (void)dealloc {
! [super dealloc];
! [self teardownOpenAL];
! [bgURL release];
! [bgPlayer release];
}
1.
• oalPlayback::dealloc
- (void)teardownOpenAL {!! // Delete the Sources alDeleteSources(1, &source);
! // Delete the Buffers alDeleteBuffers(1, &buffer);
!
//Release context
alcDestroyContext(context);
//Close device
alcCloseDevice(device);
}
2. OpenAL
• oalPlayback::teardownOpenAL
alDeleteSources
deletes one or more sources.
void alDeleteSources(
ALsizei n, ALuint *sources );
n the number of sources to be deleted
sources pointer to an array of source names identifying the sources to be deleted
alDeleteBuffers
deletes one or more buffers, freeing the resources used by the buffer.
n the number of buffers to be deleted
sources pointer to an array of buffer names identifying the sources to be deleted void alDeleteBuffers(
ALsizei n, ALuint *buffers );
alcDestroyContext
destroys a context.
context a pointer to the new context
alcCloseDevice
closes a device by name.
device a pointer to an opened device void alcDestroyContext(
ALCcontext *context );
ALCboolean alcCloseDevice(
ALCdevice *device );
avTouch Classes & Resources 3. App Delegate
- (void)dealloc {
! [playback release];
! [view release];
! [window release];
! [super dealloc];
}