当前位置: 首页 > 知识库问答 >
问题:

尽管在Swift中准备了ToPlay(),但AVAudioPlayer会产生延迟

钱照
2023-03-14

在我用Swift编程的SpriteKitiOS游戏中播放一个非常短的声音(约0.5秒)会产生一个小问题(比如延迟)。在其他问题中,我读到我应该preareToPlay()声音,我做到了。

我甚至使用了一个变量(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()
   }
}

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

其他信息:

  • 声音立即播放。
  • 最后一次结束后声音播放的速度似乎不会影响延迟。

共有3个答案

鲜于璞瑜
2023-03-14

当我多次调用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)")
        }
    }

}
从阎宝
2023-03-14

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

DispatchQueue.global().async {
    audioPlayer.play()
}
蒋招
2023-03-14

我遇到了同样的问题,并在后台队列中播放了声音。

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

let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
    audioPlayer.play()
})
 类似资料:
  • 问题内容: 在我用Swift编写的SpriteKit iOS游戏中,播放非常短的声音(约0.5秒)会产生打ic(如滞后)。在其他问题中,我读到我应该发出声音,就像以前那样。 我什至使用变量()在播放之前检查声音是否准备就绪。每当播放完()时,我也会重新准备声音。以下是代码的相关部分: 我不知道我在哪里犯了错误。我感觉我已经尝试了所有方法(包括但不限于:仅准备一次,在播放后立即准备,不使用变量,而只

  • 问题内容: 我正在阅读Redis文档,并且我对分区功能最感兴趣。 Redis文档指出以下内容: 数据存储还是缓存?在数据存储或缓存中使用Redis广告时的分区在概念上是相同的,但是存在巨大差异。当将Redis用作数据存储时,您需要确保给定的密钥始终映射到相同的实例,而当Redis用作高速缓存时,如果给定的节点不可用,那么如果我们开始使用不同的节点就不会有太大的问题节点,因为我们希望提高系统的可用性

  • 问题内容: 除了的ORM以外,还有人使用吗? 我想将Django的ORM用于对象操作,将SQLalchemy用于复杂的查询(例如那些需要左外部联接的查询)。 可能吗? 注意:我知道,但是该项目似乎尚未准备就绪。 问题答案: 我会怎么做 在Django orm中定义架构,让它通过syncdb编写数据库。您将获得管理界面。 在view1中,您需要一个复杂的联接

  • 我们的新项目有基于ApacheCXF的生产者SOAP web服务。现在我们计划将Web服务转移到生产环境中。我们正在寻找一个合适的开源容器(Web服务器或应用服务器),用于部署基于CXF的Java Web服务。首先想到的是Tomcat 7。只是需要专家的建议。CXF和基于Tomcat的Web服务的组合目前是否用于其他项目的生产中?这个解决方案是可扩展的吗 谢谢

  • 问题内容: 我正面临错误消息: 这是导致错误的代码 在Obj-C上可以这样使用: 我究竟做错了什么? 问题答案: 这似乎是由于子类模板中的问题。它带有该方法的一种版本,需要您解开序列。 将当前功能替换为: 这个版本隐式地解开了参数,所以应该没问题。

  • 我注意到Docker似乎在使用大量磁盘空间。我可以看到目录。docker/machine/machines/default是27.4GB 我最近清理了我没有使用的所有图像和容器。现在,当我运行时,我看到没有图像正在运行。 我还可以看到我有2个容器可用。 然后我可以看到我有3个图像。 它们怎么会占用近30GB的空间?