mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
AudioDeviceManager: Take sample rate compatibility into account during default device selection
This commit is contained in:
parent
5ec536f13f
commit
3323c68f96
1 changed files with 79 additions and 4 deletions
|
|
@ -502,15 +502,90 @@ String AudioDeviceManager::initialiseWithDefaultDevices (int numInputChannelsNee
|
|||
|
||||
void AudioDeviceManager::insertDefaultDeviceNames (AudioDeviceSetup& setup) const
|
||||
{
|
||||
enum class Direction { out, in };
|
||||
|
||||
if (auto* type = getCurrentDeviceTypeObject())
|
||||
{
|
||||
for (const auto isInput : { false, true })
|
||||
// We avoid selecting a device pair that doesn't share a matching sample rate, if possible.
|
||||
// If not, other parts of the AudioDeviceManager and AudioIODevice classes should generate
|
||||
// an appropriate error message when opening or starting these devices.
|
||||
const auto getDevicesToTestForMatchingSampleRate = [&setup, type, this] (Direction dir)
|
||||
{
|
||||
const auto numChannelsNeeded = isInput ? numInputChansNeeded : numOutputChansNeeded;
|
||||
const auto isInput = dir == Direction::in;
|
||||
const auto info = getSetupInfo (setup, isInput);
|
||||
|
||||
if (numChannelsNeeded > 0 && info.name.isEmpty())
|
||||
info.name = type->getDeviceNames (isInput) [type->getDefaultDeviceIndex (isInput)];
|
||||
if (! info.name.isEmpty())
|
||||
return StringArray { info.name };
|
||||
|
||||
const auto numChannelsNeeded = isInput ? numInputChansNeeded : numOutputChansNeeded;
|
||||
auto deviceNames = numChannelsNeeded > 0 ? type->getDeviceNames (isInput) : StringArray {};
|
||||
deviceNames.move (type->getDefaultDeviceIndex (isInput), 0);
|
||||
|
||||
return deviceNames;
|
||||
};
|
||||
|
||||
std::map<std::pair<Direction, String>, Array<double>> sampleRatesCache;
|
||||
|
||||
const auto getSupportedSampleRates = [&sampleRatesCache, type] (Direction dir, const String& deviceName)
|
||||
{
|
||||
const auto key = std::make_pair (dir, deviceName);
|
||||
|
||||
auto& entry = [&]() -> auto&
|
||||
{
|
||||
auto it = sampleRatesCache.find (key);
|
||||
|
||||
if (it != sampleRatesCache.end())
|
||||
return it->second;
|
||||
|
||||
auto& elem = sampleRatesCache[key];
|
||||
auto tempDevice = rawToUniquePtr (type->createDevice ((dir == Direction::in) ? "" : deviceName,
|
||||
(dir == Direction::in) ? deviceName : ""));
|
||||
if (tempDevice != nullptr)
|
||||
elem = tempDevice->getAvailableSampleRates();
|
||||
|
||||
return elem;
|
||||
}();
|
||||
|
||||
return entry;
|
||||
};
|
||||
|
||||
const auto validate = [&getSupportedSampleRates] (const String& outputDeviceName, const String& inputDeviceName)
|
||||
{
|
||||
jassert (! outputDeviceName.isEmpty() && ! inputDeviceName.isEmpty());
|
||||
|
||||
const auto outputSampleRates = getSupportedSampleRates (Direction::out, outputDeviceName);
|
||||
const auto inputSampleRates = getSupportedSampleRates (Direction::in, inputDeviceName);
|
||||
|
||||
return std::any_of (inputSampleRates.begin(),
|
||||
inputSampleRates.end(),
|
||||
[&] (auto inputSampleRate) { return outputSampleRates.contains (inputSampleRate); });
|
||||
};
|
||||
|
||||
auto outputsToTest = getDevicesToTestForMatchingSampleRate (Direction::out);
|
||||
auto inputsToTest = getDevicesToTestForMatchingSampleRate (Direction::in);
|
||||
|
||||
// We set default device names, so in case no in-out pair passes the validation, we still
|
||||
// produce the same result as before
|
||||
if (setup.outputDeviceName.isEmpty() && ! outputsToTest.isEmpty())
|
||||
setup.outputDeviceName = outputsToTest[0];
|
||||
|
||||
if (setup.inputDeviceName.isEmpty() && ! inputsToTest.isEmpty())
|
||||
setup.inputDeviceName = inputsToTest[0];
|
||||
|
||||
// We check all possible in-out pairs until the first validation pass. If no pair passes we
|
||||
// leave the setup unchanged.
|
||||
for (const auto& out : outputsToTest)
|
||||
{
|
||||
for (const auto& in : inputsToTest)
|
||||
{
|
||||
if (validate (out, in))
|
||||
{
|
||||
setup.outputDeviceName = out;
|
||||
setup.inputDeviceName = in;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue