8

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];
Holger Sindbaek
  • 2,278
  • 6
  • 41
  • 68
  • 5
    Silly question, but are you sure there isn't a moment of silence at the beginning of your audio file? Have you put it through something like audacity? – Dan F Jan 04 '13 at 18:34
  • Also, how are you testing? Device? Simulator? What hardware are you testing on if it is on a device? – Dan F Jan 04 '13 at 18:36
  • Have you searched SO. It seems like there are many other questions on this issue. Some suggest some hacks to pre-load, others suggest using system sounds (SystemSoundID) – KlausCPH Jan 04 '13 at 18:49
  • @DanF There's no moment of silence in the start. I've made the sound myself. Second time it plays, it plays instantly... it's only the very first time. I'm testing on the newest generation iPod touch which is connected to my macbook air. – Holger Sindbaek Jan 04 '13 at 18:56
  • @BjörnKaiser Just did. Would love some comments on it. – Holger Sindbaek Jan 04 '13 at 18:57
  • @KlausCPH Definitely did. There's a lot of questions, but no real conclusions. I am using SystemSoundID in one of the examples and that to has a latency. – Holger Sindbaek Jan 04 '13 at 18:58

3 Answers3

3

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);
Mike M
  • 4,358
  • 1
  • 28
  • 48
1

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];
Holger Sindbaek
  • 2,278
  • 6
  • 41
  • 68
0

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.)

Hot Licks
  • 47,103
  • 17
  • 93
  • 151