3

I'm using AVAudioPlayer from iOS SDK for playing short sounds on each click in tableView rows. I have manually made @selector on button in each row that fires up method playSound:(id)receiver {}. From receiver I get sound url so I can play it up.

This method looks like that:

- (void)playSound:(id)sender {
    [audioPlayer prepareToPlay];
    UIButton *audioButton = (UIButton *)sender;
    [audioButton setImage:[UIImage imageNamed:@"sound_preview.png"] forState:UIControlStateNormal];
    NSString *soundUrl = [[listOfItems objectForKey:[NSString stringWithFormat:@"%i",currentPlayingIndex]] objectForKey:@"sound_url"];

    //here I get mp3 file from http url via NSRequest in NSData
    NSData *soundData = [sharedAppSettingsController getSoundUrl:defaultDictionaryID uri:soundUrl];
    NSError *error;
    audioPlayer = [[AVAudioPlayer alloc] initWithData:soundData error:&error];
    audioPlayer.numberOfLoops = 0;
    if (error) {
        NSLog(@"Error: %@",[error description]);
    }
    else {
        audioPlayer.delegate = self;
        [audioPlayer play];
    }
}

Everything works fine except for the first play of some sound. The application freezes for about 2 seconds and than sound is played. Second and every other sound play works just right after click on sound button.

I wonder why there is that about 2 seconds freeze on first play when application starts?

Kara
  • 6,115
  • 16
  • 50
  • 57
Borut Tomazin
  • 8,041
  • 11
  • 78
  • 91

4 Answers4

2

Check whether you are getting data asynchronously in function..

NSData *soundData = [sharedAppSettingsController getSoundUrl:defaultDictionaryID uri:soundUrl];

If you are getting asynchronously the execution will be blocked until it will get data.

Chandan Shetty SP
  • 5,087
  • 6
  • 42
  • 63
2

From your code snippet, audioPlayer must be an ivar, right?

At the top of the method, you invoke -prepareToPlay on the existing audioPlayer instance (which could be nil, at least on the first pass).

Later in the method, you replace this existing audio player with a brand new AVAudioPlayer instance. The previous -prepareToPlay is wasted. And you're leaking memory with each new AVAudioPlayer.

Instead of caching sound data or URLs, I would try creating a cache of AVAudioPlayer objects, one for each sound. In your -playSound: method, get a reference to the appropriate audio player for the table row, and -play.

You can use -tableView:cellForRowAtIndexPath: as the appropriate point to get the AVAudioPlayer instance for that row, maybe lazily creating the instance and caching it there as well.

You can try -tableView:willDisplayCell:forRowAtIndexPath: as the point where you would invoke -prepareToPlay on the row's AVAudioPlayer instance.

Or you could just do the prepare in -tableView:cellForRowAtIndexPath:. Experiment and see which works best.

Bill Garrison
  • 2,039
  • 15
  • 18
1

If your audio is less than 30 seconds long in length and is in linear PCM or IMA4 format, and is packaged as a .caf, .wav, or .aiff you can use system sounds:

Import the AudioToolbox Framework

In your .h file create this variable:

SystemSoundID mySound;

In your .m file implement it in your init method:

-(id)init{
if (self) {
//Get path of VICTORY.WAV <-- the sound file in your bundle
 NSString* soundPath = [[NSBundle mainBundle] pathForResource:@"VICTORY" ofType:@"WAV"];
//If the file is in the bundle
if (soundPath) {
    //Create a file URL with this path
    NSURL* soundURL = [NSURL fileURLWithPath:soundPath];

    //Register sound file located at that URL as a system sound
    OSStatus err = AudioServicesCreateSystemSoundID((CFURLRef)soundURL, &mySound);

        if (err != kAudioServicesNoError) {
            NSLog(@"Could not load %@, error code: %ld", soundURL, err);
        }
    }
}
return self;
}

In your IBAction method you call the sound with this:

AudioServicesPlaySystemSound(mySound);

This works for me, plays the sound pretty damn close to when the button is pressed. Hope this helps you.

M Jesse
  • 2,213
  • 6
  • 31
  • 37
0

This sometimes happens in the simulator for me too. Everything seems to work fine on the device. Have you tested on actual hardware?

Alastair Stuart
  • 4,165
  • 3
  • 36
  • 33