Skip to content

Instantly share code, notes, and snippets.

@larussverris
Last active June 6, 2023 21:02
Show Gist options
  • Save larussverris/5387819a3a7337937084730a86cee073 to your computer and use it in GitHub Desktop.
Save larussverris/5387819a3a7337937084730a86cee073 to your computer and use it in GitHub Desktop.
Creating an aggregate device using Core Audio in Objective-C
#import <Foundation/Foundation.h>
#import <CoreAudio/CoreAudio.h>
#import "utilities.h"
/*
This example demonstrates how to create an aggregate device using Core Audio in Objective-C.
It creates an aggregate device with two sub-devices, which are the default input and output devices.
*/
int main(int argc, const char * argv[]) {
OSStatus status = noErr;
// Get the default input and output device IDs
AudioDeviceID defaultInputDeviceID = getDefaultInputDeviceID();
AudioDeviceID defaultOutputDeviceID = getDefaultOutputDeviceID();
// Get the UIDs of the default input and output devices
NSString* defaultInputDeviceUID = getDeviceUID(defaultInputDeviceID);
NSString* defaultOutputDeviceUID = getDeviceUID(defaultOutputDeviceID);
// Create a dictionary to hold the aggregate device description
NSMutableDictionary *description = [NSMutableDictionary dictionary];
// Set the name of the new aggregate device
description[@(kAudioAggregateDeviceNameKey)] = @"YourNameHere";
// Set the UID of the aggregate device
description[@(kAudioAggregateDeviceUIDKey)] = @"YourUniqueId";
// Determines if the device should be visible in the "Audio MIDI Setup"
description[@(kAudioAggregateDeviceIsPrivateKey)] = @(NO);
// Array to hold the sub devices
NSMutableArray *subDevices = [NSMutableArray array];
// Input device
NSDictionary *inputSubDevice = @{
@(kAudioSubDeviceUIDKey) : defaultInputDeviceUID,
@(kAudioSubDeviceDriftCompensationKey) : @(YES),
};
[subDevices addObject:inputSubDevice];
// Output device
NSDictionary *outputSubDevice = @{
@(kAudioSubDeviceUIDKey) : defaultOutputDeviceUID,
@(kAudioSubDeviceDriftCompensationKey) : @(YES),
};
[subDevices addObject:outputSubDevice];
// Add the devices to the description
description[@(kAudioAggregateDeviceSubDeviceListKey)] = subDevices;
// This will be the ID of the newly created aggregate device
AudioDeviceID aggregateDeviceID = 0;
// Create the aggregate device
status = AudioHardwareCreateAggregateDevice((__bridge CFDictionaryRef)description, &aggregateDeviceID);
if (status != noErr) {
NSLog(@"An error occurred while creating the aggregate device, code: %d", status);
return -1;
}
NSLog(@"A new aggregate device has been created with ID: %d", aggregateDeviceID);
return 0;
}
#ifndef helpers_h
#define helpers_h
// Get the default input device ID
AudioDeviceID getDefaultInputDeviceID(void) {
// Initialize the device ID variable
AudioDeviceID deviceID = kAudioDeviceUnknown;
UInt32 propertySize = sizeof(deviceID);
// Set the property address for retrieving the default input device ID
AudioObjectPropertyAddress propertyAddress = {
kAudioHardwarePropertyDefaultInputDevice,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMain
};
// Retrieve the default input device ID
OSStatus status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &propertySize, &deviceID);
if (status != noErr) {
// Error handling
// Handle the failure to retrieve the default input device ID
}
return deviceID;
}
// Get the default output device ID
AudioDeviceID getDefaultOutputDeviceID(void) {
// Initialize the device ID variable
AudioDeviceID deviceID = kAudioDeviceUnknown;
UInt32 propertySize = sizeof(deviceID);
// Set the property address for retrieving the default output device ID
AudioObjectPropertyAddress propertyAddress = {
kAudioHardwarePropertyDefaultOutputDevice,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMain
};
// Retrieve the default output device ID
OSStatus status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &propertySize, &deviceID);
if (status != noErr) {
// Error handling
// Handle the failure to retrieve the default output device ID
}
return deviceID;
}
// Get the UID of an audio device
NSString *getDeviceUID(AudioDeviceID deviceID) {
// Initialize the status variable
OSStatus status = noErr;
// Initialize the UID and its size variables
CFStringRef uid = NULL;
UInt32 uidSize = sizeof(uid);
// Set the property address for retrieving the device UID
AudioObjectPropertyAddress propertyAddress = {
kAudioDevicePropertyDeviceUID,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMain
};
// Retrieve the device UID
status = AudioObjectGetPropertyData(deviceID, &propertyAddress, 0, NULL, &uidSize, &uid);
if (status != noErr) {
return nil;
}
return (__bridge NSString *)uid;
}
#endif /* helpers_h */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment