Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AudioServicesAddSystemSoundCompletion callback-method is not called after a few calls

I'm using AudioServicesAddSystemSoundCompletion in my app to detect when sound has finished and then trigger some other action. For some reason I am getting the following behavior, it works for the first 8 to 12 sounds (that's at least what I tested) and then the callback defined for AudioServicesAddSystemSoundCompletion is not being called anymore.

Here is my code to create the sound:

NSString *soundPath = [[NSBundle mainBundle] pathForResource:[[soundFileName componentsSeparatedByString:@"."]objectAtIndex:0]ofType:@"wav"];
Log2(@"soundFileName: %@", soundFileName);
CFURLRef soundURL = (CFURLRef)[NSURL fileURLWithPath:soundPath];
AudioServicesCreateSystemSoundID(soundURL, &sound);
AudioServicesAddSystemSoundCompletion(sound, nil, nil, playSoundFinished, (void*) self);

to play the sound:

AudioServicesPlaySystemSound(sound);

and to do some stuff when the sound finished playing:

void playSoundFinished (SystemSoundID sound, void *data) {
    pf //Typedef for PRETTY_FUNCTION log

    AudioServicesRemoveSystemSoundCompletion(sound);
    [AppState sharedInstance].b_touchesFREE = TRUE;

    if([[AppState sharedInstance].ma_cardsToCheck count] >= 2)
{        
        [[AppState sharedInstance].vc_spiel pairFound];
}   

    if (((Card*)data).b_isTurnedFaceUp) {
        [AppState sharedInstance].i_cardsTurnedFaceUp --;
    }

    [(Card*)data release];
}

Has anyone of you any idea why it works the first few times and then stops working?

Thx in advance. Maverick1st

***** Edit ***** I just found out, that this happens when i try to play the sound a second time. Could it be, that i forgot to release it somewhere? But I always thought AudioServicesRemoveSystemSoundCompletion handles the memory management.

***** One more edit ***** So posting this on Stackoverflow made me think a bit deeper about the problem and i got the solution now (at least i think i got it ;)). Unfortunately i cannot answer the question for myself for the next 7.5 hours so i have to edit the question.

Just for you to better understand my problem.

I'm programming a memory game and every Card is a Class containing its image for front and back and the sound it plays when its turned around. since i only initialize the sound on creation of the card i was not sure if I should call AudioServicesRemoveSystemSoundCompletion every time the sound ends.

So i just tried it without AudioServicesRemoveSystemSoundCompletion and it works now.

Only thing i am not sure about now is if this could lead to a memory leak or something like that. But for now it works fine.

If someone could tell me if this is ok regarding the memory use i'd be really happe. :)

Best regards. Maverick1st

like image 331
Maverick1st Avatar asked Jun 20 '11 10:06

Maverick1st


1 Answers

If you create the sound (and set sound completion) only once during the lifetime of the app, it should be ok from memory management standpoint. It is always you create - you release.

However, you should call

AudioServicesRemoveSystemSoundCompletion(sound);
AudioServicesDisposeSystemSoundID(sound);

when you don't need the sound anymore (most probably in the dealloc method of the object where you created (or keep reference to) the sound. Do not change the order of these two, otherways you have a memory leak.

Maybe you would find AppSoundEngine useful. It is simple to use wrapper for SystemSoundID and associated C functions.

like image 61
Vilém Kurz Avatar answered Sep 28 '22 08:09

Vilém Kurz