AKNodeRecorder crash

Viewed 286

I have next flow in my app:

  1. User records audio
  2. Apply effects to recorded sound (or leave it as is)
  3. The app renders offline result audio file
  4. Then user may change effect or re-record audio

There is a problem with recording audio when we are at the last step and have rendered audio file with effect.

I got crash every time:

AKMicrophone.swift:init():45:Mixer inputs 8
AKNodeRecorder.swift:record():104:AKNodeRecorder: recording
2018-09-07 11:53:09.569326+0300 SEmoji[9009:1453392] [mcmx] 338: input bus 0 sample rate is 0
2018-09-07 11:53:09.571785+0300 SEmoji[9009:1453392] [avae] AVAEInternal.h:103:_AVAE_CheckNoErr: [AVAudioEngineGraph.mm:1839:InstallTapOnNode: (err = AUGraphParser::InitializeActiveNodesInInputChain(ThisGraph, *inputNode)): error -10875
2018-09-07 11:53:09.576701+0300 SEmoji[9009:1453392] *** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'error -10875'
*** First throw call stack:
(0x182daad8c 0x181f645ec 0x182daabf8 0x1886d31a0 0x1886eff58 0x1886ff410 0x1887785e8 0x1887686e8 0x10265b738 0x1024f24a4 0x1024f3b44 0x1024f3f54 0x18ccf8100 0x18ccf7b10 0x18ccbd870 0x18cb69484 0x18ccbd870 0x18cb69484 0x18cb5da48 0x18cb528f8 0x18cb51238 0x18d332c0c 0x18d3351b8 0x18d32e258 0x182d53404 0x182d52c2c 0x182d5079c 0x182c70da8 0x184c53020 0x18cc5178c 0x10246cf80 0x182701fc0)
libc++abi.dylib: terminating with uncaught exception of type NSException

This is how I prepare for recording:

   let mic = AKMicrophone()
   var recorder: AKNodeRecorder!

    AudioKit.engine.reset()
    AudioKit.engine.stop()

    AKSettings.bufferLength = .medium

    do {
        try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord)
        try AKSettings.setSession(category: .playAndRecord, with: .allowBluetoothA2DP)
    } catch {
        AKLog("Could not set session category.")
    }

    AKSettings.defaultToSpeaker = true


    self.recorder = try? AKNodeRecorder(node: mic)
    self.player = AKPlayer()
    do {
        try AudioKit.start()
    } catch {
        AKLog("AudioKit did not start!")
    }

Start record:

do {
      AudioKit.engine.inputNode.removeTap(onBus: 0)
      try self.recorder.record()
} catch {
      print("Cant record")
}

Stop record and save file:

let tape = self.recorder.audioFile!

self.recorder.stop()
tape.exportAsynchronously(name: "temp_test.m4a", baseDir: .temp,     exportFormat: .m4a) { file, error in
    try? self.recorder.reset()
    AudioKit.engine.inputNode.removeTap(onBus: 0) // I read in some similar topic that we need to remove tap
    self.player.load(audioFile: file)
}

Apply effect to audio file:

let pitchshifter = AKPitchShifter(self.audioPlayer)
pitchshifter.shift = 12

AudioKit.output = pitchshifter

if !AudioKit.engine.isRunning {
   try? AudioKit.start()
}

Render file:

func makeAudioFile(withCompletion completion: (Error?, URL?) -> Void) {

    let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("temp.m4a")
    if FileManager.default.fileExists(atPath: url.path) {
        try? FileManager.default.removeItem(at: url)
    }


    let recordSettings: [String: Any] = [
        AVFormatIDKey:kAudioFormatMPEG4AAC,
        AVSampleRateKey:44100.0,
        AVNumberOfChannelsKey:2,
        AVEncoderBitRateKey:12800,
        AVLinearPCMBitDepthKey:16,
        AVEncoderAudioQualityKey:AVAudioQuality.max.rawValue
    ]

    do {
        let tape = try AKAudioFile(forWriting: url, settings: recordSettings)
        try AudioKit.renderToFile(tape, seconds: Double(CMTimeGetSeconds(self.asset.duration))) {
            self.audioPlayer.setPosition(0)
            self.audioPlayer.play()
        }
        self.audioWasRendered = true
        completion(nil, url)
    } catch {
        print(error)
        completion(error, nil)
    }
}
0 Answers
Related