Удаление AVAudioPlayerNode после использования вызывает сбой

Я использую AVAudioEngine для воспроизведения звуковых файлов и записи вывода в файл. У меня есть много файлов звуковых эффектов, каждый из которых воспроизводится нажатием кнопки. Чтобы воспроизвести файл, я создаю AVAudioPlayerNode и подключаю его к движку. После воспроизведения файла я пытаюсь отключить / отсоединить узел в закрытии завершенияHandler, чтобы освободить память. Если я не удаляю узлы, я просто буду добавлять новые узлы и новые подключения к движку.

Однако в следующий раз, когда я пытаюсь воспроизвести файл, приложение просто зависает. Вот мой код:

let url = NSBundle.mainBundle().URLForResource(name, withExtension: "wav")!
let audioPlayerFile = try AVAudioFile(forReading: url)
let playerNode = AVAudioPlayerNode()
self.engine.attachNode(playerNode)
self.engine.connect(playerNode, to: self.engine.mainMixerNode, format: audioPlayerFile.processingFormat)
playerNode.scheduleFile(audioPlayerFile, atTime: nil, completionHandler: { () -> Void in
    self.engine.disconnectNodeOutput(playerNode)
    self.engine.detachNode(playerNode)
})
playerNode.play()

Как лучше всего реализовать такую ​​функциональность, то есть воспроизводить несколько файлов, потенциально перекрывающих друг друга, во время записи?


person rodskagg    schedule 04.12.2015    source источник


Ответы (1)


У меня была похожая проблема. Я обнаружил, что отключение узла в фоновом потоке предотвращает зависание приложения.

    playerNode.scheduleBuffer(buffer, atTime: nil, options: nil) { () -> Void in
        self.detach(playerNode)
    }

А вот метод:

    func detach(player: AVAudioPlayerNode) {
        let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
        dispatch_async(dispatch_get_global_queue(priority, 0)) { () -> Void in
            self.engine.detachNode(player)
    }

Однако я все еще не уверен, что это решение само по себе, потому что эти фоновые потоки могут вращаться бесконечно без моего ведома.

person eikie    schedule 26.02.2016