Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Playing sound effect with no latency in Objective-C

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];
like image 966
Holger Sindbaek Avatar asked Jan 04 '13 18:01

Holger Sindbaek


2 Answers

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);
like image 66
Mike M Avatar answered Oct 14 '22 17:10

Mike M


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];
like image 1
Holger Sindbaek Avatar answered Oct 14 '22 16:10

Holger Sindbaek