如果播放之间的距离> 1秒,AVAudioPlayer和AudioServices都会延迟声音

时间:2017-09-01 18:17:56

标签: ios audio uigesturerecognizer avaudioplayer

当用户点按视图时,我希望播放声音的延迟可以忽略不计。我已经同时使用AVAudioPlayer和AudioServices尝试过此操作,但我遇到了同样的问题:如果点击之间的时间间隔超过一秒,则会略有延迟。换句话说,这里发生了什么:

  • 快速连续点击多次,只有第一次点击延迟,
  • 暂停约一秒或更长时间,
  • 再次点击多次(或只点击一次),只有第一次点击才会延迟。

我们所谈论的延迟很短,可能只有100毫秒左右,但足以使播放不像其他人那样立即感觉/发出声音。这是代码的AVAudioPlayer版本:

import UIKit
import AVFoundation

class ViewController: UIViewController {
    var player:AVAudioPlayer!

    override func viewDidLoad() {
        super.viewDidLoad()

        let soundUrl = Bundle.main.url(forResource: "short_sound", withExtension: "wav")!

        player = try! AVAudioPlayer(contentsOf: soundUrl)
        player.volume = 0 // "Prime the pump" 
        player.play()

        let r = TouchDownGestureRecognizer(target: self, action: #selector(tapped(_:)))
        self.view.addGestureRecognizer(r)
    }

    func tapped(_ gesture: TouchDownGestureRecognizer){
        player.volume = 1
        player.play()
    }
}

这是AudioServices版本。在这种情况下,有other posts表示在初始化期间可以播放静音,然后启动泵#34;但这只会解决第一个声音。此问题会影响1秒延迟后发生的所有声音。

import UIKit
import AudioToolbox

class ViewController: UIViewController {
    var soundID:SystemSoundID = 0

    override func viewDidLoad() {
        super.viewDidLoad()

        let soundUrl = Bundle.main.url(forResource: "short_sound", withExtension: "wav")!
        AudioServicesCreateSystemSoundID(soundUrl as CFURL, &soundID)

        let r = TouchDownGestureRecognizer(target: self, action: #selector(tapped(_:)))
        self.view.addGestureRecognizer(r)
    }

    func tapped(_ gesture: TouchDownGestureRecognizer){
        AudioServicesPlaySystemSound(soundID)
    }
}

在这两种情况下,这"触地"使用识别器(by @le-sang):

import Foundation
import UIKit.UIGestureRecognizerSubclass

class TouchDownGestureRecognizer: UIGestureRecognizer {
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
        if self.state == .possible {
            self.state = .recognized
        }
    }
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
        self.state = .failed
    }
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
        self.state = .failed
    }
}

我还尝试使用UILongPressGestureRecognizerminimumPressDuration=0同样的事情发生了。同样,如果我用UIView替换UIControl并设置目标/操作,也是如此。非常感谢任何见解,感谢阅读。

1 个答案:

答案 0 :(得分:0)

这是我发现的修复方法。我对这个解决方案并不完全满意(仍然不确定为什么这种情况发生),但它确实对两个玩家都有效。

这个想法很简单:如果你让任何一个玩家独自停留一秒左右,它就会开始打盹,然后在你需要的时候花点时间醒来。因此,解决方案是定期“轻推”玩家,这样就不会开始打盹。

对于AVAudioPlayer案例:

import UIKit
import AVFoundation

class ViewController: UIViewController {

    var player:AVAudioPlayer!
    var ghostPlayer:AVAudioPlayer!

    var timer:Timer!

    override func viewDidLoad() {
        super.viewDidLoad()

        let soundUrl = Bundle.main.url(forResource: "short_sound", withExtension: "wav")!

        player = try! AVAudioPlayer(contentsOf: soundUrl)

        ghostPlayer = try! AVAudioPlayer(contentsOf: soundUrl)
        ghostPlayer.volume = 0
        ghostPlayer.play()

        timer = Timer.scheduledTimer(timeInterval: 0.5,
                                     target: self,
                                     selector: #selector(nudgeAudio),
                                     userInfo: nil,
                                     repeats: true)

        let r = TouchDownGestureRecognizer(target: self, action: #selector(tapped(_:)))
        self.view.addGestureRecognizer(r)
    }

    func tapped(_ gesture: TouchDownGestureRecognizer){
        player.play()
    }

    func nudgeAudio() {
        ghostPlayer.play()
    }
}

对于AudioServices:

import UIKit
import AudioToolbox

class ViewController: UIViewController {
    var soundID:SystemSoundID = 0
    var ghostID:SystemSoundID = 1

    var timer:Timer!

    override func viewDidLoad() {
        super.viewDidLoad()

        let soundUrl = Bundle.main.url(forResource: "short_sound", withExtension: "wav")!
        AudioServicesCreateSystemSoundID(soundUrl as CFURL, &soundID)

        let ghostUrl = Bundle.main.url(forResource: "silence", withExtension: "wav")!
        AudioServicesCreateSystemSoundID(ghostUrl as CFURL, &ghostID)

        timer = Timer.scheduledTimer(timeInterval: 0.5,
                                     target: self,
                                     selector: #selector(nudgeAudio),
                                     userInfo: nil,
                                     repeats: true)

        let r = TouchDownGestureRecognizer(target: self, action: #selector(tapped(_:)))
        self.view.addGestureRecognizer(r)
    }

    func tapped(_ gesture: TouchDownGestureRecognizer){
        AudioServicesPlaySystemSound(soundID)
    }

    func nudgeAudio() {
        AudioServicesPlaySystemSound(ghostID)
    }
}