How can I play multiple different audio files from same AVAudioEngine? (Error: !nodeimpl->HasEngineImpl())

647 views Asked by At

In my app I want to play a different audio file every time a different cell in the table view is pressed. Below is my implementation but I keep receiving the error:

Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: !nodeimpl->HasEngineImpl()'

I think this error means that it is crashing because the audio engine already contains the node. But I'm not sure how to fix it in my case.

var audioPlayerFile : AVAudioFile!
var audioEngine = AVAudioEngine()
var pitchPlayer = AVAudioPlayerNode()
var timePitch = AVAudioUnitTimePitch()
var delay = AVAudioUnitDelay()

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        pitchPlayer.stop()
        audioEngine.stop()
        audioEngine.reset()

    let filePathResource = myConversation.conversation[indexPath.row].fileName

    print("file:", filePathResource)
    if (filePathResource != nil) {
        setUpAudioFilePath(filePathRes: filePathResource!)
    }

    timePitch.pitch = 0
    delay.delayTime = 0

    //append more effect:
    audioEngine.connect(pitchPlayer, to: timePitch, format: audioPlayerFile.processingFormat)
    audioEngine.connect(timePitch, to: delay, format: audioPlayerFile.processingFormat)
    audioEngine.connect(delay, to: audioEngine.outputNode, format: audioPlayerFile.processingFormat)

    pitchPlayer.scheduleFile(audioPlayerFile, at: nil, completionHandler: nil)
    do { try audioEngine.start()}
    catch {
        print("Error: Starting Audio Engine")
    }

    pitchPlayer.play()

}

func setUpAudioFilePath (filePathRes: String) {

    if let filePath = Bundle.main.path(forResource: filePathRes, ofType: "m4a") {

        let filePathUrl = NSURL.fileURL(withPath: filePath)
        do { audioPlayerFile = try AVAudioFile(forReading: filePathUrl) }
        catch {
            print("Error: Reading Audio Player File")
        }
        audioEngine.attach(pitchPlayer)
        audioEngine.attach(timePitch)
        audioEngine.attach(delay)

    } else {
        print("Error: filePath is empty")
    }
}
1

There are 1 answers

0
woosiki On

I think that you need mixer for playing multiple audio. AVAudioEngine already had mixer that had connected with outputNode. Try this

audioEngine.connect(pitchPlayer, to: timePitch, format: audioPlayerFile.processingFormat)
audioEngine.connect(timePitch, to: delay, format: audioPlayerFile.processingFormat)
audioEngine.connect(delay, to: audioEngine.mainMixerNode, format: audioPlayerFile.processingFormat)