Are the AudioObject APIs (such as AudioObjectGetPropertyData, AudioObjectSetPropertyData, etc.) thread-safe? Meaning, for the same AudioObjectID is it safe to do things like:
Get a property in one thread while setting the same property in another thread
Set the same property in two different threads
Add and remove property listeners in different threads
Put differently, is there any internal synchronization or mutex for this kind of usage or is the burden on the caller?
I was unable to find any documentation either way which makes me think that the APIs are not thread-safe.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I'm getting unexpected values for the volume level using kAudioDevicePropertyVolumeScalarToDecibels on my laptop's built-in audio.
void volume_test()
{
AudioObjectPropertyAddress address = {
.mSelector = kAudioHardwarePropertyDefaultOutputDevice,
.mScope = kAudioObjectPropertyScopeGlobal,
.mElement = kAudioObjectPropertyElementMaster
};
AudioObjectID deviceID = kAudioObjectUnknown;
UInt32 dataSize = sizeof(deviceID);
OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &address, 0, NULL, &dataSize, &deviceID);
assert(result == noErr);
address.mSelector = kAudioDevicePropertyVolumeScalar;
address.mScope = kAudioObjectPropertyScopeOutput;
Float32 volumeScalar = 0;
dataSize = sizeof(volumeScalar);
result = AudioObjectGetPropertyData(deviceID, &address, 0, NULL, &dataSize, &volumeScalar);
assert(result == noErr);
address.mSelector = kAudioDevicePropertyVolumeDecibels;
Float32 volumeDecibels = 0;
dataSize = sizeof(volumeDecibels);
result = AudioObjectGetPropertyData(deviceID, &address, 0, NULL, &dataSize, &volumeDecibels);
assert(result == noErr);
address.mSelector = kAudioDevicePropertyVolumeScalarToDecibels;
Float32 convertedVolumeDecibels = volumeScalar;
dataSize = sizeof(convertedVolumeDecibels);
result = AudioObjectGetPropertyData(deviceID, &address, 0, NULL, &dataSize, &convertedVolumeDecibels);
assert(result == noErr);
address.mSelector = kAudioDevicePropertyVolumeDecibelsToScalar;
Float32 convertedVolumeScalar = volumeDecibels;
dataSize = sizeof(convertedVolumeScalar);
result = AudioObjectGetPropertyData(deviceID, &address, 0, NULL, &dataSize, &convertedVolumeScalar);
assert(result == noErr);
NSLog(@"Direct		= %.4f %+2.2f dB", volumeScalar, volumeDecibels);
NSLog(@"Converted = %.4f %+2.2f dB", convertedVolumeScalar, convertedVolumeDecibels);
address.mSelector = kAudioDevicePropertyVolumeRangeDecibels;
AudioValueRange decibelRange;
dataSize = sizeof(decibelRange);
result = AudioObjectGetPropertyData(deviceID, &address, 0, NULL, &dataSize, &decibelRange);
assert(result == noErr);
NSLog(@"dB range %+2.2f ... %+2.2f", decibelRange.mMinimum, decibelRange.mMaximum);
}
The output is:
Direct		= 0.0620 -47.69 dB
Converted = 0.0620 -59.56 dB
dB range -63.50 ... +0.00
The same thing occurs using the underlying AudioControl directly.
Interestingly, using my external display's audio and the elements from kAudioDevicePropertyPreferredChannelsForStereo (since it has no master element), the values match.
Also of note, for the display audio kAudioDevicePropertyVolumeDecibelsToScalarTransferFunction is 5, or kAudioLevelControlTranferFunction2Over1. Attempting to retrieve kAudioDevicePropertyVolumeDecibelsToScalarTransferFunction for the laptop fails with the message
HALC_ShellObject::GetPropertyData: call to the proxy failed, Error: 2003332927 (who?)
HALPlugIn::ObjectGetPropertyData: got an error from the plug-in routine, Error: 2003332927 (who?)
which is not a "normal" error message for an unsupported property.
How should kAudioDevicePropertyVolumeScalarToDecibels be used?