From 5fdbdc9e9ebc29579f9f701357fa1974d08cba2a Mon Sep 17 00:00:00 2001 From: jules Date: Sat, 24 May 2014 19:04:47 +0100 Subject: [PATCH] Added a method AudioIODevice::setGainPreprocessingEnabled() to allow disabling of mic AGC on iOS and Android devices. --- .../audio_io/juce_AudioIODevice.cpp | 19 ++---- .../audio_io/juce_AudioIODevice.h | 5 ++ .../juce_audio_devices/juce_audio_devices.cpp | 1 + .../native/juce_android_OpenSL.cpp | 65 ++++++++++++------- .../native/juce_ios_Audio.cpp | 16 +++-- 5 files changed, 65 insertions(+), 41 deletions(-) diff --git a/modules/juce_audio_devices/audio_io/juce_AudioIODevice.cpp b/modules/juce_audio_devices/audio_io/juce_AudioIODevice.cpp index 1386d0c509..95221ba037 100644 --- a/modules/juce_audio_devices/audio_io/juce_AudioIODevice.cpp +++ b/modules/juce_audio_devices/audio_io/juce_AudioIODevice.cpp @@ -22,20 +22,16 @@ ============================================================================== */ -AudioIODevice::AudioIODevice (const String& deviceName, const String& typeName_) - : name (deviceName), - typeName (typeName_) +AudioIODevice::AudioIODevice (const String& deviceName, const String& deviceTypeName) + : name (deviceName), typeName (deviceTypeName) { } -AudioIODevice::~AudioIODevice() -{ -} +AudioIODevice::~AudioIODevice() {} -bool AudioIODevice::hasControlPanel() const -{ - return false; -} +void AudioIODeviceCallback::audioDeviceError (const String&) {} +bool AudioIODevice::setAudioPreprocessingEnabled (bool) { return false; } +bool AudioIODevice::hasControlPanel() const { return false; } bool AudioIODevice::showControlPanel() { @@ -43,6 +39,3 @@ bool AudioIODevice::showControlPanel() // their hasControlPanel() method. return false; } - -//============================================================================== -void AudioIODeviceCallback::audioDeviceError (const String&) {} diff --git a/modules/juce_audio_devices/audio_io/juce_AudioIODevice.h b/modules/juce_audio_devices/audio_io/juce_AudioIODevice.h index 6817ae691a..8ce41d091e 100644 --- a/modules/juce_audio_devices/audio_io/juce_AudioIODevice.h +++ b/modules/juce_audio_devices/audio_io/juce_AudioIODevice.h @@ -289,6 +289,11 @@ public: */ virtual bool showControlPanel(); + /** On devices which support it, this allows automatic gain control or other + mic processing to be disabled. + If the device doesn't support this operation, it'll return false. + */ + virtual bool setAudioPreprocessingEnabled (bool shouldBeEnabled); //============================================================================== protected: diff --git a/modules/juce_audio_devices/juce_audio_devices.cpp b/modules/juce_audio_devices/juce_audio_devices.cpp index cd91ecf603..a9733db06c 100644 --- a/modules/juce_audio_devices/juce_audio_devices.cpp +++ b/modules/juce_audio_devices/juce_audio_devices.cpp @@ -125,6 +125,7 @@ #if JUCE_USE_ANDROID_OPENSLES #include #include + #include #endif #endif diff --git a/modules/juce_audio_devices/native/juce_android_OpenSL.cpp b/modules/juce_audio_devices/native/juce_android_OpenSL.cpp index 29b01efa22..e02951d3f2 100644 --- a/modules/juce_audio_devices/native/juce_android_OpenSL.cpp +++ b/modules/juce_audio_devices/native/juce_android_OpenSL.cpp @@ -165,29 +165,9 @@ public: oldCallback->audioDeviceStopped(); } - void run() override + bool setAudioPreprocessingEnabled (bool enable) override { - if (recorder != nullptr) recorder->start(); - if (player != nullptr) player->start(); - - while (! threadShouldExit()) - { - if (player != nullptr) player->writeBuffer (outputBuffer, *this); - if (recorder != nullptr) recorder->readNextBlock (inputBuffer, *this); - - const ScopedLock sl (callbackLock); - - if (callback != nullptr) - { - callback->audioDeviceIOCallback (numInputChannels > 0 ? inputBuffer.getArrayOfReadPointers() : nullptr, numInputChannels, - numOutputChannels > 0 ? outputBuffer.getArrayOfWritePointers() : nullptr, numOutputChannels, - actualBufferSize); - } - else - { - outputBuffer.clear(); - } - } + return recorder != nullptr && recorder->setAudioPreprocessingEnabled (enable); } private: @@ -212,6 +192,31 @@ private: return oldCallback; } + void run() override + { + if (recorder != nullptr) recorder->start(); + if (player != nullptr) player->start(); + + while (! threadShouldExit()) + { + if (player != nullptr) player->writeBuffer (outputBuffer, *this); + if (recorder != nullptr) recorder->readNextBlock (inputBuffer, *this); + + const ScopedLock sl (callbackLock); + + if (callback != nullptr) + { + callback->audioDeviceIOCallback (numInputChannels > 0 ? inputBuffer.getArrayOfReadPointers() : nullptr, numInputChannels, + numOutputChannels > 0 ? outputBuffer.getArrayOfWritePointers() : nullptr, numOutputChannels, + actualBufferSize); + } + else + { + outputBuffer.clear(); + } + } + } + //================================================================================================== struct Engine { @@ -230,6 +235,7 @@ private: SL_IID_ANDROIDSIMPLEBUFFERQUEUE = (SLInterfaceID*) library.getFunction ("SL_IID_ANDROIDSIMPLEBUFFERQUEUE"); SL_IID_PLAY = (SLInterfaceID*) library.getFunction ("SL_IID_PLAY"); SL_IID_RECORD = (SLInterfaceID*) library.getFunction ("SL_IID_RECORD"); + SL_IID_ANDROIDCONFIGURATION = (SLInterfaceID*) library.getFunction ("SL_IID_ANDROIDCONFIGURATION"); check ((*engineObject)->Realize (engineObject, SL_BOOLEAN_FALSE)); check ((*engineObject)->GetInterface (engineObject, *SL_IID_ENGINE, &engineInterface)); @@ -271,6 +277,7 @@ private: SLInterfaceID* SL_IID_ANDROIDSIMPLEBUFFERQUEUE; SLInterfaceID* SL_IID_PLAY; SLInterfaceID* SL_IID_RECORD; + SLInterfaceID* SL_IID_ANDROIDCONFIGURATION; private: DynamicLibrary library; @@ -434,7 +441,8 @@ private: struct Recorder { Recorder (int numChannels, int sampleRate, Engine& engine) - : recorderObject (nullptr), recorderRecord (nullptr), recorderBufferQueue (nullptr), + : recorderObject (nullptr), recorderRecord (nullptr), + recorderBufferQueue (nullptr), configObject (nullptr), bufferList (numChannels) { jassert (numChannels == 1); // STEREO doesn't always work!! @@ -466,6 +474,7 @@ private: { check ((*recorderObject)->GetInterface (recorderObject, *engine.SL_IID_RECORD, &recorderRecord)); check ((*recorderObject)->GetInterface (recorderObject, *engine.SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &recorderBufferQueue)); + check ((*recorderObject)->GetInterface (recorderObject, *engine.SL_IID_ANDROIDCONFIGURATION, &configObject)); check ((*recorderBufferQueue)->RegisterCallback (recorderBufferQueue, staticCallback, this)); check ((*recorderRecord)->SetRecordState (recorderRecord, SL_RECORDSTATE_STOPPED)); @@ -532,10 +541,20 @@ private: } } + bool setAudioPreprocessingEnabled (bool enable) + { + SLuint32 mode = enable ? SL_ANDROID_RECORDING_PRESET_GENERIC + : SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION; + + return configObject != nullptr + && check ((*configObject)->SetConfiguration (configObject, SL_ANDROID_KEY_RECORDING_PRESET, &mode, sizeof (mode))); + } + private: SLObjectItf recorderObject; SLRecordItf recorderRecord; SLAndroidSimpleBufferQueueItf recorderBufferQueue; + SLAndroidConfigurationItf configObject; BufferList bufferList; diff --git a/modules/juce_audio_devices/native/juce_ios_Audio.cpp b/modules/juce_audio_devices/native/juce_ios_Audio.cpp index 4d06593758..b7d16110c0 100644 --- a/modules/juce_audio_devices/native/juce_ios_Audio.cpp +++ b/modules/juce_audio_devices/native/juce_ios_Audio.cpp @@ -208,6 +208,12 @@ public: bool isPlaying() override { return isRunning && callback != nullptr; } String getLastError() override { return lastError; } + bool setAudioPreprocessingEnabled (bool enable) override + { + return setSessionUInt32Property (kAudioSessionProperty_Mode, enable ? kAudioSessionMode_Default + : kAudioSessionMode_Measurement); + } + private: //================================================================================================== CriticalSection callbackLock; @@ -433,12 +439,12 @@ private: static OSStatus processStatic (void* client, AudioUnitRenderActionFlags* flags, const AudioTimeStamp* time, UInt32 /*busNumber*/, UInt32 numFrames, AudioBufferList* data) { - return static_cast (client)->process (flags, time, numFrames, data); + return static_cast (client)->process (flags, time, numFrames, data); } static void routingChangedStatic (void* client, AudioSessionPropertyID, UInt32 /*inDataSize*/, const void* propertyValue) { - static_cast (client)->routingChanged (propertyValue); + static_cast (client)->routingChanged (propertyValue); } //================================================================================================== @@ -530,9 +536,9 @@ private: return AudioSessionGetProperty (propID, &valueSize, &result); } - static void setSessionUInt32Property (AudioSessionPropertyID propID, UInt32 v) noexcept { AudioSessionSetProperty (propID, sizeof (v), &v); } - static void setSessionFloat32Property (AudioSessionPropertyID propID, Float32 v) noexcept { AudioSessionSetProperty (propID, sizeof (v), &v); } - static void setSessionFloat64Property (AudioSessionPropertyID propID, Float64 v) noexcept { AudioSessionSetProperty (propID, sizeof (v), &v); } + static bool setSessionUInt32Property (AudioSessionPropertyID propID, UInt32 v) noexcept { AudioSessionSetProperty (propID, sizeof (v), &v) == kAudioSessionNoError; } + static bool setSessionFloat32Property (AudioSessionPropertyID propID, Float32 v) noexcept { AudioSessionSetProperty (propID, sizeof (v), &v) == kAudioSessionNoError; } + static bool setSessionFloat64Property (AudioSessionPropertyID propID, Float64 v) noexcept { AudioSessionSetProperty (propID, sizeof (v), &v) == kAudioSessionNoError; } JUCE_DECLARE_NON_COPYABLE (iOSAudioIODevice) };