aboutsummaryrefslogtreecommitdiffstats
path: root/al/state.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'al/state.cpp')
-rw-r--r--al/state.cpp277
1 files changed, 180 insertions, 97 deletions
diff --git a/al/state.cpp b/al/state.cpp
index 25a0efd1..86d81b13 100644
--- a/al/state.cpp
+++ b/al/state.cpp
@@ -24,26 +24,35 @@
#include <atomic>
#include <cmath>
-#include <cstdlib>
-#include <cstring>
#include <mutex>
+#include <stdexcept>
+#include <string>
#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alext.h"
-#include "alcontext.h"
-#include "alexcpt.h"
-#include "almalloc.h"
+#include "alc/alu.h"
+#include "alc/context.h"
+#include "alc/inprogext.h"
#include "alnumeric.h"
-#include "alspan.h"
-#include "alu.h"
+#include "aloptional.h"
#include "atomic.h"
-#include "event.h"
-#include "inprogext.h"
+#include "core/context.h"
+#include "core/except.h"
+#include "core/mixer/defs.h"
+#include "core/voice.h"
+#include "intrusive_ptr.h"
#include "opthelpers.h"
#include "strutils.h"
+#ifdef ALSOFT_EAX
+#include "alc/device.h"
+
+#include "eax/globals.h"
+#include "eax/x_ram.h"
+#endif // ALSOFT_EAX
+
namespace {
@@ -94,12 +103,41 @@ const ALchar *GetResamplerName(const Resampler rtype)
throw std::runtime_error{"Unexpected resampler index"};
}
+al::optional<DistanceModel> DistanceModelFromALenum(ALenum model)
+{
+ switch(model)
+ {
+ case AL_NONE: return DistanceModel::Disable;
+ case AL_INVERSE_DISTANCE: return DistanceModel::Inverse;
+ case AL_INVERSE_DISTANCE_CLAMPED: return DistanceModel::InverseClamped;
+ case AL_LINEAR_DISTANCE: return DistanceModel::Linear;
+ case AL_LINEAR_DISTANCE_CLAMPED: return DistanceModel::LinearClamped;
+ case AL_EXPONENT_DISTANCE: return DistanceModel::Exponent;
+ case AL_EXPONENT_DISTANCE_CLAMPED: return DistanceModel::ExponentClamped;
+ }
+ return al::nullopt;
+}
+ALenum ALenumFromDistanceModel(DistanceModel model)
+{
+ switch(model)
+ {
+ case DistanceModel::Disable: return AL_NONE;
+ case DistanceModel::Inverse: return AL_INVERSE_DISTANCE;
+ case DistanceModel::InverseClamped: return AL_INVERSE_DISTANCE_CLAMPED;
+ case DistanceModel::Linear: return AL_LINEAR_DISTANCE;
+ case DistanceModel::LinearClamped: return AL_LINEAR_DISTANCE_CLAMPED;
+ case DistanceModel::Exponent: return AL_EXPONENT_DISTANCE;
+ case DistanceModel::ExponentClamped: return AL_EXPONENT_DISTANCE_CLAMPED;
+ }
+ throw std::runtime_error{"Unexpected distance model "+std::to_string(static_cast<int>(model))};
+}
+
} // namespace
/* WARNING: Non-standard export! Not part of any extension, or exposed in the
* alcFunctions list.
*/
-extern "C" AL_API const ALchar* AL_APIENTRY alsoft_get_version(void)
+AL_API const ALchar* AL_APIENTRY alsoft_get_version(void)
START_API_FUNC
{
static const auto spoof = al::getenv("ALSOFT_SPOOF_VERSION");
@@ -109,25 +147,31 @@ START_API_FUNC
END_API_FUNC
#define DO_UPDATEPROPS() do { \
- if(!context->mDeferUpdates.load(std::memory_order_acquire)) \
+ if(!context->mDeferUpdates) \
UpdateContextProps(context.get()); \
else \
- context->mPropsClean.clear(std::memory_order_release); \
+ context->mPropsDirty = true; \
} while(0)
-AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
+AL_API void AL_APIENTRY alEnable(ALenum capability)
START_API_FUNC
{
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return;
+ if(!context) UNLIKELY return;
- std::lock_guard<std::mutex> _{context->mPropLock};
switch(capability)
{
case AL_SOURCE_DISTANCE_MODEL:
- context->mSourceDistanceModel = AL_TRUE;
- DO_UPDATEPROPS();
+ {
+ std::lock_guard<std::mutex> _{context->mPropLock};
+ context->mSourceDistanceModel = true;
+ DO_UPDATEPROPS();
+ }
+ break;
+
+ case AL_STOP_SOURCES_ON_DISCONNECT_SOFT:
+ context->setError(AL_INVALID_OPERATION, "Re-enabling AL_STOP_SOURCES_ON_DISCONNECT_SOFT not yet supported");
break;
default:
@@ -136,18 +180,24 @@ START_API_FUNC
}
END_API_FUNC
-AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
+AL_API void AL_APIENTRY alDisable(ALenum capability)
START_API_FUNC
{
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return;
+ if(!context) UNLIKELY return;
- std::lock_guard<std::mutex> _{context->mPropLock};
switch(capability)
{
case AL_SOURCE_DISTANCE_MODEL:
- context->mSourceDistanceModel = AL_FALSE;
- DO_UPDATEPROPS();
+ {
+ std::lock_guard<std::mutex> _{context->mPropLock};
+ context->mSourceDistanceModel = false;
+ DO_UPDATEPROPS();
+ }
+ break;
+
+ case AL_STOP_SOURCES_ON_DISCONNECT_SOFT:
+ context->mStopVoicesOnDisconnect = false;
break;
default:
@@ -160,14 +210,18 @@ AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
START_API_FUNC
{
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return AL_FALSE;
+ if(!context) UNLIKELY return AL_FALSE;
std::lock_guard<std::mutex> _{context->mPropLock};
ALboolean value{AL_FALSE};
switch(capability)
{
case AL_SOURCE_DISTANCE_MODEL:
- value = context->mSourceDistanceModel;
+ value = context->mSourceDistanceModel ? AL_TRUE : AL_FALSE;
+ break;
+
+ case AL_STOP_SOURCES_ON_DISCONNECT_SOFT:
+ value = context->mStopVoicesOnDisconnect ? AL_TRUE : AL_FALSE;
break;
default:
@@ -182,7 +236,7 @@ AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
START_API_FUNC
{
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return AL_FALSE;
+ if(!context) UNLIKELY return AL_FALSE;
std::lock_guard<std::mutex> _{context->mPropLock};
ALboolean value{AL_FALSE};
@@ -209,12 +263,12 @@ START_API_FUNC
break;
case AL_DEFERRED_UPDATES_SOFT:
- if(context->mDeferUpdates.load(std::memory_order_acquire))
+ if(context->mDeferUpdates)
value = AL_TRUE;
break;
case AL_GAIN_LIMIT_SOFT:
- if(GAIN_MIX_MAX/context->mGainBoost != 0.0f)
+ if(GainMixMax/context->mGainBoost != 0.0f)
value = AL_TRUE;
break;
@@ -239,7 +293,7 @@ AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
START_API_FUNC
{
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return 0.0;
+ if(!context) UNLIKELY return 0.0;
std::lock_guard<std::mutex> _{context->mPropLock};
ALdouble value{0.0};
@@ -254,7 +308,7 @@ START_API_FUNC
break;
case AL_DISTANCE_MODEL:
- value = static_cast<ALdouble>(context->mDistanceModel);
+ value = static_cast<ALdouble>(ALenumFromDistanceModel(context->mDistanceModel));
break;
case AL_SPEED_OF_SOUND:
@@ -262,12 +316,12 @@ START_API_FUNC
break;
case AL_DEFERRED_UPDATES_SOFT:
- if(context->mDeferUpdates.load(std::memory_order_acquire))
+ if(context->mDeferUpdates)
value = static_cast<ALdouble>(AL_TRUE);
break;
case AL_GAIN_LIMIT_SOFT:
- value = ALdouble{GAIN_MIX_MAX}/context->mGainBoost;
+ value = ALdouble{GainMixMax}/context->mGainBoost;
break;
case AL_NUM_RESAMPLERS_SOFT:
@@ -290,7 +344,7 @@ AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
START_API_FUNC
{
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return 0.0f;
+ if(!context) UNLIKELY return 0.0f;
std::lock_guard<std::mutex> _{context->mPropLock};
ALfloat value{0.0f};
@@ -305,7 +359,7 @@ START_API_FUNC
break;
case AL_DISTANCE_MODEL:
- value = static_cast<ALfloat>(context->mDistanceModel);
+ value = static_cast<ALfloat>(ALenumFromDistanceModel(context->mDistanceModel));
break;
case AL_SPEED_OF_SOUND:
@@ -313,12 +367,12 @@ START_API_FUNC
break;
case AL_DEFERRED_UPDATES_SOFT:
- if(context->mDeferUpdates.load(std::memory_order_acquire))
+ if(context->mDeferUpdates)
value = static_cast<ALfloat>(AL_TRUE);
break;
case AL_GAIN_LIMIT_SOFT:
- value = GAIN_MIX_MAX/context->mGainBoost;
+ value = GainMixMax/context->mGainBoost;
break;
case AL_NUM_RESAMPLERS_SOFT:
@@ -341,7 +395,7 @@ AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
START_API_FUNC
{
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return 0;
+ if(!context) UNLIKELY return 0;
std::lock_guard<std::mutex> _{context->mPropLock};
ALint value{0};
@@ -356,7 +410,7 @@ START_API_FUNC
break;
case AL_DISTANCE_MODEL:
- value = static_cast<ALint>(context->mDistanceModel);
+ value = ALenumFromDistanceModel(context->mDistanceModel);
break;
case AL_SPEED_OF_SOUND:
@@ -364,12 +418,12 @@ START_API_FUNC
break;
case AL_DEFERRED_UPDATES_SOFT:
- if(context->mDeferUpdates.load(std::memory_order_acquire))
+ if(context->mDeferUpdates)
value = AL_TRUE;
break;
case AL_GAIN_LIMIT_SOFT:
- value = static_cast<ALint>(GAIN_MIX_MAX/context->mGainBoost);
+ value = static_cast<ALint>(GainMixMax/context->mGainBoost);
break;
case AL_NUM_RESAMPLERS_SOFT:
@@ -380,6 +434,41 @@ START_API_FUNC
value = static_cast<int>(ResamplerDefault);
break;
+#ifdef ALSOFT_EAX
+
+#define EAX_ERROR "[alGetInteger] EAX not enabled."
+
+ case AL_EAX_RAM_SIZE:
+ if (eax_g_is_enabled)
+ {
+ value = eax_x_ram_max_size;
+ }
+ else
+ {
+ context->setError(AL_INVALID_VALUE, EAX_ERROR);
+ }
+
+ break;
+
+ case AL_EAX_RAM_FREE:
+ if (eax_g_is_enabled)
+ {
+ auto device = context->mALDevice.get();
+ std::lock_guard<std::mutex> device_lock{device->BufferLock};
+
+ value = static_cast<ALint>(device->eax_x_ram_free_size);
+ }
+ else
+ {
+ context->setError(AL_INVALID_VALUE, EAX_ERROR);
+ }
+
+ break;
+
+#undef EAX_ERROR
+
+#endif // ALSOFT_EAX
+
default:
context->setError(AL_INVALID_VALUE, "Invalid integer property 0x%04x", pname);
}
@@ -388,11 +477,11 @@ START_API_FUNC
}
END_API_FUNC
-extern "C" AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
+AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
START_API_FUNC
{
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return 0_i64;
+ if(!context) UNLIKELY return 0_i64;
std::lock_guard<std::mutex> _{context->mPropLock};
ALint64SOFT value{0};
@@ -407,7 +496,7 @@ START_API_FUNC
break;
case AL_DISTANCE_MODEL:
- value = static_cast<ALint64SOFT>(context->mDistanceModel);
+ value = ALenumFromDistanceModel(context->mDistanceModel);
break;
case AL_SPEED_OF_SOUND:
@@ -415,12 +504,12 @@ START_API_FUNC
break;
case AL_DEFERRED_UPDATES_SOFT:
- if(context->mDeferUpdates.load(std::memory_order_acquire))
+ if(context->mDeferUpdates)
value = AL_TRUE;
break;
case AL_GAIN_LIMIT_SOFT:
- value = static_cast<ALint64SOFT>(GAIN_MIX_MAX/context->mGainBoost);
+ value = static_cast<ALint64SOFT>(GainMixMax/context->mGainBoost);
break;
case AL_NUM_RESAMPLERS_SOFT:
@@ -439,11 +528,11 @@ START_API_FUNC
}
END_API_FUNC
-AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname)
+AL_API ALvoid* AL_APIENTRY alGetPointerSOFT(ALenum pname)
START_API_FUNC
{
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return nullptr;
+ if(!context) UNLIKELY return nullptr;
std::lock_guard<std::mutex> _{context->mPropLock};
void *value{nullptr};
@@ -465,7 +554,7 @@ START_API_FUNC
}
END_API_FUNC
-AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values)
+AL_API void AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values)
START_API_FUNC
{
if(values)
@@ -486,7 +575,7 @@ START_API_FUNC
}
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return;
+ if(!context) UNLIKELY return;
if(!values)
context->setError(AL_INVALID_VALUE, "NULL pointer");
@@ -498,7 +587,7 @@ START_API_FUNC
}
END_API_FUNC
-AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
+AL_API void AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
START_API_FUNC
{
if(values)
@@ -519,7 +608,7 @@ START_API_FUNC
}
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return;
+ if(!context) UNLIKELY return;
if(!values)
context->setError(AL_INVALID_VALUE, "NULL pointer");
@@ -531,7 +620,7 @@ START_API_FUNC
}
END_API_FUNC
-AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
+AL_API void AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
START_API_FUNC
{
if(values)
@@ -552,7 +641,7 @@ START_API_FUNC
}
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return;
+ if(!context) UNLIKELY return;
if(!values)
context->setError(AL_INVALID_VALUE, "NULL pointer");
@@ -564,7 +653,7 @@ START_API_FUNC
}
END_API_FUNC
-AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
+AL_API void AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
START_API_FUNC
{
if(values)
@@ -585,7 +674,7 @@ START_API_FUNC
}
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return;
+ if(!context) UNLIKELY return;
if(!values)
context->setError(AL_INVALID_VALUE, "NULL pointer");
@@ -597,7 +686,7 @@ START_API_FUNC
}
END_API_FUNC
-extern "C" AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
+AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
START_API_FUNC
{
if(values)
@@ -618,7 +707,7 @@ START_API_FUNC
}
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return;
+ if(!context) UNLIKELY return;
if(!values)
context->setError(AL_INVALID_VALUE, "NULL pointer");
@@ -630,7 +719,7 @@ START_API_FUNC
}
END_API_FUNC
-AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values)
+AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, ALvoid **values)
START_API_FUNC
{
if(values)
@@ -645,7 +734,7 @@ START_API_FUNC
}
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return;
+ if(!context) UNLIKELY return;
if(!values)
context->setError(AL_INVALID_VALUE, "NULL pointer");
@@ -661,7 +750,7 @@ AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
START_API_FUNC
{
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return nullptr;
+ if(!context) UNLIKELY return nullptr;
const ALchar *value{nullptr};
switch(pname)
@@ -713,11 +802,11 @@ START_API_FUNC
}
END_API_FUNC
-AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
+AL_API void AL_APIENTRY alDopplerFactor(ALfloat value)
START_API_FUNC
{
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return;
+ if(!context) UNLIKELY return;
if(!(value >= 0.0f && std::isfinite(value)))
context->setError(AL_INVALID_VALUE, "Doppler factor %f out of range", value);
@@ -730,25 +819,11 @@ START_API_FUNC
}
END_API_FUNC
-AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
+AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value)
START_API_FUNC
{
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return;
-
- if((context->mEnabledEvts.load(std::memory_order_relaxed)&EventType_Deprecated))
- {
- std::lock_guard<std::mutex> _{context->mEventCbLock};
- ALbitfieldSOFT enabledevts{context->mEnabledEvts.load(std::memory_order_relaxed)};
- if((enabledevts&EventType_Deprecated) && context->mEventCb)
- {
- static const char msg[] =
- "alDopplerVelocity is deprecated in AL1.1, use alSpeedOfSound";
- const ALsizei msglen{sizeof(msg)-1};
- (*context->mEventCb)(AL_EVENT_TYPE_DEPRECATED_SOFT, 0, 0, msglen, msg,
- context->mEventParam);
- }
- }
+ if(!context) UNLIKELY return;
if(!(value >= 0.0f && std::isfinite(value)))
context->setError(AL_INVALID_VALUE, "Doppler velocity %f out of range", value);
@@ -761,11 +836,11 @@ START_API_FUNC
}
END_API_FUNC
-AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value)
+AL_API void AL_APIENTRY alSpeedOfSound(ALfloat value)
START_API_FUNC
{
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return;
+ if(!context) UNLIKELY return;
if(!(value > 0.0f && std::isfinite(value)))
context->setError(AL_INVALID_VALUE, "Speed of sound %f out of range", value);
@@ -778,44 +853,43 @@ START_API_FUNC
}
END_API_FUNC
-AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
+AL_API void AL_APIENTRY alDistanceModel(ALenum value)
START_API_FUNC
{
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return;
+ if(!context) UNLIKELY return;
- if(!(value == AL_INVERSE_DISTANCE || value == AL_INVERSE_DISTANCE_CLAMPED ||
- value == AL_LINEAR_DISTANCE || value == AL_LINEAR_DISTANCE_CLAMPED ||
- value == AL_EXPONENT_DISTANCE || value == AL_EXPONENT_DISTANCE_CLAMPED ||
- value == AL_NONE))
- context->setError(AL_INVALID_VALUE, "Distance model 0x%04x out of range", value);
- else
+ if(auto model = DistanceModelFromALenum(value))
{
std::lock_guard<std::mutex> _{context->mPropLock};
- context->mDistanceModel = static_cast<DistanceModel>(value);
+ context->mDistanceModel = *model;
if(!context->mSourceDistanceModel)
DO_UPDATEPROPS();
}
+ else
+ context->setError(AL_INVALID_VALUE, "Distance model 0x%04x out of range", value);
}
END_API_FUNC
-AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void)
+AL_API void AL_APIENTRY alDeferUpdatesSOFT(void)
START_API_FUNC
{
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return;
+ if(!context) UNLIKELY return;
+ std::lock_guard<std::mutex> _{context->mPropLock};
context->deferUpdates();
}
END_API_FUNC
-AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void)
+AL_API void AL_APIENTRY alProcessUpdatesSOFT(void)
START_API_FUNC
{
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return;
+ if(!context) UNLIKELY return;
+ std::lock_guard<std::mutex> _{context->mPropLock};
context->processUpdates();
}
END_API_FUNC
@@ -825,7 +899,7 @@ AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index)
START_API_FUNC
{
ContextRef context{GetContextRef()};
- if UNLIKELY(!context) return nullptr;
+ if(!context) UNLIKELY return nullptr;
const ALchar *value{nullptr};
switch(pname)
@@ -848,12 +922,12 @@ END_API_FUNC
void UpdateContextProps(ALCcontext *context)
{
/* Get an unused proprty container, or allocate a new one as needed. */
- ALcontextProps *props{context->mFreeContextProps.load(std::memory_order_acquire)};
+ ContextProps *props{context->mFreeContextProps.load(std::memory_order_acquire)};
if(!props)
- props = new ALcontextProps{};
+ props = new ContextProps{};
else
{
- ALcontextProps *next;
+ ContextProps *next;
do {
next = props->next.load(std::memory_order_relaxed);
} while(context->mFreeContextProps.compare_exchange_weak(props, next,
@@ -861,6 +935,15 @@ void UpdateContextProps(ALCcontext *context)
}
/* Copy in current property values. */
+ ALlistener &listener = context->mListener;
+ props->Position = listener.Position;
+ props->Velocity = listener.Velocity;
+ props->OrientAt = listener.OrientAt;
+ props->OrientUp = listener.OrientUp;
+ props->Gain = listener.Gain;
+ props->MetersPerUnit = listener.mMetersPerUnit;
+
+ props->AirAbsorptionGainHF = context->mAirAbsorptionGainHF;
props->DopplerFactor = context->mDopplerFactor;
props->DopplerVelocity = context->mDopplerVelocity;
props->SpeedOfSound = context->mSpeedOfSound;
@@ -869,7 +952,7 @@ void UpdateContextProps(ALCcontext *context)
props->mDistanceModel = context->mDistanceModel;
/* Set the new container for updating internal parameters. */
- props = context->mUpdate.exchange(props, std::memory_order_acq_rel);
+ props = context->mParams.ContextUpdate.exchange(props, std::memory_order_acq_rel);
if(props)
{
/* If there was an unused update container, put it back in the