尽管在Swift中使用prepareToPlay(),AVAudioPlayer仍会产生延迟

问题描述 投票:21回答:3

在Swift中编写的SpriteKit iOS游戏中,播放非常短的声音(~0.5s)会产生打嗝(如滞后)。在其他问题中,我读到我应该prepareToPlay()声音,我做了。

我甚至使用变量(soundReady)来检查声音是否在播放之前准备好了。我也会在完成比赛后重新准备声音(audioPlayerDidFinishPlaying())。以下是代码的相关部分:

class GameScene: SKScene, AVAudioPlayerDelegate {

   var splashSound = NSURL()
   var audioPlayer = AVAudioPlayer()
   var soundReady = false

   override func didMoveToView(view: SKView) {
      let path = NSBundle.mainBundle().pathForResource("plopSound", ofType: "m4a")
      splashSound = NSURL(fileURLWithPath: path)
      audioPlayer = AVAudioPlayer(contentsOfURL: splashSound, error: nil)
      audioPlayer.delegate = self
      soundReady = audioPlayer.prepareToPlay()
   }

   func playSound(){
      if(soundReady){
         audioPlayer.play()
         soundReady = false
      }
   }

   func audioPlayerDidFinishPlaying(player: AVAudioPlayer!, successfully flag: Bool){
      //Prepare to play after Sound finished playing
      soundReady = audioPlayer.prepareToPlay()
   }
}

我不知道我在哪里出错了。我觉得我已经尝试了所有东西(包括但不限于:只准备一次,在播放后立即准备,不使用变量,而只是prepareToPlay())。

附加信息:

  • 声音播放没有延迟。
  • 最后一次完成后播放声音的速度似乎不会影响延迟。
ios audio swift avaudioplayer lag
3个回答
15
投票

我遇到了同样的问题并在backgroundQueue中播放了声音。

这是一个很好的例子:https://stackoverflow.com/a/25070476/586204

let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
    audioPlayer.play()
})

7
投票

只需从@brilliantairic添加Swift 3版本的解决方案。

DispatchQueue.global().async {
    audioPlayer.play()
}

0
投票

当我多次调用play时,会导致访问不良。我相信播放器正在被释放,因为这不是线程安全的。我创建了一个串行队列来缓解这个问题。

class SoundManager {

    static let shared = SoundManager()

    private init() {
        try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
        try? AVAudioSession.sharedInstance().setActive(true)
    }

    private let serialQueue = DispatchQueue(label: "SoundQueue", qos: .userInitiated)
    private var player: AVAudioPlayer?

    static func play(_ sound: Sound) {
        shared.play(sound)
    }

    func play(_ sound: Sound) {
        guard let url = Bundle.main.url(forResource: sound.fileName, withExtension: "mp3")
            else { return }

        do {
            try serialQueue.sync {
                self.player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileTypeMPEGLayer3)
                DispatchQueue.main.async {
                    self.player?.play()
                }
            }
        } catch let error as NSError {
            print("error: \(error.localizedDescription)")
        }
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.