Splitting Signals in Music Apps with AVAudioEngine

Today I learned that you can essentially split a signal in AVAudioEngine by utilizing a helper method.
Why would you need to do this?
In a normal AVAudioEngine app, all of your nodes are connected in one-to-one chains. A file player is connected to an effect and then to an output.
There are lots of sonic possibilities to explore with running effects in parallel instead of one long chain. You can also exert more control with creative use of submixers.
In my case, I wanted to implement a feature to record an input mixed with an audio source without hearing (monitoring) the input in the output mix.
You Could Use a Matrix Mixer
I was well on my way through manually configuring a matrix mixer inside an AVAudioUnit via the old C APIs when I stumbled on the multiple connection method in AVAudioEngine. I was actually trying to understand how the default connect method works under the hood to see if I could save myself any time with setting the stream descriptions.
Definitely a possibility, but a lot more work.
It’s Easier to Use this Multiple Connection Method
Here’s the method in question:
func connect(_ sourceNode: AVAudioNode,
to destNodes: [AVAudioConnectionPoint],
fromBus sourceBus: AVAudioNodeBus,
format: AVAudioFormat?)The docs don’t say much, but the header has more info.
Use this method to establish connections from a source node to multiple destination nodes. Connections made using this method are either one-to-one (when a single destination connection is specified) or one-to-many (when multiple connections are specified), but never many-to-one.Writing the AVAudioConnectionPoint collection is just a matter of initializing the objects with the nodes you ultimately want to connect with:
let mixerPoint = AVAudioConnectionPoint(node: mixer, bus: mixer.nextAvailableInputBus)
let subMixerPoint = AVAudioConnectionPoint(node: subMixerPoint, bus: subMixer.nextAvailableInputBus)And then it’s easy to just connect
engine.connect(input, to: [mixerPoint, subMixerPoint], fromBus: 0, format: input.outputFormat(forBus: 0))A Specific Use Case for Recording Without Monitoring on iOS 9
In iOS 9, AVAudioEngine is not going to move any sound through its signal path unless it’s connected to an output. This is a challenge if you want to realtime record without monitoring. To make any silent submixers active, just set their volume to 0, and connect to the output.
