Search code examples
iosswiftios13avaudiorecorderaudiokit

AVAudioRecorder, AudioKit issues , iOS 13.1.2


I am not sure what is going on but I cannot seem to initialize a AVAudioRecorder object successfully, given certain audio settings for a device above iOS 13.0

EDIT: commented below. but this works on 13.0 & 13.1 but not the two following patches, 13.1.1 and 13.1.2. ???

Xcode 11

Swift 5

AudioKit pod v4.9(just FYI, dont think this is the problem)

//audio Settings

private let audioSettings = [
        AVFormatIDKey : Int(kAudioFormatMPEG4AAC),
        AVSampleRateKey : 44100,
        AVNumberOfChannelsKey : 2,
        AVEncoderAudioQualityKey : AVAudioQuality.medium.rawValue
    ]


do {
     audioRecorder = try AVAudioRecorder(url: actualRecordingPath, settings: audioSettings)
      audioRecorder?.record()
      state = .recording
      try AudioKit.start()
      timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(timerDidUpdate), userInfo: nil, repeats: true)
    } catch let error{
       print("start recording", error.localizedDescription)
       return
      }

The specific error(s) includes:

AVAudioEngine.mm:160 Engine@0x2835411b0: could not initialize, error = -10868

AVAEInternal.h:109 [AVAudioEngineGraph.mm:1397:Initialize: (err = AUGraphParser::InitializeActiveNodesInInputChain(ThisGraph, *GetInputNode())): error -10868 Blockquote

AudioKit+StartStop.swift:restartEngineAfterConfigurationChange(_:):160:error restarting engine after route change

i was able to find this link:

https://www.osstatus.com/search/results?platform=all&framework=all&search=-10868

and its looking like maybe a format is not supported?

Anyone got any idea what's going on here? Again, no error on iOS 13.0, just doesn't work on 13.0+


Solution

  • I ran into the same problem with iOS 13.1.1 and 13.1.2. I've been using AudioKit's AKNodeRecorder in my code, and it turned out that I forgot to route to AudioKit.output the node which my AKNodeRecorder was recording. All I had to do was to add a mixer or booster after my node, set that new node's gain to 0, and then route that to the output.

    Here's the broken version:

    let mic = AKMicrophone()!
    let recorder = AKNodeRecorder(node: mic)!
    AudioKit.start()!
    

    Here's the working version:

    let mic = AKMicrophone()!
    let recorder = AKNodeRecorder(node: mic)!
    let recorderGain = AKBooster(mic, gain: 0)
    AudioKit.output = recorderGain
    AudioKit.start()!
    

    To explain why that is needed: AudioKit traverses your processing graph from the output node backward. Anything that is not connected to that graph may not get properly initialised, and its behaviour is undefined. You can observe such undefined behaviour in that your code works on older iOS versions, but not current ones.

    "But AKNodeRecorder is not connected to my graph", you may say. It turns out that AKNodeRecorder is not actually a node, but a tap.

    A tap can sit "on top" of a node. There can always be only one tap on top of a node. Other examples of taps are the AKFFTTap. Generally speaking, taps consume audio, but don't generate any audio, and thus they cannot be part of an audio graph - the only node that cannot generate anything is the final node, AudioKit.output.

    In other words, your audio graph should look like this:

     recordingtap
     |
    mic -> gain0 -> output
    

    Note that the gain is only needed if you don't want to hear your microphone on your output.