Skip to content

fix(audio): include tap in aggregate device creation dictionary#14

Open
sondt2709 wants to merge 1 commit into
makeusabrew:mainfrom
sondt2709:fix/aggregate-device-tap-config
Open

fix(audio): include tap in aggregate device creation dictionary#14
sondt2709 wants to merge 1 commit into
makeusabrew:mainfrom
sondt2709:fix/aggregate-device-tap-config

Conversation

@sondt2709
Copy link
Copy Markdown

Summary

  • Restructure aggregate device creation to include kAudioAggregateDeviceTapListKey directly in the creation dictionary, using structured sub-tap dictionaries (kAudioSubTapUIDKey, kAudioSubTapDriftCompensationKey)
  • Remove the post-creation addTapToAggregateDevice() step that used AudioObjectSetPropertyData with flat UID string arrays
  • Get tap UUID from CATapDescription.uuid instead of querying kAudioTapPropertyUID after creation

Problem: On macOS 26 (Tahoe), the previous approach of adding the tap to the aggregate device after creation via AudioObjectSetPropertyData silently fails — the tap creates successfully, the IO proc runs at the correct rate, but all audio buffers contain zeros. This matches a known pattern where Apple's reference implementations (sudara's gist, AudioCap) include the tap list in the aggregate device creation dictionary.

Scope: Single file change to AudioTapManager.swift. No public API changes. Should remain compatible with macOS 14.2+ where the tap API was introduced.

Test plan

  • swift build -c release compiles without errors
  • Run audiotee --stereo while playing audio → captured PCM contains non-zero samples
  • Run audiotee --sample-rate 48000 --stereo | ffmpeg -f s16le -ar 48000 -ac 2 -i pipe:0 test.mp3 → output MP3 has audible sound
  • Verify on macOS 14.x if possible (backward compatibility)

🤖 Generated with Claude Code

The aggregate device was created without the tap list, then the tap was
added afterward via AudioObjectSetPropertyData with flat UID strings.
This delivers all-zero (silent) audio on macOS 26 Tahoe.

Restructure to include kAudioAggregateDeviceTapListKey with structured
sub-tap dictionaries (kAudioSubTapUIDKey, kAudioSubTapDriftCompensationKey)
directly in the AudioHardwareCreateAggregateDevice creation dictionary,
matching Apple's reference implementation.

Constraint: Must remain compatible with macOS 14.2+ where the tap API was introduced
Rejected: Keep post-creation property-set approach | silently fails on macOS 26, not used by reference implementations
Confidence: high
Scope-risk: narrow

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
kAudioAggregateDeviceNameKey: "audiotee-aggregate-device",
kAudioAggregateDeviceUIDKey: uid,
kAudioAggregateDeviceTapListKey: tapList,
kAudioAggregateDeviceTapAutoStartKey: false,
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @sondt2709! Can you confirm the addition of this kAudioAggregateDeviceTapAutoStartKey: false setting has no adverse effects?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants