searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

[CoreAudio]如何读取macOS的声音设备

2023-03-28 06:15:33
60
0

CoreAudio提供了一系列的C接口来和底层音频设备打交道,本文先介绍如果通过C接口来获取系统音频设备列表。

1. 定义PropertyAddress

首先定义PropertyAddress,CoreAudio所有的接口访问都需要定义PropertyAddress,用于确定需要访问的属性,这是一个结构体主要包含3个成员:
1. mSelector,需要访问的属性名称,比如下面的kAudioHardwarePropertyDevices表示设备列表;
2. mScope,设备所属的域,其实就是设备属性,包括:Global(全局)、Input(输入)、Output(输出);
3. mElement,限定设备范围,一般使用kAudioObjectPropertyElementMain | kAudioObjectPropertyElementMaster (deprecated);
AudioObjectPropertyAddress addr = {
    kAudioHardwarePropertyDevices, 
    kAudioObjectPropertyScopeGlobal, 
    kAudioObjectPropertyElementMaster 
};

2. 确定返回数据大小

UInt32   size = sizeof(UInt32);
UInt32   count;
OSStatus   status;
status = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &addr, 0, NULL, &size);

3. 分配内存并读取数据

count = size / sizeof(AudioDeviceID);
AudioDeviceID *ids = malloc(size);
status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0, NULL, &size, ids);

这里我们获取到的ids,就是系统的所有音频设备ID列表,再通过音频设备ID就可以获取到所有的音频设备信息。

4. 遍历获取设备详细信息

int i = 0;
CFStringRef cf_name = NULL;
CFStringRef cf_uid = NULL;

for (i = 0; i < count; i++) {
    
    // 获取Input Streams,如果有Input Stream,说明这是一个输入设备
    AudioObjectPropertyAddress propertyAddress = {
         kAudioDevicePropertyStreams,
         kAudioDevicePropertyScopeInput,
         kAudioObjectPropertyElementMain,
    };
    UInt32 dataSize = sizeof(UInt32);
    OSStatus status = AudioObjectGetPropertyDataSize(ids[i], &propertyAddress, 0, NULL, &dataSize);
    if (noErr != status) {
            NSLog(@"Error: %i", status);    
    }

    UInt32 streamCount = dataSize / sizeof(AudioStreamID);
    if (streamCount > 0) {
        size = sizeof(CFStringRef);
        propertyAddress.mSelector = kAudioDevicePropertyDeviceNameCFString;
        status = AudioObjectGetPropertyData(ids[i], &propertyAddress, 0, NULL, &size, &cf_name);
        if (noErr == status) {
            NSLog(@"Find input device: %@", (__bridge NSString *)cf_name);    
        }
    }
    
    // 获取Output Streams,如果有Output Stream说明是输出设备
    propertyAddress.mScope = kAudioDevicePropertyScopeOutput;
    propertyAddress.mSelector = kAudioDevicePropertyStreams;
    dataSize =  sizeof(UInt32);
    status = AudioObjectGetPropertyDataSize(ids[i], &propertyAddress, 0, NULL, &dataSize);
    if (noErr != status) {
            NSLog(@"Error: %i", status);    
    }

    streamCount = dataSize / sizeof(AudioStreamID);
    if (streamCount > 0) {
        size = sizeof(CFStringRef);
        propertyAddress.mSelector = kAudioDevicePropertyDeviceNameCFString;
        status = AudioObjectGetPropertyData(ids[i], &propertyAddress, 0, NULL, &size, &cf_name);
        
        if (noErr == status) {
            NSLog(@"Find output device: %@", (__bridge NSString *)cf_name);    
        }
     }
}
0条评论
0 / 1000
l****n
14文章数
1粉丝数
l****n
14 文章 | 1 粉丝
原创

[CoreAudio]如何读取macOS的声音设备

2023-03-28 06:15:33
60
0

CoreAudio提供了一系列的C接口来和底层音频设备打交道,本文先介绍如果通过C接口来获取系统音频设备列表。

1. 定义PropertyAddress

首先定义PropertyAddress,CoreAudio所有的接口访问都需要定义PropertyAddress,用于确定需要访问的属性,这是一个结构体主要包含3个成员:
1. mSelector,需要访问的属性名称,比如下面的kAudioHardwarePropertyDevices表示设备列表;
2. mScope,设备所属的域,其实就是设备属性,包括:Global(全局)、Input(输入)、Output(输出);
3. mElement,限定设备范围,一般使用kAudioObjectPropertyElementMain | kAudioObjectPropertyElementMaster (deprecated);
AudioObjectPropertyAddress addr = {
    kAudioHardwarePropertyDevices, 
    kAudioObjectPropertyScopeGlobal, 
    kAudioObjectPropertyElementMaster 
};

2. 确定返回数据大小

UInt32   size = sizeof(UInt32);
UInt32   count;
OSStatus   status;
status = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &addr, 0, NULL, &size);

3. 分配内存并读取数据

count = size / sizeof(AudioDeviceID);
AudioDeviceID *ids = malloc(size);
status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0, NULL, &size, ids);

这里我们获取到的ids,就是系统的所有音频设备ID列表,再通过音频设备ID就可以获取到所有的音频设备信息。

4. 遍历获取设备详细信息

int i = 0;
CFStringRef cf_name = NULL;
CFStringRef cf_uid = NULL;

for (i = 0; i < count; i++) {
    
    // 获取Input Streams,如果有Input Stream,说明这是一个输入设备
    AudioObjectPropertyAddress propertyAddress = {
         kAudioDevicePropertyStreams,
         kAudioDevicePropertyScopeInput,
         kAudioObjectPropertyElementMain,
    };
    UInt32 dataSize = sizeof(UInt32);
    OSStatus status = AudioObjectGetPropertyDataSize(ids[i], &propertyAddress, 0, NULL, &dataSize);
    if (noErr != status) {
            NSLog(@"Error: %i", status);    
    }

    UInt32 streamCount = dataSize / sizeof(AudioStreamID);
    if (streamCount > 0) {
        size = sizeof(CFStringRef);
        propertyAddress.mSelector = kAudioDevicePropertyDeviceNameCFString;
        status = AudioObjectGetPropertyData(ids[i], &propertyAddress, 0, NULL, &size, &cf_name);
        if (noErr == status) {
            NSLog(@"Find input device: %@", (__bridge NSString *)cf_name);    
        }
    }
    
    // 获取Output Streams,如果有Output Stream说明是输出设备
    propertyAddress.mScope = kAudioDevicePropertyScopeOutput;
    propertyAddress.mSelector = kAudioDevicePropertyStreams;
    dataSize =  sizeof(UInt32);
    status = AudioObjectGetPropertyDataSize(ids[i], &propertyAddress, 0, NULL, &dataSize);
    if (noErr != status) {
            NSLog(@"Error: %i", status);    
    }

    streamCount = dataSize / sizeof(AudioStreamID);
    if (streamCount > 0) {
        size = sizeof(CFStringRef);
        propertyAddress.mSelector = kAudioDevicePropertyDeviceNameCFString;
        status = AudioObjectGetPropertyData(ids[i], &propertyAddress, 0, NULL, &size, &cf_name);
        
        if (noErr == status) {
            NSLog(@"Find output device: %@", (__bridge NSString *)cf_name);    
        }
     }
}
文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0