Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you completely remove and release memory of an OpenAL sound file?

I have a small level based iPhone app. I need to load and release sound files for each level. Everything works fine with my openAL SoundManager except releasing sounds.

At first, when I remove a sound, it seems to do what it is meant to do – it removes the sound and I can’t access it again unless I reload it. BUT, when I test my apps dealloc’s with ‘Instruments’ it doesn’t show any deallocation. It doesn’t seem to free up the memory. So, when you move from level to level, it doesn't take long for the memory to run out and the app to crash.

I get this error in console:

Program received signal: “0”. warning: check_safe_call: could not restore current frame kill quit

This is how I load the sounds -

- (void)loadSoundWithKey:(NSString*)aSoundKey fileName:(NSString*)aFileName fileExt:(NSString*)aFileExt {
// Check to make sure that a sound with the same key does not already exist
NSNumber *numVal = [soundLibrary objectForKey:aSoundKey];
// If the key is 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);
// 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  error = AL_NO_ERROR;
ALenum  format;
ALsizei size;
ALsizei freq;
ALvoid *data;
NSBundle *bundle = [NSBundle mainBundle];
// Get the audio data from the file which has been passed in
CFURLRef fileURL = (CFURLRef)[[NSURL fileURLWithPath:[bundle pathForResource:aFileName ofType:aFileExt]] retain];
if (fileURL)
{   
    data = MyGetOpenALAudioData(fileURL, &size, &format, &freq);
    CFRelease(fileURL);
    if((error = alGetError()) != AL_NO_ERROR) {
        NSLog(@"ERROR - SoundManager: Error loading sound: %x\n", error);
        exit(1);
    }
    // Use the static buffer data API
    alBufferDataStaticProc(bufferID, format, data, size, freq);
    if((error = alGetError()) != AL_NO_ERROR) {
        NSLog(@"ERROR - SoundManager: Error attaching audio to buffer: %x\n", error);
    }       
}
else
{
    NSLog(@"ERROR - SoundManager: Could not find file '%@.%@'", aFileName, aFileExt);
    data = NULL;
}

// Place the buffer ID into the sound library against |aSoundKey|
[soundLibrary setObject:[NSNumber numberWithUnsignedInt:bufferID] forKey:aSoundKey];
if(DEBUG) NSLog(@"INFO - SoundManager: Loaded sound with key '%@' into buffer '%d'", aSoundKey, bufferID);

}

And this is how I am trying to remove/release. But it still seems to retain the memory of the sound file -

- (void)removeSoundWithKey:(NSString*)aSoundKey {
// 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 form the sound library so that the sound buffer can be released
NSUInteger bufferID = [numVal unsignedIntValue];
alDeleteBuffers(1, &bufferID);
[soundLibrary removeObjectForKey:aSoundKey];
if(DEBUG) NSLog(@"INFO - SoundManager: Removed sound with key '%@'", aSoundKey);

}

Can anyone think of away to completely remove every trace of my sound file (with the ability to load it again)?

Thank you very much!

like image 291
Jonathan Avatar asked Jan 10 '10 03:01

Jonathan


2 Answers

If anyone is interested... my problem was resolved by changing the alBufferDataStaticProc to alBufferData. Then adding if(data) free(data); See below.

Thanks for your help.

alBufferData(bufferID, format, data, size, freq);
    if((error = alGetError()) != AL_NO_ERROR) {
        NSLog(@"ERROR - SoundManager: Error attaching audio to buffer: %x\n", error);
    }
    if (data) 
        free(data);
}else{
    NSLog(@"ERROR - SoundManager: Could not find file '%@.%@'", fileName, fileType);
    data = NULL;
like image 135
Jonathan Avatar answered Sep 28 '22 08:09

Jonathan


This is a sum up of what I did "to completely remove every trace of my sound file (with the ability to load it again)" using the same apple example and some openAL documentation:

if (device != NULL)
    [self teardownOpenAL];
[self initOpenAL];
alSourcePlay(source);

The main addition here is that if, which in my case I actually added into teardownOpenAL.

like image 27
cregox Avatar answered Sep 28 '22 09:09

cregox