Resolved AVFoundation sound lag

Discussion in 'iOS Programming' started by xArtx, Jan 5, 2013.

  1. xArtx, Jan 5, 2013
    Last edited: Jan 13, 2013

    xArtx macrumors 6502a

    Joined:
    Mar 30, 2012
    #1
    Hi :)
    I'm having a small problem with a sound sample I'm playing over & over in a program.
    It's a wav file set up like this:
    Code:
        NSURL *jurl = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/shot.wav", [[NSBundle mainBundle] resourcePath]]];
        
        NSError *jerror;
        shot = [[AVAudioPlayer alloc] initWithContentsOfURL:jurl error:&jerror];
        shot.numberOfLoops = 0;
        shot.volume = 0.20;
        
        [shot play]; // shot sound
    
    
    Now what happens is, it works, but every so often when I play the sound,
    there is about a half second pause in all the graphics when the sound is
    about to play. The action resumes just as the sample begins.

    Any ideas what might be happening?
    Cheers, Art.
     
  2. xStep macrumors 68000

    Joined:
    Jan 28, 2003
    Location:
    Less lost in L.A.
    #2
    I don't know, but from parsing the documentation, I'd try the prepareToPlay method.

    I'd also look to see how playAtTime: might work into this issue.

    If your actual code is inline like that, I suggest trying the allocation at some earlier point and making shot an ivar.

    Based on the name I'm wondering if this is a short sample sound like a gun shot. Perhaps there are better ways to execute such a thing and have it timed with the a graphic such as a gun shooting. Describe what you are trying to do as that might trigger someone with the experience to pop in on your question.
     
  3. xArtx thread starter macrumors 6502a

    Joined:
    Mar 30, 2012
    #3
    Whoops..
    Should have mentioned that the code above is only executed once,
    then I just use:
    Code:
    [shot play];
    
    Still, I'll look into your other suggestions.
    Funny how it seems to only occur more if the sample hasn't played for a while.
     
  4. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #4
    Which suggests there's a cache of audio samples, and a Least Recently Used cache algorithm has ejected the audio you want, so it has to be reloaded into RAM.
     
  5. xArtx thread starter macrumors 6502a

    Joined:
    Mar 30, 2012
    #5
    It could look that way, but this is the only sample in the program at the time I wrote the first post.
    Usually I use at least two instances of the same sample in case they have
    to be played simultaneously though.

    Code:
    
    if (swap == 0) {
    [shota play];
    swap = 1;
    } else {
    [shotb play];
    swap = 0;
    }
    
    
     
  6. xStep macrumors 68000

    Joined:
    Jan 28, 2003
    Location:
    Less lost in L.A.
    #6
    Your code doesn't support your statement of simultaneous playback. More importantly, the Apple docs clearly show how to play more than one sample in sync, if that is what you are referring to.
     
  7. xArtx thread starter macrumors 6502a

    Joined:
    Mar 30, 2012
    #7
    At the time I wrote the first post,
    I'm only referring to a program that has one instance of one sample.
    Problem is the same if I load another instance of it though.
    It makes no difference to the problem.
    Still, it's only minor.
     
  8. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #8
    Have you considered using AudioServicesPlaySystemSound instead of AVAudioPlayer?
     
  9. xArtx thread starter macrumors 6502a

    Joined:
    Mar 30, 2012
    #9
    I have used it in my very first iPhone program, and it was suitable for that,
    but the problem is if the user has their ringer volume and normal (iPod)
    volume set to different levels, system sound plays at the ringer volume level.
    This means the user has to go into settings to adjust the ringer volume to change
    the volume level of that particular app, which is going to be undesirable.

    Documentation suggested you can't play sounds simultaneously,
    but I did find that you can at least play (different) samples simultaneously,
    which means the little routine I posted above could likely play different
    instances of the same sound simultaneously.

    It was fun cycling through all of the stock system sounds though.
    You can cycle and play their IDs very fast, so the next sounds starts
    before the other has finished, and quite a few overlap each other.
    I was going to record it and use it as a ringtone :)
     
  10. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #10
    Understood. Just thought I'd check.
     
  11. xArtx thread starter macrumors 6502a

    Joined:
    Mar 30, 2012
    #11
    This seems to help.. every time you play the sample:

    Code:
            [shoot play];
            [shoot prepareToPlay];
    
     
  12. xStep macrumors 68000

    Joined:
    Jan 28, 2003
    Location:
    Less lost in L.A.
    #12
    Shouldn't play come after prepareToPlay?
     
  13. xArtx thread starter macrumors 6502a

    Joined:
    Mar 30, 2012
    #13
    I'm using prepareToPlay at the start when the sound files are loaded.
    From there it's:

    Code:
            [shoot play]; // play the sound instantly
            [shoot prepareToPlay]; // prepare to play for the next time
    

    So play is always called after prepareToPlay.
     
  14. xStep macrumors 68000

    Joined:
    Jan 28, 2003
    Location:
    Less lost in L.A.
    #14
    Ok, I get it. You. Have an initial prep and then a prep right after the play command. I wonder of there might be a better way. My concern would be that if the next play occurs after a long period if time that the prep buffersogjt bee purged.
     
  15. xArtx thread starter macrumors 6502a

    Joined:
    Mar 30, 2012
    #15
    I understand, and If you are wondering I'll be able to update soon
    with one more little experiment.

    I was going to post & say the problem is about 90% solved,
    but before posting this, I went through my source, and there
    were a couple of instances where I forgot to put the prepareToPlay
    after the play. Now everything is running smoothly :)

    Note that this is an action game where the shot sample can (and should)
    be called several times per second.

    If it turns out the prep command keeps the file in RAM for the long term,
    I guess it would be good to use it when the program shows a menu or something.
    Then the button push or whatever triggers the play.

    I have some other samples in the game that are called not so often.
    One can be called up to 50 seconds into the game, and it's still fine.

    I might test a longer period though, with a sample used only once or something like that.
     

Share This Page