Search code examples
iosswiftaudioaudiokit

Microphone attached to multiple cliprecorders crash the aplication


I am trying to create a few instances of ClipRecorders in order to later in my app just trigger cliprecorder.start(...) to record a clip. I have one instance of AKMicrophone which I provide to the ClipRecorder. To create the clip recorders I use the next setup:

for _ in 0 ... 4 {
    let t = Track(microphone: microphone)
    tracks.append(t)
}

Track:

init(microphone: Microphone) {
    self.microphone = microphone
    clipRecorder = AKClipRecorder(node: microphone.node)
}

Microphone:

class Microphone {
    private var microphone: AKMicrophone = AKMicrophone()
    private var micMixer: AKMixer!
    private var micBooster: AKBooster!

    var node: AKNode {
        return micBooster
    }

    init(){
        micMixer = AKMixer(microphone)
        micBooster = AKBooster(micMixer)
        micBooster.gain = 0.5
    }
}

The first clip recorder is indeed initialised but on the second one (in the for loop) the application crashes (checked it with only one append and worked), here is the log:

2018-10-03 18:10:59.455441+0300 BeatmanApp[56475:2289336] [avae] AVAEInternal.h:70:_AVAE_Check: required condition is false: [AVAEGraphNode.mm:851:CreateRecordingTap: (nullptr == Tap())]
2018-10-03 18:10:59.467667+0300 BeatmanApp[56475:2289336] *** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: nullptr == Tap()'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010953629b __exceptionPreprocess + 331
    1   libobjc.A.dylib                     0x0000000108373735 objc_exception_throw + 48
    2   CoreFoundation                      0x0000000109536022 +[NSException raise:format:arguments:] + 98
    3   AVFAudio                            0x000000010b44889c _Z19AVAE_RaiseExceptionP8NSStringz + 156
    4   AVFAudio                            0x000000010b48595b _Z11_AVAE_CheckPKciS0_S0_b + 323
    5   AVFAudio                            0x000000010b47e63c _ZN17AUGraphNodeBaseV318CreateRecordingTapEmjP13AVAudioFormatU13block_pointerFvP16AVAudioPCMBufferP11AVAudioTimeE + 116
    6   AVFAudio                            0x000000010b45c1be _ZN18AVAudioEngineGraph16InstallTapOnNodeEP11AVAudioNodemjP13AVAudioFormatU13block_pointerFvP16AVAudioPCMBufferP11AVAudioTimeE + 218
    7   AVFAudio                            0x000000010b4cd423 _ZN17AVAudioEngineImpl16InstallTapOnNodeEP11AVAudioNodemjP13AVAudioFormatU13block_pointerFvP16AVAudioPCMBufferP11AVAudioTimeE + 13
    8   AVFAudio                            0x000000010b4bd48c -[AVAudioNode installTapOnBus:bufferSize:format:block:] + 208
    9   BeatmanApp                          0x00000001068d47db $S8AudioKit14AKClipRecorderC4nodeAcA8AKOutput_p_tcfcTf4gn_n + 363
    10  BeatmanApp                          0x00000001068d0299 $S8AudioKit14AKClipRecorderC4nodeAcA8AKOutput_p_tcfC + 73
    11  BeatmanApp                          0x00000001066752b4 $S10BeatmanApp5TrackC10microphoneAcA10MicrophoneC_tcfc + 724
    12  BeatmanApp                          0x0000000106674f83 $S10BeatmanApp5TrackC10microphoneAcA10MicrophoneC_tcfC + 67
    13  BeatmanApp                          0x000000010667bbd1 $S10BeatmanApp4LoopC05setupC033_AA3A7D0867ACF3D9219815B736BA3641LLyyF + 385
    14  BeatmanApp                          0x000000010667b93c $S10BeatmanApp4LoopC9metronome10microphoneAcA9MetronomeC_AA10MicrophoneCtcfc + 1164
    15  BeatmanApp                          0x000000010667b44f $S10BeatmanApp4LoopC9metronome10microphoneAcA9MetronomeC_AA10MicrophoneCtcfC + 79
    16  BeatmanApp                          0x000000010666ece5 $S10BeatmanApp11CoordinatorCyACSo22UINavigationControllerCcfc + 325
    17  BeatmanApp                          0x000000010666eb43 $S10BeatmanApp11CoordinatorCyACSo22UINavigationControllerCcfC + 67
    18  BeatmanApp                          0x000000010665952e $S10BeatmanApp0B8DelegateC11application_29didFinishLaunchingWithOptionsSbSo13UIApplicationC_SDySo0j6LaunchI3KeyaypGSgtF + 686
    19  BeatmanApp                          0x0000000106659854 $S10BeatmanApp0B8DelegateC11application_29didFinishLaunchingWithOptionsSbSo13UIApplicationC_SDySo0j6LaunchI3KeyaypGSgtFTo + 228
    20  UIKitCore                           0x000000011338b4d7 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 280
    21  UIKitCore                           0x000000011338cec4 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 3979
    22  UIKitCore                           0x0000000113392527 -[UIApplication _runWithMainScene:transitionContext:completion:] + 1623
    23  UIKitCore                           0x0000000113c34e3e __111-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:]_block_invoke + 866
    24  UIKitCore                           0x0000000113c31403 +[_UICanvas _enqueuePostSettingUpdateTransactionBlock:] + 153
    25  UIKitCore                           0x0000000113c34a7b -[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:] + 233
    26  UIKitCore                           0x0000000113c35435 -[__UICanvasLifecycleMonitor_Compatability activateEventsOnly:withContext:completion:] + 1085
    27  UIKitCore                           0x0000000113bf2b31 __82-[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:]_block_invoke + 795
    28  UIKitCore                           0x0000000113bf27db -[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:] + 435
    29  UIKitCore                           0x0000000113c3792c __125-[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:]_block_invoke + 584
    30  UIKitCore                           0x0000000113c38256 _performActionsWithDelayForTransitionContext + 100
    31  UIKitCore                           0x0000000113c3768b -[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:] + 221
    32  UIKitCore                           0x0000000113c30aa1 -[_UICanvas scene:didUpdateWithDiff:transitionContext:completion:] + 392
    33  UIKitCore                           0x0000000113390d46 -[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 515
    34  UIKitCore                           0x00000001133c2856 -[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 357
    35  FrontBoardServices                  0x0000000112b2adda -[FBSSceneImpl _didCreateWithTransitionContext:completion:] + 448
    36  FrontBoardServices                  0x0000000112b35f43 __56-[FBSWorkspace client:handleCreateScene:withCompletion:]_block_invoke_2 + 271
    37  FrontBoardServices                  0x0000000112b3563a __40-[FBSWorkspace _performDelegateCallOut:]_block_invoke + 53
    38  libdispatch.dylib                   0x000000010b02863e _dispatch_client_callout + 8
    39  libdispatch.dylib                   0x000000010b02bbb4 _dispatch_block_invoke_direct + 301
    40  FrontBoardServices                  0x0000000112b6a3c8 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 30
    41  FrontBoardServices                  0x0000000112b6a080 -[FBSSerialQueue _performNext] + 457
    42  FrontBoardServices                  0x0000000112b6a660 -[FBSSerialQueue _performNextFromRunLoopSource] + 45
    43  CoreFoundation                      0x0000000109499b31 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    44  CoreFoundation                      0x00000001094993a3 __CFRunLoopDoSources0 + 243
    45  CoreFoundation                      0x0000000109493a4f __CFRunLoopRun + 1263
    46  CoreFoundation                      0x0000000109493221 CFRunLoopRunSpecific + 625
    47  GraphicsServices                    0x000000010d8101dd GSEventRunModal + 62
    48  UIKitCore                           0x0000000113394115 UIApplicationMain + 140
    49  BeatmanApp                          0x000000010665a007 main + 71
    50  libdyld.dylib                       0x000000010b09e551 start + 1
    51  ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

this looks as the microphone node could not be shared with pre initialised clip recorders, what am I doing wrong? The other possibility that I can think of is to create a cliprecorder no demand (because I am obviously not recording simultaneously) then after the recording finished and the call back closure is called I will discard the recorder and move the clip into a player (or clip player), is this the right direction?

Thanks a lot.


Solution

  • Ok after few hours of debugging, searching the source code of AudioKit and SO, the fix for the problem was only few lines of code which I needed change/add in Track.

    init(microphone: Microphone) {
        self.microphone = microphone
    }
    
    func record(){
        microphone.node.outputNode.removeTap(onBus: 0)
        clipRecorder = AKClipRecorder(node: microphone.node)
    }
    

    The removeTap function is called only in the deinit of the AKClipRecorder so until you not de-initialize the instance the tap is assigned to the microphone bus which suppose to have only one tap assigned (reference here). What I had to do is to call this method manually to clear the tap on microphone bus before I start the recording with my clip recorder. This SO thread which is closely related question about other class in AudioKit, helped me a lot.