Playing sound effect with no latency in Objective-

2019-02-13 01:44发布

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];

3条回答
太酷不给撩
2楼-- · 2019-02-13 02:28

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);
查看更多
\"骚年 ilove
3楼-- · 2019-02-13 02:32

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];
查看更多
姐就是有狂的资本
4楼-- · 2019-02-13 02:32

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

查看更多
登录 后发表回答