I want to play some simple sound effects when people press certain buttons in my app and I've tried several things, but I always get a latency that makes the sound seem out of sync.
I've followed the tutorials here, so I've tried the build in Audio Services, but that had a latency and I've tried the AVAudioPlayer, but that had a latency as well, even though I used "prepareToPlay".
Do I really have to install a big and messy library like Finch to get a simple sound effect with no latency in my simple app?
Hope you can clarify things for me!
UPDATE
Code for Audio Services:
NSURL *soundURL = [[NSBundle mainBundle] URLForResource:@"PlopsX4"
withExtension:@"aif"];
AudioServicesCreateSystemSoundID((CFURLRef)soundURL, &sound1);
AudioServicesPlaySystemSound(sound1);
Code for AVAudioPlayer in viewDidLoad:
NSURL *soundURL = [[NSBundle mainBundle] URLForResource:@"PlopsX4"
withExtension:@"aif"];
self.avSound = [[AVAudioPlayer alloc]
initWithContentsOfURL:soundURL error:nil];
[self.avSound prepareToPlay]
Code for AVAudioPlayer in method where I want to play the file:
[self.avSound play];
The way I got this to work (and I think I got the idea from another post on SO) was to create an empty 1 second .wav file and "play" it at initialization. After that, there was no delay when I called the other sound effects.
Something like this in my sound player object
SystemSoundID blID;
SystemSoundID cID;
+(void)doInit
{
if (spinitialized){
AudioServicesPlaySystemSound (blID);
return;
}
NSString *str = [[NSBundle mainBundle] pathForResource:@"ding.wav" ofType:@""];
NSURL *uref = [NSURL fileURLWithPath:str];
OSStatus error = AudioServicesCreateSystemSoundID ((CFURLRef)uref, &cID);
if (error) NSLog(@"SoundPlayer doInit Error is %ld",error);
str = [[NSBundle mainBundle] pathForResource:@"blank.wav" ofType:@""];
uref = [NSURL fileURLWithPath:str];
error = AudioServicesCreateSystemSoundID ((CFURLRef)uref, &blID);
if (error) NSLog(@"SoundPlayer doInit Error is %ld",error);
AudioServicesPlaySystemSound (blID);
spinitialized = YES;
}
Then I could just play the "ding" without any delay using:
AudioServicesPlaySystemSound (cid);
SOLUTION
I ended up doing something similar as Mike above. I ended up playing the sound with the sound volume down in viewDidLoad:
NSURL *soundURL = [[NSBundle mainBundle] URLForResource:@"PlopsX4"
withExtension:@"aif"];
self.plops = [[AVAudioPlayer alloc] initWithContentsOfURL:soundURL error:nil];
[self.plops setVolume:0.0];
[self.plops play];
And then in the function where I play it I do:
[self.plops setVolume:1.0];
[self.plops play];
One thing I found that seems to help is, upon entry to the screen where the sound MIGHT be played, to play a fraction of a second of a sound. This seems to "prime" the sound mechanism -- allocating internal objects, paging in stuff, etc.
(I observe that this is similar to Mike M's approach.)