Browse Source

Handled some uncaught error cases in android openSL

tags/2021-05-28
jules 6 years ago
parent
commit
048cfd6a3c
1 changed files with 135 additions and 113 deletions
  1. +135
    -113
      modules/juce_audio_devices/native/juce_android_OpenSL.cpp

+ 135
- 113
modules/juce_audio_devices/native/juce_android_OpenSL.cpp View File

@@ -60,6 +60,22 @@ SLInterfaceID_ IntfIID<SLRecordItf_>::iid = { 0xc5657aa0, 0xdd
SLInterfaceID_ IntfIID<SLAndroidSimpleBufferQueueItf_>::iid = { 0x198e4940, 0xc5d7, 0x11df, 0xa2a6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b} }; SLInterfaceID_ IntfIID<SLAndroidSimpleBufferQueueItf_>::iid = { 0x198e4940, 0xc5d7, 0x11df, 0xa2a6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b} };
SLInterfaceID_ IntfIID<SLAndroidConfigurationItf_>::iid = { 0x89f6a7e0, 0xbeac, 0x11df, 0x8b5c, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b} }; SLInterfaceID_ IntfIID<SLAndroidConfigurationItf_>::iid = { 0x89f6a7e0, 0xbeac, 0x11df, 0x8b5c, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b} };
template <typename SLObjectType>
static void destroyObject (SLObjectType object)
{
if (object != nullptr && *object != nullptr)
(*object)->Destroy (object);
}
template <>
struct ContainerDeletePolicy<const SLObjectItf_* const>
{
static void destroy (SLObjectItf object)
{
destroyObject (object);
}
};
//============================================================================== //==============================================================================
// Some life-time and type management of OpenSL objects // Some life-time and type management of OpenSL objects
class SlObjectRef class SlObjectRef
@@ -67,27 +83,34 @@ class SlObjectRef
public: public:
//============================================================================== //==============================================================================
SlObjectRef() noexcept {} SlObjectRef() noexcept {}
SlObjectRef (const SlObjectRef& obj) noexcept : cb (obj.cb) {}
SlObjectRef (const SlObjectRef& obj) noexcept : cb (obj.cb) {}
SlObjectRef (SlObjectRef&& obj) noexcept : cb (static_cast<ReferenceCountedObjectPtr<ControlBlock>&&> (obj.cb)) { obj.cb = nullptr; } SlObjectRef (SlObjectRef&& obj) noexcept : cb (static_cast<ReferenceCountedObjectPtr<ControlBlock>&&> (obj.cb)) { obj.cb = nullptr; }
explicit SlObjectRef (SLObjectItf o) : cb (new ControlBlock (o)) {} explicit SlObjectRef (SLObjectItf o) : cb (new ControlBlock (o)) {}
//============================================================================== //==============================================================================
SlObjectRef& operator=(const SlObjectRef& r) noexcept { cb = r.cb; return *this; }
SlObjectRef& operator=(SlObjectRef&& r) noexcept { cb = static_cast<ReferenceCountedObjectPtr<ControlBlock>&&> (r.cb); r.cb = nullptr; return *this; }
SlObjectRef& operator=(std::nullptr_t) noexcept { cb = nullptr; return *this; }
SlObjectRef& operator= (const SlObjectRef& r) noexcept { cb = r.cb; return *this; }
SlObjectRef& operator= (SlObjectRef&& r) noexcept { cb = static_cast<ReferenceCountedObjectPtr<ControlBlock>&&> (r.cb); r.cb = nullptr; return *this; }
SlObjectRef& operator= (std::nullptr_t) noexcept { cb = nullptr; return *this; }
//============================================================================== //==============================================================================
const SLObjectItf_* const operator*() noexcept { return *cb->ptr.get(); }
SLObjectItf operator->() noexcept { return (cb == nullptr ? nullptr : cb->ptr.get()); }
operator SLObjectItf() noexcept { return (cb == nullptr ? nullptr : cb->ptr.get()); }
const SLObjectItf_* operator*() noexcept { return *cb->ptr.get(); }
SLObjectItf operator->() noexcept { return (cb == nullptr ? nullptr : cb->ptr.get()); }
operator SLObjectItf() noexcept { return (cb == nullptr ? nullptr : cb->ptr.get()); }
//============================================================================== //==============================================================================
bool operator== (nullptr_t) const noexcept { return (cb == nullptr || cb->ptr == nullptr); }
bool operator!= (nullptr_t) const noexcept { return (cb != nullptr && cb->ptr != nullptr); }
private:
bool operator== (nullptr_t) const noexcept { return (cb == nullptr || cb->ptr == nullptr); }
bool operator!= (nullptr_t) const noexcept { return (cb != nullptr && cb->ptr != nullptr); }
private:
//============================================================================== //==============================================================================
struct ControlBlock : ReferenceCountedObject { std::unique_ptr<const SLObjectItf_* const> ptr; ControlBlock() {} ControlBlock (SLObjectItf o) : ptr (o) {} };
struct ControlBlock : ReferenceCountedObject
{
ControlBlock() = default;
ControlBlock (SLObjectItf o) : ptr (o) {}
std::unique_ptr<const SLObjectItf_* const> ptr;
};
ReferenceCountedObjectPtr<ControlBlock> cb; ReferenceCountedObjectPtr<ControlBlock> cb;
}; };
@@ -96,53 +119,53 @@ class SlRef : public SlObjectRef
{ {
public: public:
//============================================================================== //==============================================================================
SlRef() noexcept : type (nullptr) {}
SlRef (SlRef& r) noexcept : SlObjectRef (r), type (r.type) {}
SlRef() noexcept {}
SlRef (const SlRef& r) noexcept : SlObjectRef (r), type (r.type) {}
SlRef (SlRef&& r) noexcept : SlObjectRef (static_cast<SlRef&&> (r)), type (r.type) { r.type = nullptr; } SlRef (SlRef&& r) noexcept : SlObjectRef (static_cast<SlRef&&> (r)), type (r.type) { r.type = nullptr; }
//============================================================================== //==============================================================================
SlRef& operator= (const SlRef& r) noexcept { SlObjectRef::operator= (r); type = r.type; return *this; } SlRef& operator= (const SlRef& r) noexcept { SlObjectRef::operator= (r); type = r.type; return *this; }
SlRef& operator= (SlRef&& r) noexcept { SlObjectRef::operator= (static_cast<SlObjectRef&&> (r)); type = r.type; r.type = nullptr; return *this; }
SlRef& operator= (std::nullptr_t) noexcept { SlObjectRef::operator= (nullptr); type = nullptr; return *this; }
SlRef& operator= (SlRef&& r) noexcept { SlObjectRef::operator= (static_cast<SlObjectRef&&> (r)); type = r.type; r.type = nullptr; return *this; }
SlRef& operator= (std::nullptr_t) noexcept { SlObjectRef::operator= (nullptr); type = nullptr; return *this; }
//============================================================================== //==============================================================================
T* const operator*() noexcept { return *type; }
T* const * operator->() noexcept { return type; }
operator T* const *() noexcept { return type; }
T* const operator*() noexcept { return *type; }
T* const* operator->() noexcept { return type; }
operator T* const*() noexcept { return type; }
//============================================================================== //==============================================================================
static SlRef cast (SlObjectRef& base) { return SlRef (base); }
static SlRef cast (SlObjectRef&& base) { return SlRef (static_cast<SlObjectRef&&> (base)); }
static SlRef cast (SlObjectRef& base) { return SlRef (base); }
static SlRef cast (SlObjectRef&& base) { return SlRef (static_cast<SlObjectRef&&> (base)); }
private: private:
//==============================================================================
SlRef (SlObjectRef& base) : SlObjectRef (base) SlRef (SlObjectRef& base) : SlObjectRef (base)
{ {
SLObjectItf obj = SlObjectRef::operator->();
SLresult err = (*obj)->GetInterface (obj, &IntfIID<T>::iid, &type);
if (type == nullptr || err != SL_RESULT_SUCCESS)
*this = nullptr;
if (auto obj = SlObjectRef::operator->())
{
auto err = (*obj)->GetInterface (obj, &IntfIID<T>::iid, &type);
if (type != nullptr && err == SL_RESULT_SUCCESS)
return;
}
*this = nullptr;
} }
SlRef (SlObjectRef&& base) : SlObjectRef (static_cast<SlObjectRef&&> (base)) SlRef (SlObjectRef&& base) : SlObjectRef (static_cast<SlObjectRef&&> (base))
{ {
SLObjectItf obj = SlObjectRef::operator->();
SLresult err = (*obj)->GetInterface (obj, &IntfIID<T>::iid, &type);
base = nullptr;
if (auto obj = SlObjectRef::operator->())
{
auto err = (*obj)->GetInterface (obj, &IntfIID<T>::iid, &type);
base = nullptr;
if (type == nullptr || err != SL_RESULT_SUCCESS)
*this = nullptr;
}
T* const * type;
};
if (type != nullptr && err == SL_RESULT_SUCCESS)
return;
}
template <>
struct ContainerDeletePolicy<const SLObjectItf_* const>
{
static void destroy (SLObjectItf object)
{
if (object != nullptr)
(*object)->Destroy (object);
*this = nullptr;
} }
T* const* type = nullptr;
}; };
//============================================================================== //==============================================================================
@@ -281,8 +304,7 @@ public:
numChannels (numChannelsToUse), numChannels (numChannelsToUse),
nativeBuffer (static_cast<size_t> (numChannels * owner.bufferSize * owner.numBuffers)), nativeBuffer (static_cast<size_t> (numChannels * owner.bufferSize * owner.numBuffers)),
scratchBuffer (numChannelsToUse, owner.bufferSize), scratchBuffer (numChannelsToUse, owner.bufferSize),
sampleBuffer (scratchBuffer.getArrayOfWritePointers(), numChannelsToUse, owner.bufferSize),
nextBlock (0), numBlocksOut (0)
sampleBuffer (scratchBuffer.getArrayOfWritePointers(), numChannelsToUse, owner.bufferSize)
{} {}
~OpenSLQueueRunner() ~OpenSLQueueRunner()
@@ -297,6 +319,7 @@ public:
bool init() bool init()
{ {
runner = crtp().createPlayerOrRecorder(); runner = crtp().createPlayerOrRecorder();
if (runner == nullptr) if (runner == nullptr)
return false; return false;
@@ -319,13 +342,13 @@ public:
} }
queue = SlRef<SLAndroidSimpleBufferQueueItf_>::cast (runner); queue = SlRef<SLAndroidSimpleBufferQueueItf_>::cast (runner);
if (queue == nullptr) if (queue == nullptr)
return false; return false;
return ((*queue)->RegisterCallback (queue, staticFinished, this) == SL_RESULT_SUCCESS); return ((*queue)->RegisterCallback (queue, staticFinished, this) == SL_RESULT_SUCCESS);
} }
void clear() void clear()
{ {
nextBlock.set (0); nextBlock.set (0);
@@ -376,7 +399,7 @@ public:
HeapBlock<T> nativeBuffer; HeapBlock<T> nativeBuffer;
AudioBuffer<float> scratchBuffer, sampleBuffer; AudioBuffer<float> scratchBuffer, sampleBuffer;
Atomic<int> nextBlock, numBlocksOut;
Atomic<int> nextBlock { 0 }, numBlocksOut { 0 };
}; };
//============================================================================== //==============================================================================
@@ -385,35 +408,36 @@ public:
{ {
using Base = OpenSLQueueRunner<T, OpenSLQueueRunnerPlayer<T>, SLPlayItf_>; using Base = OpenSLQueueRunner<T, OpenSLQueueRunnerPlayer<T>, SLPlayItf_>;
enum { isPlayer = 1 };
OpenSLQueueRunnerPlayer (OpenSLSessionT<T>& sessionToUse, int numChannelsToUse) OpenSLQueueRunnerPlayer (OpenSLSessionT<T>& sessionToUse, int numChannelsToUse)
: Base (sessionToUse, numChannelsToUse) : Base (sessionToUse, numChannelsToUse)
{} {}
SlRef<SLPlayItf_> createPlayerOrRecorder() SlRef<SLPlayItf_> createPlayerOrRecorder()
{ {
SLDataLocator_AndroidSimpleBufferQueue queueLocator = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, static_cast<SLuint32> (Base::owner.numBuffers)};
SLDataLocator_OutputMix outputMix = {SL_DATALOCATOR_OUTPUTMIX, Base::owner.outputMix};
SLDataLocator_AndroidSimpleBufferQueue queueLocator = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, static_cast<SLuint32> (Base::owner.numBuffers) };
SLDataLocator_OutputMix outputMix = { SL_DATALOCATOR_OUTPUTMIX, Base::owner.outputMix };
PCMDataFormatEx dataFormat; PCMDataFormatEx dataFormat;
BufferHelpers<T>::initPCMDataFormat (dataFormat, Base::numChannels, Base::owner.sampleRate); BufferHelpers<T>::initPCMDataFormat (dataFormat, Base::numChannels, Base::owner.sampleRate);
SLDataSource source = {&queueLocator, &dataFormat};
SLDataSink sink = {&outputMix, nullptr};
SLDataSource source = { &queueLocator, &dataFormat };
SLDataSink sink = { &outputMix, nullptr };
SLInterfaceID queueInterfaces[] = { &IntfIID<SLAndroidSimpleBufferQueueItf_>::iid, &IntfIID<SLAndroidConfigurationItf_>::iid }; SLInterfaceID queueInterfaces[] = { &IntfIID<SLAndroidSimpleBufferQueueItf_>::iid, &IntfIID<SLAndroidConfigurationItf_>::iid };
SLboolean interfaceRequired[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_FALSE}; SLboolean interfaceRequired[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_FALSE};
SLObjectItf obj = nullptr; SLObjectItf obj = nullptr;
SLresult status = (*Base::owner.engine)->CreateAudioPlayer (Base::owner.engine, &obj, &source, &sink, 2, queueInterfaces, interfaceRequired);
if (status != SL_RESULT_SUCCESS || obj == nullptr || (*obj)->Realize (obj, 0) != SL_RESULT_SUCCESS)
if (auto e = *Base::owner.engine)
{ {
if (obj != nullptr)
(*obj)->Destroy (obj);
auto status = e->CreateAudioPlayer (Base::owner.engine, &obj, &source, &sink, 2,
queueInterfaces, interfaceRequired);
return SlRef<SLPlayItf_>();
if (status != SL_RESULT_SUCCESS || obj == nullptr || (*obj)->Realize(obj, 0) != SL_RESULT_SUCCESS)
{
destroyObject (obj);
return {};
}
} }
return SlRef<SLPlayItf_>::cast (SlObjectRef (obj)); return SlRef<SLPlayItf_>::cast (SlObjectRef (obj));
@@ -423,44 +447,42 @@ public:
}; };
template <typename T> template <typename T>
struct OpenSLQueueRunnerRecorder : OpenSLQueueRunner<T, OpenSLQueueRunnerRecorder<T>, SLRecordItf_>
struct OpenSLQueueRunnerRecorder : public OpenSLQueueRunner<T, OpenSLQueueRunnerRecorder<T>, SLRecordItf_>
{ {
using Base = OpenSLQueueRunner<T, OpenSLQueueRunnerRecorder<T>, SLRecordItf_>; using Base = OpenSLQueueRunner<T, OpenSLQueueRunnerRecorder<T>, SLRecordItf_>;
enum { isPlayer = 0 };
OpenSLQueueRunnerRecorder (OpenSLSessionT<T>& sessionToUse, int numChannelsToUse) OpenSLQueueRunnerRecorder (OpenSLSessionT<T>& sessionToUse, int numChannelsToUse)
: Base (sessionToUse, numChannelsToUse) : Base (sessionToUse, numChannelsToUse)
{} {}
SlRef<SLRecordItf_> createPlayerOrRecorder() SlRef<SLRecordItf_> createPlayerOrRecorder()
{ {
SLDataLocator_IODevice ioDeviceLocator = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, nullptr};
SLDataLocator_AndroidSimpleBufferQueue queueLocator = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, static_cast<SLuint32> (Base::owner.numBuffers)};
SLDataLocator_IODevice ioDeviceLocator = { SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, nullptr };
SLDataLocator_AndroidSimpleBufferQueue queueLocator = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, static_cast<SLuint32> (Base::owner.numBuffers) };
PCMDataFormatEx dataFormat; PCMDataFormatEx dataFormat;
BufferHelpers<T>::initPCMDataFormat (dataFormat, Base::numChannels, Base::owner.sampleRate); BufferHelpers<T>::initPCMDataFormat (dataFormat, Base::numChannels, Base::owner.sampleRate);
SLDataSource source = {&ioDeviceLocator, nullptr};
SLDataSink sink = {&queueLocator, &dataFormat};
SLDataSource source = { &ioDeviceLocator, nullptr };
SLDataSink sink = { &queueLocator, &dataFormat };
SLInterfaceID queueInterfaces[] = { &IntfIID<SLAndroidSimpleBufferQueueItf_>::iid, &IntfIID<SLAndroidConfigurationItf_>::iid }; SLInterfaceID queueInterfaces[] = { &IntfIID<SLAndroidSimpleBufferQueueItf_>::iid, &IntfIID<SLAndroidConfigurationItf_>::iid };
SLboolean interfaceRequired[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_FALSE};
SLboolean interfaceRequired[] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_FALSE };
SLObjectItf obj = nullptr; SLObjectItf obj = nullptr;
SLresult status = (*Base::owner.engine)->CreateAudioRecorder (Base::owner.engine, &obj, &source, &sink, 2, queueInterfaces, interfaceRequired);
if (status != SL_RESULT_SUCCESS || obj == nullptr || (*obj)->Realize (obj, 0) != SL_RESULT_SUCCESS)
if (auto e = *Base::owner.engine)
{ {
if (obj != nullptr)
(*obj)->Destroy (obj);
auto status = e->CreateAudioRecorder (Base::owner.engine, &obj, &source, &sink, 2, queueInterfaces, interfaceRequired);
return SlRef<SLRecordItf_>();
if (status != SL_RESULT_SUCCESS || obj == nullptr || (*obj)->Realize (obj, 0) != SL_RESULT_SUCCESS)
{
destroyObject (obj);
return {};
}
} }
SlRef<SLRecordItf_> recorder = SlRef<SLRecordItf_>::cast (SlObjectRef (obj));
return recorder;
return SlRef<SLRecordItf_>::cast (SlObjectRef (obj));
} }
bool setAudioPreprocessingEnabled (bool shouldEnable) bool setAudioPreprocessingEnabled (bool shouldEnable)
@@ -468,13 +490,14 @@ public:
if (Base::config != nullptr) if (Base::config != nullptr)
{ {
const bool supportsUnprocessed = (getEnv()->GetStaticIntField (AndroidBuildVersion, AndroidBuildVersion.SDK_INT) >= 25); const bool supportsUnprocessed = (getEnv()->GetStaticIntField (AndroidBuildVersion, AndroidBuildVersion.SDK_INT) >= 25);
const SLuint32 recordingPresetValue const SLuint32 recordingPresetValue
= (shouldEnable ? SL_ANDROID_RECORDING_PRESET_GENERIC = (shouldEnable ? SL_ANDROID_RECORDING_PRESET_GENERIC
: (supportsUnprocessed ? SL_ANDROID_RECORDING_PRESET_UNPROCESSED : (supportsUnprocessed ? SL_ANDROID_RECORDING_PRESET_UNPROCESSED
: SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION)); : SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION));
SLresult status = (*Base::config)->SetConfiguration (Base::config, SL_ANDROID_KEY_RECORDING_PRESET,
&recordingPresetValue, sizeof (recordingPresetValue));
auto status = (*Base::config)->SetConfiguration (Base::config, SL_ANDROID_KEY_RECORDING_PRESET,
&recordingPresetValue, sizeof (recordingPresetValue));
return (status == SL_RESULT_SUCCESS); return (status == SL_RESULT_SUCCESS);
} }
@@ -482,7 +505,8 @@ public:
return false; return false;
} }
void setState (bool running) { (*Base::runner)->SetRecordState (Base::runner, running ? SL_RECORDSTATE_RECORDING : SL_RECORDSTATE_STOPPED); }
void setState (bool running) { (*Base::runner)->SetRecordState (Base::runner, running ? SL_RECORDSTATE_RECORDING
: SL_RECORDSTATE_STOPPED); }
}; };
//============================================================================== //==============================================================================
@@ -494,21 +518,19 @@ public:
double samleRateToUse, int bufferSizeToUse, double samleRateToUse, int bufferSizeToUse,
int numBuffersToUse) int numBuffersToUse)
: inputChannels (numInputChannels), outputChannels (numOutputChannels), : inputChannels (numInputChannels), outputChannels (numOutputChannels),
sampleRate (samleRateToUse), bufferSize (bufferSizeToUse), numBuffers (numBuffersToUse),
running (false), audioProcessingEnabled (true), callback (nullptr)
sampleRate (samleRateToUse), bufferSize (bufferSizeToUse), numBuffers (numBuffersToUse)
{ {
jassert (numInputChannels > 0 || numOutputChannels > 0); jassert (numInputChannels > 0 || numOutputChannels > 0);
if (CreateEngineFunc createEngine = (CreateEngineFunc) slLibraryToUse.getFunction ("slCreateEngine"))
if (auto createEngine = (CreateEngineFunc) slLibraryToUse.getFunction ("slCreateEngine"))
{ {
SLObjectItf obj = nullptr; SLObjectItf obj = nullptr;
auto err = createEngine (&obj, 0, nullptr, 0, nullptr, nullptr);
SLresult err = createEngine (&obj, 0, nullptr, 0, nullptr, nullptr);
if (err != SL_RESULT_SUCCESS || obj == nullptr || (*obj)->Realize (obj, 0) != SL_RESULT_SUCCESS)
if (err != SL_RESULT_SUCCESS || obj == nullptr || *obj == nullptr
|| (*obj)->Realize (obj, 0) != SL_RESULT_SUCCESS)
{ {
if (obj != nullptr)
(*obj)->Destroy (obj);
destroyObject (obj);
return; return;
} }
@@ -518,13 +540,12 @@ public:
if (outputChannels > 0) if (outputChannels > 0)
{ {
SLObjectItf obj = nullptr; SLObjectItf obj = nullptr;
auto err = (*engine)->CreateOutputMix (engine, &obj, 0, nullptr, nullptr);
SLresult err = (*engine)->CreateOutputMix (engine, &obj, 0, nullptr, nullptr);
if (err != SL_RESULT_SUCCESS || obj == nullptr || (*obj)->Realize (obj, 0) != SL_RESULT_SUCCESS)
if (err != SL_RESULT_SUCCESS || obj == nullptr || *obj == nullptr
|| (*obj)->Realize (obj, 0) != SL_RESULT_SUCCESS)
{ {
if (obj != nullptr)
(*obj)->Destroy (obj);
destroyObject (obj);
return; return;
} }
@@ -537,6 +558,7 @@ public:
virtual bool openedOK() const { return (engine != nullptr && (outputChannels == 0 || (outputMix != nullptr))); } virtual bool openedOK() const { return (engine != nullptr && (outputChannels == 0 || (outputMix != nullptr))); }
virtual void start() { stop(); jassert (callback.get() != nullptr); running = true; } virtual void start() { stop(); jassert (callback.get() != nullptr); running = true; }
virtual void stop() { running = false; } virtual void stop() { running = false; }
virtual bool setAudioPreprocessingEnabled (bool shouldEnable) = 0; virtual bool setAudioPreprocessingEnabled (bool shouldEnable) = 0;
virtual bool supportsFloatingPoint() const noexcept = 0; virtual bool supportsFloatingPoint() const noexcept = 0;
virtual int getXRunCount() const noexcept = 0; virtual int getXRunCount() const noexcept = 0;
@@ -553,9 +575,10 @@ public:
jassert (callbackToUse != nullptr); jassert (callbackToUse != nullptr);
// spin-lock until we can set the callback // spin-lock until we can set the callback
while (true)
for (;;)
{ {
AudioIODeviceCallback* old = callback.get();
auto old = callback.get();
if (old == callbackToUse) if (old == callbackToUse)
break; break;
@@ -568,7 +591,7 @@ public:
void process (const float** inputChannelData, float** outputChannelData) void process (const float** inputChannelData, float** outputChannelData)
{ {
if (AudioIODeviceCallback* cb = callback.exchange(nullptr))
if (auto* cb = callback.exchange (nullptr))
{ {
cb->audioDeviceIOCallback (inputChannelData, inputChannels, outputChannelData, outputChannels, bufferSize); cb->audioDeviceIOCallback (inputChannelData, inputChannels, outputChannelData, outputChannels, bufferSize);
callback.set (cb); callback.set (cb);
@@ -586,19 +609,19 @@ public:
int numBuffersToUse); int numBuffersToUse);
//============================================================================== //==============================================================================
typedef SLresult (*CreateEngineFunc)(SLObjectItf*, SLuint32, const SLEngineOption*, SLuint32, const SLInterfaceID*, const SLboolean*);
using CreateEngineFunc = SLresult (*) (SLObjectItf*, SLuint32, const SLEngineOption*,
SLuint32, const SLInterfaceID*, const SLboolean*);
//============================================================================== //==============================================================================
int inputChannels, outputChannels; int inputChannels, outputChannels;
double sampleRate; double sampleRate;
int bufferSize, numBuffers; int bufferSize, numBuffers;
bool running, audioProcessingEnabled;
bool running = false, audioProcessingEnabled = true;
SlRef<SLEngineItf_> engine; SlRef<SLEngineItf_> engine;
SlRef<SLOutputMixItf_> outputMix; SlRef<SLOutputMixItf_> outputMix;
Atomic<AudioIODeviceCallback*> callback;
Atomic<AudioIODeviceCallback*> callback { nullptr };
}; };
template <typename T> template <typename T>
@@ -609,7 +632,8 @@ public:
int numInputChannels, int numOutputChannels, int numInputChannels, int numOutputChannels,
double samleRateToUse, int bufferSizeToUse, double samleRateToUse, int bufferSizeToUse,
int numBuffersToUse) int numBuffersToUse)
: OpenSLSession (slLibraryToUse, numInputChannels, numOutputChannels, samleRateToUse, bufferSizeToUse, numBuffersToUse)
: OpenSLSession (slLibraryToUse, numInputChannels, numOutputChannels,
samleRateToUse, bufferSizeToUse, numBuffersToUse)
{ {
jassert (numInputChannels > 0 || numOutputChannels > 0); jassert (numInputChannels > 0 || numOutputChannels > 0);
@@ -644,8 +668,8 @@ public:
bool openedOK() const override bool openedOK() const override
{ {
return (OpenSLSession::openedOK() && (inputChannels == 0 || recorder != nullptr)
&& (outputChannels == 0 || player != nullptr));
return OpenSLSession::openedOK() && (inputChannels == 0 || recorder != nullptr)
&& (outputChannels == 0 || player != nullptr);
} }
void start() override void start() override
@@ -762,11 +786,7 @@ public:
}; };
//============================================================================== //==============================================================================
OpenSLAudioIODevice (const String& deviceName)
: AudioIODevice (deviceName, openSLTypeName),
actualBufferSize (0), sampleRate (0), audioBuffersToEnqueue (0),
audioProcessingEnabled (true),
callback (nullptr)
OpenSLAudioIODevice (const String& deviceName) : AudioIODevice (deviceName, openSLTypeName)
{ {
// OpenSL has piss-poor support for determining latency, so the only way I can find to // OpenSL has piss-poor support for determining latency, so the only way I can find to
// get a number for this is by asking the AudioTrack/AudioRecord classes.. // get a number for this is by asking the AudioTrack/AudioRecord classes..
@@ -879,7 +899,9 @@ public:
session.reset (OpenSLSession::create (slLibrary, numInputChannels, numOutputChannels, session.reset (OpenSLSession::create (slLibrary, numInputChannels, numOutputChannels,
sampleRate, actualBufferSize, audioBuffersToEnqueue)); sampleRate, actualBufferSize, audioBuffersToEnqueue));
if (session != nullptr) if (session != nullptr)
{
session->setAudioPreprocessingEnabled (audioProcessingEnabled); session->setAudioPreprocessingEnabled (audioProcessingEnabled);
}
else else
{ {
if (numInputChannels > 0 && numOutputChannels > 0 && RuntimePermissions::isGranted (RuntimePermissions::recordAudio)) if (numInputChannels > 0 && numOutputChannels > 0 && RuntimePermissions::isGranted (RuntimePermissions::recordAudio))
@@ -945,7 +967,7 @@ public:
{ {
if (session != nullptr && callback != newCallback) if (session != nullptr && callback != newCallback)
{ {
AudioIODeviceCallback* oldCallback = callback;
auto oldCallback = callback;
if (newCallback != nullptr) if (newCallback != nullptr)
newCallback->audioDeviceAboutToStart (this); newCallback->audioDeviceAboutToStart (this);
@@ -1001,12 +1023,12 @@ private:
//============================================================================== //==============================================================================
DynamicLibrary slLibrary; DynamicLibrary slLibrary;
int actualBufferSize, sampleRate, audioBuffersToEnqueue;
int actualBufferSize = 0, sampleRate = 0, audioBuffersToEnqueue = 0;
int inputLatency, outputLatency; int inputLatency, outputLatency;
bool deviceOpen, audioProcessingEnabled;
bool deviceOpen = false, audioProcessingEnabled = true;
String lastError; String lastError;
BigInteger activeOutputChans, activeInputChans; BigInteger activeOutputChans, activeInputChans;
AudioIODeviceCallback* callback;
AudioIODeviceCallback* callback = nullptr;
std::unique_ptr<OpenSLSession> session; std::unique_ptr<OpenSLSession> session;
@@ -1210,12 +1232,12 @@ public:
SLObjectItf obj = nullptr; SLObjectItf obj = nullptr;
auto err = createEngine (&obj, 0, nullptr, 0, nullptr, nullptr); auto err = createEngine (&obj, 0, nullptr, 0, nullptr, nullptr);
if (err != SL_RESULT_SUCCESS || obj == nullptr)
if (err != SL_RESULT_SUCCESS || obj == nullptr || *obj == nullptr)
return; return;
if ((*obj)->Realize (obj, 0) != SL_RESULT_SUCCESS) if ((*obj)->Realize (obj, 0) != SL_RESULT_SUCCESS)
{ {
(*obj)->Destroy (obj);
destroyObject (obj);
return; return;
} }
@@ -1223,7 +1245,7 @@ public:
if (engine == nullptr) if (engine == nullptr)
{ {
(*obj)->Destroy (obj);
destroyObject (obj);
return; return;
} }
@@ -1232,7 +1254,7 @@ public:
if (err != SL_RESULT_SUCCESS || obj == nullptr || (*obj)->Realize (obj, 0) != SL_RESULT_SUCCESS) if (err != SL_RESULT_SUCCESS || obj == nullptr || (*obj)->Realize (obj, 0) != SL_RESULT_SUCCESS)
{ {
(*obj)->Destroy (obj);
destroyObject (obj);
return; return;
} }
@@ -1240,7 +1262,7 @@ public:
if (outputMix == nullptr) if (outputMix == nullptr)
{ {
(*obj)->Destroy (obj);
destroyObject (obj);
return; return;
} }
@@ -1264,7 +1286,7 @@ public:
if ((*obj)->Realize (obj, 0) != SL_RESULT_SUCCESS) if ((*obj)->Realize (obj, 0) != SL_RESULT_SUCCESS)
{ {
(*obj)->Destroy (obj);
destroyObject (obj);
return; return;
} }
@@ -1272,7 +1294,7 @@ public:
if (player == nullptr) if (player == nullptr)
{ {
(*obj)->Destroy (obj);
destroyObject (obj);
return; return;
} }


Loading…
Cancel
Save