This repository was archived by the owner on Dec 11, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathAudioTap.mm
More file actions
81 lines (69 loc) · 2.65 KB
/
Copy pathAudioTap.mm
File metadata and controls
81 lines (69 loc) · 2.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//
// AudioTap.mm
// SoundPusher
//
// Created by Daniel Vollmer on 18/04/2025.
//
//
#import <Foundation/NSDictionary.h>
#import <CoreAudio/CATapDescription.h>
#import <CoreAudio/AudioHardwareTapping.h>
#include "AudioTap.h"
#include "CoreAudioHelper.hpp"
static const AudioObjectPropertyAddress TapUIDAddress = {kAudioTapPropertyUID, 0, 0};
AudioTap::AudioTap(NSString *deviceUID, const NSInteger streamIndex)
: _tap(kAudioObjectUnknown)
, _deviceUID([deviceUID copy])
{
CATapDescription *tapConfig = [[CATapDescription alloc] initExcludingProcesses:@[] andDeviceUID:_deviceUID withStream:streamIndex];
tapConfig.privateTap = YES;
tapConfig.muteBehavior = CATapMutedWhenTapped;
tapConfig.name = [NSString stringWithFormat:@"SoundPusher Tap for '%@'", deviceUID];
OSStatus status = AudioHardwareCreateProcessTap(tapConfig, &_tap);
if (status != noErr)
throw CAHelper::CoreAudioException("AudioHardwareCreateProcessTap()", status);
_tapUID = CFBridgingRelease(CAHelper::GetStringProperty(_tap, TapUIDAddress));
}
AudioTap::AudioTap(AudioTap &&other)
: _tap(other._tap)
, _deviceUID(other._deviceUID)
, _tapUID(other._tapUID)
{
other._tap = kAudioObjectUnknown;
}
AudioTap::~AudioTap()
{
if (_tap != kAudioObjectUnknown)
AudioHardwareDestroyProcessTap(_tap);
}
AggregateTappedDevice::AggregateTappedDevice(AudioTap &&audioTap, const bool enableDriftCompensation)
: _audioTap(std::move(audioTap))
{
NSDictionary *dict = @{
@kAudioAggregateDeviceUIDKey : [NSString stringWithFormat:@"%@%@", kAggregateDeviceUIDPrefix, _audioTap._deviceUID],
@kAudioAggregateDeviceNameKey : [NSString stringWithFormat:@"SoundPusher Aggregate for '%@'", _audioTap._deviceUID],
// it seems we only need the tap, not the actual device in there
// @kAudioAggregateDeviceMainSubDeviceKey : _audioTap._deviceUID,
// @kAudioAggregateDeviceSubDeviceListKey : @[
// @{
// @kAudioSubDeviceUIDKey : _audioTap._deviceUID,
// },
// ],
@kAudioAggregateDeviceIsPrivateKey : @YES,
@kAudioAggregateDeviceTapListKey : @[
@{
@kAudioSubTapUIDKey : _audioTap._tapUID,
// since we only have a single device, drift compensation seems pointless?
@kAudioSubTapDriftCompensationKey : [NSNumber numberWithBool:enableDriftCompensation],
},
],
// @kAudioAggregateDeviceTapAutoStartKey : @YES,
};
OSStatus status = AudioHardwareCreateAggregateDevice((__bridge CFDictionaryRef)dict, &_aggregateDevice);
if (status != noErr)
throw CAHelper::CoreAudioException("AudioHardwareCreateAggregateDevice()", status);
}
AggregateTappedDevice::~AggregateTappedDevice()
{
AudioHardwareDestroyAggregateDevice(_aggregateDevice);
}