From 990a67a01ee02820a11ff9e4e072f72d82f5330c Mon Sep 17 00:00:00 2001 From: jules Date: Thu, 24 Jan 2013 11:24:16 +0000 Subject: [PATCH] ASIO: when a device refuses to change sample-rate, it now ignores this and carries on with the device's current rate. --- .../native/juce_win32_ASIO.cpp | 304 +++++++++--------- 1 file changed, 153 insertions(+), 151 deletions(-) diff --git a/modules/juce_audio_devices/native/juce_win32_ASIO.cpp b/modules/juce_audio_devices/native/juce_win32_ASIO.cpp index bf9d9e4804..f1994a1a33 100644 --- a/modules/juce_audio_devices/native/juce_win32_ASIO.cpp +++ b/modules/juce_audio_devices/native/juce_win32_ASIO.cpp @@ -35,12 +35,13 @@ //============================================================================== namespace ASIODebugging { - #if ASIO_DEBUGGING + #if JUCE_ASIO_DEBUGGING #define JUCE_ASIO_LOG(a) ASIODebugging::logMessage (a) #define JUCE_ASIO_LOG_ERROR(a, b) ASIODebugging::logError ((a), (b)) - static void logMessage (const String& message) + static void logMessage (String message) { + message = "ASIO: " + message; DBG (message); Logger::writeToLog (message); } @@ -62,7 +63,7 @@ namespace ASIODebugging default: break; } - logMessage ("ASIO error: " + context + " - " + err); + logMessage ("error: " + context + " - " + err); } #else static void dummyLog() {} @@ -341,7 +342,7 @@ public: currentASIODev[i] = nullptr; close(); - JUCE_ASIO_LOG ("ASIO - exiting"); + JUCE_ASIO_LOG ("closed"); removeCurrentDriver(); } @@ -493,7 +494,7 @@ public: else { if (numSources == 0) - JUCE_ASIO_LOG ("ASIO - no clock sources!"); + JUCE_ASIO_LOG ("no clock sources!"); } { @@ -509,7 +510,7 @@ public: if (currentSampleRate != sampleRate) { - JUCE_ASIO_LOG ("ASIO samplerate: " + String (currentSampleRate) + " to " + String (sampleRate)); + JUCE_ASIO_LOG ("rate change: " + String (currentSampleRate) + " to " + String (sampleRate)); err = asioObject->setSampleRate (sampleRate); if (err == ASE_NoClock && numSources > 0) @@ -522,192 +523,157 @@ public: Thread::sleep (10); err = asioObject->setSampleRate (sampleRate); } - } - if (err == 0) - { - currentSampleRate = sampleRate; + if (err == 0) + currentSampleRate = sampleRate; - if (needToReset) - { - JUCE_ASIO_LOG ("! Resetting ASIO after sample rate change"); - removeCurrentDriver(); + // on fail, ignore the attempt to change rate, and run with the current one.. + } - loadDriver(); - const String error (initDriver()); + if (needToReset) + { + JUCE_ASIO_LOG (" Resetting"); + removeCurrentDriver(); - if (error.isNotEmpty()) - JUCE_ASIO_LOG ("ASIOInit: " + error); + loadDriver(); + const String error (initDriver()); - needToReset = false; - } + if (error.isNotEmpty()) + JUCE_ASIO_LOG ("ASIOInit: " + error); - numActiveInputChans = 0; - numActiveOutputChans = 0; + needToReset = false; + } - ASIOBufferInfo* info = bufferInfos; - for (int i = 0; i < totalNumInputChans; ++i) - { - if (inputChannels[i]) - { - currentChansIn.setBit (i); - info->isInput = 1; - info->channelNum = i; - info->buffers[0] = info->buffers[1] = nullptr; - ++info; - ++numActiveInputChans; - } - } + const int totalBuffers = resetBuffers (inputChannels, outputChannels); - for (int i = 0; i < totalNumOutputChans; ++i) - { - if (outputChannels[i]) - { - currentChansOut.setBit (i); - info->isInput = 0; - info->channelNum = i; - info->buffers[0] = info->buffers[1] = nullptr; - ++info; - ++numActiveOutputChans; - } - } + setCallbackFunctions(); - const int totalBuffers = numActiveInputChans + numActiveOutputChans; + JUCE_ASIO_LOG ("disposing buffers"); + err = asioObject->disposeBuffers(); - setCallbackFunctions(); + JUCE_ASIO_LOG ("creating buffers: " + String (totalBuffers) + ", " + String (currentBlockSizeSamples)); + err = asioObject->createBuffers (bufferInfos, + totalBuffers, + currentBlockSizeSamples, + &callbacks); - JUCE_ASIO_LOG ("disposing buffers"); - err = asioObject->disposeBuffers(); + if (err != 0) + { + currentBlockSizeSamples = preferredSize; + JUCE_ASIO_LOG_ERROR ("create buffers 2", err); - JUCE_ASIO_LOG ("creating buffers: " + String (totalBuffers) + ", " + String (currentBlockSizeSamples)); + asioObject->disposeBuffers(); err = asioObject->createBuffers (bufferInfos, totalBuffers, currentBlockSizeSamples, &callbacks); + } - if (err != 0) - { - currentBlockSizeSamples = preferredSize; - JUCE_ASIO_LOG_ERROR ("create buffers 2", err); - - asioObject->disposeBuffers(); - err = asioObject->createBuffers (bufferInfos, - totalBuffers, - currentBlockSizeSamples, - &callbacks); - } - - if (err == 0) - { - buffersCreated = true; + if (err == 0) + { + buffersCreated = true; - tempBuffer.calloc (totalBuffers * currentBlockSizeSamples + 32); + tempBuffer.calloc (totalBuffers * currentBlockSizeSamples + 32); - int n = 0; - Array types; - currentBitDepth = 16; + int n = 0; + Array types; + currentBitDepth = 16; - for (int i = 0; i < (int) totalNumInputChans; ++i) + for (int i = 0; i < (int) totalNumInputChans; ++i) + { + if (inputChannels[i]) { - if (inputChannels[i]) - { - inBuffers[n] = tempBuffer + (currentBlockSizeSamples * n); + inBuffers[n] = tempBuffer + (currentBlockSizeSamples * n); - ASIOChannelInfo channelInfo = { 0 }; - channelInfo.channel = i; - channelInfo.isInput = 1; - asioObject->getChannelInfo (&channelInfo); + ASIOChannelInfo channelInfo = { 0 }; + channelInfo.channel = i; + channelInfo.isInput = 1; + asioObject->getChannelInfo (&channelInfo); - types.addIfNotAlreadyThere (channelInfo.type); - inputFormat[n] = ASIOSampleFormat (channelInfo.type); + types.addIfNotAlreadyThere (channelInfo.type); + inputFormat[n] = ASIOSampleFormat (channelInfo.type); - currentBitDepth = jmax (currentBitDepth, inputFormat[n].bitDepth); - ++n; - } + currentBitDepth = jmax (currentBitDepth, inputFormat[n].bitDepth); + ++n; } + } - jassert (numActiveInputChans == n); - n = 0; + jassert (numActiveInputChans == n); + n = 0; - for (int i = 0; i < (int) totalNumOutputChans; ++i) + for (int i = 0; i < (int) totalNumOutputChans; ++i) + { + if (outputChannels[i]) { - if (outputChannels[i]) - { - outBuffers[n] = tempBuffer + (currentBlockSizeSamples * (numActiveInputChans + n)); + outBuffers[n] = tempBuffer + (currentBlockSizeSamples * (numActiveInputChans + n)); - ASIOChannelInfo channelInfo = { 0 }; - channelInfo.channel = i; - channelInfo.isInput = 0; - asioObject->getChannelInfo (&channelInfo); + ASIOChannelInfo channelInfo = { 0 }; + channelInfo.channel = i; + channelInfo.isInput = 0; + asioObject->getChannelInfo (&channelInfo); - types.addIfNotAlreadyThere (channelInfo.type); - outputFormat[n] = ASIOSampleFormat (channelInfo.type); + types.addIfNotAlreadyThere (channelInfo.type); + outputFormat[n] = ASIOSampleFormat (channelInfo.type); - currentBitDepth = jmax (currentBitDepth, outputFormat[n].bitDepth); - ++n; - } + currentBitDepth = jmax (currentBitDepth, outputFormat[n].bitDepth); + ++n; } + } - jassert (numActiveOutputChans == n); + jassert (numActiveOutputChans == n); - for (int i = types.size(); --i >= 0;) - JUCE_ASIO_LOG ("channel format: " + String (types[i])); + for (int i = types.size(); --i >= 0;) + JUCE_ASIO_LOG ("channel format: " + String (types[i])); - jassert (n <= totalBuffers); + jassert (n <= totalBuffers); - for (int i = 0; i < numActiveOutputChans; ++i) - { - outputFormat[i].clear (bufferInfos [numActiveInputChans + i].buffers[0], currentBlockSizeSamples); - outputFormat[i].clear (bufferInfos [numActiveInputChans + i].buffers[1], currentBlockSizeSamples); - } + for (int i = 0; i < numActiveOutputChans; ++i) + { + outputFormat[i].clear (bufferInfos [numActiveInputChans + i].buffers[0], currentBlockSizeSamples); + outputFormat[i].clear (bufferInfos [numActiveInputChans + i].buffers[1], currentBlockSizeSamples); + } - inputLatency = outputLatency = 0; + inputLatency = outputLatency = 0; - if (asioObject->getLatencies (&inputLatency, &outputLatency) != 0) - JUCE_ASIO_LOG ("ASIO - no latencies"); - else - JUCE_ASIO_LOG ("ASIO latencies: " + String ((int) outputLatency) + ", " + String ((int) inputLatency)); + if (asioObject->getLatencies (&inputLatency, &outputLatency) != 0) + JUCE_ASIO_LOG ("no latencies"); + else + JUCE_ASIO_LOG ("latencies: " + String ((int) outputLatency) + ", " + String ((int) inputLatency)); - deviceIsOpen = true; + deviceIsOpen = true; - JUCE_ASIO_LOG ("starting ASIO"); - calledback = false; - err = asioObject->start(); + JUCE_ASIO_LOG ("starting"); + calledback = false; + err = asioObject->start(); - if (err != 0) - { - deviceIsOpen = false; - JUCE_ASIO_LOG ("ASIO - stop on failure"); - Thread::sleep (10); - asioObject->stop(); - error = "Can't start device"; + if (err != 0) + { + deviceIsOpen = false; + JUCE_ASIO_LOG ("stop on failure"); + Thread::sleep (10); + asioObject->stop(); + error = "Can't start device"; + Thread::sleep (10); + } + else + { + int count = 300; + while (--count > 0 && ! calledback) Thread::sleep (10); - } - else - { - int count = 300; - while (--count > 0 && ! calledback) - Thread::sleep (10); - isStarted = true; + isStarted = true; - if (! calledback) - { - error = "Device didn't start correctly"; - JUCE_ASIO_LOG ("ASIO didn't callback - stopping.."); - asioObject->stop(); - } + if (! calledback) + { + error = "Device didn't start correctly"; + JUCE_ASIO_LOG ("no callbacks - stopping.."); + asioObject->stop(); } } - else - { - error = "Can't create i/o buffers"; - } } else { - error = "Can't set sample rate: "; - error << sampleRate; + error = "Can't create i/o buffers"; } if (error.isNotEmpty()) @@ -742,7 +708,7 @@ public: isStarted = false; needToReset = false; - JUCE_ASIO_LOG ("ASIO - stopping"); + JUCE_ASIO_LOG ("stopping"); if (asioObject != nullptr) { @@ -798,7 +764,7 @@ public: bool showControlPanel() { - JUCE_ASIO_LOG ("ASIO - showing control panel"); + JUCE_ASIO_LOG ("showing control panel"); bool done = false; @@ -843,7 +809,7 @@ public: stopTimer(); // used to cause a reset - JUCE_ASIO_LOG ("! ASIO restart request!"); + JUCE_ASIO_LOG ("restart request!"); if (deviceIsOpen) { @@ -914,6 +880,42 @@ private: return wideVersion; } + int resetBuffers (const BigInteger& inputChannels, + const BigInteger& outputChannels) + { + numActiveInputChans = 0; + numActiveOutputChans = 0; + + ASIOBufferInfo* info = bufferInfos; + for (int i = 0; i < totalNumInputChans; ++i) + { + if (inputChannels[i]) + { + currentChansIn.setBit (i); + info->isInput = 1; + info->channelNum = i; + info->buffers[0] = info->buffers[1] = nullptr; + ++info; + ++numActiveInputChans; + } + } + + for (int i = 0; i < totalNumOutputChans; ++i) + { + if (outputChannels[i]) + { + currentChansOut.setBit (i); + info->isInput = 0; + info->channelNum = i; + info->buffers[0] = info->buffers[1] = nullptr; + ++info; + ++numActiveOutputChans; + } + } + + return numActiveInputChans + numActiveOutputChans; + } + void removeCurrentDriver() { if (asioObject != nullptr) @@ -1004,7 +1006,7 @@ private: String openDevice() { // open the device and get its info.. - JUCE_ASIO_LOG ("opening ASIO device: " + getName()); + JUCE_ASIO_LOG ("opening device: " + getName()); needToReset = false; outputChannelNames.clear(); @@ -1089,14 +1091,14 @@ private: postOutput = (asioObject->outputReady() == 0); if (postOutput) - JUCE_ASIO_LOG ("ASIO outputReady = ok"); + JUCE_ASIO_LOG ("outputReady true"); updateSampleRates(); // ..because cubase does it at this point inputLatency = outputLatency = 0; if (asioObject->getLatencies (&inputLatency, &outputLatency) != 0) - JUCE_ASIO_LOG ("ASIO - no latencies"); + JUCE_ASIO_LOG ("no latencies"); JUCE_ASIO_LOG ("latencies: " + String ((int) inputLatency) + ", " + String ((int) outputLatency)); @@ -1187,7 +1189,7 @@ private: err = asioObject->start(); // ignore an error here, as it might start later after setting other stuff up - JUCE_ASIO_LOG_ERROR ("ASIO start", err); + JUCE_ASIO_LOG_ERROR ("start", err); Thread::sleep (100); asioObject->stop(); @@ -1218,7 +1220,7 @@ private: else { isASIOOpen = true; - JUCE_ASIO_LOG ("ASIO device open"); + JUCE_ASIO_LOG ("device open"); } deviceIsOpen = false;