Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Audio and the Phantom Device ID

So here's what is going on.

I am attempting to work with Core Audio, specifically input devices. I want to mute, change volume, etc, etc. I've encountered something absolutely bizarre that I cannot figure out. Thus far, google has been of no help.

When I query the system and ask for a list of all audio devices, I am returned an array of device IDs. In this case, 261, 259, 263, 257.

Using kAudioDevicePropertyDeviceName, I get the following:

261: Built-in Microphone
259: Built-in Input
263: Built-in Output
257: iPhoneSimulatorAudioDevice

This is all well and good.

// This method returns an NSArray of all the audio devices on the system, both input and
// On my system, it returns 261, 259, 263, 257
- (NSArray*)getAudioDevices
{
  AudioObjectPropertyAddress propertyAddress = { 
    kAudioHardwarePropertyDevices, 
    kAudioObjectPropertyScopeGlobal, 
    kAudioObjectPropertyElementMaster 
  };

  UInt32 dataSize = 0;
  OSStatus status = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize);
  if(kAudioHardwareNoError != status)
  {
    MZLog(@"Unable to get number of audio devices. Error: %d",status);
    return NULL;
  }

  UInt32 deviceCount = dataSize / sizeof(AudioDeviceID);

  AudioDeviceID *audioDevices = malloc(dataSize);

  status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize, audioDevices);
  if(kAudioHardwareNoError != status) 
  {
    MZLog(@"AudioObjectGetPropertyData failed when getting device IDs. Error: %d",status);
    free(audioDevices), audioDevices = NULL;
    return NULL;
  }

  NSMutableArray* devices = [NSMutableArray array];

  for(UInt32 i = 0; i < deviceCount; i++)
  {    
    MZLog(@"device found: %d",audioDevices[i]);   
    [devices addObject:[NSNumber numberWithInt:audioDevices[i]]];
  }

  free(audioDevices);

  return [NSArray arrayWithArray:devices];
}

The problem crops up when I then query the system and ask it for the ID of the default input device. This method returns an ID of 269, which is not listed in the array of all devices.

If I attempt to use kAudioDevicePropertyDeviceName to get the name of the device, I am returned an empty string. Although it doesn't appear to have a name, if I mute this device ID, my built-in microphone will mute. Conversely, if I mute the 261 ID, which is named "Built-In Microphone", my microphone does not mute.

// Gets the current default audio input device
// On my system, it returns 269, which is NOT LISTED in the array of ALL audio devices
- (AudioDeviceID)defaultInputDevice
{
  AudioDeviceID defaultAudioDevice;
  UInt32 propertySize = 0;
  OSStatus status = noErr;
  AudioObjectPropertyAddress propertyAOPA;

  propertyAOPA.mElement = kAudioObjectPropertyElementMaster;
  propertyAOPA.mScope = kAudioObjectPropertyScopeGlobal;
  propertyAOPA.mSelector = kAudioHardwarePropertyDefaultInputDevice;
  propertySize = sizeof(AudioDeviceID);

  status = AudioHardwareServiceGetPropertyData(kAudioObjectSystemObject, &propertyAOPA, 0, NULL, &propertySize, &defaultAudioDevice); 

  if(status) 
  { //Error
    NSLog(@"Error %d retreiving default input device",status);
    return 0;
  }

  return defaultAudioDevice;
}

To further confuse things, if I manually switch my input to "Line In" and re-run the program, I get an ID of 259 when querying for the default input device, which is listed in the array of all devices.

So, to summarize:

I am attempting to interact with the input devices in my system. If I try to interact with device ID 261 which is my "Built-In Microphone", nothing happens. If I try to interact with device ID 269 which is, apparently, a phantom ID, my built-in microphone is affected. The 269 ID is returned when I query the system for the default input device, but it is not listed when I query the system for a list of all devices.

Does anyone know what is happening? Am I simply going insane?

Thanks in advance!

like image 661
Tyler Avatar asked Jan 20 '12 03:01

Tyler


1 Answers

Fixed it.

First off, the phantom device ID was simply a virtual device the system was using.

Secondly, the reason I couldn't mute or do anything with the actual devices was because I was using AudioHardwareServiceSetPropertyData instead of AudioObjectSetPropertyData.

It all works now.

like image 188
Tyler Avatar answered Sep 23 '22 06:09

Tyler