mirror of
https://github.com/love2d/megasource.git
synced 2026-08-18 19:54:37 +02:00
Update OpenAL-soft to 1.23.1-bc7cb17.
This commit is contained in:
@@ -23,23 +23,26 @@
|
||||
|
||||
#include "opensl.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <jni.h>
|
||||
|
||||
#include <new>
|
||||
#include <array>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
#include <new>
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
|
||||
#include "albit.h"
|
||||
#include "alnumeric.h"
|
||||
#include "alsem.h"
|
||||
#include "alstring.h"
|
||||
#include "althrd_setname.h"
|
||||
#include "core/device.h"
|
||||
#include "core/helpers.h"
|
||||
#include "core/logging.h"
|
||||
#include "opthelpers.h"
|
||||
#include "ringbuffer.h"
|
||||
#include "threads.h"
|
||||
|
||||
#include <SLES/OpenSLES.h>
|
||||
#include <SLES/OpenSLES_Android.h>
|
||||
@@ -48,15 +51,17 @@
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
/* Helper macros */
|
||||
#define EXTRACT_VCALL_ARGS(...) __VA_ARGS__))
|
||||
#define VCALL(obj, func) ((*(obj))->func((obj), EXTRACT_VCALL_ARGS
|
||||
#define VCALL0(obj, func) ((*(obj))->func((obj) EXTRACT_VCALL_ARGS
|
||||
|
||||
|
||||
constexpr char opensl_device[] = "OpenSL";
|
||||
|
||||
[[nodiscard]] constexpr auto GetDeviceName() noexcept { return "OpenSL"sv; }
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr SLuint32 GetChannelMask(DevFmtChannels chans) noexcept
|
||||
{
|
||||
switch(chans)
|
||||
@@ -71,9 +76,15 @@ constexpr SLuint32 GetChannelMask(DevFmtChannels chans) noexcept
|
||||
case DevFmtX61: return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
|
||||
SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY | SL_SPEAKER_BACK_CENTER |
|
||||
SL_SPEAKER_SIDE_LEFT | SL_SPEAKER_SIDE_RIGHT;
|
||||
case DevFmtX71: return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
|
||||
case DevFmtX71:
|
||||
case DevFmtX3D71: return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
|
||||
SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY | SL_SPEAKER_BACK_LEFT |
|
||||
SL_SPEAKER_BACK_RIGHT | SL_SPEAKER_SIDE_LEFT | SL_SPEAKER_SIDE_RIGHT;
|
||||
case DevFmtX714: return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
|
||||
SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY | SL_SPEAKER_BACK_LEFT |
|
||||
SL_SPEAKER_BACK_RIGHT | SL_SPEAKER_SIDE_LEFT | SL_SPEAKER_SIDE_RIGHT |
|
||||
SL_SPEAKER_TOP_FRONT_LEFT | SL_SPEAKER_TOP_FRONT_RIGHT | SL_SPEAKER_TOP_BACK_LEFT |
|
||||
SL_SPEAKER_TOP_BACK_RIGHT;
|
||||
case DevFmtAmbi3D:
|
||||
break;
|
||||
}
|
||||
@@ -107,7 +118,7 @@ constexpr SLuint32 GetByteOrderEndianness() noexcept
|
||||
return SL_BYTEORDER_BIGENDIAN;
|
||||
}
|
||||
|
||||
const char *res_str(SLresult result) noexcept
|
||||
constexpr const char *res_str(SLresult result) noexcept
|
||||
{
|
||||
switch(result)
|
||||
{
|
||||
@@ -141,10 +152,11 @@ const char *res_str(SLresult result) noexcept
|
||||
return "Unknown error code";
|
||||
}
|
||||
|
||||
#define PRINTERR(x, s) do { \
|
||||
if UNLIKELY((x) != SL_RESULT_SUCCESS) \
|
||||
ERR("%s: %s\n", (s), res_str((x))); \
|
||||
} while(0)
|
||||
inline void PrintErr(SLresult res, const char *str)
|
||||
{
|
||||
if(res != SL_RESULT_SUCCESS) UNLIKELY
|
||||
ERR("%s: %s\n", str, res_str(res));
|
||||
}
|
||||
|
||||
|
||||
struct OpenSLPlayback final : public BackendBase {
|
||||
@@ -152,12 +164,10 @@ struct OpenSLPlayback final : public BackendBase {
|
||||
~OpenSLPlayback() override;
|
||||
|
||||
void process(SLAndroidSimpleBufferQueueItf bq) noexcept;
|
||||
static void processC(SLAndroidSimpleBufferQueueItf bq, void *context) noexcept
|
||||
{ static_cast<OpenSLPlayback*>(context)->process(bq); }
|
||||
|
||||
int mixerProc();
|
||||
|
||||
void open(const char *name) override;
|
||||
void open(std::string_view name) override;
|
||||
bool reset() override;
|
||||
void start() override;
|
||||
void stop() override;
|
||||
@@ -182,8 +192,6 @@ struct OpenSLPlayback final : public BackendBase {
|
||||
|
||||
std::atomic<bool> mKillNow{true};
|
||||
std::thread mThread;
|
||||
|
||||
DEF_NEWDEL(OpenSLPlayback)
|
||||
};
|
||||
|
||||
OpenSLPlayback::~OpenSLPlayback()
|
||||
@@ -222,17 +230,17 @@ void OpenSLPlayback::process(SLAndroidSimpleBufferQueueItf) noexcept
|
||||
int OpenSLPlayback::mixerProc()
|
||||
{
|
||||
SetRTPriority();
|
||||
althrd_setname(MIXER_THREAD_NAME);
|
||||
althrd_setname(GetMixerThreadName());
|
||||
|
||||
SLPlayItf player;
|
||||
SLAndroidSimpleBufferQueueItf bufferQueue;
|
||||
SLresult result{VCALL(mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
|
||||
&bufferQueue)};
|
||||
PRINTERR(result, "bufferQueue->GetInterface SL_IID_ANDROIDSIMPLEBUFFERQUEUE");
|
||||
PrintErr(result, "bufferQueue->GetInterface SL_IID_ANDROIDSIMPLEBUFFERQUEUE");
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = VCALL(mBufferQueueObj,GetInterface)(SL_IID_PLAY, &player);
|
||||
PRINTERR(result, "bufferQueue->GetInterface SL_IID_PLAY");
|
||||
PrintErr(result, "bufferQueue->GetInterface SL_IID_PLAY");
|
||||
}
|
||||
|
||||
const size_t frame_step{mDevice->channelsFromFmt()};
|
||||
@@ -248,11 +256,11 @@ int OpenSLPlayback::mixerProc()
|
||||
SLuint32 state{0};
|
||||
|
||||
result = VCALL(player,GetPlayState)(&state);
|
||||
PRINTERR(result, "player->GetPlayState");
|
||||
PrintErr(result, "player->GetPlayState");
|
||||
if(SL_RESULT_SUCCESS == result && state != SL_PLAYSTATE_PLAYING)
|
||||
{
|
||||
result = VCALL(player,SetPlayState)(SL_PLAYSTATE_PLAYING);
|
||||
PRINTERR(result, "player->SetPlayState");
|
||||
PrintErr(result, "player->SetPlayState");
|
||||
}
|
||||
if(SL_RESULT_SUCCESS != result)
|
||||
{
|
||||
@@ -289,7 +297,7 @@ int OpenSLPlayback::mixerProc()
|
||||
}
|
||||
|
||||
result = VCALL(bufferQueue,Enqueue)(data.first.buf, mDevice->UpdateSize*mFrameSize);
|
||||
PRINTERR(result, "bufferQueue->Enqueue");
|
||||
PrintErr(result, "bufferQueue->Enqueue");
|
||||
if(SL_RESULT_SUCCESS != result)
|
||||
{
|
||||
mDevice->handleDisconnect("Failed to queue audio: 0x%08x", result);
|
||||
@@ -305,39 +313,39 @@ int OpenSLPlayback::mixerProc()
|
||||
}
|
||||
|
||||
|
||||
void OpenSLPlayback::open(const char *name)
|
||||
void OpenSLPlayback::open(std::string_view name)
|
||||
{
|
||||
if(!name)
|
||||
name = opensl_device;
|
||||
else if(strcmp(name, opensl_device) != 0)
|
||||
throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%s\" not found",
|
||||
name};
|
||||
if(name.empty())
|
||||
name = GetDeviceName();
|
||||
else if(name != GetDeviceName())
|
||||
throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found",
|
||||
al::sizei(name), name.data()};
|
||||
|
||||
/* There's only one device, so if it's already open, there's nothing to do. */
|
||||
if(mEngineObj) return;
|
||||
|
||||
// create engine
|
||||
SLresult result{slCreateEngine(&mEngineObj, 0, nullptr, 0, nullptr, nullptr)};
|
||||
PRINTERR(result, "slCreateEngine");
|
||||
PrintErr(result, "slCreateEngine");
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = VCALL(mEngineObj,Realize)(SL_BOOLEAN_FALSE);
|
||||
PRINTERR(result, "engine->Realize");
|
||||
PrintErr(result, "engine->Realize");
|
||||
}
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = VCALL(mEngineObj,GetInterface)(SL_IID_ENGINE, &mEngine);
|
||||
PRINTERR(result, "engine->GetInterface");
|
||||
PrintErr(result, "engine->GetInterface");
|
||||
}
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = VCALL(mEngine,CreateOutputMix)(&mOutputMix, 0, nullptr, nullptr);
|
||||
PRINTERR(result, "engine->CreateOutputMix");
|
||||
PrintErr(result, "engine->CreateOutputMix");
|
||||
}
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = VCALL(mOutputMix,Realize)(SL_BOOLEAN_FALSE);
|
||||
PRINTERR(result, "outputMix->Realize");
|
||||
PrintErr(result, "outputMix->Realize");
|
||||
}
|
||||
|
||||
if(SL_RESULT_SUCCESS != result)
|
||||
@@ -368,74 +376,6 @@ bool OpenSLPlayback::reset()
|
||||
|
||||
mRing = nullptr;
|
||||
|
||||
#if 0
|
||||
if(!mDevice->Flags.get<FrequencyRequest>())
|
||||
{
|
||||
/* FIXME: Disabled until I figure out how to get the Context needed for
|
||||
* the getSystemService call.
|
||||
*/
|
||||
JNIEnv *env = Android_GetJNIEnv();
|
||||
jobject jctx = Android_GetContext();
|
||||
|
||||
/* Get necessary stuff for using java.lang.Integer,
|
||||
* android.content.Context, and android.media.AudioManager.
|
||||
*/
|
||||
jclass int_cls = JCALL(env,FindClass)("java/lang/Integer");
|
||||
jmethodID int_parseint = JCALL(env,GetStaticMethodID)(int_cls,
|
||||
"parseInt", "(Ljava/lang/String;)I"
|
||||
);
|
||||
TRACE("Integer: %p, parseInt: %p\n", int_cls, int_parseint);
|
||||
|
||||
jclass ctx_cls = JCALL(env,FindClass)("android/content/Context");
|
||||
jfieldID ctx_audsvc = JCALL(env,GetStaticFieldID)(ctx_cls,
|
||||
"AUDIO_SERVICE", "Ljava/lang/String;"
|
||||
);
|
||||
jmethodID ctx_getSysSvc = JCALL(env,GetMethodID)(ctx_cls,
|
||||
"getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;"
|
||||
);
|
||||
TRACE("Context: %p, AUDIO_SERVICE: %p, getSystemService: %p\n",
|
||||
ctx_cls, ctx_audsvc, ctx_getSysSvc);
|
||||
|
||||
jclass audmgr_cls = JCALL(env,FindClass)("android/media/AudioManager");
|
||||
jfieldID audmgr_prop_out_srate = JCALL(env,GetStaticFieldID)(audmgr_cls,
|
||||
"PROPERTY_OUTPUT_SAMPLE_RATE", "Ljava/lang/String;"
|
||||
);
|
||||
jmethodID audmgr_getproperty = JCALL(env,GetMethodID)(audmgr_cls,
|
||||
"getProperty", "(Ljava/lang/String;)Ljava/lang/String;"
|
||||
);
|
||||
TRACE("AudioManager: %p, PROPERTY_OUTPUT_SAMPLE_RATE: %p, getProperty: %p\n",
|
||||
audmgr_cls, audmgr_prop_out_srate, audmgr_getproperty);
|
||||
|
||||
const char *strchars;
|
||||
jstring strobj;
|
||||
|
||||
/* Now make the calls. */
|
||||
//AudioManager audMgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
|
||||
strobj = JCALL(env,GetStaticObjectField)(ctx_cls, ctx_audsvc);
|
||||
jobject audMgr = JCALL(env,CallObjectMethod)(jctx, ctx_getSysSvc, strobj);
|
||||
strchars = JCALL(env,GetStringUTFChars)(strobj, nullptr);
|
||||
TRACE("Context.getSystemService(%s) = %p\n", strchars, audMgr);
|
||||
JCALL(env,ReleaseStringUTFChars)(strobj, strchars);
|
||||
|
||||
//String srateStr = audMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
|
||||
strobj = JCALL(env,GetStaticObjectField)(audmgr_cls, audmgr_prop_out_srate);
|
||||
jstring srateStr = JCALL(env,CallObjectMethod)(audMgr, audmgr_getproperty, strobj);
|
||||
strchars = JCALL(env,GetStringUTFChars)(strobj, nullptr);
|
||||
TRACE("audMgr.getProperty(%s) = %p\n", strchars, srateStr);
|
||||
JCALL(env,ReleaseStringUTFChars)(strobj, strchars);
|
||||
|
||||
//int sampleRate = Integer.parseInt(srateStr);
|
||||
sampleRate = JCALL(env,CallStaticIntMethod)(int_cls, int_parseint, srateStr);
|
||||
|
||||
strchars = JCALL(env,GetStringUTFChars)(srateStr, nullptr);
|
||||
TRACE("Got system sample rate %uhz (%s)\n", sampleRate, strchars);
|
||||
JCALL(env,ReleaseStringUTFChars)(srateStr, strchars);
|
||||
|
||||
if(!sampleRate) sampleRate = device->Frequency;
|
||||
else sampleRate = maxu(sampleRate, MIN_OUTPUT_RATE);
|
||||
}
|
||||
#endif
|
||||
|
||||
mDevice->FmtChans = DevFmtStereo;
|
||||
mDevice->FmtType = DevFmtShort;
|
||||
|
||||
@@ -505,20 +445,20 @@ bool OpenSLPlayback::reset()
|
||||
|
||||
result = VCALL(mEngine,CreateAudioPlayer)(&mBufferQueueObj, &audioSrc, &audioSnk, ids.size(),
|
||||
ids.data(), reqs.data());
|
||||
PRINTERR(result, "engine->CreateAudioPlayer");
|
||||
PrintErr(result, "engine->CreateAudioPlayer");
|
||||
}
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
/* Set the stream type to "media" (games, music, etc), if possible. */
|
||||
SLAndroidConfigurationItf config;
|
||||
result = VCALL(mBufferQueueObj,GetInterface)(SL_IID_ANDROIDCONFIGURATION, &config);
|
||||
PRINTERR(result, "bufferQueue->GetInterface SL_IID_ANDROIDCONFIGURATION");
|
||||
PrintErr(result, "bufferQueue->GetInterface SL_IID_ANDROIDCONFIGURATION");
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
SLint32 streamType = SL_ANDROID_STREAM_MEDIA;
|
||||
result = VCALL(config,SetConfiguration)(SL_ANDROID_KEY_STREAM_TYPE, &streamType,
|
||||
sizeof(streamType));
|
||||
PRINTERR(result, "config->SetConfiguration");
|
||||
PrintErr(result, "config->SetConfiguration");
|
||||
}
|
||||
|
||||
/* Clear any error since this was optional. */
|
||||
@@ -527,7 +467,7 @@ bool OpenSLPlayback::reset()
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = VCALL(mBufferQueueObj,Realize)(SL_BOOLEAN_FALSE);
|
||||
PRINTERR(result, "bufferQueue->Realize");
|
||||
PrintErr(result, "bufferQueue->Realize");
|
||||
}
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
@@ -554,11 +494,13 @@ void OpenSLPlayback::start()
|
||||
SLAndroidSimpleBufferQueueItf bufferQueue;
|
||||
SLresult result{VCALL(mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
|
||||
&bufferQueue)};
|
||||
PRINTERR(result, "bufferQueue->GetInterface");
|
||||
PrintErr(result, "bufferQueue->GetInterface");
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = VCALL(bufferQueue,RegisterCallback)(&OpenSLPlayback::processC, this);
|
||||
PRINTERR(result, "bufferQueue->RegisterCallback");
|
||||
result = VCALL(bufferQueue,RegisterCallback)(
|
||||
[](SLAndroidSimpleBufferQueueItf bq, void *context) noexcept
|
||||
{ static_cast<OpenSLPlayback*>(context)->process(bq); }, this);
|
||||
PrintErr(result, "bufferQueue->RegisterCallback");
|
||||
}
|
||||
if(SL_RESULT_SUCCESS != result)
|
||||
throw al::backend_exception{al::backend_error::DeviceError,
|
||||
@@ -584,25 +526,25 @@ void OpenSLPlayback::stop()
|
||||
|
||||
SLPlayItf player;
|
||||
SLresult result{VCALL(mBufferQueueObj,GetInterface)(SL_IID_PLAY, &player)};
|
||||
PRINTERR(result, "bufferQueue->GetInterface");
|
||||
PrintErr(result, "bufferQueue->GetInterface");
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = VCALL(player,SetPlayState)(SL_PLAYSTATE_STOPPED);
|
||||
PRINTERR(result, "player->SetPlayState");
|
||||
PrintErr(result, "player->SetPlayState");
|
||||
}
|
||||
|
||||
SLAndroidSimpleBufferQueueItf bufferQueue;
|
||||
result = VCALL(mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bufferQueue);
|
||||
PRINTERR(result, "bufferQueue->GetInterface");
|
||||
PrintErr(result, "bufferQueue->GetInterface");
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = VCALL0(bufferQueue,Clear)();
|
||||
PRINTERR(result, "bufferQueue->Clear");
|
||||
PrintErr(result, "bufferQueue->Clear");
|
||||
}
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = VCALL(bufferQueue,RegisterCallback)(nullptr, nullptr);
|
||||
PRINTERR(result, "bufferQueue->RegisterCallback");
|
||||
PrintErr(result, "bufferQueue->RegisterCallback");
|
||||
}
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
@@ -611,7 +553,9 @@ void OpenSLPlayback::stop()
|
||||
std::this_thread::yield();
|
||||
result = VCALL(bufferQueue,GetState)(&state);
|
||||
} while(SL_RESULT_SUCCESS == result && state.count > 0);
|
||||
PRINTERR(result, "bufferQueue->GetState");
|
||||
PrintErr(result, "bufferQueue->GetState");
|
||||
|
||||
mRing->reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -619,8 +563,8 @@ ClockLatency OpenSLPlayback::getClockLatency()
|
||||
{
|
||||
ClockLatency ret;
|
||||
|
||||
std::lock_guard<std::mutex> _{mMutex};
|
||||
ret.ClockTime = GetDeviceClockTime(mDevice);
|
||||
std::lock_guard<std::mutex> dlock{mMutex};
|
||||
ret.ClockTime = mDevice->getClockTime();
|
||||
ret.Latency = std::chrono::seconds{mRing->readSpace() * mDevice->UpdateSize};
|
||||
ret.Latency /= mDevice->Frequency;
|
||||
|
||||
@@ -633,13 +577,11 @@ struct OpenSLCapture final : public BackendBase {
|
||||
~OpenSLCapture() override;
|
||||
|
||||
void process(SLAndroidSimpleBufferQueueItf bq) noexcept;
|
||||
static void processC(SLAndroidSimpleBufferQueueItf bq, void *context) noexcept
|
||||
{ static_cast<OpenSLCapture*>(context)->process(bq); }
|
||||
|
||||
void open(const char *name) override;
|
||||
void open(std::string_view name) override;
|
||||
void start() override;
|
||||
void stop() override;
|
||||
void captureSamples(al::byte *buffer, uint samples) override;
|
||||
void captureSamples(std::byte *buffer, uint samples) override;
|
||||
uint availableSamples() override;
|
||||
|
||||
/* engine interfaces */
|
||||
@@ -653,8 +595,6 @@ struct OpenSLCapture final : public BackendBase {
|
||||
uint mSplOffset{0u};
|
||||
|
||||
uint mFrameSize{0};
|
||||
|
||||
DEF_NEWDEL(OpenSLCapture)
|
||||
};
|
||||
|
||||
OpenSLCapture::~OpenSLCapture()
|
||||
@@ -677,34 +617,34 @@ void OpenSLCapture::process(SLAndroidSimpleBufferQueueItf) noexcept
|
||||
}
|
||||
|
||||
|
||||
void OpenSLCapture::open(const char* name)
|
||||
void OpenSLCapture::open(std::string_view name)
|
||||
{
|
||||
if(!name)
|
||||
name = opensl_device;
|
||||
else if(strcmp(name, opensl_device) != 0)
|
||||
throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%s\" not found",
|
||||
name};
|
||||
if(name.empty())
|
||||
name = GetDeviceName();
|
||||
else if(name != GetDeviceName())
|
||||
throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found",
|
||||
al::sizei(name), name.data()};
|
||||
|
||||
SLresult result{slCreateEngine(&mEngineObj, 0, nullptr, 0, nullptr, nullptr)};
|
||||
PRINTERR(result, "slCreateEngine");
|
||||
PrintErr(result, "slCreateEngine");
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = VCALL(mEngineObj,Realize)(SL_BOOLEAN_FALSE);
|
||||
PRINTERR(result, "engine->Realize");
|
||||
PrintErr(result, "engine->Realize");
|
||||
}
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = VCALL(mEngineObj,GetInterface)(SL_IID_ENGINE, &mEngine);
|
||||
PRINTERR(result, "engine->GetInterface");
|
||||
PrintErr(result, "engine->GetInterface");
|
||||
}
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
mFrameSize = mDevice->frameSizeFromFmt();
|
||||
/* Ensure the total length is at least 100ms */
|
||||
uint length{maxu(mDevice->BufferSize, mDevice->Frequency/10)};
|
||||
uint length{std::max(mDevice->BufferSize, mDevice->Frequency/10u)};
|
||||
/* Ensure the per-chunk length is at least 10ms, and no more than 50ms. */
|
||||
uint update_len{clampu(mDevice->BufferSize/3, mDevice->Frequency/100,
|
||||
mDevice->Frequency/100*5)};
|
||||
uint update_len{std::clamp(mDevice->BufferSize/3u, mDevice->Frequency/100u,
|
||||
mDevice->Frequency/100u*5u)};
|
||||
uint num_updates{(length+update_len-1) / update_len};
|
||||
|
||||
mRing = RingBuffer::Create(num_updates, update_len*mFrameSize, false);
|
||||
@@ -770,7 +710,7 @@ void OpenSLCapture::open(const char* name)
|
||||
result = VCALL(mEngine,CreateAudioRecorder)(&mRecordObj, &audioSrc, &audioSnk,
|
||||
ids.size(), ids.data(), reqs.data());
|
||||
}
|
||||
PRINTERR(result, "engine->CreateAudioRecorder");
|
||||
PrintErr(result, "engine->CreateAudioRecorder");
|
||||
}
|
||||
}
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
@@ -778,13 +718,13 @@ void OpenSLCapture::open(const char* name)
|
||||
/* Set the record preset to "generic", if possible. */
|
||||
SLAndroidConfigurationItf config;
|
||||
result = VCALL(mRecordObj,GetInterface)(SL_IID_ANDROIDCONFIGURATION, &config);
|
||||
PRINTERR(result, "recordObj->GetInterface SL_IID_ANDROIDCONFIGURATION");
|
||||
PrintErr(result, "recordObj->GetInterface SL_IID_ANDROIDCONFIGURATION");
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
SLuint32 preset = SL_ANDROID_RECORDING_PRESET_GENERIC;
|
||||
result = VCALL(config,SetConfiguration)(SL_ANDROID_KEY_RECORDING_PRESET, &preset,
|
||||
sizeof(preset));
|
||||
PRINTERR(result, "config->SetConfiguration");
|
||||
PrintErr(result, "config->SetConfiguration");
|
||||
}
|
||||
|
||||
/* Clear any error since this was optional. */
|
||||
@@ -793,24 +733,26 @@ void OpenSLCapture::open(const char* name)
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = VCALL(mRecordObj,Realize)(SL_BOOLEAN_FALSE);
|
||||
PRINTERR(result, "recordObj->Realize");
|
||||
PrintErr(result, "recordObj->Realize");
|
||||
}
|
||||
|
||||
SLAndroidSimpleBufferQueueItf bufferQueue;
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = VCALL(mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bufferQueue);
|
||||
PRINTERR(result, "recordObj->GetInterface");
|
||||
PrintErr(result, "recordObj->GetInterface");
|
||||
}
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = VCALL(bufferQueue,RegisterCallback)(&OpenSLCapture::processC, this);
|
||||
PRINTERR(result, "bufferQueue->RegisterCallback");
|
||||
result = VCALL(bufferQueue,RegisterCallback)(
|
||||
[](SLAndroidSimpleBufferQueueItf bq, void *context) noexcept
|
||||
{ static_cast<OpenSLCapture*>(context)->process(bq); }, this);
|
||||
PrintErr(result, "bufferQueue->RegisterCallback");
|
||||
}
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
const uint chunk_size{mDevice->UpdateSize * mFrameSize};
|
||||
const auto silence = (mDevice->FmtType == DevFmtUByte) ? al::byte{0x80} : al::byte{0};
|
||||
const auto silence = (mDevice->FmtType == DevFmtUByte) ? std::byte{0x80} : std::byte{0};
|
||||
|
||||
auto data = mRing->getWriteVector();
|
||||
std::fill_n(data.first.buf, data.first.len*chunk_size, silence);
|
||||
@@ -818,12 +760,12 @@ void OpenSLCapture::open(const char* name)
|
||||
for(size_t i{0u};i < data.first.len && SL_RESULT_SUCCESS == result;i++)
|
||||
{
|
||||
result = VCALL(bufferQueue,Enqueue)(data.first.buf + chunk_size*i, chunk_size);
|
||||
PRINTERR(result, "bufferQueue->Enqueue");
|
||||
PrintErr(result, "bufferQueue->Enqueue");
|
||||
}
|
||||
for(size_t i{0u};i < data.second.len && SL_RESULT_SUCCESS == result;i++)
|
||||
{
|
||||
result = VCALL(bufferQueue,Enqueue)(data.second.buf + chunk_size*i, chunk_size);
|
||||
PRINTERR(result, "bufferQueue->Enqueue");
|
||||
PrintErr(result, "bufferQueue->Enqueue");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -849,12 +791,12 @@ void OpenSLCapture::start()
|
||||
{
|
||||
SLRecordItf record;
|
||||
SLresult result{VCALL(mRecordObj,GetInterface)(SL_IID_RECORD, &record)};
|
||||
PRINTERR(result, "recordObj->GetInterface");
|
||||
PrintErr(result, "recordObj->GetInterface");
|
||||
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = VCALL(record,SetRecordState)(SL_RECORDSTATE_RECORDING);
|
||||
PRINTERR(result, "record->SetRecordState");
|
||||
PrintErr(result, "record->SetRecordState");
|
||||
}
|
||||
if(SL_RESULT_SUCCESS != result)
|
||||
throw al::backend_exception{al::backend_error::DeviceError,
|
||||
@@ -865,16 +807,16 @@ void OpenSLCapture::stop()
|
||||
{
|
||||
SLRecordItf record;
|
||||
SLresult result{VCALL(mRecordObj,GetInterface)(SL_IID_RECORD, &record)};
|
||||
PRINTERR(result, "recordObj->GetInterface");
|
||||
PrintErr(result, "recordObj->GetInterface");
|
||||
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = VCALL(record,SetRecordState)(SL_RECORDSTATE_PAUSED);
|
||||
PRINTERR(result, "record->SetRecordState");
|
||||
PrintErr(result, "record->SetRecordState");
|
||||
}
|
||||
}
|
||||
|
||||
void OpenSLCapture::captureSamples(al::byte *buffer, uint samples)
|
||||
void OpenSLCapture::captureSamples(std::byte *buffer, uint samples)
|
||||
{
|
||||
const uint update_size{mDevice->UpdateSize};
|
||||
const uint chunk_size{update_size * mFrameSize};
|
||||
@@ -886,7 +828,7 @@ void OpenSLCapture::captureSamples(al::byte *buffer, uint samples)
|
||||
auto rdata = mRing->getReadVector();
|
||||
for(uint i{0};i < samples;)
|
||||
{
|
||||
const uint rem{minu(samples - i, update_size - mSplOffset)};
|
||||
const uint rem{std::min(samples - i, update_size - mSplOffset)};
|
||||
std::copy_n(rdata.first.buf + mSplOffset*size_t{mFrameSize}, rem*size_t{mFrameSize},
|
||||
buffer + i*size_t{mFrameSize});
|
||||
|
||||
@@ -908,22 +850,22 @@ void OpenSLCapture::captureSamples(al::byte *buffer, uint samples)
|
||||
}
|
||||
|
||||
SLAndroidSimpleBufferQueueItf bufferQueue{};
|
||||
if(likely(mDevice->Connected.load(std::memory_order_acquire)))
|
||||
if(mDevice->Connected.load(std::memory_order_acquire)) LIKELY
|
||||
{
|
||||
const SLresult result{VCALL(mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
|
||||
&bufferQueue)};
|
||||
PRINTERR(result, "recordObj->GetInterface");
|
||||
if(unlikely(SL_RESULT_SUCCESS != result))
|
||||
PrintErr(result, "recordObj->GetInterface");
|
||||
if(SL_RESULT_SUCCESS != result) UNLIKELY
|
||||
{
|
||||
mDevice->handleDisconnect("Failed to get capture buffer queue: 0x%08x", result);
|
||||
bufferQueue = nullptr;
|
||||
}
|
||||
}
|
||||
if(unlikely(!bufferQueue) || adv_count == 0)
|
||||
if(!bufferQueue || adv_count == 0)
|
||||
return;
|
||||
|
||||
/* For each buffer chunk that was fully read, queue another writable buffer
|
||||
* chunk to keep the OpenSL queue full. This is rather convulated, as a
|
||||
* chunk to keep the OpenSL queue full. This is rather convoluted, as a
|
||||
* result of the ring buffer holding more elements than are writable at a
|
||||
* given time. The end of the write vector increments when the read pointer
|
||||
* advances, which will "expose" a previously unwritable element. So for
|
||||
@@ -934,14 +876,14 @@ void OpenSLCapture::captureSamples(al::byte *buffer, uint samples)
|
||||
|
||||
SLresult result{SL_RESULT_SUCCESS};
|
||||
auto wdata = mRing->getWriteVector();
|
||||
if(likely(adv_count > wdata.second.len))
|
||||
if(adv_count > wdata.second.len) LIKELY
|
||||
{
|
||||
auto len1 = std::min(wdata.first.len, adv_count-wdata.second.len);
|
||||
auto buf1 = wdata.first.buf + chunk_size*(wdata.first.len-len1);
|
||||
for(size_t i{0u};i < len1 && SL_RESULT_SUCCESS == result;i++)
|
||||
{
|
||||
result = VCALL(bufferQueue,Enqueue)(buf1 + chunk_size*i, chunk_size);
|
||||
PRINTERR(result, "bufferQueue->Enqueue");
|
||||
PrintErr(result, "bufferQueue->Enqueue");
|
||||
}
|
||||
}
|
||||
if(wdata.second.len > 0)
|
||||
@@ -951,7 +893,7 @@ void OpenSLCapture::captureSamples(al::byte *buffer, uint samples)
|
||||
for(size_t i{0u};i < len2 && SL_RESULT_SUCCESS == result;i++)
|
||||
{
|
||||
result = VCALL(bufferQueue,Enqueue)(buf2 + chunk_size*i, chunk_size);
|
||||
PRINTERR(result, "bufferQueue->Enqueue");
|
||||
PrintErr(result, "bufferQueue->Enqueue");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -968,16 +910,14 @@ bool OSLBackendFactory::querySupport(BackendType type)
|
||||
|
||||
std::string OSLBackendFactory::probe(BackendType type)
|
||||
{
|
||||
std::string outnames;
|
||||
switch(type)
|
||||
{
|
||||
case BackendType::Playback:
|
||||
case BackendType::Capture:
|
||||
/* Includes null char. */
|
||||
outnames.append(opensl_device, sizeof(opensl_device));
|
||||
break;
|
||||
/* Include null char. */
|
||||
return std::string{GetDeviceName()} + '\0';
|
||||
}
|
||||
return outnames;
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
BackendPtr OSLBackendFactory::createBackend(DeviceBase *device, BackendType type)
|
||||
|
||||
Reference in New Issue
Block a user