Core Audio Tap: per-device attenuation vs. number of stereo output pairs — how to get unattenuated “raw” app streams?

Hi all,

I’ve implemented the new Core Audio Tap API (AudioHardwareCreateProcessTap with CATapDescription) and I’m seeing consistent level attenuation that scales with the number of stereo output pairs exposed by the target device.

What I observe

Device with 4 stereo pairs (8 outs) → tap shows −12.04 dB relative to source.

True 2-ch devices (built-in speakers, AirPods) → ~0 dB attenuation.

The attenuation appears regardless of whether I:

Create a global (default-output) tap via initStereoGlobalTapButExcludeProcesses:

Or create a per-process/per-device tap via initWithProcesses:andDeviceUID:withStream:

Additionally, the routing choice inside the sending app matters:

App output to “System/Default Output” → I often see no attenuation.

App output directly to a multi-out interface (e.g., RME Fireface) → I see the pair-count-scaled attenuation.

I can query Core Audio for the number of output channels/pairs and gain-compensate (+20·log10(N_pairs) dB) and that matches my measurements for many cases. However, this compensation is not universally correct because it seems to depend on where each process routes its audio (Default Output vs. direct device), even when those processes are included in the same tap aggregate.

Question

Is there a supported way to obtain the raw, unattenuated streams for all processes through the Tap API—i.e., to bypass this automatic headroom/attenuation behavior entirely? If this attenuation is expected by design:

Is there a documented rule for when it applies (global vs. device taps, per-process taps, stream selection, etc.)?

Is there a property/flag to disable it, or a reliable, official method to compute the exact compensation (beyond counting stereo pairs)?

Any guidance on ensuring consistent levels when multiple processes route differently (Default Output vs. direct device) but are captured by the same tap?

Environment

API: AudioHardwareCreateProcessTap + CATapDescription

Devices: built-in output (2-ch), RME Fireface (8+ outs / 4+ stereo pairs)

Behavior reproducible with both global and per-process/per-device tap descriptions.

Attenuation example: 4 stereo pairs → −12.04 dB observed.

Happy to provide a minimal sample, measurements, and device logs. Thanks!

— David

Core Audio Tap: per-device attenuation vs. number of stereo output pairs — how to get unattenuated “raw” app streams?
 
 
Q