Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift AVAudioEngine crash: player started when in a disconnected state

So my code below is supposed to replay the chimes.wav file over and over again, with a higher pitch, but crashes with the error at the bottom. Can anyone find what is causing this error?

import UIKit
import AVFoundation
class aboutViewController: UIViewController {


    var audioEngine: AVAudioEngine = AVAudioEngine()
    var audioFilePlayer: AVAudioPlayerNode = AVAudioPlayerNode()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.



        var timePitch = AVAudioUnitTimePitch()
        timePitch.pitch = 2000
        let filePath: String = NSBundle.mainBundle().pathForResource("chimes", ofType: "wav")!
        let fileURL: NSURL = NSURL(fileURLWithPath: filePath)!
        let audioFile = AVAudioFile(forReading: fileURL, error: nil)
        let audioFormat = audioFile.processingFormat
        let audioFrameCount = UInt32(audioFile.length)
        let audioFileBuffer = AVAudioPCMBuffer(PCMFormat: audioFormat, frameCapacity: audioFrameCount)
        audioFile.readIntoBuffer(audioFileBuffer, error: nil)

        var mainMixer = audioEngine.mainMixerNode
        audioEngine.attachNode(audioFilePlayer)
        audioEngine.attachNode(timePitch)
        audioEngine.connect(audioFilePlayer, to:mainMixer, format: audioFileBuffer.format)
        audioEngine.connect(timePitch, to: audioEngine.outputNode, format: audioFile.processingFormat)


        audioEngine.startAndReturnError(nil)

        audioFilePlayer.play()

        audioFilePlayer.scheduleFile(audioFile, atTime: nil, completionHandler: nil)
        audioFilePlayer.scheduleBuffer(audioFileBuffer, atTime: nil, options:.Loops, completionHandler: nil)

    }

2014-11-10 18:34:37.746 windChimes[2350:108235] **** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'player started when in a disconnected state' **** First throw call stack: (0x185f01e48 0x1965f40e4 0x185f01d08 0x1848726c0 0x18489a33c 0x18489975c 0x10009e638 0x10009e858 0x18a6b0e84 0x18a6b0b94 0x18a853ad4 0x18a765310 0x18a7650dc 0x18a76505c 0x18a6ada2c 0x18a005994 0x18a000564 0x18a000408 0x189fffc08 0x189fff98c 0x189ff93bc 0x185eba14c 0x185eb70d8 0x185eb74b8 0x185de51f4 0x18ef7b5a4 0x18a716784 0x1000a54f8 0x1000a5538 0x196c62a08) libc++abi.dylib: terminating with uncaught exception of type NSException (lldb)

like image 360
CarveDrone Avatar asked Feb 12 '23 14:02

CarveDrone


2 Answers

The statement: "player started when in a disconnected state" indicates that there is a problem with the connection chain. This means either the nodes were not attached to the engine or the nodes were not linked together properly.Because both the audioFilePlayer and the timePitch nodes were attached, my impression would be to say that the problem lies with these two lines:

audioEngine.connect(audioFilePlayer, to:mainMixer, format: audioFileBuffer.format)
audioEngine.connect(timePitch, to: audioEngine.outputNode, format: audioFile.processingFormat)

The connection should link all components together:

audioFilePlayer -> timePitch -> audioEngine.mainMixerNode (or outputNode)

So the connection should look like:

audioEngine.connect(audioFilePlayer, to:timePitch, format: audioFile.processingFormat)
audioEngine.connect(timePitch, to: audioEngine.outputNode, format: audioFile.processingFormat)

I hope this helps.

like image 83
Daniel J Avatar answered Feb 14 '23 08:02

Daniel J


This error can also happen if you connect more than one AVAudioPlayerNode to a node that only takes in one input.

For example:

let playerOne = AVAudioPlayerNode()
let playerTwo = AVAudioPlayerNode()
let reverbEffect = AVAudioUnitReverb()

engine.attach(playerOne)
engine.attach(playerTwo)
engine.attach(reverbEffect)

engine.connect(playerOne, to: reverbEffect, format: format)
engine.connect(playerTwo, to: reverbEffect, format: format)
engine.connect(reverbEffect, to: engine.outputNode, format: format)

An error will now be thrown if you try to play audio with playerOne, because it's no longer connected to any node (its output was implicitly disconnected when we called engine.connect(playerTwo, to: reverbEffect, format: format))

The fix is simple; connect both your player nodes to an AVAudioMixerNode:

let playerOne = AVAudioPlayerNode()
let playerTwo = AVAudioPlayerNode()
let mixer = AVAudioMixerNode()
let reverbEffect = AVAudioUnitReverb()

engine.attach(playerOne)
engine.attach(playerTwo)
engine.attach(mixer)
engine.attach(reverbEffect)

engine.connect(playerOne, to: mixer, format: format)
engine.connect(playerTwo, to: mixer, format: format)
engine.connect(mixer, to: reverbEffect, format: format)
engine.connect(reverbEffect, to: engine.outputNode, format: format)
like image 42
Eric Avatar answered Feb 14 '23 09:02

Eric