AVAudioPlayer производит лаг, несмотря на то, что prepareToPlay() в Swift
Воспроизведение очень короткого звука (~ 0,5 с) вызывает икоту (например, отставание) в моей игре IIS SpriteKit, запрограммированной в Swift. В других вопросах я читал, что должен 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()
}
}
Я понятия не имею, где я ошибся в этом. Я чувствую, что я пробовал все (включая, но не ограничиваясь: только готовить один раз, готовить сразу после игры, не использовать переменную, а просто подготовитьToPlay()).
Дополнительная информация:
- Звук воспроизводится без задержек.
- Как быстро звук воспроизводится после последнего финиша, похоже, не влияет на задержку.
Ответы
Ответ 1
Я столкнулся с этой проблемой и воспроизвел звук в backgroundQueue.
Это хороший пример: fooobar.com/questions/31332/....
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
audioPlayer.play()
})
Ответ 2
Просто добавив версию Swift 3 от @brilliantairic.
DispatchQueue.global().async {
audioPlayer.play()
}
Ответ 3
Когда я звонил 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)")
}
}
}