diff --git a/modules/juce_audio_devices/native/juce_android_OpenSL.cpp b/modules/juce_audio_devices/native/juce_android_OpenSL.cpp index 82736fe1e5..248db71a90 100644 --- a/modules/juce_audio_devices/native/juce_android_OpenSL.cpp +++ b/modules/juce_audio_devices/native/juce_android_OpenSL.cpp @@ -155,6 +155,8 @@ template struct BufferHelpers {}; template <> struct BufferHelpers { + enum { isFloatingPoint = 0 }; + static void initPCMDataFormat (PCMDataFormatEx& dataFormat, int numChannels, double sampleRate) { dataFormat.formatType = SL_DATAFORMAT_PCM; @@ -202,6 +204,8 @@ struct BufferHelpers template <> struct BufferHelpers { + enum { isFloatingPoint = 1 }; + static void initPCMDataFormat (PCMDataFormatEx& dataFormat, int numChannels, double sampleRate) { dataFormat.formatType = SL_ANDROID_DATAFORMAT_PCM_EX; @@ -514,6 +518,7 @@ public: virtual void start() { stop(); jassert (callback.get() != nullptr); running = true; } virtual void stop() { running = false; } virtual bool setAudioPreprocessingEnabled (bool shouldEnable) = 0; + virtual bool supportsFloatingPoint() const noexcept = 0; void setCallback (AudioIODeviceCallback* callbackToUse) { @@ -557,8 +562,7 @@ public: static OpenSLSession* create (DynamicLibrary& slLibrary, int numInputChannels, int numOutputChannels, double samleRateToUse, int bufferSizeToUse, - int numBuffersToUse, - bool floatingPointSupport); + int numBuffersToUse); //============================================================================== typedef SLresult (*CreateEngineFunc)(SLObjectItf*,SLuint32,const SLEngineOption*,SLuint32,const SLInterfaceID*,const SLboolean*); @@ -667,6 +671,8 @@ public: return true; } + bool supportsFloatingPoint() const noexcept override { return (BufferHelpers::isFloatingPoint != 0); } + void doSomeWorkOnAudioThread() { // only the player or the recorder should enter this section at any time @@ -738,8 +744,6 @@ public: inputLatency = (int) ((longestLatency * inputLatency) / totalLatency) & ~15; outputLatency = (int) ((longestLatency * outputLatency) / totalLatency) & ~15; - supportsFloatingPoint = getSupportsFloatingPoint(); - bool success = slLibrary.open ("libOpenSLES.so"); // You can only create this class if you are sure that your hardware supports OpenSL @@ -824,15 +828,6 @@ public: const int audioBuffersToEnqueue = hasLowLatencyAudioPath() ? buffersToEnqueueForLowLatency : buffersToEnqueueSlowAudio; - DBG ("OpenSL: numInputChannels = " << numInputChannels - << ", numOutputChannels = " << numOutputChannels - << ", nativeBufferSize = " << getNativeBufferSize() - << ", nativeSampleRate = " << getNativeSampleRate() - << ", actualBufferSize = " << actualBufferSize - << ", audioBuffersToEnqueue = " << audioBuffersToEnqueue - << ", sampleRate = " << sampleRate - << ", supportsFloatingPoint = " << (supportsFloatingPoint ? "true" : "false")); - if (numInputChannels > 0 && (! RuntimePermissions::isGranted (RuntimePermissions::recordAudio))) { // If you hit this assert, you probably forgot to get RuntimePermissions::recordAudio @@ -842,8 +837,7 @@ public: } session = OpenSLSession::create (slLibrary, numInputChannels, numOutputChannels, - sampleRate, actualBufferSize, audioBuffersToEnqueue, - supportsFloatingPoint); + sampleRate, actualBufferSize, audioBuffersToEnqueue); if (session != nullptr) session->setAudioPreprocessingEnabled (audioProcessingEnabled); else @@ -855,11 +849,19 @@ public: numInputChannels = 0; session = OpenSLSession::create(slLibrary, numInputChannels, numOutputChannels, - sampleRate, actualBufferSize, audioBuffersToEnqueue, - supportsFloatingPoint); + sampleRate, actualBufferSize, audioBuffersToEnqueue); } } + DBG ("OpenSL: numInputChannels = " << numInputChannels + << ", numOutputChannels = " << numOutputChannels + << ", nativeBufferSize = " << getNativeBufferSize() + << ", nativeSampleRate = " << getNativeSampleRate() + << ", actualBufferSize = " << actualBufferSize + << ", audioBuffersToEnqueue = " << audioBuffersToEnqueue + << ", sampleRate = " << sampleRate + << ", supportsFloatingPoint = " << (session != nullptr && session->supportsFloatingPoint() ? "true" : "false")); + if (session == nullptr) lastError = "Unknown error initializing opensl session"; @@ -878,7 +880,7 @@ public: int getInputLatencyInSamples() override { return inputLatency; } bool isOpen() override { return deviceOpen; } int getCurrentBufferSizeSamples() override { return actualBufferSize; } - int getCurrentBitDepth() override { return supportsFloatingPoint ? 32 : 16; } + int getCurrentBitDepth() override { return (session != nullptr && session->supportsFloatingPoint() ? 32 : 16); } BigInteger getActiveOutputChannels() const override { return activeOutputChans; } BigInteger getActiveInputChannels() const override { return activeInputChans; } String getLastError() override { return lastError; } @@ -960,7 +962,7 @@ private: DynamicLibrary slLibrary; int actualBufferSize, sampleRate; int inputLatency, outputLatency; - bool deviceOpen, supportsFloatingPoint, audioProcessingEnabled; + bool deviceOpen, audioProcessingEnabled; String lastError; BigInteger activeOutputChans, activeInputChans; AudioIODeviceCallback* callback; @@ -1015,31 +1017,36 @@ private: return androidHasSystemFeature ("android.hardware.audio.low_latency"); } - static bool getSupportsFloatingPoint() - { - return (getEnv()->GetStaticIntField (AndroidBuildVersion, AndroidBuildVersion.SDK_INT) >= 21); - } - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenSLAudioIODevice) }; OpenSLAudioIODevice::OpenSLSession* OpenSLAudioIODevice::OpenSLSession::create (DynamicLibrary& slLibrary, int numInputChannels, int numOutputChannels, double samleRateToUse, int bufferSizeToUse, - int numBuffersToUse, - bool floatingPointSupport) + int numBuffersToUse) { ScopedPointer retval; + auto sdkVersion = getEnv()->GetStaticIntField (AndroidBuildVersion, AndroidBuildVersion.SDK_INT); - if (floatingPointSupport) + // SDK versions 21 and higher should natively support floating point... + if (sdkVersion >= 21) + { retval = new OpenSLSessionT (slLibrary, numInputChannels, numOutputChannels, samleRateToUse, bufferSizeToUse, numBuffersToUse); - else + + // ...however, some devices lie so re-try without floating point + if (retval != nullptr && (! retval->openedOK())) + retval = nullptr; + } + + if (retval == nullptr) + { retval = new OpenSLSessionT (slLibrary, numInputChannels, numOutputChannels, samleRateToUse, bufferSizeToUse, numBuffersToUse); - if (retval != nullptr && (! retval->openedOK())) - retval = nullptr; + if (retval != nullptr && (! retval->openedOK())) + retval = nullptr; + } return retval.release(); }