· 5 min read
Routing audio between Mac apps without the virtual cable mess
You need the output of one application to become the input of another. On macOS this is a solved problem in the sense that there are several solutions, and an unsolved problem in the sense that every one of them is a device you have to install, name, remember, and explain to whoever inherits the rig.
Why this is hard at all
CoreAudio’s model is that applications talk to devices. An application asks for an output device and writes samples to it; another asks for an input device and reads samples from it. There is no built-in concept of “connect this app’s output to that app’s input”.
Every tool that appears to do inter-app routing on macOS is really doing the same trick: installing a virtual device that is not attached to any hardware. The sending app writes to it as an output; the receiving app reads from it as an input. The samples pass through a system-level driver in the middle.
Once you understand that, the failure modes stop being mysterious.
The four building blocks
Loopback or pass-through devices. A virtual device whose output is wired to its input. Simple, effective for a single hop, and the most common thing people install.
Aggregate devices. macOS’s own way to present multiple interfaces as one. Solves channel count, not routing, and brings its own clocking problems — covered here.
Multi-output devices. macOS’s other native construct: one logical output that sends the same audio to several real devices. Useful for a duplicate feed, and it has the same clock-drift caveat.
Routing applications. A virtual device plus a control surface that decides what goes where, with metering. This is the category that actually matches how a rig is described on paper.
Where a stack of virtual cables goes wrong
The pattern that causes trouble: each new requirement adds another virtual device. One to get a browser into a conferencing app, another to record what the conferencing app outputs, an aggregate to combine that with the interface, a multi-output to also send it to speakers. Four constructs, three of them created at different times for different reasons.
The specific ways that bites:
- Device names are the only documentation. “Loopback 2” tells the next operator nothing about what it carries or why it exists.
- Sample rates must agree, and nothing enforces it. One app at 44.1k writing into a device configured for 48k gets resampled, or gets silence, depending on the tool.
- Channel maps are implicit. Which stereo pair carries what is knowledge in someone’s head.
- Devices vanish. A reboot, an OS update, a driver that did not load. The applications pointing at them fall back to built-in output, and now the show goes out of the laptop speaker.
- Feedback loops are easy to build and hard to see. Route an output back into something that feeds it and you get a howl with no obvious source, because the path is not visible anywhere.
- Latency compounds. Every hop adds a buffer. Four hops is enough to break lip sync.
- Nothing is metered. When there is no audio you cannot tell whether the source is silent, the routing is wrong, or a level is at zero — which are three completely different fixes.
None of these is a defect in any individual tool. They are what happens when the routing layer is inferred from a set of device names rather than described anywhere.
Making it survivable
If you are staying with a stack of virtual devices — a perfectly reasonable choice — a few habits remove most of the fragility.
Name devices for their job. Not “Loopback 3” but “Browser → Stream”. The name is the documentation, so make it a sentence about purpose.
Fix the sample rate everywhere, once. Pick 48k, set every physical interface, every virtual device and every application to it, and write it on the show file. Mismatched rates are the single most common cause of audio that is present but wrong.
Draw the routing. Literally, on paper or in the show notes: boxes for applications, boxes for devices, arrows between them. Ten minutes, and it is the difference between a rig someone else can debug and one only you can.
Minimise hops. Every intermediate device is latency plus a failure point. If a path can go direct, make it direct.
Test the reboot. Restart the Mac, do not touch anything, and see whether the whole chain comes back. If applications need to be re-pointed at devices after a restart, you have found a show-day failure in advance.
Have a bypass. Know how to get the essential feed out of the interface directly, with no virtual devices involved, and be able to do it in under a minute. That is the plan when the routing layer does not come back.
The case for making routing explicit
The alternative to inferring the routing from device names is to have the routing be the thing you look at. That is what SpectraRoute is for: a matrix of sources against destinations, with a visible connection at each crossing point and a level you can watch.
The properties that matter in a live context are not really features so much as consequences of the model:
- You can see the whole path at once, so a feedback loop is a visible cycle rather than a mystery howl.
- Signal presence is visible per point, which collapses “no audio” from three possible causes to one.
- One source can feed several destinations without building a multi-output device for each combination.
- The configuration is a file you can save with the show, rather than state distributed across four System Settings panes.
- Video devices are in the same picture. Video routing on macOS has historically been a separate and much poorer story — see CoreMediaIO in plain terms — and having both in one matrix is how a rig is actually described.
A worked example
A common corporate requirement: a presenter’s Mac joins a Teams call, the call audio needs to go to the room PA and to the recording, the room microphones need to go to the call and the recording, and playback video from another app needs to reach both the call and the room.
Described as devices, that is at least three virtual devices, one aggregate, and a set of application preferences that each have to be right.
Described as a matrix, it is nine crossing points. Mics to call, mics to record, mics to PA. Call to PA, call to record. Playback to call, playback to PA, playback to record. Two of those nine are the ones that cause feedback if you get them wrong, and in a matrix you can see which two.
The audio is identical either way. What differs is whether the rig can be understood at 6pm by someone who did not build it — which is the only quality that matters when something goes wrong.