Summary
Using AudioHardwareCreateProcessTap + AudioHardwareCreateAggregateDevice for system audio capture. During long sessions, the AudioDeviceIOProc callback continues firing normally but every PCM sample is exactly 0.0f — while the system is producing audible output.
Environment
Field
Value
macOS
26.5 Beta
Hardware
MacBook Air (M2)
API
AudioHardwareCreateProcessTap + AudioHardwareCreateAggregateDevice
Tap
CATapDescription, processes = [], .unmuted, private
Format
48,000 Hz, Float32, interleaved stereo
Aggregate anchor
kAudioAggregateDeviceMainSubDeviceKey = current default output UID
Observed behavior
After running normally for several minutes, the stream transitions into an all-zero state:
AudioDeviceIOProc continues to fire at expected cadence
Frame count, timestamps (mHostTime, mSampleTime), and mDataByteSize all look normal
AudioBufferList pointers are valid
Every sample in every buffer is exactly 0.0f
Other apps are still producing audible output through the same output device
The condition may self-recover or persist until the session is stopped
Confirmed via RMS logging both inside the IOProc and after the ring buffer consumer — data is zero on delivery, not introduced downstream.
Example: 51-minute session on MacBook Air M2
Segment 1 (~7 min): Three all-zero periods: 60 s, 53 s, 141 s. Real PCM briefly returned between them.
Segment 2 (~44 min): Two all-zero periods: 16 min 3 s, 3 min 8 s. IOProc cadence, timestamp deltas, default output UID, and kAudioDevicePropertyDeviceIsRunningSomewhere all remained normal throughout.
What I have ruled out
Actual silence: User was in an active video call and could hear participants through the output device.
Default output device change: Monitored kAudioHardwarePropertyDefaultOutputDevice — no change during affected periods.
IOProc stall: Heartbeat and kAudioDevicePropertyDeviceIsRunningSomewhere remained normal.
Aggregate device destroyed: AudioObjectGetPropertyData on the aggregate UID continued returning the expected device.
Tap descriptor misconfiguration: The same tap produces valid PCM earlier in the same session, so this is not a startup-time issue.
Why detection is hard
All-zero buffers from a broken tap are indistinguishable from legitimate silence (muted participant, waiting room, paused media). kAudioProcessPropertyIsRunningOutput reports whether a process has active output IO, not whether it is contributing non-zero samples — a muted Zoom call still reports true.
Possible correlations
Sample-rate renegotiation on the output device (44.1 kHz ↔ 48 kHz) when another app changes output
Bluetooth device state changes (AirPods sleep/wake) where UID stays the same
MacBook Air more frequently affected than MacBook Pro
Always occurs after extended uptime — first few minutes are consistently clean
Current workaround
Full teardown and rebuild restores real PCM. Restarting the IOProc alone or recreating only the aggregate device is not reliable — both the Process Tap and Aggregate Device must be destroyed and recreated.
1. AudioDeviceStop
2. AudioDeviceDestroyIOProcID
3. AudioHardwareDestroyAggregateDevice
4. AudioHardwareDestroyProcessTap
5. AudioHardwareCreateProcessTap
6. AudioHardwareCreateAggregateDevice
7. Create + start new IOProc
Applying this automatically is risky because it cannot be reliably distinguished from legitimate silence.
Questions
Expected failure mode? Can a Process Tap continue delivering zero-filled buffers while the system output is audible? Is this expected under certain device or routing conditions?
Detection signal? Is there any HAL property, notification, or diagnostic counter that distinguishes "sources are genuinely silent" from "the tap data path has stopped receiving the real mix"?
Targeted recovery? Is there a supported way to re-anchor or reset the tap data path without destroying and recreating both objects?
Full rebuild as intended workaround? If so, it would help to confirm this so developers can converge on a consistent approach.
Mixer activity signal? kAudioProcessPropertyIsRunningOutput reflects IO registration, not sample contribution. Is there any AudioProcess property that indicates a process is currently delivering non-zero audio to the system mixer?
0
0
379