views:

258

answers:

2

I'm attempting to play a sound using AVAudioPlayer. Should be simple, but I'm seeing some odd results.

Code:

NSString *path = [[NSBundle mainBundle] pathForResource:@"pop" ofType:@"wav"];
NSURL *url = [NSURL fileURLWithPath:path];
AVAudioPlayer *sound = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[sound play];
[sound release];

What I'm seeing is that the sound doesn't play when using the app normally.

It plays only if I step through the code using the debugger, it doesn't play when executing any other way...

I'm not creating any new threads or run loops within my app, so this should all be running on the main thread, at least [NSThread isMainThread] returns true.

Anyone got any ideas as to what is going on here?

+3  A: 

AVAudioPlayer's play method is asynchronous, so you're starting to play the sound and then immediately releasing it! That's why it works when you step through it in the debugger -- you're giving it time to play before killing it. What you want to do is implement AVAudioPlayerDelegate's - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag method and release the audio player there, after the sound is done playing.

John Biesnecker
A: 

papajohn is right you should do it like this

Have a class level variable of audio player like

AVAudioPlayer *classLevelPlayer;

synthesize this object. and in the call to player method

-(void)playTheSong{

if(classLevelPlayer!=nil){
[classLevelPlayer stop];
[self setClassLevelPlayer:nil];
}

NSString *path = [[NSBundle mainBundle] pathForResource:@"pop" ofType:@"wav"];
NSURL *url = [NSURL fileURLWithPath:path];

AVAudioPlayer *sound = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];

if(sound){
[self setClassLevelPlayer:sound];
[classLevelPlayer play];
}
[sound release];
}

and in

-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
 [self setClassLevelPlayer:nil];
}

Hope this helps.

Madhup