mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-02-07 04:10:08 +00:00
Added a method AudioIODevice::setGainPreprocessingEnabled() to allow disabling of mic AGC on iOS and Android devices.
This commit is contained in:
parent
d8180f7ba5
commit
5fdbdc9e9e
5 changed files with 65 additions and 41 deletions
|
|
@ -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&) {}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -165,6 +165,33 @@ public:
|
|||
oldCallback->audioDeviceStopped();
|
||||
}
|
||||
|
||||
bool setAudioPreprocessingEnabled (bool enable) override
|
||||
{
|
||||
return recorder != nullptr && recorder->setAudioPreprocessingEnabled (enable);
|
||||
}
|
||||
|
||||
private:
|
||||
//==================================================================================================
|
||||
CriticalSection callbackLock;
|
||||
AudioIODeviceCallback* callback;
|
||||
int actualBufferSize, sampleRate;
|
||||
int inputLatency, outputLatency;
|
||||
bool deviceOpen;
|
||||
String lastError;
|
||||
BigInteger activeOutputChans, activeInputChans;
|
||||
int numInputChannels, numOutputChannels;
|
||||
AudioSampleBuffer inputBuffer, outputBuffer;
|
||||
struct Player;
|
||||
struct Recorder;
|
||||
|
||||
AudioIODeviceCallback* setCallback (AudioIODeviceCallback* const newCallback)
|
||||
{
|
||||
const ScopedLock sl (callbackLock);
|
||||
AudioIODeviceCallback* const oldCallback = callback;
|
||||
callback = newCallback;
|
||||
return oldCallback;
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
if (recorder != nullptr) recorder->start();
|
||||
|
|
@ -190,28 +217,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//==================================================================================================
|
||||
CriticalSection callbackLock;
|
||||
AudioIODeviceCallback* callback;
|
||||
int actualBufferSize, sampleRate;
|
||||
int inputLatency, outputLatency;
|
||||
bool deviceOpen;
|
||||
String lastError;
|
||||
BigInteger activeOutputChans, activeInputChans;
|
||||
int numInputChannels, numOutputChannels;
|
||||
AudioSampleBuffer inputBuffer, outputBuffer;
|
||||
struct Player;
|
||||
struct Recorder;
|
||||
|
||||
AudioIODeviceCallback* setCallback (AudioIODeviceCallback* const newCallback)
|
||||
{
|
||||
const ScopedLock sl (callbackLock);
|
||||
AudioIODeviceCallback* const oldCallback = callback;
|
||||
callback = newCallback;
|
||||
return oldCallback;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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…
Add table
Add a link
Reference in a new issue