Slow start for AVAudioPlayer the first time a sound is played

后端 未结 9 1334
孤城傲影
孤城傲影 2020-12-02 09:23

I\'m trying to eliminate startup lag when playing a (very short -- less than 2 seconds) audio file via AVAudioPlayer on the iPhone.

First, the code:

         


        
相关标签:
9条回答
  • 2020-12-02 09:42

    I wrote a simple wrapper for AVAudioPlayer that provides a prepareToPlay method that actually works:

    https://github.com/nicklockwood/SoundManager

    It basically just scans your app for sound files, picks one and plays it at zero volume. That initialises the audio hardware and allows the next sound to play instantly.

    0 讨论(0)
  • 2020-12-02 09:48

    The delay seems to be related to instantiating AVAudioPlayer for the first time. If I load any audio, run [audioPlayer prepareToPlay] and then immediately release it, the load times for all of my other audio is very close to imperceptible. So now I'm doing that in applicationDidFinishLaunching and everything else runs well.

    I can't find anything about this in the docs, but it certainly seems to be the case.

    0 讨论(0)
  • 2020-12-02 09:49

    The answer is

    AVAudioPlayer *audioplayer;
    [audioplayer prepareToPlay];
    
    0 讨论(0)
  • 2020-12-02 09:50

    I don't know for sure, but I suspect the NSData object is being lazy and loading the contents of the file on demand. You can try "cheating" by calling [audioData getBytes:someBuffer length:1]; at some early point to get it to load that file before it's needed.

    0 讨论(0)
  • 2020-12-02 09:53

    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.

    0 讨论(0)
  • 2020-12-02 09:58

    Other workaround is to create a short & silent audio and play it on the first time player is initiated.

    1. Set the microphone level to 0 on System Preferences.
    2. Open QuickTime.
    3. Create new Audio Recording (File > New Audio Recording).
    4. Record for 1 or 2 second.
    5. Save / Export the audio file. (it will have .m4a extension and about 2 kb on size).
    6. Add the file to your project and play it.

    If you dont want to create a new sound file yourself, you may download a short & silent audio file here : https://www.dropbox.com/s/3u45x9v72ic70tk/silent.m4a?dl=0

    0 讨论(0)
提交回复
热议问题