@@ -246871,7 +246871,6 @@ public: | |||||
defaultBufferSize = jmax (inputDevice->defaultBufferSize, outputDevice->defaultBufferSize); | defaultBufferSize = jmax (inputDevice->defaultBufferSize, outputDevice->defaultBufferSize); | ||||
sampleRates = inputDevice->rates; | sampleRates = inputDevice->rates; | ||||
sampleRates.removeValuesNotIn (outputDevice->rates); | sampleRates.removeValuesNotIn (outputDevice->rates); | ||||
jassert (sampleRates.size() > 0); // in and out devices don't share any common sample rates! | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
@@ -246945,6 +246944,12 @@ public: | |||||
close(); | close(); | ||||
lastError = String::empty; | lastError = String::empty; | ||||
if (sampleRates.size() == 0 && inputDevice != 0 && outputDevice != 0) | |||||
{ | |||||
lastError = "The input and output devices don't share a common sample rate!"; | |||||
return lastError; | |||||
} | |||||
currentBufferSizeSamples = bufferSizeSamples <= 0 ? defaultBufferSize : jmax (bufferSizeSamples, minBufferSize); | currentBufferSizeSamples = bufferSizeSamples <= 0 ? defaultBufferSize : jmax (bufferSizeSamples, minBufferSize); | ||||
currentSampleRate = sampleRate > 0 ? sampleRate : defaultSampleRate; | currentSampleRate = sampleRate > 0 ? sampleRate : defaultSampleRate; | ||||
@@ -263162,6 +263167,8 @@ public: | |||||
isSlaveDevice (false), | isSlaveDevice (false), | ||||
deviceID (id), | deviceID (id), | ||||
started (false), | started (false), | ||||
sampleRate (0), | |||||
bufferSize (512), | |||||
audioBuffer (0), | audioBuffer (0), | ||||
numInputChans (0), | numInputChans (0), | ||||
numOutputChans (0), | numOutputChans (0), | ||||
@@ -263173,24 +263180,16 @@ public: | |||||
inputChannelInfo (0), | inputChannelInfo (0), | ||||
outputChannelInfo (0) | outputChannelInfo (0) | ||||
{ | { | ||||
sampleRate = 0; | |||||
bufferSize = 512; | |||||
jassert (deviceID != 0); | |||||
if (deviceID == 0) | |||||
{ | |||||
error = TRANS("can't open device"); | |||||
} | |||||
else | |||||
{ | |||||
updateDetailsFromDevice(); | |||||
updateDetailsFromDevice(); | |||||
AudioObjectPropertyAddress pa; | |||||
pa.mSelector = kAudioObjectPropertySelectorWildcard; | |||||
pa.mScope = kAudioObjectPropertyScopeWildcard; | |||||
pa.mElement = kAudioObjectPropertyElementWildcard; | |||||
AudioObjectPropertyAddress pa; | |||||
pa.mSelector = kAudioObjectPropertySelectorWildcard; | |||||
pa.mScope = kAudioObjectPropertyScopeWildcard; | |||||
pa.mElement = kAudioObjectPropertyElementWildcard; | |||||
AudioObjectAddPropertyListener (deviceID, &pa, deviceListenerProc, this); | |||||
} | |||||
AudioObjectAddPropertyListener (deviceID, &pa, deviceListenerProc, this); | |||||
} | } | ||||
~CoreAudioInternal() | ~CoreAudioInternal() | ||||
@@ -263203,13 +263202,13 @@ public: | |||||
AudioObjectRemovePropertyListener (deviceID, &pa, deviceListenerProc, this); | AudioObjectRemovePropertyListener (deviceID, &pa, deviceListenerProc, this); | ||||
stop (false); | stop (false); | ||||
delete inputDevice; | |||||
juce_free (audioBuffer); | juce_free (audioBuffer); | ||||
juce_free (tempInputBuffers); | juce_free (tempInputBuffers); | ||||
juce_free (tempOutputBuffers); | juce_free (tempOutputBuffers); | ||||
juce_free (inputChannelInfo); | juce_free (inputChannelInfo); | ||||
juce_free (outputChannelInfo); | juce_free (outputChannelInfo); | ||||
delete inputDevice; | |||||
} | } | ||||
void allocateTempBuffers() | void allocateTempBuffers() | ||||
@@ -263551,7 +263550,7 @@ public: | |||||
double newSampleRate, | double newSampleRate, | ||||
int bufferSizeSamples) | int bufferSizeSamples) | ||||
{ | { | ||||
error = String::empty; | |||||
String error; | |||||
log ("CoreAudio reopen"); | log ("CoreAudio reopen"); | ||||
callbacksAllowed = false; | callbacksAllowed = false; | ||||
stopTimer(); | stopTimer(); | ||||
@@ -263559,12 +263558,11 @@ public: | |||||
stop (false); | stop (false); | ||||
activeInputChans = inputChannels; | activeInputChans = inputChannels; | ||||
activeOutputChans = outputChannels; | |||||
activeInputChans.setRange (inChanNames.size(), | activeInputChans.setRange (inChanNames.size(), | ||||
activeInputChans.getHighestBit() + 1 - inChanNames.size(), | activeInputChans.getHighestBit() + 1 - inChanNames.size(), | ||||
false); | false); | ||||
activeOutputChans = outputChannels; | |||||
activeOutputChans.setRange (outChanNames.size(), | activeOutputChans.setRange (outChanNames.size(), | ||||
activeOutputChans.getHighestBit() + 1 - outChanNames.size(), | activeOutputChans.getHighestBit() + 1 - outChanNames.size(), | ||||
false); | false); | ||||
@@ -263573,52 +263571,49 @@ public: | |||||
numOutputChans = activeOutputChans.countNumberOfSetBits(); | numOutputChans = activeOutputChans.countNumberOfSetBits(); | ||||
// set sample rate | // set sample rate | ||||
Float64 sr = newSampleRate; | |||||
UInt32 size = sizeof (sr); | |||||
AudioObjectPropertyAddress pa; | AudioObjectPropertyAddress pa; | ||||
pa.mSelector = kAudioDevicePropertyNominalSampleRate; | pa.mSelector = kAudioDevicePropertyNominalSampleRate; | ||||
pa.mScope = kAudioObjectPropertyScopeWildcard; | pa.mScope = kAudioObjectPropertyScopeWildcard; | ||||
pa.mElement = kAudioObjectPropertyElementMaster; | pa.mElement = kAudioObjectPropertyElementMaster; | ||||
Float64 sr = newSampleRate; | |||||
OK (AudioObjectSetPropertyData (deviceID, &pa, 0, 0, size, &sr)); | |||||
// change buffer size | |||||
UInt32 framesPerBuf = bufferSizeSamples; | |||||
size = sizeof (framesPerBuf); | |||||
pa.mSelector = kAudioDevicePropertyBufferFrameSize; | |||||
OK (AudioObjectSetPropertyData (deviceID, &pa, 0, 0, size, &framesPerBuf)); | |||||
// wait for the changes to happen (on some devices) | |||||
int i = 30; | |||||
while (--i >= 0) | |||||
if (! OK (AudioObjectSetPropertyData (deviceID, &pa, 0, 0, sizeof (sr), &sr))) | |||||
{ | { | ||||
updateDetailsFromDevice(); | |||||
if (sampleRate == newSampleRate && bufferSizeSamples == bufferSize) | |||||
break; | |||||
Thread::sleep (100); | |||||
error = "Couldn't change sample rate"; | |||||
} | } | ||||
else | |||||
{ | |||||
// change buffer size | |||||
UInt32 framesPerBuf = bufferSizeSamples; | |||||
pa.mSelector = kAudioDevicePropertyBufferFrameSize; | |||||
if (i < 0) | |||||
error = "Couldn't change sample rate/buffer size"; | |||||
if (sampleRates.size() == 0) | |||||
error = "Device has no available sample-rates"; | |||||
if (bufferSizes.size() == 0) | |||||
error = "Device has no available buffer-sizes"; | |||||
if (! OK (AudioObjectSetPropertyData (deviceID, &pa, 0, 0, sizeof (framesPerBuf), &framesPerBuf))) | |||||
{ | |||||
error = "Couldn't change buffer size"; | |||||
} | |||||
else | |||||
{ | |||||
// Annoyingly, after changing the rate and buffer size, some devices fail to | |||||
// correctly report their new settings until some random time in the future, so | |||||
// after calling updateDetailsFromDevice, we need to manually bodge these values | |||||
// to make sure we're using the correct numbers.. | |||||
updateDetailsFromDevice(); | |||||
sampleRate = newSampleRate; | |||||
bufferSize = bufferSizeSamples; | |||||
if (inputDevice != 0 && error.isEmpty()) | |||||
error = inputDevice->reopen (inputChannels, | |||||
outputChannels, | |||||
newSampleRate, | |||||
bufferSizeSamples); | |||||
if (sampleRates.size() == 0) | |||||
error = "Device has no available sample-rates"; | |||||
else if (bufferSizes.size() == 0) | |||||
error = "Device has no available buffer-sizes"; | |||||
else if (inputDevice != 0) | |||||
error = inputDevice->reopen (inputChannels, | |||||
outputChannels, | |||||
newSampleRate, | |||||
bufferSizeSamples); | |||||
} | |||||
} | |||||
callbacksAllowed = true; | callbacksAllowed = true; | ||||
return error; | return error; | ||||
} | } | ||||
@@ -263869,16 +263864,13 @@ public: | |||||
{ | { | ||||
result = new CoreAudioInternal (devs[i]); | result = new CoreAudioInternal (devs[i]); | ||||
if (result->error.isEmpty()) | |||||
{ | |||||
const bool thisIsInput = inChanNames.size() > 0 && outChanNames.size() == 0; | |||||
const bool otherIsInput = result->inChanNames.size() > 0 && result->outChanNames.size() == 0; | |||||
const bool thisIsInput = inChanNames.size() > 0 && outChanNames.size() == 0; | |||||
const bool otherIsInput = result->inChanNames.size() > 0 && result->outChanNames.size() == 0; | |||||
if (thisIsInput != otherIsInput | |||||
|| (inChanNames.size() + outChanNames.size() == 0) | |||||
|| (result->inChanNames.size() + result->outChanNames.size()) == 0) | |||||
break; | |||||
} | |||||
if (thisIsInput != otherIsInput | |||||
|| (inChanNames.size() + outChanNames.size() == 0) | |||||
|| (result->inChanNames.size() + result->outChanNames.size()) == 0) | |||||
break; | |||||
deleteAndZero (result); | deleteAndZero (result); | ||||
} | } | ||||
@@ -263893,7 +263885,6 @@ public: | |||||
juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
String error; | |||||
int inputLatency, outputLatency; | int inputLatency, outputLatency; | ||||
BitArray activeInputChans, activeOutputChans; | BitArray activeInputChans, activeOutputChans; | ||||
StringArray inChanNames, outChanNames; | StringArray inChanNames, outChanNames; | ||||
@@ -264024,34 +264015,17 @@ public: | |||||
jassert (inputDeviceId != 0); | jassert (inputDeviceId != 0); | ||||
device = new CoreAudioInternal (inputDeviceId); | device = new CoreAudioInternal (inputDeviceId); | ||||
lastError = device->error; | |||||
if (lastError.isNotEmpty()) | |||||
deleteAndZero (device); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
device = new CoreAudioInternal (outputDeviceId); | device = new CoreAudioInternal (outputDeviceId); | ||||
lastError = device->error; | |||||
if (lastError.isNotEmpty()) | |||||
{ | |||||
deleteAndZero (device); | |||||
} | |||||
else if (inputDeviceId != 0) | |||||
if (inputDeviceId != 0) | |||||
{ | { | ||||
CoreAudioInternal* secondDevice = new CoreAudioInternal (inputDeviceId); | CoreAudioInternal* secondDevice = new CoreAudioInternal (inputDeviceId); | ||||
lastError = device->error; | |||||
if (lastError.isNotEmpty()) | |||||
{ | |||||
delete secondDevice; | |||||
} | |||||
else | |||||
{ | |||||
device->inputDevice = secondDevice; | |||||
secondDevice->isSlaveDevice = true; | |||||
} | |||||
device->inputDevice = secondDevice; | |||||
secondDevice->isSlaveDevice = true; | |||||
} | } | ||||
} | } | ||||
@@ -264129,14 +264103,15 @@ public: | |||||
if (bufferSizeSamples <= 0) | if (bufferSizeSamples <= 0) | ||||
bufferSizeSamples = getDefaultBufferSize(); | bufferSizeSamples = getDefaultBufferSize(); | ||||
internal->reopen (inputChannels, outputChannels, sampleRate, bufferSizeSamples); | |||||
lastError = internal->error; | |||||
lastError = internal->reopen (inputChannels, outputChannels, sampleRate, bufferSizeSamples); | |||||
isOpen_ = lastError.isEmpty(); | |||||
return lastError; | return lastError; | ||||
} | } | ||||
void close() | void close() | ||||
{ | { | ||||
isOpen_ = false; | isOpen_ = false; | ||||
internal->stop (false); | |||||
} | } | ||||
bool isOpen() | bool isOpen() | ||||
@@ -75,6 +75,8 @@ public: | |||||
isSlaveDevice (false), | isSlaveDevice (false), | ||||
deviceID (id), | deviceID (id), | ||||
started (false), | started (false), | ||||
sampleRate (0), | |||||
bufferSize (512), | |||||
audioBuffer (0), | audioBuffer (0), | ||||
numInputChans (0), | numInputChans (0), | ||||
numOutputChans (0), | numOutputChans (0), | ||||
@@ -86,24 +88,16 @@ public: | |||||
inputChannelInfo (0), | inputChannelInfo (0), | ||||
outputChannelInfo (0) | outputChannelInfo (0) | ||||
{ | { | ||||
sampleRate = 0; | |||||
bufferSize = 512; | |||||
jassert (deviceID != 0); | |||||
if (deviceID == 0) | |||||
{ | |||||
error = TRANS("can't open device"); | |||||
} | |||||
else | |||||
{ | |||||
updateDetailsFromDevice(); | |||||
updateDetailsFromDevice(); | |||||
AudioObjectPropertyAddress pa; | |||||
pa.mSelector = kAudioObjectPropertySelectorWildcard; | |||||
pa.mScope = kAudioObjectPropertyScopeWildcard; | |||||
pa.mElement = kAudioObjectPropertyElementWildcard; | |||||
AudioObjectPropertyAddress pa; | |||||
pa.mSelector = kAudioObjectPropertySelectorWildcard; | |||||
pa.mScope = kAudioObjectPropertyScopeWildcard; | |||||
pa.mElement = kAudioObjectPropertyElementWildcard; | |||||
AudioObjectAddPropertyListener (deviceID, &pa, deviceListenerProc, this); | |||||
} | |||||
AudioObjectAddPropertyListener (deviceID, &pa, deviceListenerProc, this); | |||||
} | } | ||||
~CoreAudioInternal() | ~CoreAudioInternal() | ||||
@@ -116,13 +110,13 @@ public: | |||||
AudioObjectRemovePropertyListener (deviceID, &pa, deviceListenerProc, this); | AudioObjectRemovePropertyListener (deviceID, &pa, deviceListenerProc, this); | ||||
stop (false); | stop (false); | ||||
delete inputDevice; | |||||
juce_free (audioBuffer); | juce_free (audioBuffer); | ||||
juce_free (tempInputBuffers); | juce_free (tempInputBuffers); | ||||
juce_free (tempOutputBuffers); | juce_free (tempOutputBuffers); | ||||
juce_free (inputChannelInfo); | juce_free (inputChannelInfo); | ||||
juce_free (outputChannelInfo); | juce_free (outputChannelInfo); | ||||
delete inputDevice; | |||||
} | } | ||||
void allocateTempBuffers() | void allocateTempBuffers() | ||||
@@ -466,7 +460,7 @@ public: | |||||
double newSampleRate, | double newSampleRate, | ||||
int bufferSizeSamples) | int bufferSizeSamples) | ||||
{ | { | ||||
error = String::empty; | |||||
String error; | |||||
log ("CoreAudio reopen"); | log ("CoreAudio reopen"); | ||||
callbacksAllowed = false; | callbacksAllowed = false; | ||||
stopTimer(); | stopTimer(); | ||||
@@ -474,12 +468,11 @@ public: | |||||
stop (false); | stop (false); | ||||
activeInputChans = inputChannels; | activeInputChans = inputChannels; | ||||
activeOutputChans = outputChannels; | |||||
activeInputChans.setRange (inChanNames.size(), | activeInputChans.setRange (inChanNames.size(), | ||||
activeInputChans.getHighestBit() + 1 - inChanNames.size(), | activeInputChans.getHighestBit() + 1 - inChanNames.size(), | ||||
false); | false); | ||||
activeOutputChans = outputChannels; | |||||
activeOutputChans.setRange (outChanNames.size(), | activeOutputChans.setRange (outChanNames.size(), | ||||
activeOutputChans.getHighestBit() + 1 - outChanNames.size(), | activeOutputChans.getHighestBit() + 1 - outChanNames.size(), | ||||
false); | false); | ||||
@@ -488,52 +481,49 @@ public: | |||||
numOutputChans = activeOutputChans.countNumberOfSetBits(); | numOutputChans = activeOutputChans.countNumberOfSetBits(); | ||||
// set sample rate | // set sample rate | ||||
Float64 sr = newSampleRate; | |||||
UInt32 size = sizeof (sr); | |||||
AudioObjectPropertyAddress pa; | AudioObjectPropertyAddress pa; | ||||
pa.mSelector = kAudioDevicePropertyNominalSampleRate; | pa.mSelector = kAudioDevicePropertyNominalSampleRate; | ||||
pa.mScope = kAudioObjectPropertyScopeWildcard; | pa.mScope = kAudioObjectPropertyScopeWildcard; | ||||
pa.mElement = kAudioObjectPropertyElementMaster; | pa.mElement = kAudioObjectPropertyElementMaster; | ||||
Float64 sr = newSampleRate; | |||||
OK (AudioObjectSetPropertyData (deviceID, &pa, 0, 0, size, &sr)); | |||||
// change buffer size | |||||
UInt32 framesPerBuf = bufferSizeSamples; | |||||
size = sizeof (framesPerBuf); | |||||
pa.mSelector = kAudioDevicePropertyBufferFrameSize; | |||||
OK (AudioObjectSetPropertyData (deviceID, &pa, 0, 0, size, &framesPerBuf)); | |||||
// wait for the changes to happen (on some devices) | |||||
int i = 30; | |||||
while (--i >= 0) | |||||
if (! OK (AudioObjectSetPropertyData (deviceID, &pa, 0, 0, sizeof (sr), &sr))) | |||||
{ | { | ||||
updateDetailsFromDevice(); | |||||
if (sampleRate == newSampleRate && bufferSizeSamples == bufferSize) | |||||
break; | |||||
Thread::sleep (100); | |||||
error = "Couldn't change sample rate"; | |||||
} | } | ||||
else | |||||
{ | |||||
// change buffer size | |||||
UInt32 framesPerBuf = bufferSizeSamples; | |||||
pa.mSelector = kAudioDevicePropertyBufferFrameSize; | |||||
if (i < 0) | |||||
error = "Couldn't change sample rate/buffer size"; | |||||
if (sampleRates.size() == 0) | |||||
error = "Device has no available sample-rates"; | |||||
if (bufferSizes.size() == 0) | |||||
error = "Device has no available buffer-sizes"; | |||||
if (inputDevice != 0 && error.isEmpty()) | |||||
error = inputDevice->reopen (inputChannels, | |||||
outputChannels, | |||||
newSampleRate, | |||||
bufferSizeSamples); | |||||
if (! OK (AudioObjectSetPropertyData (deviceID, &pa, 0, 0, sizeof (framesPerBuf), &framesPerBuf))) | |||||
{ | |||||
error = "Couldn't change buffer size"; | |||||
} | |||||
else | |||||
{ | |||||
// Annoyingly, after changing the rate and buffer size, some devices fail to | |||||
// correctly report their new settings until some random time in the future, so | |||||
// after calling updateDetailsFromDevice, we need to manually bodge these values | |||||
// to make sure we're using the correct numbers.. | |||||
updateDetailsFromDevice(); | |||||
sampleRate = newSampleRate; | |||||
bufferSize = bufferSizeSamples; | |||||
if (sampleRates.size() == 0) | |||||
error = "Device has no available sample-rates"; | |||||
else if (bufferSizes.size() == 0) | |||||
error = "Device has no available buffer-sizes"; | |||||
else if (inputDevice != 0) | |||||
error = inputDevice->reopen (inputChannels, | |||||
outputChannels, | |||||
newSampleRate, | |||||
bufferSizeSamples); | |||||
} | |||||
} | |||||
callbacksAllowed = true; | callbacksAllowed = true; | ||||
return error; | return error; | ||||
} | } | ||||
@@ -784,16 +774,13 @@ public: | |||||
{ | { | ||||
result = new CoreAudioInternal (devs[i]); | result = new CoreAudioInternal (devs[i]); | ||||
if (result->error.isEmpty()) | |||||
{ | |||||
const bool thisIsInput = inChanNames.size() > 0 && outChanNames.size() == 0; | |||||
const bool otherIsInput = result->inChanNames.size() > 0 && result->outChanNames.size() == 0; | |||||
const bool thisIsInput = inChanNames.size() > 0 && outChanNames.size() == 0; | |||||
const bool otherIsInput = result->inChanNames.size() > 0 && result->outChanNames.size() == 0; | |||||
if (thisIsInput != otherIsInput | |||||
|| (inChanNames.size() + outChanNames.size() == 0) | |||||
|| (result->inChanNames.size() + result->outChanNames.size()) == 0) | |||||
break; | |||||
} | |||||
if (thisIsInput != otherIsInput | |||||
|| (inChanNames.size() + outChanNames.size() == 0) | |||||
|| (result->inChanNames.size() + result->outChanNames.size()) == 0) | |||||
break; | |||||
deleteAndZero (result); | deleteAndZero (result); | ||||
} | } | ||||
@@ -809,7 +796,6 @@ public: | |||||
//============================================================================== | //============================================================================== | ||||
juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
String error; | |||||
int inputLatency, outputLatency; | int inputLatency, outputLatency; | ||||
BitArray activeInputChans, activeOutputChans; | BitArray activeInputChans, activeOutputChans; | ||||
StringArray inChanNames, outChanNames; | StringArray inChanNames, outChanNames; | ||||
@@ -944,34 +930,17 @@ public: | |||||
jassert (inputDeviceId != 0); | jassert (inputDeviceId != 0); | ||||
device = new CoreAudioInternal (inputDeviceId); | device = new CoreAudioInternal (inputDeviceId); | ||||
lastError = device->error; | |||||
if (lastError.isNotEmpty()) | |||||
deleteAndZero (device); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
device = new CoreAudioInternal (outputDeviceId); | device = new CoreAudioInternal (outputDeviceId); | ||||
lastError = device->error; | |||||
if (lastError.isNotEmpty()) | |||||
{ | |||||
deleteAndZero (device); | |||||
} | |||||
else if (inputDeviceId != 0) | |||||
if (inputDeviceId != 0) | |||||
{ | { | ||||
CoreAudioInternal* secondDevice = new CoreAudioInternal (inputDeviceId); | CoreAudioInternal* secondDevice = new CoreAudioInternal (inputDeviceId); | ||||
lastError = device->error; | |||||
if (lastError.isNotEmpty()) | |||||
{ | |||||
delete secondDevice; | |||||
} | |||||
else | |||||
{ | |||||
device->inputDevice = secondDevice; | |||||
secondDevice->isSlaveDevice = true; | |||||
} | |||||
device->inputDevice = secondDevice; | |||||
secondDevice->isSlaveDevice = true; | |||||
} | } | ||||
} | } | ||||
@@ -1049,14 +1018,15 @@ public: | |||||
if (bufferSizeSamples <= 0) | if (bufferSizeSamples <= 0) | ||||
bufferSizeSamples = getDefaultBufferSize(); | bufferSizeSamples = getDefaultBufferSize(); | ||||
internal->reopen (inputChannels, outputChannels, sampleRate, bufferSizeSamples); | |||||
lastError = internal->error; | |||||
lastError = internal->reopen (inputChannels, outputChannels, sampleRate, bufferSizeSamples); | |||||
isOpen_ = lastError.isEmpty(); | |||||
return lastError; | return lastError; | ||||
} | } | ||||
void close() | void close() | ||||
{ | { | ||||
isOpen_ = false; | isOpen_ = false; | ||||
internal->stop (false); | |||||
} | } | ||||
bool isOpen() | bool isOpen() | ||||
@@ -599,7 +599,6 @@ public: | |||||
defaultBufferSize = jmax (inputDevice->defaultBufferSize, outputDevice->defaultBufferSize); | defaultBufferSize = jmax (inputDevice->defaultBufferSize, outputDevice->defaultBufferSize); | ||||
sampleRates = inputDevice->rates; | sampleRates = inputDevice->rates; | ||||
sampleRates.removeValuesNotIn (outputDevice->rates); | sampleRates.removeValuesNotIn (outputDevice->rates); | ||||
jassert (sampleRates.size() > 0); // in and out devices don't share any common sample rates! | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
@@ -674,6 +673,12 @@ public: | |||||
close(); | close(); | ||||
lastError = String::empty; | lastError = String::empty; | ||||
if (sampleRates.size() == 0 && inputDevice != 0 && outputDevice != 0) | |||||
{ | |||||
lastError = "The input and output devices don't share a common sample rate!"; | |||||
return lastError; | |||||
} | |||||
currentBufferSizeSamples = bufferSizeSamples <= 0 ? defaultBufferSize : jmax (bufferSizeSamples, minBufferSize); | currentBufferSizeSamples = bufferSizeSamples <= 0 ? defaultBufferSize : jmax (bufferSizeSamples, minBufferSize); | ||||
currentSampleRate = sampleRate > 0 ? sampleRate : defaultSampleRate; | currentSampleRate = sampleRate > 0 ? sampleRate : defaultSampleRate; | ||||