Browse Source

Added a method AudioIODevice::setGainPreprocessingEnabled() to allow disabling of mic AGC on iOS and Android devices.

tags/2021-05-28
jules 11 years ago
parent
commit
5fdbdc9e9e
5 changed files with 65 additions and 41 deletions
  1. +6
    -13
      modules/juce_audio_devices/audio_io/juce_AudioIODevice.cpp
  2. +5
    -0
      modules/juce_audio_devices/audio_io/juce_AudioIODevice.h
  3. +1
    -0
      modules/juce_audio_devices/juce_audio_devices.cpp
  4. +42
    -23
      modules/juce_audio_devices/native/juce_android_OpenSL.cpp
  5. +11
    -5
      modules/juce_audio_devices/native/juce_ios_Audio.cpp

+ 6
- 13
modules/juce_audio_devices/audio_io/juce_AudioIODevice.cpp View File

@@ -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&) {}

+ 5
- 0
modules/juce_audio_devices/audio_io/juce_AudioIODevice.h View File

@@ -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:


+ 1
- 0
modules/juce_audio_devices/juce_audio_devices.cpp View File

@@ -125,6 +125,7 @@
#if JUCE_USE_ANDROID_OPENSLES
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#include <SLES/OpenSLES_AndroidConfiguration.h>
#endif
#endif


+ 42
- 23
modules/juce_audio_devices/native/juce_android_OpenSL.cpp View File

@@ -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;


+ 11
- 5
modules/juce_audio_devices/native/juce_ios_Audio.cpp View File

@@ -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 <iOSAudioIODevice*> (client)->process (flags, time, numFrames, data);
return static_cast<iOSAudioIODevice*> (client)->process (flags, time, numFrames, data);
}
static void routingChangedStatic (void* client, AudioSessionPropertyID, UInt32 /*inDataSize*/, const void* propertyValue)
{
static_cast <iOSAudioIODevice*> (client)->routingChanged (propertyValue);
static_cast<iOSAudioIODevice*> (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)
};


Loading…
Cancel
Save