SETTINGS
Appearance
Language
About

Settings

Select a category to the left.

Appearance

Theme

Choose an overall theme for the entire blog. Each can have their own colours.

Colourscheme

Light or dark? Choose how the site looks to you by clicking an image below.

Light Dark
AMOLED

Language

Preferred Language

All content on blog.claranguyen.me is originally in UK English. However, if content exists in your preferred language, it will display as that instead. Feel free to choose that below. This will require a page refresh to take effect.

About

"blog.claranguyen.me" details

Domain Name: claranguyen.me
Site Version: 2.0.0
Last Updated: 2025/03/09
Virtual audio routing on macOS isn't lossless
Sunday, March 9, 2025

Introduction

Recently I purchased a Mac Mini for messing around. I built an arcade cabinet around it and even an automated recorder that records my sessions when I play, with separated gameplay audio and microphone audio. It's neat, but when I record gameplay, I noticed something a bit off with macOS. The audio spectrogram reveals that the audio has been tampered somehow. At first, I thought this was a quirk of MAME. But then I noticed it happening in other applications and figured something bigger was at play.

I had to verify my settings and everything. Sample rates were set to 48kHz across the board and everything. So what gives? Let's break it down.

Stock macOS: Capturing properly lossless audio

To start, I am on macOS Sequoia 15.3.2. Let's get to capturing some audio. I go through how to capture both microphone and desktop audio. But this isn't a tutorial. Let's get to it.

Microphones

macOS provides ways to record microphone audio losslessly. When you hook up a microphone, it will show up in Audio MIDI and allow capture.

When capturing the audio stream, the spectrogram goes up to the top easily showing that it is a fully lossless capture.

No problems here.

Capturing System Audio

Unlike Windows with Stereo Mix, macOS doesn't provide a built-in way to record system audio. You need applications like BlackHole or Loopback in order to record application audio. For simplicity, we'll use Loopback. So assume the following simple Loopback setup:

This setup is as simple as it gets. It simply captures Google Chrome input and outputs it. In Audio MIDI, this will create a virtual device that can be used as audio input in applications such as Audacity. Here's an example recording where I threw some FLAC audio into Chrome and recorded it with Audacity:

You can hear the audio sample here:

Identifying the problem

In the previous section, I demonstrated audio capture of both microphone and desktop audio. But the latter of the two was not a lossless capture. What went wrong?

Using the Chrome audio

Using the previously recorded audio from Chrome, we can compare it to the original file (or the small segment of the original file which was recorded).

That gives us these spectrograms:

Top = Loopback / Bottom = Original file.

The bottom one fills up the spectrum completely. The top one seems to go up to around the 22050 Hz range, implying a 44100 Hz capture rather than 48000 Hz. What gives? In Audio MIDI, the sample rate is set to 48000 Hz, as shown here:

In fact, every device on my Mac is set to 48 kHz. So why it's capturing at the wrong sample rate is beyond me.

Microphone Aggregate

There are many points of failure here. As a software engineer, one of the big focuses is to narrow down the issue as much as possible. For instance, is it Loopback causing the issues? Is it Chrome? Is it macOS? We don't know yet. But we can narrow it down to either Loopback or macOS by using a Microphone with Aggregate devices in macOS. Let's assume the following setups:

Loopback
Audio MIDI

This gives us a 4 channel device that we can record in Audacity. Channels 1 and 2 will be the raw audio from the QuadCast. Channels 3 and 4 will be from Loopback. Here are the results:

Things are looking kind of grim. So now we know it isn't a Chrome issue. It either is Loopback or macOS. Thankfully, I have another trick up my sleeve.

BlackHole

BlackHole is an alternative that's free and sets up a dummy device that can accept audio for recording. The purpose is to make a multi-output device in Audio MIDI. Then add BlackHole to the devices. Audio will output on devices like speakers, earphones, etc. But it will also go to BlackHole, which can then be captured. My setup looks like this:

I'm not going to show a spectrogram for this one. But when I record the BlackHole 2ch device, I get the same degrading of quality as before. This confirms it isn't Loopback. It's the API that both Loopback and Blackhole use to route audio. Both of them have the same issue.

The Digital Sledgehammer: GC573

One thing I was curious about is whether macOS is actually outputting this bad audio at the wrong sample rate, or if it's just the audio routing API. Rather than trust my ears, I can cheat and use a capture card. In my last post, " The GC573 can record 7.1 Surround Sound (via FFmpeg) ", I went into recording lossless audio from the GC573. So let's put that to some good use and capture some macOS audio. The same audio sample from before.

So, to be clear, macOS is outputting lossless audio. But the routing API is degraded quality for some reason.

Is the loss generational?

Loopback is perfect for testing this. If we nest audio devices, will the loss continue to get worse per iteration? Let's build upon the Chrome virtual audio interface and simply make another. Then let's build an aggregate device to capture both of them.

Loopback
Audio MIDI

Alright. Then we throw the test recording once again at Audacity and hope for the best. Here is the spectrogram for both the first and second generation of audio:

Top = Loopback (First Gen) / Bottom = Loopback (Second Gen).

There doesn't appear to be much of a difference here. But this spectrogram doesn't tell the whole story. Let's invert these two to get the differences between them. Then amplify it to show the differences more clearly:

There is generational loss. So the more times you nest audio devices, the more quality you lose. Again, I don't think this is the fault of Loopback. We have just proven it isn't Loopback, but rather macOS's audio routing API. The moment you introduce any kind of audio degradation at capture, of course it was going to get progressively worse the more you nest it. Just in case you were curious about more specifics, here's a zoom-in on the spectrogram:

It appears to have a hard cutoff for frequencies under 20 kHz, as I limited the zoom from 19 kHz to 24 kHz. Audio quality past 20 kHz is affected in some way.

Conclusion

I'm going to keep this post quite short. I just wanted to point out that macOS's virtual audio devices aren't lossless. I have no idea if this is intentional or not but it hinders audio production as lossless audio is very useful for editing in post. Windows and Linux do not have this issue, and I recorded audio production sessions while in a VC on Discord in lossless easily. So it's kind of ironic that macOS, an operating system oriented around content creation, has such a weird quirk.

If it's a bug, I hope it's fixed soon. Until then, I'll be recording audio via Windows or Linux. If it's not a bug, I'd like to know why. Though it very likely is a bug given the audio outputs to 44100 Hz regardless of my settings. It doesn't look like it's doing compression in real-time. Anyway, I hope the post was educational at least.




Clara Nguyễn
Hi! I am a Vietnamese/Italian mix with a Master's Degree in Computer Science from UTK. I have been programming since I was 6 and love to write apps and tools to make people's lives easier. I also love to do photography and media production. Nice to meet you!


Blog Links
Post Archive