I'm having a crash when I try connecting two AVAudioMixerNodes
to the microphone input of AVAudioEngine
.
I couldn't find documentation online how to manage two or more nodes to the same input.
What is the proper way to handle that case where you have multiple node listening to the microphone?
I'm calling those three method of after the other on the background thread:
private func setupSession() {
let session = AVAudioSession.sharedInstance()
do {
try session.setCategory(.playAndRecord, options: [.mixWithOthers])
if session.isInputGainSettable {
try session.setInputGain(0.2)
}
try session.setActive(true, options: .notifyOthersOnDeactivation)
} catch let error as NSError {
LoggerManager.shared.error(error: error, message: "Error while setting up AVAudioSession Category/Active status")
}
}
private func setupMixerNodes() {
analyzerNode = AVAudioMixerNode()
analyzerNode.volume = 0
volumeNode = AVAudioMixerNode()
volumeNode.volume = 0
engine.attach(analyzerNode)
engine.attach(volumeNode)
}
private func makeConnections() {
/* input microphone */
let inputNode = engine.inputNode
let inputFormat = inputNode.outputFormat(forBus: 0)
let analyzerConnectionPoint = AVAudioConnectionPoint(node: analyzerNode, bus: 0)
let volumeConnectionPoint = AVAudioConnectionPoint(node: volumeNode, bus: 0)
engine.connect(inputNode, to: [analyzerConnectionPoint, volumeConnectionPoint], fromBus: 0, format: inputFormat)
let mainMixerNode = engine.mainMixerNode
let mixerFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: inputFormat.sampleRate, channels: 1, interleaved: false)
engine.connect(analyzerNode, to: mainMixerNode, fromBus: 0, toBus: 0, format: mixerFormat)
engine.connect(volumeNode, to: mainMixerNode, fromBus: 0, toBus: 1, format: mixerFormat)
}
and I get this crash:
AURemoteIO.cpp:1128 failed: -10851 (enable 1, outf< 2 ch, 0 Hz, Float32, deinterleaved> inf< 2 ch, 0 Hz, Float32, deinterleaved>)
2022-03-08 12:59:57.950612-0500 SnoreLabo[2914:456147] [avae] AVAEInternal.h:76 required condition is false: [AVAudioEngineGraph.mm:2401:ConnectMultipleOutputs: (IsFormatSampleRateAndChannelCountValid(format))]
2022-03-08 12:59:58.030789-0500 SnoreLabo[2914:456147] *** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: IsFormatSampleRateAndChannelCountValid(format)'
*** First throw call stack:
(0x18273ed3c 0x199aa36a8 0x1828085bc 0x1ddf44eac 0x1ddf9b020 0x1de01bfa0 0x1de018328 0x104d4db1c 0x104d4e1f8 0x104ed4f6c 0x104bcdbe8 0x10dc00718 0x10dc01f94 0x10dc13edc 0x10dc146fc 0x1dcc4ae48 0x1dcc4a9f0)
libc++abi: terminating with uncaught exception of type NSException
dyld4 config: DYLD_LIBRARY_PATH=/usr/lib/system/introspection DYLD_INSERT_LIBRARIES=/Developer/usr/lib/libBacktraceRecording.dylib:/Developer/usr/lib/libMainThreadChecker.dylib:/Developer/Library/PrivateFrameworks/DTDDISupport.framework/libViewDebuggerSupport.dylib
*** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: IsFormatSampleRateAndChannelCountValid(format)'
terminating with uncaught exception of type NSException
EDIT
I ended up using this:
print("Current category: \(AVAudioSession.sharedInstance().category)")
engine.connect(inputNode, to: [analyzerConnectionPoint, volumeConnectionPoint], fromBus: 0, format: inputFormat)
But I still get the same crash from time to time... And the category is properly set to .playAndRecord
when it crash so that's not the issue...
AVAudioEngine
documentation they refer to the "audio processing chain", not "tree". This leads me to believe that it's designed to be connected serially. Have you tried connectingInput -> Analyzer -> Volume -> Mixer
? – Mimesisnil
for the format when you perform the connections? – Mimesis