Many (most?) drivers do this very well - e.g. if you use the Apple built-in soundcard, it'll happily run a mixtures of apps at different rates.
It's not the driver doing the conversion. it's the application itself doing it in realtime via AudioConverterServices from the AudioToolbox framework.
yes, your code defaults to the first available sample rate in the list of sample rates returned by the driver. It would be awesome if it defaulted to the currently selected sample rate.
Here is the solution I arrived at, borrowing a lot from Learning Core Audio's section on getting hardware sample rates.
OSStatus GetDefaultInputDeviceSampleRate(Float64 *outSampleRate) {
OSStatus error;
AudioDeviceID deviceID = 0;
AudioObjectPropertyAddress propertyAddress;
UInt32 propertySize;
//
propertyAddress.mSelector = kAudioHardwarePropertyDefaultSystemOutputDevice;
propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
propertyAddress.mElement = 0;
propertySize = sizeof(AudioDeviceID);
//
error = AudioHardwareServiceGetPropertyData( kAudioObjectSystemObject,
&propertyAddress,
0,
nullptr,
&propertySize,
&deviceID);
if( error) return error;
//
propertyAddress.mSelector = kAudioDevicePropertyNominalSampleRate;
propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
propertyAddress.mElement = 0;
propertySize = sizeof(Float64);
//gets property( nominal sample rate)
error = AudioHardwareServiceGetPropertyData(deviceID,
&propertyAddress,
0,
nullptr,
&propertySize,
outSampleRate);
return error;
}
OSStatus GetDefaultInputDeviceName(CFStringRef *name) {
OSStatus error;
AudioDeviceID deviceID = 0;
AudioObjectPropertyAddress propertyAddress;
UInt32 propertySize;
//sets which property to check
propertyAddress.mSelector = kAudioHardwarePropertyDefaultSystemOutputDevice;
propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
propertyAddress.mElement = 0;
propertySize = sizeof(AudioDeviceID);
//gets property (system output device)
error = AudioHardwareServiceGetPropertyData( kAudioObjectSystemObject,
&propertyAddress,
0,
nullptr,
&propertySize,
&deviceID);
if( error) return error; //we couldn't get the default system device
//sets which property to check
propertyAddress.mSelector = kAudioObjectPropertyName;
propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
propertyAddress.mElement = 0;
propertySize = sizeof(String);
//gets property (name)
error = AudioHardwareServiceGetPropertyData(deviceID,
&propertyAddress,
0,
nullptr,
&propertySize,
name);
return error;
}
OSStatus GetDefaultInputDeviceBufferSize(UInt32 *bufferSize) {
OSStatus error;
AudioDeviceID deviceID = 0;
AudioObjectPropertyAddress propertyAddress;
UInt32 propertySize;
//sets which property to check
propertyAddress.mSelector = kAudioHardwarePropertyDefaultSystemOutputDevice;
propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
propertyAddress.mElement = 0;
propertySize = sizeof(AudioDeviceID);
//gets property (system output device)
error = AudioHardwareServiceGetPropertyData( kAudioObjectSystemObject,
&propertyAddress,
0,
nullptr,
&propertySize,
&deviceID);
if( error) return error; //we couldn't get the default system device
//sets which property to check
propertyAddress.mSelector = kAudioDevicePropertyBufferFrameSize;
propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
propertyAddress.mElement = 0;
propertySize = sizeof(bufferSize); //UInt32
//gets property (bufferSize)
error = AudioHardwareServiceGetPropertyData(deviceID,
&propertyAddress,
0,
nullptr,
&propertySize,
bufferSize);
return error;
}
//in my application window constructor
juce::AudioDeviceManager::AudioDeviceSetup defaultDeviceSetup;
int inChan = 1;
int outChan = 1;
//get current system device sample rate
Float64 sampleRate;
GetDefaultInputDeviceSampleRate(&sampleRate);
//get current system device name
CFStringRef deviceName;
GetDefaultInputDeviceName( &deviceName);
CFShow( deviceName);
String name = String( CFStringGetCStringPtr(deviceName, kCFStringEncodingMacRoman) );
//get current system device buffer size
UInt32 bufferSize;
GetDefaultInputDeviceBufferSize( &bufferSize);
//update our device setup with these gathered values
defaultDeviceSetup.sampleRate = sampleRate;
defaultDeviceSetup.outputDeviceName = name;
defaultDeviceSetup.inputDeviceName = name;
defaultDeviceSetup.bufferSize = bufferSize;
//initialise our audioDeviceManager with this default system device setup.
audioDeviceManager.initialise(inChan, outChan, nullptr, false, name, &defaultDeviceSetup );
//audioDeviceManager.initialiseWithDefaultDevices(1, 1); //old way of doing it
This problem is solved. Hopefully someone else will find this helpful.