Files
wagic/projects/mtg/iOS/SoundManager/SoundManager.m

862 lines
25 KiB
Objective-C

//
// SoundManager.m
// SLQTSOR
//
// Created by Michael Daley on 22/05/2009.
// Copyright 2009 Michael Daley. All rights reserved.
//
#import "SoundManager.h"
#import "SynthesizeSingleton.h"
#import "MyOpenALSupport.h"
#pragma mark -
#pragma mark Private interface
@interface SoundManager (Private)
// This method is used to initialize OpenAL. It gets the default device, creates a new context
// to be used and then preloads the define # sources. This preloading means we wil be able to play up to
// (max 32) different sounds at the same time
- (BOOL)initOpenAL;
// Used to get the next available OpenAL source. The returned source is then bound to a sound
// buffer so that the sound can be played. This method checks each of the available OpenAL
// soucres which have been generated and returns the first source which is not currently being
// used. If no sources are found to be free then the first looping source is returned. If there
// are no looping sources then the first source created is returned
- (NSUInteger)nextAvailableSource;
// Used to set the current state of OpenAL. When the game is interrupted the OpenAL state is
// stopped and then restarted when the game becomes active again.
- (void)setActivated:(BOOL)aState;
// If audio is currently playing this method returns YES
- (BOOL)isAudioPlaying;
// Checks to see if an OpenAL error has been logged. If so it renders the error to the screen
- (void)checkForErrors;
@end
#pragma mark -
#pragma mark Public implementation
@implementation SoundManager
// Make this class a singleton class
SYNTHESIZE_SINGLETON_FOR_CLASS(SoundManager);
@synthesize currentMusicVolume;
@synthesize fxVolume;
@synthesize isExternalAudioPlaying;
@synthesize isMusicPlaying;
@synthesize usePlaylist;
@synthesize loopLastPlaylistTrack;
@synthesize musicVolume;
#pragma mark -
#pragma mark Dealloc and Init and Shutdown
- (void)dealloc {
// Loop through the OpenAL sources and delete them
for(NSNumber *sourceIDVal in soundSources) {
NSUInteger sourceID = [sourceIDVal unsignedIntValue];
alDeleteSources(1, &sourceID);
[self checkForErrors];
}
// Loop through the OpenAL buffers and delete
NSEnumerator *enumerator = [soundLibrary keyEnumerator];
id key;
while ((key = [enumerator nextObject])) {
NSNumber *bufferIDVal = [soundLibrary objectForKey:key];
NSUInteger bufferID = [bufferIDVal unsignedIntValue];
alDeleteBuffers(1, &bufferID);
[self checkForErrors];
}
// Release the arrays and dictionaries we have been using
[soundLibrary release];
[soundSources release];
[musicLibrary release];
[musicPlaylists release];
if (currentPlaylistTracks) {
[currentPlaylistTracks release];
}
// If background music has been played then release the AVAudioPlayer
if(musicPlayer)
[musicPlayer release];
// Disable and then destroy the context
alcMakeContextCurrent(NULL);
[self checkForErrors];
alcDestroyContext(context);
[self checkForErrors];
// Close the device
alcCloseDevice(device);
[self checkForErrors];
[super dealloc];
}
- (id)init {
self = [super init];
if(self != nil) {
// Initialize the array and dictionaries we are going to use
soundSources = [[NSMutableArray alloc] init];
soundLibrary = [[NSMutableDictionary alloc] init];
musicLibrary = [[NSMutableDictionary alloc] init];
musicPlaylists = [[NSMutableDictionary alloc] init];
// Grab a reference to the AVAudioSession singleton
audioSession = [AVAudioSession sharedInstance];
// Reset the error ivar
audioSessionError = nil;
// Check to see if music is already playing. If that is the case then you can leave the sound category as AmbientSound.
// If music is not playing we can set the sound category to SoloAmbientSound so that decoding is done using the hardware.
isExternalAudioPlaying = [self isAudioPlaying];
if (!isExternalAudioPlaying) {
NSLog(@"INFO - SoundManager: No external audio playing so using the SoloAmbient audio session category");
soundCategory = AVAudioSessionCategorySoloAmbient;
} else {
NSLog(@"INFO - SoundManager: External sound detected so using the Ambient audio session category");
soundCategory = AVAudioSessionCategoryAmbient;
}
// Having decided on the category we then set it
[audioSession setCategory:soundCategory error:&audioSessionError];
if (audioSessionError) {
NSLog(@"WARNING - SoundManager: Unable to set the sound category to ambient");
}
// Set up the OpenAL. If an error occurs then nil will be returned.
BOOL success = [self initOpenAL];
if(!success) {
NSLog(@"ERROR - SoundManager: Error initializing OpenAL");
return nil;
}
// Set up the listener position
float listener_pos[] = {0, 0, 0};
float listener_ori[] = {0.0, 1.0, 0.0, 0.0, 0.0, 1.0};
float listener_vel[] = {0, 0, 0};
alListenerfv(AL_POSITION, listener_pos);
[self checkForErrors];
alListenerfv(AL_ORIENTATION, listener_ori);
[self checkForErrors];
alListenerfv(AL_VELOCITY, listener_vel);
[self checkForErrors];
// Set the default volume for music and fx along the fading flag
currentMusicVolume = 0.5f;
musicVolume = 0.5f;
fxVolume = 0.5f;
playlistIndex = 0;
// Set up initial flag values
isFading = NO;
isMusicPlaying = NO;
stopMusicAfterFade = YES;
usePlaylist = NO;
loopLastPlaylistTrack = NO;
}
return self;
}
- (void)shutdownSoundManager {
@synchronized(self) {
if(sharedSoundManager != nil) {
[self dealloc];
}
}
}
#pragma mark -
#pragma mark Sound management
- (void)loadSoundWithKey:(NSString*)aSoundKey musicFile:(NSString*)aMusicFile {
// Check to make sure that a sound with the same key does not already exist
NSNumber *numVal = [soundLibrary objectForKey:aSoundKey];
// If the key is not found log it and finish
if(numVal != nil) {
NSLog(@"WARNING - SoundManager: Sound key '%@' already exists.", aSoundKey);
return;
}
NSUInteger bufferID;
// Generate a buffer within OpenAL for this sound
alGenBuffers(1, &bufferID);
[self checkForErrors];
// Set up the variables which are going to be used to hold the format
// size and frequency of the sound file we are loading
ALenum format;
ALsizei size;
ALsizei freq;
ALvoid *data;
alError = AL_NO_ERROR;
NSBundle *bundle = [NSBundle mainBundle];
// Get the audio data from the file which has been passed in
NSString *fileName = [[aMusicFile lastPathComponent] stringByDeletingPathExtension];
NSString *fileType = [aMusicFile pathExtension];
NSString *filePath = [bundle pathForResource:fileName ofType:fileType];
if ( filePath == nil )
filePath = aMusicFile;
CFURLRef fileURL = (CFURLRef)[[NSURL fileURLWithPath: filePath] retain];
if (fileURL)
{
data = MyGetOpenALAudioData(fileURL, &size, &format, &freq);
CFRelease(fileURL);
if((alError = alGetError()) != AL_NO_ERROR) {
NSLog(@"ERROR - SoundManager: Error loading sound: %@ with error %x\n", fileName, alError);
}
// Use the static buffer data API
alBufferData(bufferID, format, data, size, freq);
[self checkForErrors];
if((alError = alGetError()) != AL_NO_ERROR) {
NSLog(@"ERROR - SoundManager: Error attaching audio to buffer: %x\n", alError);
}
// Free the memory we used when getting the audio data
if (data)
free(data);
}
else
{
NSLog(@"ERROR - SoundManager: Could not find file '%@.%@'", fileName, fileType);
if (data)
free(data);
data = NULL;
}
// Place the buffer ID into the sound library against |aSoundKey|
[soundLibrary setObject:[NSNumber numberWithUnsignedInt:bufferID] forKey:aSoundKey];
NSLog(@"INFO - SoundManager: Loaded sound with key '%@' into buffer '%d'", aSoundKey, bufferID);
}
- (void)removeSoundWithKey:(NSString*)aSoundKey {
// Reset errors in OpenAL
alError = alGetError();
alError = AL_NO_ERROR;
// Find the buffer which has been linked to the sound key provided
NSNumber *numVal = [soundLibrary objectForKey:aSoundKey];
// If the key is not found log it and finish
if(numVal == nil) {
NSLog(@"WARNING - SoundManager: No sound with key '%@' was found so cannot be removed", aSoundKey);
return;
}
// Get the buffer number from
NSUInteger bufferID = [numVal unsignedIntValue];
NSInteger bufferForSource;
NSInteger sourceState;
for(NSNumber *sourceID in soundSources) {
NSUInteger currentSourceID = [sourceID unsignedIntValue];
// Grab the current state of the source and also the buffer attached to it
alGetSourcei(currentSourceID, AL_SOURCE_STATE, &sourceState);
[self checkForErrors];
alGetSourcei(currentSourceID, AL_BUFFER, &bufferForSource);
[self checkForErrors];
// If this source is not playing then unbind it. If it is playing and the buffer it
// is playing is the one we are removing, then also unbind that source from this buffer
if(sourceState != AL_PLAYING || (sourceState == AL_PLAYING && bufferForSource == bufferID)) {
alSourceStop(currentSourceID);
[self checkForErrors];
alSourcei(currentSourceID, AL_BUFFER, 0);
[self checkForErrors];
}
}
// Delete the buffer
alDeleteBuffers(1, &bufferID);
// Check for any errors
if((alError = alGetError()) != AL_NO_ERROR) {
NSLog(@"ERROR - SoundManager: Could not delete buffer %d with error %x", bufferID, alError);
exit(1);
}
// Remove the soundkey from the soundLibrary
[soundLibrary removeObjectForKey:aSoundKey];
NSLog(@"INFO - SoundManager: Removed sound with key '%@'", aSoundKey);
}
- (void)loadBackgroundMusicWithKey:(NSString*)aMusicKey musicFile:(NSString*)aMusicFile {
// Get the filename and type from the music file name passed in
NSString *fileName = [[aMusicFile lastPathComponent] stringByDeletingPathExtension];
NSString *fileType = [aMusicFile pathExtension];
// Check to make sure that a sound with the same key does not already exist
NSString *path = [musicLibrary objectForKey:aMusicKey];
// If the key is found log it and finish
if(path != nil) {
NSLog(@"WARNING - SoundManager: Music with the key '%@' already exists.", aMusicKey);
return;
}
path = [[NSBundle mainBundle] pathForResource:fileName ofType:fileType];
if (!path) {
if ( ![[NSFileManager defaultManager] fileExistsAtPath: aMusicFile] )
{
NSLog(@"WARNING - SoundManager: Cannot find file '%@.%@'", fileName, fileType);
return;
}
else
path = aMusicFile;
}
[musicLibrary setObject:path forKey:aMusicKey];
NSLog(@"INFO - SoundManager: Loaded background music with key '%@'", aMusicKey);
}
- (void)removeBackgroundMusicWithKey:(NSString*)aMusicKey {
NSString *path = [musicLibrary objectForKey:aMusicKey];
if(path == NULL) {
NSLog(@"WARNING - SoundManager: No music found with key '%@' was found so cannot be removed", aMusicKey);
return;
}
[musicLibrary removeObjectForKey:aMusicKey];
NSLog(@"INFO - SoundManager: Removed music with key '%@'", aMusicKey);
}
- (void)addToPlaylistNamed:(NSString*)aPlaylistName track:(NSString*)aTrackName {
NSString *path = [musicLibrary objectForKey:aTrackName];
if (!path) {
NSLog(@"WARNING - SoundManager: Track '%@' does not exist in the music library and cannot be added to the play list.");
return;
}
// See if the playlist already exists
NSMutableArray *playlistTracks = [musicPlaylists objectForKey:aPlaylistName];
if (!playlistTracks) {
playlistTracks = [[NSMutableArray alloc] init];
}
[playlistTracks addObject:aTrackName];
// Add the track key to the play list
[musicPlaylists setObject:playlistTracks forKey:aPlaylistName];
}
- (void)startPlaylistNamed:(NSString*)aPlaylistName {
NSMutableArray *playlistTracks = [musicPlaylists objectForKey:aPlaylistName];
if (!playlistTracks) {
NSLog(@"WARNING - SoundManager: No play list exists with the name '%@'", aPlaylistName);
return;
}
currentPlaylistName = aPlaylistName;
currentPlaylistTracks = playlistTracks;
usePlaylist = YES;
[self playMusicWithKey:[playlistTracks objectAtIndex:0] timesToRepeat:0];
}
- (void)removeFromPlaylistNamed:(NSString*)aPlaylistName track:(NSString*)aTrackName {
NSMutableArray *playlistTracks = [musicPlaylists objectForKey:aPlaylistName];
if (playlistTracks) {
int indexToRemove;
for (int index=0; index < [currentPlaylistTracks count]; index++) {
if ([[currentPlaylistTracks objectAtIndex:index] isEqualToString:aTrackName]) {
indexToRemove = index;
break;
}
}
[currentPlaylistTracks removeObjectAtIndex:indexToRemove];
}
}
- (void)removePlaylistNamed:(NSString*)aPlaylistName {
[musicPlaylists removeObjectForKey:aPlaylistName];
}
- (void)clearPlaylistNamed:(NSString*)aPlaylistName {
NSMutableArray *playlistTracks = [musicPlaylists objectForKey:aPlaylistName];
if (playlistTracks) {
[playlistTracks removeAllObjects];
}
}
#pragma mark -
#pragma mark Sound control
- (NSUInteger)playSoundWithKey:(NSString*)aSoundKey gain:(float)aGain pitch:(float)aPitch location:(CGPoint)aLocation shouldLoop:(BOOL)aLoop sourceID:(NSUInteger)aSourceID {
// Find the buffer linked to the key which has been passed in
NSNumber *numVal = [soundLibrary objectForKey:aSoundKey];
if(numVal == nil) return 0;
NSUInteger bufferID = [numVal unsignedIntValue];
// Find an available source if -1 has been passed in as the sourceID. If the sourceID is
// not -1 i.e. a source ID has been passed in then check to make sure that source is not playing
// and if not play the identified buffer ID within the provided source
NSUInteger sourceID;
if(aSourceID == -1) {
sourceID = [self nextAvailableSource];
} else {
NSInteger sourceState;
alGetSourcei(aSourceID, AL_SOURCE_STATE, &sourceState);
if(sourceState == AL_PLAYING)
return 0;
sourceID = aSourceID;
}
// Make sure that the source is clean by resetting the buffer assigned to the source
// to 0
alSourcei(sourceID, AL_BUFFER, 0);
// Attach the buffer we have looked up to the source we have just found
alSourcei(sourceID, AL_BUFFER, bufferID);
// Set the pitch and gain of the source
alSourcef(sourceID, AL_PITCH, aPitch);
alSourcef(sourceID, AL_GAIN, aGain * fxVolume);
// Set the looping value
if(aLoop) {
alSourcei(sourceID, AL_LOOPING, AL_TRUE);
} else {
alSourcei(sourceID, AL_LOOPING, AL_FALSE);
}
// Set the source location
alSource3f(sourceID, AL_POSITION, aLocation.x, aLocation.y, 0.0f);
// Now play the sound
alSourcePlay(sourceID);
alError = alGetError();
// Check to see if there were any errors
[self checkForErrors];
// Return the source ID so that loops can be stopped etc
return sourceID;
}
- (void)stopSoundWithKey:(NSString*)aSoundKey {
// Reset errors in OpenAL
alError = alGetError();
alError = AL_NO_ERROR;
// Find the buffer which has been linked to the sound key provided
NSNumber *numVal = [soundLibrary objectForKey:aSoundKey];
// If the key is not found log it and finish
if(numVal == nil) {
NSLog(@"WARNING - SoundManager: No sound with key '%@' was found so cannot be stopped", aSoundKey);
return;
}
// Get the buffer number from
NSUInteger bufferID = [numVal unsignedIntValue];
NSInteger bufferForSource;
NSInteger sourceState;
for(NSNumber *sourceID in soundSources) {
NSUInteger currentSourceID = [sourceID unsignedIntValue];
// Grab the current state of the source and also the buffer attached to it
alGetSourcei(currentSourceID, AL_SOURCE_STATE, &sourceState);
alGetSourcei(currentSourceID, AL_BUFFER, &bufferForSource);
// If this source is not playing then unbind it. If it is playing and the buffer it
// is playing is the one we are removing, then also unbind that source from this buffer
if(bufferForSource == bufferID) {
alSourceStop(currentSourceID);
alSourcei(currentSourceID, AL_BUFFER, 0);
}
}
// Check for any errors
[self checkForErrors];
// Remove the soundkey from the soundLibrary
[soundLibrary removeObjectForKey:aSoundKey];
NSLog(@"INFO - SoundManager: Removed sound with key '%@'", aSoundKey);
}
- (void)playMusicWithKey:(NSString*)aMusicKey timesToRepeat:(NSUInteger)aRepeatCount {
NSError *error;
NSString *path = [musicLibrary objectForKey:aMusicKey];
if(!path) {
NSLog(@"ERROR - SoundManager: The music key '%@' could not be found", aMusicKey);
return;
}
if(musicPlayer)
[musicPlayer release];
// Initialize the AVAudioPlayer using the path that we have retrieved from the music library dictionary
musicPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&error];
// If the backgroundMusicPlayer object is nil then there was an error
if(!musicPlayer) {
NSLog(@"ERROR - SoundManager: Could not play music for key '%d'", error);
return;
}
// Set the delegate for this music player to be the sound manager
musicPlayer.delegate = self;
// Set the number of times this music should repeat. -1 means never stop until its asked to stop
[musicPlayer setNumberOfLoops:aRepeatCount];
// Set the volume of the music
[musicPlayer setVolume:currentMusicVolume];
// Play the music
[musicPlayer play];
// Set the isMusicPlaying flag
isMusicPlaying = YES;
}
- (void)playNextTrack {
if (playlistIndex + 1 == [currentPlaylistTracks count]-1 && loopLastPlaylistTrack) {
playlistIndex += 1;
[self playMusicWithKey:[currentPlaylistTracks objectAtIndex:playlistIndex] timesToRepeat:-1];
} else if (playlistIndex + 1 < [currentPlaylistTracks count]) {
playlistIndex += 1;
[self playMusicWithKey:[currentPlaylistTracks objectAtIndex:playlistIndex] timesToRepeat:0];
} else if (loopPlaylist) {
playlistIndex = 0;
[self playMusicWithKey:[currentPlaylistTracks objectAtIndex:playlistIndex] timesToRepeat:0];
}
}
- (void)stopMusic {
[musicPlayer stop];
isMusicPlaying = NO;
usePlaylist = NO;
}
- (void)pauseMusic {
if(musicPlayer)
[musicPlayer pause];
isMusicPlaying = NO;
}
- (void)resumeMusic {
if (musicPlayer) {
[musicPlayer play];
isMusicPlaying = YES;
}
}
#pragma mark -
#pragma mark SoundManager settings
- (void)setMusicVolume:(float)aVolume {
// Set the volume iVar
if (aVolume > 1)
aVolume = 1.0f;
currentMusicVolume = aVolume;
musicVolume = aVolume;
// Check to make sure that the audio player exists and if so set its volume
if(musicPlayer) {
[musicPlayer setVolume:currentMusicVolume];
}
}
- (void)setFxVolume:(float)aVolume {
fxVolume = aVolume;
}
- (void)setListenerPosition:(CGPoint)aPosition {
listenerPosition = aPosition;
alListener3f(AL_POSITION, aPosition.x, aPosition.y, 0.0f);
}
- (void)setOrientation:(CGPoint)aPosition {
float orientation[] = {aPosition.x, aPosition.y, 0.0f, 0.0f, 0.0f, 1.0f};
alListenerfv(AL_ORIENTATION, orientation);
}
- (void)fadeMusicVolumeFrom:(float)aFromVolume toVolume:(float)aToVolume duration:(float)aSeconds stop:(BOOL)aStop {
// If there is already a fade timer active, invalidate it so we can start another one
if (timer) {
[timer invalidate];
timer = NULL;
}
// Work out how much to fade the music by based on the current volume, the requested volume
// and the duration
fadeAmount = (aToVolume - aFromVolume) / (aSeconds / kFadeInterval);
currentMusicVolume = aFromVolume;
// Reset the fades duration
fadeDuration = 0;
targetFadeDuration = aSeconds;
isFading = YES;
stopMusicAfterFade = aStop;
// Set up a timer that fires kFadeInterval times per second calling the fadeVolume method
timer = [NSTimer scheduledTimerWithTimeInterval:kFadeInterval target:self selector:@selector(fadeVolume:) userInfo:nil repeats:TRUE];
}
- (void)crossFadeTo:(NSString*)aTrack duration:(float)aDuration {
// TODO: Finish this method
}
#pragma mark -
#pragma mark AVAudioPlayerDelegate
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
isMusicPlaying = NO;
// If we are using a play list then handle the next track to be played
if (usePlaylist) {
[self playNextTrack];
}
}
#pragma mark -
#pragma mark AVAudioSessionDelegate
- (void)beginInterruption {
NSLog(@"BEGIN");
[self setActivated:NO];
}
- (void)endInterruption {
[self setActivated:YES];
}
@end
#pragma mark -
#pragma mark Private implementation
@implementation SoundManager (Private)
// Define the number of sources which will be created. iPhone can have a max of 32
#define MAX_OPENAL_SOURCES 16
- (BOOL)initOpenAL {
NSLog(@"INFO - Sound Manager: Initializing sound manager");
// Get the device we are going to use for sound. Using NULL gets the default device
device = alcOpenDevice(NULL);
// If a device has been found we then need to create a context, make it current and then
// preload the OpenAL Sources
if(device) {
// Use the device we have now got to create a context in which to play our sounds
context = alcCreateContext(device, NULL);
[self checkForErrors];
// Make the context we have just created into the active context
alcMakeContextCurrent(context);
[self checkForErrors];
// Set the distance model to be used
alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
[self checkForErrors];
// Pre-create sound sources which can be dynamically allocated to buffers (sounds)
NSUInteger sourceID;
for(int index = 0; index < MAX_OPENAL_SOURCES; index++) {
// Generate an OpenAL source
alGenSources(1, &sourceID);
[self checkForErrors];
// Configure the generated source so that sounds fade as the player moves
// away from them
alSourcef(sourceID, AL_REFERENCE_DISTANCE, 25.0f);
alSourcef(sourceID, AL_MAX_DISTANCE, 150.0f);
alSourcef(sourceID, AL_ROLLOFF_FACTOR, 6.0f);
[self checkForErrors];
// Add the generated sourceID to our array of sound sources
[soundSources addObject:[NSNumber numberWithUnsignedInt:sourceID]];
}
NSLog(@"INFO - Sound Manager: Finished initializing the sound manager");
// Return YES as we have successfully initialized OpenAL
return YES;
}
// We were unable to obtain a device for playing sound so tell the user and return NO.
NSLog(@"ERROR - SoundManager: Unable to allocate a device for sound.");
return NO;
}
- (NSUInteger)nextAvailableSource {
// Holder for the current state of the current source
NSInteger sourceState;
// Find a source which is not being used at the moment
for(NSNumber *sourceNumber in soundSources) {
alGetSourcei([sourceNumber unsignedIntValue], AL_SOURCE_STATE, &sourceState);
// If this source is not playing then return it
if(sourceState != AL_PLAYING) return [sourceNumber unsignedIntValue];
}
// If all the sources are being used we look for the first non looping source
// and use the source associated with that
NSInteger looping;
for(NSNumber *sourceNumber in soundSources) {
alGetSourcei([sourceNumber unsignedIntValue], AL_LOOPING, &looping);
if(!looping) {
// We have found a none looping source so return this source and stop checking
NSUInteger sourceID = [sourceNumber unsignedIntValue];
alSourceStop(sourceID);
return sourceID;
}
}
// If there are no looping sources to be found then just use the first source and use that
NSUInteger sourceID = [[soundSources objectAtIndex:0] unsignedIntegerValue];
alSourceStop(sourceID);
// Check for any errors that may have been raised
[self checkForErrors];
// Return the sourceID found
return sourceID;
}
#pragma mark -
#pragma mark Interruption handling
- (void)setActivated:(BOOL)aState {
OSStatus result;
if(aState) {
NSLog(@"INFO - SoundManager: OpenAL Active");
// Set the AudioSession AudioCategory to what has been defined in soundCategory
[audioSession setCategory:soundCategory error:&audioSessionError];
if(audioSessionError) {
NSLog(@"ERROR - SoundManager: Unable to set the audio session category");
return;
}
// Set the audio session state to true and report any errors
[audioSession setActive:YES error:&audioSessionError];
if (audioSessionError) {
NSLog(@"ERROR - SoundManager: Unable to set the audio session state to YES with error %d.", result);
return;
}
if (musicPlayer) {
[musicPlayer play];
}
// As we are finishing the interruption we need to bind back to our context.
alcMakeContextCurrent(context);
[self checkForErrors];
} else {
NSLog(@"INFO - SoundManager: OpenAL Inactive");
// As we are being interrupted we set the current context to NULL. If this sound manager is to be
// compaitble with firmware prior to 3.0 then the context would need to also be destroyed and
// then re-created when the interruption ended.
alcMakeContextCurrent(NULL);
[self checkForErrors];
}
}
- (BOOL)isAudioPlaying {
UInt32 audioPlaying = 0;
UInt32 audioPlayingSize = sizeof(audioPlaying);
AudioSessionGetProperty(kAudioSessionProperty_OtherAudioIsPlaying, &audioPlayingSize, &audioPlaying);
return (BOOL)audioPlaying;
}
- (void)fadeVolume:(NSTimer*)aTimer {
fadeDuration += kFadeInterval;
if (fadeDuration > targetFadeDuration) {
if (timer) {
[timer invalidate];
timer = NULL;
}
isFading = NO;
if (stopMusicAfterFade) {
[musicPlayer stop];
isMusicPlaying = NO;
}
} else {
currentMusicVolume += fadeAmount;
}
// If music is current playing then set its volume
if(isMusicPlaying) {
[musicPlayer setVolume:currentMusicVolume];
}
}
- (void)checkForErrors {
alError = alGetError();
if(alError != AL_NO_ERROR) {
NSLog(@"ERROR - SoundManager: OpenAL reported error '%d'", alError);
}
}
@end