再生が終了したらコールバックを送信する AVAudioPlayerNode オブジェクトがあります。そのコールバックはアプリ内の他の多くの関数をトリガーし、そのうちの 1 つが礼儀の stop() メッセージを送信します。何らかの理由で、AVAudioPlayerNode が終了した瞬間に stop() を呼び出すと、クラッシュが発生します。ここのコードでは、(アプリケーション全体を含めるのではなく) 効果を示すために AVAudioPlayerNode がただちに stop を呼び出すように省略しています。崩れているのがよくわかります。理由がわかりません。a) ノードがまだ再生中で、stop() がノードを停止するか、b) 再生が終了し、stop を無視できるかのいずれかです。
私の推測では、これはファイル バッファの最後にあるエッジ ケースであり、バッファが残っていないあいまいな状態にありますが、技術的にはまだ再生中です。おそらく、stop() を呼び出して残りのバッファをフラッシュしようとして、それらが空になるのでしょうか?
func testAVAudioPlayerNode(){
let testBundle = Bundle(for: type(of: self))
let url = URL(fileURLWithPath: testBundle.path(forResource: "19_lyrics_1", ofType: "m4a")!)
let player = AVAudioPlayerNode()
let engine = AVAudioEngine()
let format = engine.mainMixerNode.outputFormat(forBus: 0)
engine.attach(player)
engine.connect(player, to: engine.mainMixerNode, format: format)
let delegate = FakePlayMonitorDelegate()
do {
let audioFile = try AVAudioFile(forReading: url)
let length = audioFile.length
player.scheduleFile(audioFile, at: nil, completionCallbackType: AVAudioPlayerNodeCompletionCallbackType.dataPlayedBack, completionHandler: {(completionType) in
print("playing = \(player.isPlaying)")
player.stop()
})
try engine.start()
let expectation = self.expectation(description: "playback")
delegate.expectation = expectation
player.play()
self.waitForExpectations(timeout: 6.0, handler: nil)
} catch {
}
}