aboutsummaryrefslogtreecommitdiffstats
path: root/al/source.cpp
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-11-28 12:51:46 +0100
committerSven Gothel <[email protected]>2023-11-28 12:51:46 +0100
commit1aaf4f070011490bcece50394b9b32dfa593fd9e (patch)
tree17d68284e401a35eea3d3a574d986d446a60763a /al/source.cpp
parent6e7cee4fa9a8af03f28ca26cd89f8357390dfc90 (diff)
parent571b546f35eead77ce109f8d4dd6c3de3199d573 (diff)
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'al/source.cpp')
-rw-r--r--al/source.cpp2631
1 files changed, 1117 insertions, 1514 deletions
diff --git a/al/source.cpp b/al/source.cpp
index cba33862..fe5bba40 100644
--- a/al/source.cpp
+++ b/al/source.cpp
@@ -27,20 +27,22 @@
#include <atomic>
#include <cassert>
#include <chrono>
+#include <cinttypes>
#include <climits>
#include <cmath>
#include <cstdint>
#include <functional>
-#include <inttypes.h>
#include <iterator>
#include <limits>
#include <memory>
#include <mutex>
#include <new>
#include <numeric>
+#include <optional>
#include <stdexcept>
#include <thread>
#include <utility>
+#include <vector>
#include "AL/al.h"
#include "AL/alc.h"
@@ -55,7 +57,6 @@
#include "alc/inprogext.h"
#include "almalloc.h"
#include "alnumeric.h"
-#include "aloptional.h"
#include "alspan.h"
#include "atomic.h"
#include "auxeffectslot.h"
@@ -67,22 +68,21 @@
#include "core/filters/splitter.h"
#include "core/logging.h"
#include "core/voice_change.h"
+#include "direct_defs.h"
#include "event.h"
#include "filter.h"
#include "opthelpers.h"
#include "ringbuffer.h"
-#include "threads.h"
#ifdef ALSOFT_EAX
#include <cassert>
#endif // ALSOFT_EAX
-bool sBufferSubDataCompat{false};
-
namespace {
using namespace std::placeholders;
using std::chrono::nanoseconds;
+using seconds_d = std::chrono::duration<double>;
Voice *GetSourceVoice(ALsource *source, ALCcontext *context)
{
@@ -95,7 +95,7 @@ Voice *GetSourceVoice(ALsource *source, ALCcontext *context)
if(voice->mSourceID.load(std::memory_order_acquire) == sid)
return voice;
}
- source->VoiceIdx = INVALID_VOICE_IDX;
+ source->VoiceIdx = InvalidVoiceIndex;
return nullptr;
}
@@ -281,7 +281,8 @@ double GetSourceSecOffset(ALsource *Source, ALCcontext *context, nanoseconds *cl
* (Bytes, Samples or Seconds). The offset is relative to the start of the
* queue (not the start of the current buffer).
*/
-double GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context)
+template<typename T>
+NOINLINE T GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context)
{
ALCdevice *device{context->mALDevice.get()};
const VoiceBufferItem *Current{};
@@ -304,7 +305,7 @@ double GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context)
} while(refcount != device->MixCount.load(std::memory_order_relaxed));
if(!voice)
- return 0.0;
+ return T{0};
const ALbuffer *BufferFmt{nullptr};
auto BufferList = Source->mQueue.cbegin();
@@ -321,24 +322,48 @@ double GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context)
}
ASSUME(BufferFmt != nullptr);
- double offset{};
+ T offset{};
switch(name)
{
case AL_SEC_OFFSET:
- offset = static_cast<double>(readPos) + readPosFrac/double{MixerFracOne};
- offset /= BufferFmt->mSampleRate;
+ if constexpr(std::is_floating_point_v<T>)
+ {
+ offset = static_cast<T>(readPos) + static_cast<T>(readPosFrac)/T{MixerFracOne};
+ offset /= static_cast<T>(BufferFmt->mSampleRate);
+ }
+ else
+ {
+ readPos /= BufferFmt->mSampleRate;
+ offset = static_cast<T>(clampi64(readPos, std::numeric_limits<T>::min(),
+ std::numeric_limits<T>::max()));
+ }
break;
case AL_SAMPLE_OFFSET:
- offset = static_cast<double>(readPos) + readPosFrac/double{MixerFracOne};
+ if constexpr(std::is_floating_point_v<T>)
+ offset = static_cast<T>(readPos) + static_cast<T>(readPosFrac)/T{MixerFracOne};
+ else
+ offset = static_cast<T>(clampi64(readPos, std::numeric_limits<T>::min(),
+ std::numeric_limits<T>::max()));
break;
case AL_BYTE_OFFSET:
const ALuint BlockSamples{BufferFmt->mBlockAlign};
const ALuint BlockSize{BufferFmt->blockSizeFromFmt()};
-
/* Round down to the block boundary. */
- offset = static_cast<double>(readPos / BlockSamples) * BlockSize;
+ readPos = readPos / BlockSamples * BlockSize;
+
+ if constexpr(std::is_floating_point_v<T>)
+ offset = static_cast<T>(readPos);
+ else
+ {
+ if(readPos > std::numeric_limits<T>::max())
+ offset = RoundDown(std::numeric_limits<T>::max(), static_cast<T>(BlockSize));
+ else if(readPos < std::numeric_limits<T>::min())
+ offset = RoundUp(std::numeric_limits<T>::min(), static_cast<T>(BlockSize));
+ else
+ offset = static_cast<T>(readPos);
+ }
break;
}
return offset;
@@ -349,7 +374,8 @@ double GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context)
* Gets the length of the given Source's buffer queue, in the appropriate
* format (Bytes, Samples or Seconds).
*/
-double GetSourceLength(const ALsource *source, ALenum name)
+template<typename T>
+NOINLINE T GetSourceLength(const ALsource *source, ALenum name)
{
uint64_t length{0};
const ALbuffer *BufferFmt{nullptr};
@@ -360,25 +386,40 @@ double GetSourceLength(const ALsource *source, ALenum name)
length += listitem.mSampleLen;
}
if(length == 0)
- return 0.0;
+ return T{0};
ASSUME(BufferFmt != nullptr);
switch(name)
{
case AL_SEC_LENGTH_SOFT:
- return static_cast<double>(length) / BufferFmt->mSampleRate;
+ if constexpr(std::is_floating_point_v<T>)
+ return static_cast<T>(length) / static_cast<T>(BufferFmt->mSampleRate);
+ else
+ return static_cast<T>(minu64(length/BufferFmt->mSampleRate,
+ std::numeric_limits<T>::max()));
case AL_SAMPLE_LENGTH_SOFT:
- return static_cast<double>(length);
+ if constexpr(std::is_floating_point_v<T>)
+ return static_cast<T>(length);
+ else
+ return static_cast<T>(minu64(length, std::numeric_limits<T>::max()));
case AL_BYTE_LENGTH_SOFT:
const ALuint BlockSamples{BufferFmt->mBlockAlign};
const ALuint BlockSize{BufferFmt->blockSizeFromFmt()};
-
/* Round down to the block boundary. */
- return static_cast<double>(length / BlockSamples) * BlockSize;
+ length = length / BlockSamples * BlockSize;
+
+ if constexpr(std::is_floating_point_v<T>)
+ return static_cast<T>(length);
+ else
+ {
+ if(length > std::numeric_limits<T>::max())
+ return RoundDown(std::numeric_limits<T>::max(), static_cast<T>(BlockSize));
+ return static_cast<T>(length);
+ }
}
- return 0.0;
+ return T{0};
}
@@ -392,11 +433,11 @@ struct VoicePos {
* GetSampleOffset
*
* Retrieves the voice position, fixed-point fraction, and bufferlist item
- * using the givem offset type and offset. If the offset is out of range,
+ * using the given offset type and offset. If the offset is out of range,
* returns an empty optional.
*/
-al::optional<VoicePos> GetSampleOffset(al::deque<ALbufferQueueItem> &BufferList, ALenum OffsetType,
- double Offset)
+std::optional<VoicePos> GetSampleOffset(std::deque<ALbufferQueueItem> &BufferList,
+ ALenum OffsetType, double Offset)
{
/* Find the first valid Buffer in the Queue */
const ALbuffer *BufferFmt{nullptr};
@@ -406,7 +447,7 @@ al::optional<VoicePos> GetSampleOffset(al::deque<ALbufferQueueItem> &BufferList,
if(BufferFmt) break;
}
if(!BufferFmt) UNLIKELY
- return al::nullopt;
+ return std::nullopt;
/* Get sample frame offset */
int64_t offset{};
@@ -452,12 +493,12 @@ al::optional<VoicePos> GetSampleOffset(al::deque<ALbufferQueueItem> &BufferList,
if(offset < 0)
{
if(offset < std::numeric_limits<int>::min())
- return al::nullopt;
+ return std::nullopt;
return VoicePos{static_cast<int>(offset), frac, &BufferList.front()};
}
if(BufferFmt->mCallback)
- return al::nullopt;
+ return std::nullopt;
int64_t totalBufferLen{0};
for(auto &item : BufferList)
@@ -473,7 +514,7 @@ al::optional<VoicePos> GetSampleOffset(al::deque<ALbufferQueueItem> &BufferList,
}
/* Offset is out of range of the queue */
- return al::nullopt;
+ return std::nullopt;
}
@@ -676,8 +717,7 @@ inline ALenum GetSourceState(ALsource *source, Voice *voice)
bool EnsureSources(ALCcontext *context, size_t needed)
{
- size_t count{std::accumulate(context->mSourceList.cbegin(), context->mSourceList.cend(),
- size_t{0},
+ size_t count{std::accumulate(context->mSourceList.cbegin(), context->mSourceList.cend(), 0_uz,
[](size_t cur, const SourceSubList &sublist) noexcept -> size_t
{ return cur + static_cast<ALuint>(al::popcount(sublist.FreeMask)); })};
@@ -722,6 +762,8 @@ ALsource *AllocSource(ALCcontext *context)
void FreeSource(ALCcontext *context, ALsource *source)
{
+ context->mSourceNames.erase(source->id);
+
const ALuint id{source->id - 1};
const size_t lidx{id >> 6};
const ALuint slidx{id & 0x3f};
@@ -738,7 +780,7 @@ void FreeSource(ALCcontext *context, ALsource *source)
SendVoiceChanges(context, vchg);
}
- al::destroy_at(source);
+ std::destroy_at(source);
context->mSourceList[lidx].FreeMask |= 1_u64 << slidx;
context->mNumSources--;
@@ -758,56 +800,55 @@ inline ALsource *LookupSource(ALCcontext *context, ALuint id) noexcept
return sublist.Sources + slidx;
}
-inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id) noexcept
+auto LookupBuffer = [](ALCdevice *device, auto id) noexcept -> ALbuffer*
{
- const size_t lidx{(id-1) >> 6};
- const ALuint slidx{(id-1) & 0x3f};
+ const auto lidx{(id-1) >> 6};
+ const auto slidx{(id-1) & 0x3f};
if(lidx >= device->BufferList.size()) UNLIKELY
return nullptr;
- BufferSubList &sublist = device->BufferList[lidx];
+ BufferSubList &sublist = device->BufferList[static_cast<size_t>(lidx)];
if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY
return nullptr;
- return sublist.Buffers + slidx;
-}
+ return sublist.Buffers + static_cast<size_t>(slidx);
+};
-inline ALfilter *LookupFilter(ALCdevice *device, ALuint id) noexcept
+auto LookupFilter = [](ALCdevice *device, auto id) noexcept -> ALfilter*
{
- const size_t lidx{(id-1) >> 6};
- const ALuint slidx{(id-1) & 0x3f};
+ const auto lidx{(id-1) >> 6};
+ const auto slidx{(id-1) & 0x3f};
if(lidx >= device->FilterList.size()) UNLIKELY
return nullptr;
- FilterSubList &sublist = device->FilterList[lidx];
+ FilterSubList &sublist = device->FilterList[static_cast<size_t>(lidx)];
if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY
return nullptr;
- return sublist.Filters + slidx;
-}
+ return sublist.Filters + static_cast<size_t>(slidx);
+};
-inline ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id) noexcept
+auto LookupEffectSlot = [](ALCcontext *context, auto id) noexcept -> ALeffectslot*
{
- const size_t lidx{(id-1) >> 6};
- const ALuint slidx{(id-1) & 0x3f};
+ const auto lidx{(id-1) >> 6};
+ const auto slidx{(id-1) & 0x3f};
if(lidx >= context->mEffectSlotList.size()) UNLIKELY
return nullptr;
- EffectSlotSubList &sublist{context->mEffectSlotList[lidx]};
+ EffectSlotSubList &sublist{context->mEffectSlotList[static_cast<size_t>(lidx)]};
if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY
return nullptr;
- return sublist.EffectSlots + slidx;
-}
+ return sublist.EffectSlots + static_cast<size_t>(slidx);
+};
-al::optional<SourceStereo> StereoModeFromEnum(ALenum mode)
+auto StereoModeFromEnum = [](auto mode) noexcept -> std::optional<SourceStereo>
{
switch(mode)
{
case AL_NORMAL_SOFT: return SourceStereo::Normal;
case AL_SUPER_STEREO_SOFT: return SourceStereo::Enhanced;
}
- WARN("Unsupported stereo mode: 0x%04x\n", mode);
- return al::nullopt;
-}
+ return std::nullopt;
+};
ALenum EnumFromStereoMode(SourceStereo mode)
{
switch(mode)
@@ -818,7 +859,7 @@ ALenum EnumFromStereoMode(SourceStereo mode)
throw std::runtime_error{"Invalid SourceStereo: "+std::to_string(int(mode))};
}
-al::optional<SpatializeMode> SpatializeModeFromEnum(ALenum mode)
+auto SpatializeModeFromEnum = [](auto mode) noexcept -> std::optional<SpatializeMode>
{
switch(mode)
{
@@ -826,9 +867,8 @@ al::optional<SpatializeMode> SpatializeModeFromEnum(ALenum mode)
case AL_TRUE: return SpatializeMode::On;
case AL_AUTO_SOFT: return SpatializeMode::Auto;
}
- WARN("Unsupported spatialize mode: 0x%04x\n", mode);
- return al::nullopt;
-}
+ return std::nullopt;
+};
ALenum EnumFromSpatializeMode(SpatializeMode mode)
{
switch(mode)
@@ -840,7 +880,7 @@ ALenum EnumFromSpatializeMode(SpatializeMode mode)
throw std::runtime_error{"Invalid SpatializeMode: "+std::to_string(int(mode))};
}
-al::optional<DirectMode> DirectModeFromEnum(ALenum mode)
+auto DirectModeFromEnum = [](auto mode) noexcept -> std::optional<DirectMode>
{
switch(mode)
{
@@ -848,9 +888,8 @@ al::optional<DirectMode> DirectModeFromEnum(ALenum mode)
case AL_DROP_UNMATCHED_SOFT: return DirectMode::DropMismatch;
case AL_REMIX_UNMATCHED_SOFT: return DirectMode::RemixMismatch;
}
- WARN("Unsupported direct mode: 0x%04x\n", mode);
- return al::nullopt;
-}
+ return std::nullopt;
+};
ALenum EnumFromDirectMode(DirectMode mode)
{
switch(mode)
@@ -862,7 +901,7 @@ ALenum EnumFromDirectMode(DirectMode mode)
throw std::runtime_error{"Invalid DirectMode: "+std::to_string(int(mode))};
}
-al::optional<DistanceModel> DistanceModelFromALenum(ALenum model)
+auto DistanceModelFromALenum = [](auto model) noexcept -> std::optional<DistanceModel>
{
switch(model)
{
@@ -874,8 +913,8 @@ al::optional<DistanceModel> DistanceModelFromALenum(ALenum model)
case AL_EXPONENT_DISTANCE: return DistanceModel::Exponent;
case AL_EXPONENT_DISTANCE_CLAMPED: return DistanceModel::ExponentClamped;
}
- return al::nullopt;
-}
+ return std::nullopt;
+};
ALenum ALenumFromDistanceModel(DistanceModel model)
{
switch(model)
@@ -973,8 +1012,6 @@ enum SourceProp : ALenum {
};
-constexpr size_t MaxValues{6u};
-
constexpr ALuint IntValsByProp(ALenum prop)
{
switch(static_cast<SourceProp>(prop))
@@ -1276,10 +1313,6 @@ constexpr ALuint DoubleValsByProp(ALenum prop)
}
-void SetSourcefv(ALsource *const Source, ALCcontext *const Context, const SourceProp prop, const al::span<const float> values);
-void SetSourceiv(ALsource *const Source, ALCcontext *const Context, const SourceProp prop, const al::span<const int> values);
-void SetSourcei64v(ALsource *const Source, ALCcontext *const Context, const SourceProp prop, const al::span<const int64_t> values);
-
struct check_exception : std::exception {
};
struct check_size_exception final : check_exception {
@@ -1327,10 +1360,39 @@ inline void CommitAndUpdateSourceProps(ALsource *source, ALCcontext *context)
#endif
+template<typename T>
+struct PropType { };
+template<>
+struct PropType<ALint> { static const char *Name() { return "integer"; } };
+template<>
+struct PropType<ALint64SOFT> { static const char *Name() { return "int64"; } };
+template<>
+struct PropType<ALfloat> { static const char *Name() { return "float"; } };
+template<>
+struct PropType<ALdouble> { static const char *Name() { return "double"; } };
+
+template<typename T>
+struct HexPrinter {
+ char mStr[sizeof(T)*2 + 3]{};
+ HexPrinter(T value)
+ {
+ using ST = std::make_signed_t<std::remove_cv_t<T>>;
+ if constexpr(std::is_same_v<ST,int>)
+ std::snprintf(mStr, std::size(mStr), "0x%x", value);
+ else if constexpr(std::is_same_v<ST,long>)
+ std::snprintf(mStr, std::size(mStr), "0x%lx", value);
+ else if constexpr(std::is_same_v<ST,long long>)
+ std::snprintf(mStr, std::size(mStr), "0x%llx", value);
+ }
+
+ const char *c_str() const noexcept { return mStr; }
+};
+
+
/**
- * Returns a pair of lambdas to check the following setters and getters.
+ * Returns a pair of lambdas to check the following setter.
*
- * The first lambda checks the size of the span is valid for its given size,
+ * The first lambda checks the size of the span is valid for the required size,
* setting the proper context error and throwing a check_size_exception if it
* fails.
*
@@ -1357,19 +1419,33 @@ auto GetCheckers(ALCcontext *const Context, const SourceProp prop, const al::spa
);
}
-void SetSourcefv(ALsource *const Source, ALCcontext *const Context, const SourceProp prop,
- const al::span<const float> values)
-try {
- /* Structured bindings would be nice (C++17). */
- auto Checkers = GetCheckers(Context, prop, values);
- auto &CheckSize = Checkers.first;
- auto &CheckValue = Checkers.second;
- int ival;
+template<typename T>
+NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, const SourceProp prop,
+ const al::span<const T> values) try
+{
+ auto&& [CheckSize, CheckValue] = GetCheckers(Context, prop, values);
+ ALCdevice *device{Context->mALDevice.get()};
switch(prop)
{
+ case AL_SOURCE_STATE:
+ case AL_SOURCE_TYPE:
+ case AL_BUFFERS_QUEUED:
+ case AL_BUFFERS_PROCESSED:
+ if constexpr(std::is_integral_v<T>)
+ {
+ /* Query only */
+ return Context->setError(AL_INVALID_OPERATION,
+ "Setting read-only source property 0x%04x", prop);
+ }
+ break;
+
+ case AL_BYTE_LENGTH_SOFT:
+ case AL_SAMPLE_LENGTH_SOFT:
case AL_SEC_LENGTH_SOFT:
+ case AL_SAMPLE_OFFSET_LATENCY_SOFT:
case AL_SEC_OFFSET_LATENCY_SOFT:
+ case AL_SAMPLE_OFFSET_CLOCK_SOFT:
case AL_SEC_OFFSET_CLOCK_SOFT:
/* Query only */
return Context->setError(AL_INVALID_OPERATION,
@@ -1377,712 +1453,540 @@ try {
case AL_PITCH:
CheckSize(1);
- CheckValue(values[0] >= 0.0f);
+ CheckValue(values[0] >= T{0});
- Source->Pitch = values[0];
+ Source->Pitch = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_CONE_INNER_ANGLE:
CheckSize(1);
- CheckValue(values[0] >= 0.0f && values[0] <= 360.0f);
+ CheckValue(values[0] >= T{0} && values[0] <= T{360});
- Source->InnerAngle = values[0];
+ Source->InnerAngle = static_cast<float>(values[0]);
return CommitAndUpdateSourceProps(Source, Context);
case AL_CONE_OUTER_ANGLE:
CheckSize(1);
- CheckValue(values[0] >= 0.0f && values[0] <= 360.0f);
+ CheckValue(values[0] >= T{0} && values[0] <= T{360});
- Source->OuterAngle = values[0];
+ Source->OuterAngle = static_cast<float>(values[0]);
return CommitAndUpdateSourceProps(Source, Context);
case AL_GAIN:
CheckSize(1);
- CheckValue(values[0] >= 0.0f);
+ CheckValue(values[0] >= T{0});
- Source->Gain = values[0];
+ Source->Gain = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_MAX_DISTANCE:
CheckSize(1);
- CheckValue(values[0] >= 0.0f);
+ CheckValue(values[0] >= T{0});
- Source->MaxDistance = values[0];
+ Source->MaxDistance = static_cast<float>(values[0]);
return CommitAndUpdateSourceProps(Source, Context);
case AL_ROLLOFF_FACTOR:
CheckSize(1);
- CheckValue(values[0] >= 0.0f);
+ CheckValue(values[0] >= T{0});
- Source->RolloffFactor = values[0];
+ Source->RolloffFactor = static_cast<float>(values[0]);
return CommitAndUpdateSourceProps(Source, Context);
case AL_REFERENCE_DISTANCE:
CheckSize(1);
- CheckValue(values[0] >= 0.0f);
+ CheckValue(values[0] >= T{0});
- Source->RefDistance = values[0];
+ Source->RefDistance = static_cast<float>(values[0]);
return CommitAndUpdateSourceProps(Source, Context);
case AL_MIN_GAIN:
CheckSize(1);
- CheckValue(values[0] >= 0.0f);
+ CheckValue(values[0] >= T{0});
- Source->MinGain = values[0];
+ Source->MinGain = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_MAX_GAIN:
CheckSize(1);
- CheckValue(values[0] >= 0.0f);
+ CheckValue(values[0] >= T{0});
- Source->MaxGain = values[0];
+ Source->MaxGain = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_CONE_OUTER_GAIN:
CheckSize(1);
- CheckValue(values[0] >= 0.0f && values[0] <= 1.0f);
+ CheckValue(values[0] >= T{0} && values[0] <= T{1});
- Source->OuterGain = values[0];
+ Source->OuterGain = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_CONE_OUTER_GAINHF:
CheckSize(1);
- CheckValue(values[0] >= 0.0f && values[0] <= 1.0f);
+ CheckValue(values[0] >= T{0} && values[0] <= T{1});
- Source->OuterGainHF = values[0];
+ Source->OuterGainHF = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_AIR_ABSORPTION_FACTOR:
CheckSize(1);
- CheckValue(values[0] >= 0.0f && values[0] <= 10.0f);
+ CheckValue(values[0] >= T{0} && values[0] <= T{10});
- Source->AirAbsorptionFactor = values[0];
+ Source->AirAbsorptionFactor = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_ROOM_ROLLOFF_FACTOR:
CheckSize(1);
- CheckValue(values[0] >= 0.0f && values[0] <= 10.0f);
+ CheckValue(values[0] >= T{0} && values[0] <= T{1});
- Source->RoomRolloffFactor = values[0];
+ Source->RoomRolloffFactor = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_DOPPLER_FACTOR:
CheckSize(1);
- CheckValue(values[0] >= 0.0f && values[0] <= 1.0f);
+ CheckValue(values[0] >= T{0} && values[0] <= T{1});
- Source->DopplerFactor = values[0];
+ Source->DopplerFactor = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
+
+ case AL_SOURCE_RELATIVE:
+ if constexpr(std::is_integral_v<T>)
+ {
+ CheckSize(1);
+ CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
+
+ Source->HeadRelative = values[0] != AL_FALSE;
+ return CommitAndUpdateSourceProps(Source, Context);
+ }
+ break;
+
+ case AL_LOOPING:
+ if constexpr(std::is_integral_v<T>)
+ {
+ CheckSize(1);
+ CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
+
+ Source->Looping = values[0] != AL_FALSE;
+ if(Voice *voice{GetSourceVoice(Source, Context)})
+ {
+ if(Source->Looping)
+ voice->mLoopBuffer.store(&Source->mQueue.front(), std::memory_order_release);
+ else
+ voice->mLoopBuffer.store(nullptr, std::memory_order_release);
+
+ /* If the source is playing, wait for the current mix to finish
+ * to ensure it isn't currently looping back or reaching the
+ * end.
+ */
+ device->waitForMix();
+ }
+ return;
+ }
+ break;
+
+ case AL_BUFFER:
+ if constexpr(std::is_integral_v<T>)
+ {
+ CheckSize(1);
+ {
+ const ALenum state{GetSourceState(Source, GetSourceVoice(Source, Context))};
+ if(state == AL_PLAYING || state == AL_PAUSED)
+ return Context->setError(AL_INVALID_OPERATION,
+ "Setting buffer on playing or paused source %u", Source->id);
+ }
+ std::deque<ALbufferQueueItem> oldlist;
+ if(values[0])
+ {
+ using UT = std::make_unsigned_t<T>;
+ std::lock_guard<std::mutex> _{device->BufferLock};
+ ALbuffer *buffer{LookupBuffer(device, static_cast<UT>(values[0]))};
+ if(!buffer) UNLIKELY
+ return Context->setError(AL_INVALID_VALUE, "Invalid buffer ID %s",
+ std::to_string(values[0]).c_str());
+ if(buffer->MappedAccess && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT)) UNLIKELY
+ return Context->setError(AL_INVALID_OPERATION,
+ "Setting non-persistently mapped buffer %u", buffer->id);
+ if(buffer->mCallback && ReadRef(buffer->ref) != 0) UNLIKELY
+ return Context->setError(AL_INVALID_OPERATION,
+ "Setting already-set callback buffer %u", buffer->id);
+
+ /* Add the selected buffer to a one-item queue */
+ std::deque<ALbufferQueueItem> newlist;
+ newlist.emplace_back();
+ newlist.back().mCallback = buffer->mCallback;
+ newlist.back().mUserData = buffer->mUserData;
+ newlist.back().mBlockAlign = buffer->mBlockAlign;
+ newlist.back().mSampleLen = buffer->mSampleLen;
+ newlist.back().mLoopStart = buffer->mLoopStart;
+ newlist.back().mLoopEnd = buffer->mLoopEnd;
+ newlist.back().mSamples = buffer->mData.data();
+ newlist.back().mBuffer = buffer;
+ IncrementRef(buffer->ref);
+
+ /* Source is now Static */
+ Source->SourceType = AL_STATIC;
+ Source->mQueue.swap(oldlist);
+ Source->mQueue.swap(newlist);
+ }
+ else
+ {
+ /* Source is now Undetermined */
+ Source->SourceType = AL_UNDETERMINED;
+ Source->mQueue.swap(oldlist);
+ }
+
+ /* Delete all elements in the previous queue */
+ for(auto &item : oldlist)
+ {
+ if(ALbuffer *buffer{item.mBuffer})
+ DecrementRef(buffer->ref);
+ }
+ return;
+ }
+ break;
+
+
case AL_SEC_OFFSET:
case AL_SAMPLE_OFFSET:
case AL_BYTE_OFFSET:
CheckSize(1);
- CheckValue(std::isfinite(values[0]));
+ if constexpr(std::is_floating_point_v<T>)
+ CheckValue(std::isfinite(values[0]));
if(Voice *voice{GetSourceVoice(Source, Context)})
{
- auto vpos = GetSampleOffset(Source->mQueue, prop, values[0]);
+ auto vpos = GetSampleOffset(Source->mQueue, prop, static_cast<double>(values[0]));
if(!vpos) return Context->setError(AL_INVALID_VALUE, "Invalid offset");
if(SetVoiceOffset(voice, *vpos, Source, Context, Context->mALDevice.get()))
return;
}
Source->OffsetType = prop;
- Source->Offset = values[0];
+ Source->Offset = static_cast<double>(values[0]);
return;
case AL_SAMPLE_RW_OFFSETS_SOFT:
+ if(sBufferSubDataCompat)
+ {
+ if constexpr(std::is_integral_v<T>)
+ {
+ /* Query only */
+ return Context->setError(AL_INVALID_OPERATION,
+ "Setting read-only source property 0x%04x", prop);
+ }
+ }
break;
case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/
if(sBufferSubDataCompat)
+ {
+ if constexpr(std::is_integral_v<T>)
+ {
+ /* Query only */
+ return Context->setError(AL_INVALID_OPERATION,
+ "Setting read-only source property 0x%04x", prop);
+ }
break;
+ }
CheckSize(1);
- CheckValue(values[0] >= 0.0f && std::isfinite(values[0]));
+ if constexpr(std::is_floating_point_v<T>)
+ CheckValue(values[0] >= T{0} && std::isfinite(static_cast<float>(values[0])));
+ else
+ CheckValue(values[0] >= T{0});
- Source->Radius = values[0];
+ Source->Radius = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_SUPER_STEREO_WIDTH_SOFT:
CheckSize(1);
- CheckValue(values[0] >= 0.0f && values[0] <= 1.0f);
+ CheckValue(values[0] >= T{0} && values[0] <= T{1});
- Source->EnhWidth = values[0];
+ Source->EnhWidth = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_STEREO_ANGLES:
CheckSize(2);
- CheckValue(std::isfinite(values[0]) && std::isfinite(values[1]));
+ if constexpr(std::is_floating_point_v<T>)
+ CheckValue(std::isfinite(static_cast<float>(values[0]))
+ && std::isfinite(static_cast<float>(values[1])));
- Source->StereoPan[0] = values[0];
- Source->StereoPan[1] = values[1];
+ Source->StereoPan[0] = static_cast<float>(values[0]);
+ Source->StereoPan[1] = static_cast<float>(values[1]);
return UpdateSourceProps(Source, Context);
case AL_POSITION:
CheckSize(3);
- CheckValue(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2]));
-
- Source->Position[0] = values[0];
- Source->Position[1] = values[1];
- Source->Position[2] = values[2];
+ if constexpr(std::is_floating_point_v<T>)
+ CheckValue(std::isfinite(static_cast<float>(values[0]))
+ && std::isfinite(static_cast<float>(values[1]))
+ && std::isfinite(static_cast<float>(values[2])));
+
+ Source->Position[0] = static_cast<float>(values[0]);
+ Source->Position[1] = static_cast<float>(values[1]);
+ Source->Position[2] = static_cast<float>(values[2]);
return CommitAndUpdateSourceProps(Source, Context);
case AL_VELOCITY:
CheckSize(3);
- CheckValue(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2]));
-
- Source->Velocity[0] = values[0];
- Source->Velocity[1] = values[1];
- Source->Velocity[2] = values[2];
+ if constexpr(std::is_floating_point_v<T>)
+ CheckValue(std::isfinite(static_cast<float>(values[0]))
+ && std::isfinite(static_cast<float>(values[1]))
+ && std::isfinite(static_cast<float>(values[2])));
+
+ Source->Velocity[0] = static_cast<float>(values[0]);
+ Source->Velocity[1] = static_cast<float>(values[1]);
+ Source->Velocity[2] = static_cast<float>(values[2]);
return CommitAndUpdateSourceProps(Source, Context);
case AL_DIRECTION:
CheckSize(3);
- CheckValue(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2]));
-
- Source->Direction[0] = values[0];
- Source->Direction[1] = values[1];
- Source->Direction[2] = values[2];
+ if constexpr(std::is_floating_point_v<T>)
+ CheckValue(std::isfinite(static_cast<float>(values[0]))
+ && std::isfinite(static_cast<float>(values[1]))
+ && std::isfinite(static_cast<float>(values[2])));
+
+ Source->Direction[0] = static_cast<float>(values[0]);
+ Source->Direction[1] = static_cast<float>(values[1]);
+ Source->Direction[2] = static_cast<float>(values[2]);
return CommitAndUpdateSourceProps(Source, Context);
case AL_ORIENTATION:
CheckSize(6);
- CheckValue(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2])
- && std::isfinite(values[3]) && std::isfinite(values[4]) && std::isfinite(values[5]));
-
- Source->OrientAt[0] = values[0];
- Source->OrientAt[1] = values[1];
- Source->OrientAt[2] = values[2];
- Source->OrientUp[0] = values[3];
- Source->OrientUp[1] = values[4];
- Source->OrientUp[2] = values[5];
+ if constexpr(std::is_floating_point_v<T>)
+ CheckValue(std::isfinite(static_cast<float>(values[0]))
+ && std::isfinite(static_cast<float>(values[1]))
+ && std::isfinite(static_cast<float>(values[2]))
+ && std::isfinite(static_cast<float>(values[3]))
+ && std::isfinite(static_cast<float>(values[4]))
+ && std::isfinite(static_cast<float>(values[5])));
+
+ Source->OrientAt[0] = static_cast<float>(values[0]);
+ Source->OrientAt[1] = static_cast<float>(values[1]);
+ Source->OrientAt[2] = static_cast<float>(values[2]);
+ Source->OrientUp[0] = static_cast<float>(values[3]);
+ Source->OrientUp[1] = static_cast<float>(values[4]);
+ Source->OrientUp[2] = static_cast<float>(values[5]);
return UpdateSourceProps(Source, Context);
- case AL_SOURCE_RELATIVE:
- case AL_LOOPING:
- case AL_SOURCE_STATE:
- case AL_SOURCE_TYPE:
- case AL_DISTANCE_MODEL:
- case AL_DIRECT_FILTER_GAINHF_AUTO:
- case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
- case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
- case AL_DIRECT_CHANNELS_SOFT:
- case AL_SOURCE_RESAMPLER_SOFT:
- case AL_SOURCE_SPATIALIZE_SOFT:
- case AL_BYTE_LENGTH_SOFT:
- case AL_SAMPLE_LENGTH_SOFT:
- case AL_STEREO_MODE_SOFT:
- CheckSize(1);
- ival = static_cast<int>(values[0]);
- return SetSourceiv(Source, Context, prop, {&ival, 1u});
-
- case AL_BUFFERS_QUEUED:
- case AL_BUFFERS_PROCESSED:
- CheckSize(1);
- ival = static_cast<int>(static_cast<ALuint>(values[0]));
- return SetSourceiv(Source, Context, prop, {&ival, 1u});
-
- case AL_BUFFER:
case AL_DIRECT_FILTER:
- case AL_AUXILIARY_SEND_FILTER:
- case AL_SAMPLE_OFFSET_LATENCY_SOFT:
- case AL_SAMPLE_OFFSET_CLOCK_SOFT:
- break;
- }
-
- ERR("Unexpected property: 0x%04x\n", prop);
- Context->setError(AL_INVALID_ENUM, "Invalid source float property 0x%04x", prop);
-}
-catch(check_exception&) {
-}
-
-void SetSourceiv(ALsource *const Source, ALCcontext *const Context, const SourceProp prop,
- const al::span<const int> values)
-try {
- auto Checkers = GetCheckers(Context, prop, values);
- auto &CheckSize = Checkers.first;
- auto &CheckValue = Checkers.second;
- ALCdevice *device{Context->mALDevice.get()};
- ALeffectslot *slot{nullptr};
- al::deque<ALbufferQueueItem> oldlist;
- std::unique_lock<std::mutex> slotlock;
- float fvals[6];
-
- switch(prop)
- {
- case AL_SOURCE_STATE:
- case AL_SOURCE_TYPE:
- case AL_BUFFERS_QUEUED:
- case AL_BUFFERS_PROCESSED:
- case AL_BYTE_LENGTH_SOFT:
- case AL_SAMPLE_LENGTH_SOFT:
- /* Query only */
- return Context->setError(AL_INVALID_OPERATION,
- "Setting read-only source property 0x%04x", prop);
-
- case AL_SOURCE_RELATIVE:
- CheckSize(1);
- CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
-
- Source->HeadRelative = values[0] != AL_FALSE;
- return CommitAndUpdateSourceProps(Source, Context);
-
- case AL_LOOPING:
- CheckSize(1);
- CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
-
- Source->Looping = values[0] != AL_FALSE;
- if(Voice *voice{GetSourceVoice(Source, Context)})
+ if constexpr(std::is_integral_v<T>)
{
- if(Source->Looping)
- voice->mLoopBuffer.store(&Source->mQueue.front(), std::memory_order_release);
+ CheckSize(1);
+ const auto filterid = static_cast<std::make_unsigned_t<T>>(values[0]);
+ if(values[0])
+ {
+ std::lock_guard<std::mutex> _{device->FilterLock};
+ ALfilter *filter{LookupFilter(device, filterid)};
+ if(!filter) UNLIKELY
+ return Context->setError(AL_INVALID_VALUE, "Invalid filter ID %s",
+ std::to_string(filterid).c_str());
+ Source->Direct.Gain = filter->Gain;
+ Source->Direct.GainHF = filter->GainHF;
+ Source->Direct.HFReference = filter->HFReference;
+ Source->Direct.GainLF = filter->GainLF;
+ Source->Direct.LFReference = filter->LFReference;
+ }
else
- voice->mLoopBuffer.store(nullptr, std::memory_order_release);
-
- /* If the source is playing, wait for the current mix to finish to
- * ensure it isn't currently looping back or reaching the end.
- */
- device->waitForMix();
+ {
+ Source->Direct.Gain = 1.0f;
+ Source->Direct.GainHF = 1.0f;
+ Source->Direct.HFReference = LOWPASSFREQREF;
+ Source->Direct.GainLF = 1.0f;
+ Source->Direct.LFReference = HIGHPASSFREQREF;
+ }
+ return UpdateSourceProps(Source, Context);
}
- return;
+ break;
- case AL_BUFFER:
- CheckSize(1);
- {
- const ALenum state{GetSourceState(Source, GetSourceVoice(Source, Context))};
- if(state == AL_PLAYING || state == AL_PAUSED)
- return Context->setError(AL_INVALID_OPERATION,
- "Setting buffer on playing or paused source %u", Source->id);
- }
- if(values[0])
- {
- std::lock_guard<std::mutex> _{device->BufferLock};
- ALbuffer *buffer{LookupBuffer(device, static_cast<ALuint>(values[0]))};
- if(!buffer)
- return Context->setError(AL_INVALID_VALUE, "Invalid buffer ID %u",
- static_cast<ALuint>(values[0]));
- if(buffer->MappedAccess && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT))
- return Context->setError(AL_INVALID_OPERATION,
- "Setting non-persistently mapped buffer %u", buffer->id);
- if(buffer->mCallback && ReadRef(buffer->ref) != 0)
- return Context->setError(AL_INVALID_OPERATION,
- "Setting already-set callback buffer %u", buffer->id);
-
- /* Add the selected buffer to a one-item queue */
- al::deque<ALbufferQueueItem> newlist;
- newlist.emplace_back();
- newlist.back().mCallback = buffer->mCallback;
- newlist.back().mUserData = buffer->mUserData;
- newlist.back().mBlockAlign = buffer->mBlockAlign;
- newlist.back().mSampleLen = buffer->mSampleLen;
- newlist.back().mLoopStart = buffer->mLoopStart;
- newlist.back().mLoopEnd = buffer->mLoopEnd;
- newlist.back().mSamples = buffer->mData.data();
- newlist.back().mBuffer = buffer;
- IncrementRef(buffer->ref);
-
- /* Source is now Static */
- Source->SourceType = AL_STATIC;
- Source->mQueue.swap(oldlist);
- Source->mQueue.swap(newlist);
- }
- else
+ case AL_DIRECT_FILTER_GAINHF_AUTO:
+ if constexpr(std::is_integral_v<T>)
{
- /* Source is now Undetermined */
- Source->SourceType = AL_UNDETERMINED;
- Source->mQueue.swap(oldlist);
- }
+ CheckSize(1);
+ CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
- /* Delete all elements in the previous queue */
- for(auto &item : oldlist)
- {
- if(ALbuffer *buffer{item.mBuffer})
- DecrementRef(buffer->ref);
+ Source->DryGainHFAuto = values[0] != AL_FALSE;
+ return UpdateSourceProps(Source, Context);
}
- return;
-
- case AL_SEC_OFFSET:
- case AL_SAMPLE_OFFSET:
- case AL_BYTE_OFFSET:
- CheckSize(1);
+ break;
- if(Voice *voice{GetSourceVoice(Source, Context)})
+ case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
+ if constexpr(std::is_integral_v<T>)
{
- auto vpos = GetSampleOffset(Source->mQueue, prop, values[0]);
- if(!vpos) return Context->setError(AL_INVALID_VALUE, "Invalid source offset");
+ CheckSize(1);
+ CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
- if(SetVoiceOffset(voice, *vpos, Source, Context, device))
- return;
- }
- Source->OffsetType = prop;
- Source->Offset = values[0];
- return;
-
- case AL_DIRECT_FILTER:
- CheckSize(1);
- if(values[0])
- {
- std::lock_guard<std::mutex> _{device->FilterLock};
- ALfilter *filter{LookupFilter(device, static_cast<ALuint>(values[0]))};
- if(!filter)
- return Context->setError(AL_INVALID_VALUE, "Invalid filter ID %u",
- static_cast<ALuint>(values[0]));
- Source->Direct.Gain = filter->Gain;
- Source->Direct.GainHF = filter->GainHF;
- Source->Direct.HFReference = filter->HFReference;
- Source->Direct.GainLF = filter->GainLF;
- Source->Direct.LFReference = filter->LFReference;
- }
- else
- {
- Source->Direct.Gain = 1.0f;
- Source->Direct.GainHF = 1.0f;
- Source->Direct.HFReference = LOWPASSFREQREF;
- Source->Direct.GainLF = 1.0f;
- Source->Direct.LFReference = HIGHPASSFREQREF;
+ Source->WetGainAuto = values[0] != AL_FALSE;
+ return UpdateSourceProps(Source, Context);
}
- return UpdateSourceProps(Source, Context);
-
- case AL_DIRECT_FILTER_GAINHF_AUTO:
- CheckSize(1);
- CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
-
- Source->DryGainHFAuto = values[0] != AL_FALSE;
- return UpdateSourceProps(Source, Context);
-
- case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
- CheckSize(1);
- CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
-
- Source->WetGainAuto = values[0] != AL_FALSE;
- return UpdateSourceProps(Source, Context);
+ break;
case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
- CheckSize(1);
- CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
+ if constexpr(std::is_integral_v<T>)
+ {
+ CheckSize(1);
+ CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
- Source->WetGainHFAuto = values[0] != AL_FALSE;
- return UpdateSourceProps(Source, Context);
+ Source->WetGainHFAuto = values[0] != AL_FALSE;
+ return UpdateSourceProps(Source, Context);
+ }
+ break;
case AL_DIRECT_CHANNELS_SOFT:
- CheckSize(1);
- if(auto mode = DirectModeFromEnum(values[0]))
+ if constexpr(std::is_integral_v<T>)
{
- Source->DirectChannels = *mode;
- return UpdateSourceProps(Source, Context);
+ CheckSize(1);
+ if(auto mode = DirectModeFromEnum(values[0]))
+ {
+ Source->DirectChannels = *mode;
+ return UpdateSourceProps(Source, Context);
+ }
+ return Context->setError(AL_INVALID_VALUE, "Invalid direct channels mode: %s\n",
+ HexPrinter{values[0]}.c_str());
}
- Context->setError(AL_INVALID_VALUE, "Unsupported AL_DIRECT_CHANNELS_SOFT: 0x%04x\n",
- values[0]);
- return;
+ break;
case AL_DISTANCE_MODEL:
- CheckSize(1);
- if(auto model = DistanceModelFromALenum(values[0]))
+ if constexpr(std::is_integral_v<T>)
{
- Source->mDistanceModel = *model;
- if(Context->mSourceDistanceModel)
- UpdateSourceProps(Source, Context);
- return;
+ CheckSize(1);
+ if(auto model = DistanceModelFromALenum(values[0]))
+ {
+ Source->mDistanceModel = *model;
+ if(Context->mSourceDistanceModel)
+ UpdateSourceProps(Source, Context);
+ return;
+ }
+ return Context->setError(AL_INVALID_VALUE, "Invalid distance model: %s\n",
+ HexPrinter{values[0]}.c_str());
}
- Context->setError(AL_INVALID_VALUE, "Distance model out of range: 0x%04x", values[0]);
- return;
+ break;
case AL_SOURCE_RESAMPLER_SOFT:
- CheckSize(1);
- CheckValue(values[0] >= 0 && values[0] <= static_cast<int>(Resampler::Max));
-
- Source->mResampler = static_cast<Resampler>(values[0]);
- return UpdateSourceProps(Source, Context);
-
- case AL_SOURCE_SPATIALIZE_SOFT:
- CheckSize(1);
- if(auto mode = SpatializeModeFromEnum(values[0]))
+ if constexpr(std::is_integral_v<T>)
{
- Source->mSpatialize = *mode;
- return UpdateSourceProps(Source, Context);
- }
- Context->setError(AL_INVALID_VALUE, "Unsupported AL_SOURCE_SPATIALIZE_SOFT: 0x%04x\n",
- values[0]);
- return;
+ CheckSize(1);
+ CheckValue(values[0] >= 0 && values[0] <= static_cast<int>(Resampler::Max));
- case AL_STEREO_MODE_SOFT:
- CheckSize(1);
- {
- const ALenum state{GetSourceState(Source, GetSourceVoice(Source, Context))};
- if(state == AL_PLAYING || state == AL_PAUSED)
- return Context->setError(AL_INVALID_OPERATION,
- "Modifying stereo mode on playing or paused source %u", Source->id);
- }
- if(auto mode = StereoModeFromEnum(values[0]))
- {
- Source->mStereoMode = *mode;
- return;
- }
- Context->setError(AL_INVALID_VALUE, "Unsupported AL_STEREO_MODE_SOFT: 0x%04x\n",
- values[0]);
- return;
-
- case AL_AUXILIARY_SEND_FILTER:
- CheckSize(3);
- slotlock = std::unique_lock<std::mutex>{Context->mEffectSlotLock};
- if(values[0] && (slot=LookupEffectSlot(Context, static_cast<ALuint>(values[0]))) == nullptr)
- return Context->setError(AL_INVALID_VALUE, "Invalid effect ID %u", values[0]);
- if(static_cast<ALuint>(values[1]) >= device->NumAuxSends)
- return Context->setError(AL_INVALID_VALUE, "Invalid send %u", values[1]);
-
- if(values[2])
- {
- std::lock_guard<std::mutex> _{device->FilterLock};
- ALfilter *filter{LookupFilter(device, static_cast<ALuint>(values[2]))};
- if(!filter)
- return Context->setError(AL_INVALID_VALUE, "Invalid filter ID %u", values[2]);
-
- auto &send = Source->Send[static_cast<ALuint>(values[1])];
- send.Gain = filter->Gain;
- send.GainHF = filter->GainHF;
- send.HFReference = filter->HFReference;
- send.GainLF = filter->GainLF;
- send.LFReference = filter->LFReference;
- }
- else
- {
- /* Disable filter */
- auto &send = Source->Send[static_cast<ALuint>(values[1])];
- send.Gain = 1.0f;
- send.GainHF = 1.0f;
- send.HFReference = LOWPASSFREQREF;
- send.GainLF = 1.0f;
- send.LFReference = HIGHPASSFREQREF;
+ Source->mResampler = static_cast<Resampler>(values[0]);
+ return UpdateSourceProps(Source, Context);
}
+ break;
- /* We must force an update if the current auxiliary slot is valid and
- * about to be changed on an active source, in case the old slot is
- * about to be deleted.
- */
- if(Source->Send[static_cast<ALuint>(values[1])].Slot
- && slot != Source->Send[static_cast<ALuint>(values[1])].Slot
- && IsPlayingOrPaused(Source))
- {
- /* Add refcount on the new slot, and release the previous slot */
- if(slot) IncrementRef(slot->ref);
- if(auto *oldslot = Source->Send[static_cast<ALuint>(values[1])].Slot)
- DecrementRef(oldslot->ref);
- Source->Send[static_cast<ALuint>(values[1])].Slot = slot;
-
- Voice *voice{GetSourceVoice(Source, Context)};
- if(voice) UpdateSourceProps(Source, voice, Context);
- else Source->mPropsDirty = true;
- }
- else
+ case AL_SOURCE_SPATIALIZE_SOFT:
+ if constexpr(std::is_integral_v<T>)
{
- if(slot) IncrementRef(slot->ref);
- if(auto *oldslot = Source->Send[static_cast<ALuint>(values[1])].Slot)
- DecrementRef(oldslot->ref);
- Source->Send[static_cast<ALuint>(values[1])].Slot = slot;
- UpdateSourceProps(Source, Context);
+ CheckSize(1);
+ if(auto mode = SpatializeModeFromEnum(values[0]))
+ {
+ Source->mSpatialize = *mode;
+ return UpdateSourceProps(Source, Context);
+ }
+ return Context->setError(AL_INVALID_VALUE, "Invalid source spatialize mode: %s\n",
+ HexPrinter{values[0]}.c_str());
}
- return;
-
-
- case AL_SAMPLE_RW_OFFSETS_SOFT:
- if(sBufferSubDataCompat)
- /* Query only */
- return Context->setError(AL_INVALID_OPERATION,
- "Setting read-only source property 0x%04x", prop);
- break;
-
- case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/
- if(sBufferSubDataCompat)
- return Context->setError(AL_INVALID_OPERATION,
- "Setting read-only source property 0x%04x", prop);
- /*fall-through*/
-
- /* 1x float */
- case AL_CONE_INNER_ANGLE:
- case AL_CONE_OUTER_ANGLE:
- case AL_PITCH:
- case AL_GAIN:
- case AL_MIN_GAIN:
- case AL_MAX_GAIN:
- case AL_REFERENCE_DISTANCE:
- case AL_ROLLOFF_FACTOR:
- case AL_CONE_OUTER_GAIN:
- case AL_MAX_DISTANCE:
- case AL_DOPPLER_FACTOR:
- case AL_CONE_OUTER_GAINHF:
- case AL_AIR_ABSORPTION_FACTOR:
- case AL_ROOM_ROLLOFF_FACTOR:
- case AL_SEC_LENGTH_SOFT:
- case AL_SUPER_STEREO_WIDTH_SOFT:
- CheckSize(1);
- fvals[0] = static_cast<float>(values[0]);
- return SetSourcefv(Source, Context, prop, {fvals, 1u});
-
- /* 3x float */
- case AL_POSITION:
- case AL_VELOCITY:
- case AL_DIRECTION:
- CheckSize(3);
- fvals[0] = static_cast<float>(values[0]);
- fvals[1] = static_cast<float>(values[1]);
- fvals[2] = static_cast<float>(values[2]);
- return SetSourcefv(Source, Context, prop, {fvals, 3u});
-
- /* 6x float */
- case AL_ORIENTATION:
- CheckSize(6);
- fvals[0] = static_cast<float>(values[0]);
- fvals[1] = static_cast<float>(values[1]);
- fvals[2] = static_cast<float>(values[2]);
- fvals[3] = static_cast<float>(values[3]);
- fvals[4] = static_cast<float>(values[4]);
- fvals[5] = static_cast<float>(values[5]);
- return SetSourcefv(Source, Context, prop, {fvals, 6u});
-
- case AL_SAMPLE_OFFSET_LATENCY_SOFT:
- case AL_SEC_OFFSET_LATENCY_SOFT:
- case AL_SEC_OFFSET_CLOCK_SOFT:
- case AL_SAMPLE_OFFSET_CLOCK_SOFT:
- case AL_STEREO_ANGLES:
break;
- }
- ERR("Unexpected property: 0x%04x\n", prop);
- Context->setError(AL_INVALID_ENUM, "Invalid source integer property 0x%04x", prop);
-}
-catch(check_exception&) {
-}
-
-void SetSourcei64v(ALsource *const Source, ALCcontext *const Context, const SourceProp prop,
- const al::span<const int64_t> values)
-try {
- auto Checkers = GetCheckers(Context, prop, values);
- auto &CheckSize = Checkers.first;
- auto &CheckValue = Checkers.second;
- float fvals[MaxValues];
- int ivals[MaxValues];
-
- switch(prop)
- {
- case AL_SOURCE_TYPE:
- case AL_BUFFERS_QUEUED:
- case AL_BUFFERS_PROCESSED:
- case AL_SOURCE_STATE:
- case AL_BYTE_LENGTH_SOFT:
- case AL_SAMPLE_LENGTH_SOFT:
- case AL_SAMPLE_OFFSET_LATENCY_SOFT:
- case AL_SAMPLE_OFFSET_CLOCK_SOFT:
- /* Query only */
- return Context->setError(AL_INVALID_OPERATION,
- "Setting read-only source property 0x%04x", prop);
-
- /* 1x int */
- case AL_SOURCE_RELATIVE:
- case AL_LOOPING:
- case AL_SEC_OFFSET:
- case AL_SAMPLE_OFFSET:
- case AL_BYTE_OFFSET:
- case AL_DIRECT_FILTER_GAINHF_AUTO:
- case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
- case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
- case AL_DIRECT_CHANNELS_SOFT:
- case AL_DISTANCE_MODEL:
- case AL_SOURCE_RESAMPLER_SOFT:
- case AL_SOURCE_SPATIALIZE_SOFT:
case AL_STEREO_MODE_SOFT:
- CheckSize(1);
- CheckValue(values[0] <= INT_MAX && values[0] >= INT_MIN);
-
- ivals[0] = static_cast<int>(values[0]);
- return SetSourceiv(Source, Context, prop, {ivals, 1u});
-
- /* 1x uint */
- case AL_BUFFER:
- case AL_DIRECT_FILTER:
- CheckSize(1);
- CheckValue(values[0] <= UINT_MAX && values[0] >= 0);
-
- ivals[0] = static_cast<int>(values[0]);
- return SetSourceiv(Source, Context, prop, {ivals, 1u});
-
- /* 3x uint */
- case AL_AUXILIARY_SEND_FILTER:
- CheckSize(3);
- CheckValue(values[0] <= UINT_MAX && values[0] >= 0 && values[1] <= UINT_MAX
- && values[1] >= 0 && values[2] <= UINT_MAX && values[2] >= 0);
-
- ivals[0] = static_cast<int>(values[0]);
- ivals[1] = static_cast<int>(values[1]);
- ivals[2] = static_cast<int>(values[2]);
- return SetSourceiv(Source, Context, prop, {ivals, 3u});
-
- case AL_SAMPLE_RW_OFFSETS_SOFT:
- if(sBufferSubDataCompat)
+ if constexpr(std::is_integral_v<T>)
{
- /* Query only */
- return Context->setError(AL_INVALID_OPERATION,
- "Setting read-only source property 0x%04x", prop);
+ CheckSize(1);
+ {
+ const ALenum state{GetSourceState(Source, GetSourceVoice(Source, Context))};
+ if(state == AL_PLAYING || state == AL_PAUSED)
+ return Context->setError(AL_INVALID_OPERATION,
+ "Modifying stereo mode on playing or paused source %u", Source->id);
+ }
+ if(auto mode = StereoModeFromEnum(values[0]))
+ {
+ Source->mStereoMode = *mode;
+ return;
+ }
+ return Context->setError(AL_INVALID_VALUE, "Invalid stereo mode: %s\n",
+ HexPrinter{values[0]}.c_str());
}
break;
- case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/
- if(sBufferSubDataCompat)
- return Context->setError(AL_INVALID_OPERATION,
- "Setting read-only source property 0x%04x", prop);
- /*fall-through*/
-
- /* 1x float */
- case AL_CONE_INNER_ANGLE:
- case AL_CONE_OUTER_ANGLE:
- case AL_PITCH:
- case AL_GAIN:
- case AL_MIN_GAIN:
- case AL_MAX_GAIN:
- case AL_REFERENCE_DISTANCE:
- case AL_ROLLOFF_FACTOR:
- case AL_CONE_OUTER_GAIN:
- case AL_MAX_DISTANCE:
- case AL_DOPPLER_FACTOR:
- case AL_CONE_OUTER_GAINHF:
- case AL_AIR_ABSORPTION_FACTOR:
- case AL_ROOM_ROLLOFF_FACTOR:
- case AL_SEC_LENGTH_SOFT:
- case AL_SUPER_STEREO_WIDTH_SOFT:
- CheckSize(1);
- fvals[0] = static_cast<float>(values[0]);
- return SetSourcefv(Source, Context, prop, {fvals, 1u});
+ case AL_AUXILIARY_SEND_FILTER:
+ if constexpr(std::is_integral_v<T>)
+ {
+ CheckSize(3);
+ const auto slotid = static_cast<std::make_unsigned_t<T>>(values[0]);
+ const auto sendidx = static_cast<std::make_unsigned_t<T>>(values[1]);
+ const auto filterid = static_cast<std::make_unsigned_t<T>>(values[2]);
+
+ std::unique_lock slotlock{Context->mEffectSlotLock};
+ ALeffectslot *slot{};
+ if(values[0])
+ {
+ if((slot=LookupEffectSlot(Context, slotid)) == nullptr) UNLIKELY
+ return Context->setError(AL_INVALID_VALUE, "Invalid effect ID %s",
+ std::to_string(slotid).c_str());
+ }
- /* 3x float */
- case AL_POSITION:
- case AL_VELOCITY:
- case AL_DIRECTION:
- CheckSize(3);
- fvals[0] = static_cast<float>(values[0]);
- fvals[1] = static_cast<float>(values[1]);
- fvals[2] = static_cast<float>(values[2]);
- return SetSourcefv(Source, Context, prop, {fvals, 3u});
+ if(sendidx >= device->NumAuxSends) UNLIKELY
+ return Context->setError(AL_INVALID_VALUE, "Invalid send %s",
+ std::to_string(sendidx).c_str());
+ auto &send = Source->Send[static_cast<size_t>(sendidx)];
- /* 6x float */
- case AL_ORIENTATION:
- CheckSize(6);
- fvals[0] = static_cast<float>(values[0]);
- fvals[1] = static_cast<float>(values[1]);
- fvals[2] = static_cast<float>(values[2]);
- fvals[3] = static_cast<float>(values[3]);
- fvals[4] = static_cast<float>(values[4]);
- fvals[5] = static_cast<float>(values[5]);
- return SetSourcefv(Source, Context, prop, {fvals, 6u});
+ if(values[2])
+ {
+ std::lock_guard<std::mutex> _{device->FilterLock};
+ ALfilter *filter{LookupFilter(device, filterid)};
+ if(!filter) UNLIKELY
+ return Context->setError(AL_INVALID_VALUE, "Invalid filter ID %s",
+ std::to_string(filterid).c_str());
+
+ send.Gain = filter->Gain;
+ send.GainHF = filter->GainHF;
+ send.HFReference = filter->HFReference;
+ send.GainLF = filter->GainLF;
+ send.LFReference = filter->LFReference;
+ }
+ else
+ {
+ /* Disable filter */
+ send.Gain = 1.0f;
+ send.GainHF = 1.0f;
+ send.HFReference = LOWPASSFREQREF;
+ send.GainLF = 1.0f;
+ send.LFReference = HIGHPASSFREQREF;
+ }
- case AL_SEC_OFFSET_LATENCY_SOFT:
- case AL_SEC_OFFSET_CLOCK_SOFT:
- case AL_STEREO_ANGLES:
+ /* We must force an update if the current auxiliary slot is valid
+ * and about to be changed on an active source, in case the old
+ * slot is about to be deleted.
+ */
+ if(send.Slot && slot != send.Slot && IsPlayingOrPaused(Source))
+ {
+ /* Add refcount on the new slot, and release the previous slot */
+ if(slot) IncrementRef(slot->ref);
+ if(auto *oldslot = send.Slot)
+ DecrementRef(oldslot->ref);
+ send.Slot = slot;
+
+ Voice *voice{GetSourceVoice(Source, Context)};
+ if(voice) UpdateSourceProps(Source, voice, Context);
+ else Source->mPropsDirty = true;
+ }
+ else
+ {
+ if(slot) IncrementRef(slot->ref);
+ if(auto *oldslot = send.Slot)
+ DecrementRef(oldslot->ref);
+ send.Slot = slot;
+ UpdateSourceProps(Source, Context);
+ }
+ return;
+ }
break;
}
- ERR("Unexpected property: 0x%04x\n", prop);
- Context->setError(AL_INVALID_ENUM, "Invalid source integer64 property 0x%04x", prop);
+ ERR("Unexpected %s property: 0x%04x\n", PropType<T>::Name(), prop);
+ Context->setError(AL_INVALID_ENUM, "Invalid source %s property 0x%04x", PropType<T>::Name(),
+ prop);
}
catch(check_exception&) {
}
@@ -2100,245 +2004,292 @@ auto GetSizeChecker(ALCcontext *const Context, const SourceProp prop, const al::
};
}
-bool GetSourcedv(ALsource *const Source, ALCcontext *const Context, const SourceProp prop, const al::span<double> values);
-bool GetSourceiv(ALsource *const Source, ALCcontext *const Context, const SourceProp prop, const al::span<int> values);
-bool GetSourcei64v(ALsource *const Source, ALCcontext *const Context, const SourceProp prop, const al::span<int64_t> values);
-
-bool GetSourcedv(ALsource *const Source, ALCcontext *const Context, const SourceProp prop,
- const al::span<double> values)
-try {
+template<typename T>
+[[nodiscard]] NOINLINE
+bool GetProperty(ALsource *const Source, ALCcontext *const Context, const SourceProp prop,
+ const al::span<T> values) try
+{
+ using std::chrono::duration_cast;
auto CheckSize = GetSizeChecker(Context, prop, values);
ALCdevice *device{Context->mALDevice.get()};
- ClockLatency clocktime;
- nanoseconds srcclock;
- int ivals[MaxValues];
- bool err;
switch(prop)
{
case AL_GAIN:
CheckSize(1);
- values[0] = Source->Gain;
+ values[0] = static_cast<T>(Source->Gain);
return true;
case AL_PITCH:
CheckSize(1);
- values[0] = Source->Pitch;
+ values[0] = static_cast<T>(Source->Pitch);
return true;
case AL_MAX_DISTANCE:
CheckSize(1);
- values[0] = Source->MaxDistance;
+ values[0] = static_cast<T>(Source->MaxDistance);
return true;
case AL_ROLLOFF_FACTOR:
CheckSize(1);
- values[0] = Source->RolloffFactor;
+ values[0] = static_cast<T>(Source->RolloffFactor);
return true;
case AL_REFERENCE_DISTANCE:
CheckSize(1);
- values[0] = Source->RefDistance;
+ values[0] = static_cast<T>(Source->RefDistance);
return true;
case AL_CONE_INNER_ANGLE:
CheckSize(1);
- values[0] = Source->InnerAngle;
+ values[0] = static_cast<T>(Source->InnerAngle);
return true;
case AL_CONE_OUTER_ANGLE:
CheckSize(1);
- values[0] = Source->OuterAngle;
+ values[0] = static_cast<T>(Source->OuterAngle);
return true;
case AL_MIN_GAIN:
CheckSize(1);
- values[0] = Source->MinGain;
+ values[0] = static_cast<T>(Source->MinGain);
return true;
case AL_MAX_GAIN:
CheckSize(1);
- values[0] = Source->MaxGain;
+ values[0] = static_cast<T>(Source->MaxGain);
return true;
case AL_CONE_OUTER_GAIN:
CheckSize(1);
- values[0] = Source->OuterGain;
+ values[0] = static_cast<T>(Source->OuterGain);
return true;
case AL_SEC_OFFSET:
case AL_SAMPLE_OFFSET:
case AL_BYTE_OFFSET:
CheckSize(1);
- values[0] = GetSourceOffset(Source, prop, Context);
+ values[0] = GetSourceOffset<T>(Source, prop, Context);
return true;
case AL_CONE_OUTER_GAINHF:
CheckSize(1);
- values[0] = Source->OuterGainHF;
+ values[0] = static_cast<T>(Source->OuterGainHF);
return true;
case AL_AIR_ABSORPTION_FACTOR:
CheckSize(1);
- values[0] = Source->AirAbsorptionFactor;
+ values[0] = static_cast<T>(Source->AirAbsorptionFactor);
return true;
case AL_ROOM_ROLLOFF_FACTOR:
CheckSize(1);
- values[0] = Source->RoomRolloffFactor;
+ values[0] = static_cast<T>(Source->RoomRolloffFactor);
return true;
case AL_DOPPLER_FACTOR:
CheckSize(1);
- values[0] = Source->DopplerFactor;
+ values[0] = static_cast<T>(Source->DopplerFactor);
return true;
case AL_SAMPLE_RW_OFFSETS_SOFT:
+ if constexpr(std::is_integral_v<T>)
+ {
+ if(sBufferSubDataCompat)
+ {
+ CheckSize(2);
+ values[0] = GetSourceOffset<T>(Source, AL_SAMPLE_OFFSET, Context);
+ /* FIXME: values[1] should be ahead of values[0] by the device
+ * update time. It needs to clamp or wrap the length of the
+ * buffer queue.
+ */
+ values[1] = values[0];
+ return true;
+ }
+ }
break;
case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/
- if(sBufferSubDataCompat)
- break;
+ if constexpr(std::is_floating_point_v<T>)
+ {
+ if(sBufferSubDataCompat)
+ break;
- CheckSize(1);
- values[0] = Source->Radius;
- return true;
+ CheckSize(1);
+ values[0] = static_cast<T>(Source->Radius);
+ return true;
+ }
+ else
+ {
+ if(sBufferSubDataCompat)
+ {
+ CheckSize(2);
+ values[0] = GetSourceOffset<T>(Source, AL_BYTE_OFFSET, Context);
+ /* FIXME: values[1] should be ahead of values[0] by the device
+ * update time. It needs to clamp or wrap the length of the
+ * buffer queue.
+ */
+ values[1] = values[0];
+ return true;
+ }
+ break;
+ }
case AL_SUPER_STEREO_WIDTH_SOFT:
CheckSize(1);
- values[0] = Source->EnhWidth;
+ values[0] = static_cast<T>(Source->EnhWidth);
return true;
case AL_BYTE_LENGTH_SOFT:
case AL_SAMPLE_LENGTH_SOFT:
case AL_SEC_LENGTH_SOFT:
CheckSize(1);
- values[0] = GetSourceLength(Source, prop);
+ values[0] = GetSourceLength<T>(Source, prop);
return true;
case AL_STEREO_ANGLES:
- CheckSize(2);
- values[0] = Source->StereoPan[0];
- values[1] = Source->StereoPan[1];
- return true;
+ if constexpr(std::is_floating_point_v<T>)
+ {
+ CheckSize(2);
+ values[0] = static_cast<T>(Source->StereoPan[0]);
+ values[1] = static_cast<T>(Source->StereoPan[1]);
+ return true;
+ }
+ break;
- case AL_SEC_OFFSET_LATENCY_SOFT:
- CheckSize(2);
- /* Get the source offset with the clock time first. Then get the clock
- * time with the device latency. Order is important.
- */
- values[0] = GetSourceSecOffset(Source, Context, &srcclock);
+ case AL_SAMPLE_OFFSET_LATENCY_SOFT:
+ if constexpr(std::is_same_v<T,int64_t>)
{
- std::lock_guard<std::mutex> _{device->StateLock};
- clocktime = GetClockLatency(device, device->Backend.get());
+ CheckSize(2);
+ /* Get the source offset with the clock time first. Then get the
+ * clock time with the device latency. Order is important.
+ */
+ ClockLatency clocktime{};
+ nanoseconds srcclock{};
+ values[0] = GetSourceSampleOffset(Source, Context, &srcclock);
+ {
+ std::lock_guard<std::mutex> _{device->StateLock};
+ clocktime = GetClockLatency(device, device->Backend.get());
+ }
+ if(srcclock == clocktime.ClockTime)
+ values[1] = nanoseconds{clocktime.Latency}.count();
+ else
+ {
+ /* If the clock time incremented, reduce the latency by that
+ * much since it's that much closer to the source offset it got
+ * earlier.
+ */
+ const auto diff = std::min(clocktime.Latency, clocktime.ClockTime-srcclock);
+ values[1] = nanoseconds{clocktime.Latency - diff}.count();
+ }
+ return true;
}
- if(srcclock == clocktime.ClockTime)
- values[1] = static_cast<double>(clocktime.Latency.count()) / 1000000000.0;
- else
+ break;
+
+ case AL_SAMPLE_OFFSET_CLOCK_SOFT:
+ if constexpr(std::is_same_v<T,int64_t>)
+ {
+ CheckSize(2);
+ nanoseconds srcclock{};
+ values[0] = GetSourceSampleOffset(Source, Context, &srcclock);
+ values[1] = srcclock.count();
+ return true;
+ }
+ break;
+
+ case AL_SEC_OFFSET_LATENCY_SOFT:
+ if constexpr(std::is_same_v<T,double>)
{
- /* If the clock time incremented, reduce the latency by that much
- * since it's that much closer to the source offset it got earlier.
+ CheckSize(2);
+ /* Get the source offset with the clock time first. Then get the
+ * clock time with the device latency. Order is important.
*/
- const nanoseconds diff{clocktime.ClockTime - srcclock};
- const nanoseconds latency{clocktime.Latency - std::min(clocktime.Latency, diff)};
- values[1] = static_cast<double>(latency.count()) / 1000000000.0;
+ ClockLatency clocktime{};
+ nanoseconds srcclock{};
+ values[0] = GetSourceSecOffset(Source, Context, &srcclock);
+ {
+ std::lock_guard<std::mutex> _{device->StateLock};
+ clocktime = GetClockLatency(device, device->Backend.get());
+ }
+ if(srcclock == clocktime.ClockTime)
+ values[1] = duration_cast<seconds_d>(clocktime.Latency).count();
+ else
+ {
+ /* If the clock time incremented, reduce the latency by that
+ * much since it's that much closer to the source offset it got
+ * earlier.
+ */
+ const auto diff = std::min(clocktime.Latency, clocktime.ClockTime-srcclock);
+ values[1] = duration_cast<seconds_d>(clocktime.Latency - diff).count();
+ }
+ return true;
}
- return true;
+ break;
case AL_SEC_OFFSET_CLOCK_SOFT:
- CheckSize(2);
- values[0] = GetSourceSecOffset(Source, Context, &srcclock);
- values[1] = static_cast<double>(srcclock.count()) / 1000000000.0;
- return true;
+ if constexpr(std::is_same_v<T,double>)
+ {
+ CheckSize(2);
+ nanoseconds srcclock{};
+ values[0] = GetSourceSecOffset(Source, Context, &srcclock);
+ values[1] = duration_cast<seconds_d>(srcclock).count();
+ return true;
+ }
+ break;
case AL_POSITION:
CheckSize(3);
- values[0] = Source->Position[0];
- values[1] = Source->Position[1];
- values[2] = Source->Position[2];
+ values[0] = static_cast<T>(Source->Position[0]);
+ values[1] = static_cast<T>(Source->Position[1]);
+ values[2] = static_cast<T>(Source->Position[2]);
return true;
case AL_VELOCITY:
CheckSize(3);
- values[0] = Source->Velocity[0];
- values[1] = Source->Velocity[1];
- values[2] = Source->Velocity[2];
+ values[0] = static_cast<T>(Source->Velocity[0]);
+ values[1] = static_cast<T>(Source->Velocity[1]);
+ values[2] = static_cast<T>(Source->Velocity[2]);
return true;
case AL_DIRECTION:
CheckSize(3);
- values[0] = Source->Direction[0];
- values[1] = Source->Direction[1];
- values[2] = Source->Direction[2];
+ values[0] = static_cast<T>(Source->Direction[0]);
+ values[1] = static_cast<T>(Source->Direction[1]);
+ values[2] = static_cast<T>(Source->Direction[2]);
return true;
case AL_ORIENTATION:
CheckSize(6);
- values[0] = Source->OrientAt[0];
- values[1] = Source->OrientAt[1];
- values[2] = Source->OrientAt[2];
- values[3] = Source->OrientUp[0];
- values[4] = Source->OrientUp[1];
- values[5] = Source->OrientUp[2];
+ values[0] = static_cast<T>(Source->OrientAt[0]);
+ values[1] = static_cast<T>(Source->OrientAt[1]);
+ values[2] = static_cast<T>(Source->OrientAt[2]);
+ values[3] = static_cast<T>(Source->OrientUp[0]);
+ values[4] = static_cast<T>(Source->OrientUp[1]);
+ values[5] = static_cast<T>(Source->OrientUp[2]);
return true;
- /* 1x int */
- case AL_SOURCE_RELATIVE:
- case AL_LOOPING:
- case AL_SOURCE_STATE:
- case AL_BUFFERS_QUEUED:
- case AL_BUFFERS_PROCESSED:
- case AL_SOURCE_TYPE:
- case AL_DIRECT_FILTER_GAINHF_AUTO:
- case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
- case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
- case AL_DIRECT_CHANNELS_SOFT:
- case AL_DISTANCE_MODEL:
- case AL_SOURCE_RESAMPLER_SOFT:
- case AL_SOURCE_SPATIALIZE_SOFT:
- case AL_STEREO_MODE_SOFT:
- CheckSize(1);
- if((err=GetSourceiv(Source, Context, prop, {ivals, 1u})) != false)
- values[0] = static_cast<double>(ivals[0]);
- return err;
-
- case AL_BUFFER:
- case AL_DIRECT_FILTER:
- case AL_AUXILIARY_SEND_FILTER:
- case AL_SAMPLE_OFFSET_LATENCY_SOFT:
- case AL_SAMPLE_OFFSET_CLOCK_SOFT:
- break;
- }
-
- ERR("Unexpected property: 0x%04x\n", prop);
- Context->setError(AL_INVALID_ENUM, "Invalid source double property 0x%04x", prop);
- return false;
-}
-catch(check_exception&) {
- return false;
-}
-
-bool GetSourceiv(ALsource *const Source, ALCcontext *const Context, const SourceProp prop,
- const al::span<int> values)
-try {
- auto CheckSize = GetSizeChecker(Context, prop, values);
- double dvals[MaxValues];
- bool err;
- switch(prop)
- {
case AL_SOURCE_RELATIVE:
- CheckSize(1);
- values[0] = Source->HeadRelative;
- return true;
+ if constexpr(std::is_integral_v<T>)
+ {
+ CheckSize(1);
+ values[0] = Source->HeadRelative;
+ return true;
+ }
+ break;
case AL_LOOPING:
- CheckSize(1);
- values[0] = Source->Looping;
- return true;
+ if constexpr(std::is_integral_v<T>)
+ {
+ CheckSize(1);
+ values[0] = Source->Looping;
+ return true;
+ }
+ break;
case AL_BUFFER:
- CheckSize(1);
+ if constexpr(std::is_integral_v<T>)
{
+ CheckSize(1);
ALbufferQueueItem *BufferList{};
/* HACK: This query should technically only return the buffer set
* on a static source. However, some apps had used it to detect
@@ -2356,377 +2307,150 @@ try {
BufferList = static_cast<ALbufferQueueItem*>(Current);
}
ALbuffer *buffer{BufferList ? BufferList->mBuffer : nullptr};
- values[0] = buffer ? static_cast<int>(buffer->id) : 0;
+ values[0] = buffer ? static_cast<T>(buffer->id) : T{0};
+ return true;
}
- return true;
+ break;
case AL_SOURCE_STATE:
- CheckSize(1);
- values[0] = GetSourceState(Source, GetSourceVoice(Source, Context));
- return true;
+ if constexpr(std::is_integral_v<T>)
+ {
+ CheckSize(1);
+ values[0] = GetSourceState(Source, GetSourceVoice(Source, Context));
+ return true;
+ }
+ break;
case AL_BUFFERS_QUEUED:
- CheckSize(1);
- values[0] = static_cast<int>(Source->mQueue.size());
- return true;
-
- case AL_BUFFERS_PROCESSED:
- CheckSize(1);
- if(Source->Looping || Source->SourceType != AL_STREAMING)
+ if constexpr(std::is_integral_v<T>)
{
- /* Buffers on a looping source are in a perpetual state of PENDING,
- * so don't report any as PROCESSED
- */
- values[0] = 0;
+ CheckSize(1);
+ values[0] = static_cast<T>(Source->mQueue.size());
+ return true;
}
- else
+ break;
+
+ case AL_BUFFERS_PROCESSED:
+ if constexpr(std::is_integral_v<T>)
{
- int played{0};
- if(Source->state != AL_INITIAL)
+ CheckSize(1);
+ if(Source->Looping || Source->SourceType != AL_STREAMING)
+ {
+ /* Buffers on a looping source are in a perpetual state of
+ * PENDING, so don't report any as PROCESSED
+ */
+ values[0] = 0;
+ }
+ else
{
- const VoiceBufferItem *Current{nullptr};
- if(Voice *voice{GetSourceVoice(Source, Context)})
- Current = voice->mCurrentBuffer.load(std::memory_order_relaxed);
- for(auto &item : Source->mQueue)
+ int played{0};
+ if(Source->state != AL_INITIAL)
{
- if(&item == Current)
- break;
- ++played;
+ const VoiceBufferItem *Current{nullptr};
+ if(Voice *voice{GetSourceVoice(Source, Context)})
+ Current = voice->mCurrentBuffer.load(std::memory_order_relaxed);
+ for(auto &item : Source->mQueue)
+ {
+ if(&item == Current)
+ break;
+ ++played;
+ }
}
+ values[0] = played;
}
- values[0] = played;
+ return true;
}
- return true;
+ break;
case AL_SOURCE_TYPE:
- CheckSize(1);
- values[0] = Source->SourceType;
- return true;
-
- case AL_DIRECT_FILTER_GAINHF_AUTO:
- CheckSize(1);
- values[0] = Source->DryGainHFAuto;
- return true;
-
- case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
- CheckSize(1);
- values[0] = Source->WetGainAuto;
- return true;
-
- case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
- CheckSize(1);
- values[0] = Source->WetGainHFAuto;
- return true;
-
- case AL_DIRECT_CHANNELS_SOFT:
- CheckSize(1);
- values[0] = EnumFromDirectMode(Source->DirectChannels);
- return true;
-
- case AL_DISTANCE_MODEL:
- CheckSize(1);
- values[0] = ALenumFromDistanceModel(Source->mDistanceModel);
- return true;
-
- case AL_BYTE_LENGTH_SOFT:
- case AL_SAMPLE_LENGTH_SOFT:
- case AL_SEC_LENGTH_SOFT:
- CheckSize(1);
- values[0] = static_cast<int>(mind(GetSourceLength(Source, prop),
- std::numeric_limits<int>::max()));
- return true;
-
- case AL_SOURCE_RESAMPLER_SOFT:
- CheckSize(1);
- values[0] = static_cast<int>(Source->mResampler);
- return true;
-
- case AL_SOURCE_SPATIALIZE_SOFT:
- CheckSize(1);
- values[0] = EnumFromSpatializeMode(Source->mSpatialize);
- return true;
-
- case AL_STEREO_MODE_SOFT:
- CheckSize(1);
- values[0] = EnumFromStereoMode(Source->mStereoMode);
- return true;
-
- case AL_SAMPLE_RW_OFFSETS_SOFT:
- if(sBufferSubDataCompat)
+ if constexpr(std::is_integral_v<T>)
{
- CheckSize(2);
- const auto offset = GetSourceOffset(Source, AL_SAMPLE_OFFSET, Context);
- /* FIXME: values[1] should be ahead of values[0] by the device
- * update time. It needs to clamp or wrap the length of the buffer
- * queue.
- */
- values[0] = static_cast<int>(mind(offset, std::numeric_limits<int>::max()));
- values[1] = values[0];
+ CheckSize(1);
+ values[0] = Source->SourceType;
return true;
}
break;
- case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/
- if(sBufferSubDataCompat)
+
+ case AL_DIRECT_FILTER_GAINHF_AUTO:
+ if constexpr(std::is_integral_v<T>)
{
- CheckSize(2);
- const auto offset = GetSourceOffset(Source, AL_BYTE_OFFSET, Context);
- /* FIXME: values[1] should be ahead of values[0] by the device
- * update time. It needs to clamp or wrap the length of the buffer
- * queue.
- */
- values[0] = static_cast<int>(mind(offset, std::numeric_limits<int>::max()));
- values[1] = values[0];
+ CheckSize(1);
+ values[0] = Source->DryGainHFAuto;
return true;
}
- /*fall-through*/
-
- /* 1x float/double */
- case AL_CONE_INNER_ANGLE:
- case AL_CONE_OUTER_ANGLE:
- case AL_PITCH:
- case AL_GAIN:
- case AL_MIN_GAIN:
- case AL_MAX_GAIN:
- case AL_REFERENCE_DISTANCE:
- case AL_ROLLOFF_FACTOR:
- case AL_CONE_OUTER_GAIN:
- case AL_MAX_DISTANCE:
- case AL_SEC_OFFSET:
- case AL_SAMPLE_OFFSET:
- case AL_BYTE_OFFSET:
- case AL_DOPPLER_FACTOR:
- case AL_AIR_ABSORPTION_FACTOR:
- case AL_ROOM_ROLLOFF_FACTOR:
- case AL_CONE_OUTER_GAINHF:
- case AL_SUPER_STEREO_WIDTH_SOFT:
- CheckSize(1);
- if((err=GetSourcedv(Source, Context, prop, {dvals, 1u})) != false)
- values[0] = static_cast<int>(dvals[0]);
- return err;
+ break;
- /* 3x float/double */
- case AL_POSITION:
- case AL_VELOCITY:
- case AL_DIRECTION:
- CheckSize(3);
- if((err=GetSourcedv(Source, Context, prop, {dvals, 3u})) != false)
+ case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
+ if constexpr(std::is_integral_v<T>)
{
- values[0] = static_cast<int>(dvals[0]);
- values[1] = static_cast<int>(dvals[1]);
- values[2] = static_cast<int>(dvals[2]);
+ CheckSize(1);
+ values[0] = Source->WetGainAuto;
+ return true;
}
- return err;
+ break;
- /* 6x float/double */
- case AL_ORIENTATION:
- CheckSize(6);
- if((err=GetSourcedv(Source, Context, prop, {dvals, 6u})) != false)
+ case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
+ if constexpr(std::is_integral_v<T>)
{
- values[0] = static_cast<int>(dvals[0]);
- values[1] = static_cast<int>(dvals[1]);
- values[2] = static_cast<int>(dvals[2]);
- values[3] = static_cast<int>(dvals[3]);
- values[4] = static_cast<int>(dvals[4]);
- values[5] = static_cast<int>(dvals[5]);
+ CheckSize(1);
+ values[0] = Source->WetGainHFAuto;
+ return true;
}
- return err;
-
- case AL_SAMPLE_OFFSET_LATENCY_SOFT:
- case AL_SAMPLE_OFFSET_CLOCK_SOFT:
- break; /* i64 only */
- case AL_SEC_OFFSET_LATENCY_SOFT:
- case AL_SEC_OFFSET_CLOCK_SOFT:
- break; /* Double only */
- case AL_STEREO_ANGLES:
- break; /* Float/double only */
-
- case AL_DIRECT_FILTER:
- case AL_AUXILIARY_SEND_FILTER:
- break; /* ??? */
- }
-
- ERR("Unexpected property: 0x%04x\n", prop);
- Context->setError(AL_INVALID_ENUM, "Invalid source integer property 0x%04x", prop);
- return false;
-}
-catch(check_exception&) {
- return false;
-}
-
-bool GetSourcei64v(ALsource *const Source, ALCcontext *const Context, const SourceProp prop,
- const al::span<int64_t> values)
-try {
- auto CheckSize = GetSizeChecker(Context, prop, values);
- ALCdevice *device{Context->mALDevice.get()};
- ClockLatency clocktime;
- nanoseconds srcclock;
- double dvals[MaxValues];
- int ivals[MaxValues];
- bool err;
-
- switch(prop)
- {
- case AL_BYTE_LENGTH_SOFT:
- case AL_SAMPLE_LENGTH_SOFT:
- case AL_SEC_LENGTH_SOFT:
- CheckSize(1);
- values[0] = static_cast<int64_t>(GetSourceLength(Source, prop));
- return true;
+ break;
- case AL_SAMPLE_OFFSET_LATENCY_SOFT:
- CheckSize(2);
- /* Get the source offset with the clock time first. Then get the clock
- * time with the device latency. Order is important.
- */
- values[0] = GetSourceSampleOffset(Source, Context, &srcclock);
- {
- std::lock_guard<std::mutex> _{device->StateLock};
- clocktime = GetClockLatency(device, device->Backend.get());
- }
- if(srcclock == clocktime.ClockTime)
- values[1] = clocktime.Latency.count();
- else
+ case AL_DIRECT_CHANNELS_SOFT:
+ if constexpr(std::is_integral_v<T>)
{
- /* If the clock time incremented, reduce the latency by that much
- * since it's that much closer to the source offset it got earlier.
- */
- const nanoseconds diff{clocktime.ClockTime - srcclock};
- values[1] = nanoseconds{clocktime.Latency - std::min(clocktime.Latency, diff)}.count();
+ CheckSize(1);
+ values[0] = EnumFromDirectMode(Source->DirectChannels);
+ return true;
}
- return true;
-
- case AL_SAMPLE_OFFSET_CLOCK_SOFT:
- CheckSize(2);
- values[0] = GetSourceSampleOffset(Source, Context, &srcclock);
- values[1] = srcclock.count();
- return true;
+ break;
- case AL_SAMPLE_RW_OFFSETS_SOFT:
- if(sBufferSubDataCompat)
+ case AL_DISTANCE_MODEL:
+ if constexpr(std::is_integral_v<T>)
{
- CheckSize(2);
- /* FIXME: values[1] should be ahead of values[0] by the device
- * update time. It needs to clamp or wrap the length of the buffer
- * queue.
- */
- values[0] = static_cast<int64_t>(GetSourceOffset(Source, AL_SAMPLE_OFFSET, Context));
- values[1] = values[0];
+ CheckSize(1);
+ values[0] = ALenumFromDistanceModel(Source->mDistanceModel);
return true;
}
break;
- case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/
- if(sBufferSubDataCompat)
+
+ case AL_SOURCE_RESAMPLER_SOFT:
+ if constexpr(std::is_integral_v<T>)
{
- CheckSize(2);
- /* FIXME: values[1] should be ahead of values[0] by the device
- * update time. It needs to clamp or wrap the length of the buffer
- * queue.
- */
- values[0] = static_cast<int64_t>(GetSourceOffset(Source, AL_BYTE_OFFSET, Context));
- values[1] = values[0];
+ CheckSize(1);
+ values[0] = static_cast<T>(Source->mResampler);
return true;
}
- /*fall-through*/
-
- /* 1x float/double */
- case AL_CONE_INNER_ANGLE:
- case AL_CONE_OUTER_ANGLE:
- case AL_PITCH:
- case AL_GAIN:
- case AL_MIN_GAIN:
- case AL_MAX_GAIN:
- case AL_REFERENCE_DISTANCE:
- case AL_ROLLOFF_FACTOR:
- case AL_CONE_OUTER_GAIN:
- case AL_MAX_DISTANCE:
- case AL_SEC_OFFSET:
- case AL_SAMPLE_OFFSET:
- case AL_BYTE_OFFSET:
- case AL_DOPPLER_FACTOR:
- case AL_AIR_ABSORPTION_FACTOR:
- case AL_ROOM_ROLLOFF_FACTOR:
- case AL_CONE_OUTER_GAINHF:
- case AL_SUPER_STEREO_WIDTH_SOFT:
- CheckSize(1);
- if((err=GetSourcedv(Source, Context, prop, {dvals, 1u})) != false)
- values[0] = static_cast<int64_t>(dvals[0]);
- return err;
+ break;
- /* 3x float/double */
- case AL_POSITION:
- case AL_VELOCITY:
- case AL_DIRECTION:
- CheckSize(3);
- if((err=GetSourcedv(Source, Context, prop, {dvals, 3u})) != false)
+ case AL_SOURCE_SPATIALIZE_SOFT:
+ if constexpr(std::is_integral_v<T>)
{
- values[0] = static_cast<int64_t>(dvals[0]);
- values[1] = static_cast<int64_t>(dvals[1]);
- values[2] = static_cast<int64_t>(dvals[2]);
+ CheckSize(1);
+ values[0] = EnumFromSpatializeMode(Source->mSpatialize);
+ return true;
}
- return err;
+ break;
- /* 6x float/double */
- case AL_ORIENTATION:
- CheckSize(6);
- if((err=GetSourcedv(Source, Context, prop, {dvals, 6u})) != false)
+ case AL_STEREO_MODE_SOFT:
+ if constexpr(std::is_integral_v<T>)
{
- values[0] = static_cast<int64_t>(dvals[0]);
- values[1] = static_cast<int64_t>(dvals[1]);
- values[2] = static_cast<int64_t>(dvals[2]);
- values[3] = static_cast<int64_t>(dvals[3]);
- values[4] = static_cast<int64_t>(dvals[4]);
- values[5] = static_cast<int64_t>(dvals[5]);
+ CheckSize(1);
+ values[0] = EnumFromStereoMode(Source->mStereoMode);
+ return true;
}
- return err;
-
- /* 1x int */
- case AL_SOURCE_RELATIVE:
- case AL_LOOPING:
- case AL_SOURCE_STATE:
- case AL_BUFFERS_QUEUED:
- case AL_BUFFERS_PROCESSED:
- case AL_SOURCE_TYPE:
- case AL_DIRECT_FILTER_GAINHF_AUTO:
- case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
- case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
- case AL_DIRECT_CHANNELS_SOFT:
- case AL_DISTANCE_MODEL:
- case AL_SOURCE_RESAMPLER_SOFT:
- case AL_SOURCE_SPATIALIZE_SOFT:
- case AL_STEREO_MODE_SOFT:
- CheckSize(1);
- if((err=GetSourceiv(Source, Context, prop, {ivals, 1u})) != false)
- values[0] = ivals[0];
- return err;
+ break;
- /* 1x uint */
- case AL_BUFFER:
case AL_DIRECT_FILTER:
- CheckSize(1);
- if((err=GetSourceiv(Source, Context, prop, {ivals, 1u})) != false)
- values[0] = static_cast<ALuint>(ivals[0]);
- return err;
-
- /* 3x uint */
case AL_AUXILIARY_SEND_FILTER:
- CheckSize(3);
- if((err=GetSourceiv(Source, Context, prop, {ivals, 3u})) != false)
- {
- values[0] = static_cast<ALuint>(ivals[0]);
- values[1] = static_cast<ALuint>(ivals[1]);
- values[2] = static_cast<ALuint>(ivals[2]);
- }
- return err;
-
- case AL_SEC_OFFSET_LATENCY_SOFT:
- case AL_SEC_OFFSET_CLOCK_SOFT:
- break; /* Double only */
- case AL_STEREO_ANGLES:
- break; /* Float/double only */
+ break;
}
- ERR("Unexpected property: 0x%04x\n", prop);
- Context->setError(AL_INVALID_ENUM, "Invalid source integer64 property 0x%04x", prop);
+ ERR("Unexpected %s query property: 0x%04x\n", PropType<T>::Name(), prop);
+ Context->setError(AL_INVALID_ENUM, "Invalid source %s query property 0x%04x",
+ PropType<T>::Name(), prop);
return false;
}
catch(check_exception&) {
@@ -2905,12 +2629,9 @@ void StartSources(ALCcontext *const context, const al::span<ALsource*> srchandle
} // namespace
-AL_API void AL_APIENTRY alGenSources(ALsizei n, ALuint *sources)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alGenSources, ALsizei, ALuint*)
+FORCE_ALIGN void AL_APIENTRY alGenSourcesDirect(ALCcontext *context, ALsizei n, ALuint *sources) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Generating %d sources", n);
if(n <= 0) UNLIKELY return;
@@ -2923,7 +2644,7 @@ START_API_FUNC
device->SourcesMax, context->mNumSources, n);
return;
}
- if(!EnsureSources(context.get(), static_cast<ALuint>(n)))
+ if(!EnsureSources(context, static_cast<ALuint>(n)))
{
context->setError(AL_OUT_OF_MEMORY, "Failed to allocate %d source%s", n, (n==1)?"":"s");
return;
@@ -2931,36 +2652,33 @@ START_API_FUNC
if(n == 1)
{
- ALsource *source{AllocSource(context.get())};
+ ALsource *source{AllocSource(context)};
sources[0] = source->id;
#ifdef ALSOFT_EAX
- source->eaxInitialize(context.get());
+ source->eaxInitialize(context);
#endif // ALSOFT_EAX
}
else
{
- al::vector<ALuint> ids;
+ std::vector<ALuint> ids;
ids.reserve(static_cast<ALuint>(n));
do {
- ALsource *source{AllocSource(context.get())};
+ ALsource *source{AllocSource(context)};
ids.emplace_back(source->id);
#ifdef ALSOFT_EAX
- source->eaxInitialize(context.get());
+ source->eaxInitialize(context);
#endif // ALSOFT_EAX
} while(--n);
std::copy(ids.cbegin(), ids.cend(), sources);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alDeleteSources, ALsizei, const ALuint*)
+FORCE_ALIGN void AL_APIENTRY alDeleteSourcesDirect(ALCcontext *context, ALsizei n,
+ const ALuint *sources) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Deleting %d sources", n);
if(n <= 0) UNLIKELY return;
@@ -2968,8 +2686,8 @@ START_API_FUNC
std::lock_guard<std::mutex> _{context->mSourceLock};
/* Check that all Sources are valid */
- auto validate_source = [&context](const ALuint sid) -> bool
- { return LookupSource(context.get(), sid) != nullptr; };
+ auto validate_source = [context](const ALuint sid) -> bool
+ { return LookupSource(context, sid) != nullptr; };
const ALuint *sources_end = sources + n;
auto invsrc = std::find_if_not(sources, sources_end, validate_source);
@@ -2979,577 +2697,462 @@ START_API_FUNC
/* All good. Delete source IDs. */
auto delete_source = [&context](const ALuint sid) -> void
{
- ALsource *src{LookupSource(context.get(), sid)};
- if(src) FreeSource(context.get(), src);
+ ALsource *src{LookupSource(context, sid)};
+ if(src) FreeSource(context, src);
};
std::for_each(sources, sources_end, delete_source);
}
-END_API_FUNC
-AL_API ALboolean AL_APIENTRY alIsSource(ALuint source)
-START_API_FUNC
+AL_API DECL_FUNC1(ALboolean, alIsSource, ALuint)
+FORCE_ALIGN ALboolean AL_APIENTRY alIsSourceDirect(ALCcontext *context, ALuint source) noexcept
{
- ContextRef context{GetContextRef()};
- if(context) LIKELY
- {
- std::lock_guard<std::mutex> _{context->mSourceLock};
- if(LookupSource(context.get(), source) != nullptr)
- return AL_TRUE;
- }
+ std::lock_guard<std::mutex> _{context->mSourceLock};
+ if(LookupSource(context, source) != nullptr)
+ return AL_TRUE;
return AL_FALSE;
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alSourcef, ALuint, ALenum, ALfloat)
+FORCE_ALIGN void AL_APIENTRY alSourcefDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALfloat value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source = LookupSource(context.get(), source);
+ ALsource *Source = LookupSource(context, source);
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else
- SetSourcefv(Source, context.get(), static_cast<SourceProp>(param), {&value, 1u});
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+
+ SetProperty<float>(Source, context, static_cast<SourceProp>(param), al::span{&value, 1u});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3)
-START_API_FUNC
+AL_API DECL_FUNC5(void, alSource3f, ALuint, ALenum, ALfloat, ALfloat, ALfloat)
+FORCE_ALIGN void AL_APIENTRY alSource3fDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALfloat value1, ALfloat value2, ALfloat value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source = LookupSource(context.get(), source);
+ ALsource *Source = LookupSource(context, source);
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else
- {
- const float fvals[3]{ value1, value2, value3 };
- SetSourcefv(Source, context.get(), static_cast<SourceProp>(param), fvals);
- }
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+
+ const float fvals[3]{ value1, value2, value3 };
+ SetProperty<float>(Source, context, static_cast<SourceProp>(param), al::span{fvals});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alSourcefv, ALuint, ALenum, const ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alSourcefvDirect(ALCcontext *context, ALuint source, ALenum param,
+ const ALfloat *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source = LookupSource(context.get(), source);
+ ALsource *Source = LookupSource(context, source);
if(!Source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
if(!values) UNLIKELY
return context->setError(AL_INVALID_VALUE, "NULL pointer");
const ALuint count{FloatValsByProp(param)};
- SetSourcefv(Source, context.get(), static_cast<SourceProp>(param), {values, count});
+ SetProperty(Source, context, static_cast<SourceProp>(param), al::span{values, count});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alSourced,SOFT, ALuint, ALenum, ALdouble)
+FORCE_ALIGN void AL_APIENTRY alSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param,
+ ALdouble value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source = LookupSource(context.get(), source);
+ ALsource *Source = LookupSource(context, source);
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else
- {
- const float fval[1]{static_cast<float>(value)};
- SetSourcefv(Source, context.get(), static_cast<SourceProp>(param), fval);
- }
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+
+ SetProperty<double>(Source, context, static_cast<SourceProp>(param), al::span{&value, 1});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3)
-START_API_FUNC
+AL_API DECL_FUNCEXT5(void, alSource3d,SOFT, ALuint, ALenum, ALdouble, ALdouble, ALdouble)
+FORCE_ALIGN void AL_APIENTRY alSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param,
+ ALdouble value1, ALdouble value2, ALdouble value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source = LookupSource(context.get(), source);
+ ALsource *Source = LookupSource(context, source);
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else
- {
- const float fvals[3]{static_cast<float>(value1), static_cast<float>(value2),
- static_cast<float>(value3)};
- SetSourcefv(Source, context.get(), static_cast<SourceProp>(param), fvals);
- }
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+
+ const double dvals[3]{value1, value2, value3};
+ SetProperty<double>(Source, context, static_cast<SourceProp>(param), al::span{dvals});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alSourcedv,SOFT, ALuint, ALenum, const ALdouble*)
+FORCE_ALIGN void AL_APIENTRY alSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param,
+ const ALdouble *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source = LookupSource(context.get(), source);
+ ALsource *Source = LookupSource(context, source);
if(!Source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
if(!values) UNLIKELY
return context->setError(AL_INVALID_VALUE, "NULL pointer");
const ALuint count{DoubleValsByProp(param)};
- float fvals[MaxValues];
- std::copy_n(values, count, fvals);
- SetSourcefv(Source, context.get(), static_cast<SourceProp>(param), {fvals, count});
+ SetProperty(Source, context, static_cast<SourceProp>(param), al::span{values, count});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alSourcei, ALuint, ALenum, ALint)
+FORCE_ALIGN void AL_APIENTRY alSourceiDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALint value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source = LookupSource(context.get(), source);
+ ALsource *Source = LookupSource(context, source);
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else
- SetSourceiv(Source, context.get(), static_cast<SourceProp>(param), {&value, 1u});
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+
+ SetProperty<int>(Source, context, static_cast<SourceProp>(param), al::span{&value, 1u});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3)
-START_API_FUNC
+AL_API DECL_FUNC5(void, alSource3i, ALuint, ALenum, ALint, ALint, ALint)
+FORCE_ALIGN void AL_APIENTRY alSource3iDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALint value1, ALint value2, ALint value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source = LookupSource(context.get(), source);
+ ALsource *Source = LookupSource(context, source);
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else
- {
- const int ivals[3]{ value1, value2, value3 };
- SetSourceiv(Source, context.get(), static_cast<SourceProp>(param), ivals);
- }
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+
+ const int ivals[3]{ value1, value2, value3 };
+ SetProperty<int>(Source, context, static_cast<SourceProp>(param), al::span{ivals});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alSourceiv, ALuint, ALenum, const ALint*)
+FORCE_ALIGN void AL_APIENTRY alSourceivDirect(ALCcontext *context, ALuint source, ALenum param,
+ const ALint *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source = LookupSource(context.get(), source);
+ ALsource *Source = LookupSource(context, source);
if(!Source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
if(!values) UNLIKELY
return context->setError(AL_INVALID_VALUE, "NULL pointer");
const ALuint count{IntValsByProp(param)};
- SetSourceiv(Source, context.get(), static_cast<SourceProp>(param), {values, count});
+ SetProperty(Source, context, static_cast<SourceProp>(param), al::span{values, count});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alSourcei64,SOFT, ALuint, ALenum, ALint64SOFT)
+FORCE_ALIGN void AL_APIENTRY alSourcei64DirectSOFT(ALCcontext *context, ALuint source,
+ ALenum param, ALint64SOFT value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else
- SetSourcei64v(Source, context.get(), static_cast<SourceProp>(param), {&value, 1u});
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+
+ SetProperty<int64_t>(Source, context, static_cast<SourceProp>(param), al::span{&value, 1u});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3)
-START_API_FUNC
+AL_API DECL_FUNCEXT5(void, alSource3i64,SOFT, ALuint, ALenum, ALint64SOFT, ALint64SOFT, ALint64SOFT)
+FORCE_ALIGN void AL_APIENTRY alSource3i64DirectSOFT(ALCcontext *context, ALuint source,
+ ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else
- {
- const int64_t i64vals[3]{ value1, value2, value3 };
- SetSourcei64v(Source, context.get(), static_cast<SourceProp>(param), i64vals);
- }
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+
+ const int64_t i64vals[3]{ value1, value2, value3 };
+ SetProperty<int64_t>(Source, context, static_cast<SourceProp>(param), al::span{i64vals});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alSourcei64v,SOFT, ALuint, ALenum, const ALint64SOFT*)
+FORCE_ALIGN void AL_APIENTRY alSourcei64vDirectSOFT(ALCcontext *context, ALuint source,
+ ALenum param, const ALint64SOFT *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
if(!values) UNLIKELY
return context->setError(AL_INVALID_VALUE, "NULL pointer");
const ALuint count{Int64ValsByProp(param)};
- SetSourcei64v(Source, context.get(), static_cast<SourceProp>(param), {values, count});
+ SetProperty(Source, context, static_cast<SourceProp>(param), al::span{values, count});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetSourcef, ALuint, ALenum, ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alGetSourcefDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALfloat *value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!value) UNLIKELY
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else
- {
- double dval[1];
- if(GetSourcedv(Source, context.get(), static_cast<SourceProp>(param), dval))
- *value = static_cast<float>(dval[0]);
- }
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+ if(!value) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ std::ignore = GetProperty(Source, context, static_cast<SourceProp>(param), al::span{value, 1});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
-START_API_FUNC
+AL_API DECL_FUNC5(void, alGetSource3f, ALuint, ALenum, ALfloat*, ALfloat*, ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alGetSource3fDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALfloat *value1, ALfloat *value2, ALfloat *value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!(value1 && value2 && value3)) UNLIKELY
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+ if(!(value1 && value2 && value3)) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ float fvals[3];
+ if(GetProperty<float>(Source, context, static_cast<SourceProp>(param), al::span{fvals}))
{
- double dvals[3];
- if(GetSourcedv(Source, context.get(), static_cast<SourceProp>(param), dvals))
- {
- *value1 = static_cast<float>(dvals[0]);
- *value2 = static_cast<float>(dvals[1]);
- *value3 = static_cast<float>(dvals[2]);
- }
+ *value1 = fvals[0];
+ *value2 = fvals[1];
+ *value3 = fvals[2];
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetSourcefv, ALuint, ALenum, ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alGetSourcefvDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALfloat *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
if(!values) UNLIKELY
return context->setError(AL_INVALID_VALUE, "NULL pointer");
const ALuint count{FloatValsByProp(param)};
- double dvals[MaxValues];
- if(GetSourcedv(Source, context.get(), static_cast<SourceProp>(param), {dvals, count}))
- std::copy_n(dvals, count, values);
+ std::ignore = GetProperty(Source, context, static_cast<SourceProp>(param),
+ al::span{values, count});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alGetSourced,SOFT, ALuint, ALenum, ALdouble*)
+FORCE_ALIGN void AL_APIENTRY alGetSourcedDirectSOFT(ALCcontext *context, ALuint source,
+ ALenum param, ALdouble *value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!value) UNLIKELY
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else
- GetSourcedv(Source, context.get(), static_cast<SourceProp>(param), {value, 1u});
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+ if(!value) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ std::ignore = GetProperty(Source, context, static_cast<SourceProp>(param), al::span{value, 1});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3)
-START_API_FUNC
+AL_API DECL_FUNCEXT5(void, alGetSource3d,SOFT, ALuint, ALenum, ALdouble*, ALdouble*, ALdouble*)
+FORCE_ALIGN void AL_APIENTRY alGetSource3dDirectSOFT(ALCcontext *context, ALuint source,
+ ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!(value1 && value2 && value3)) UNLIKELY
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+ if(!(value1 && value2 && value3)) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ double dvals[3];
+ if(GetProperty<double>(Source, context, static_cast<SourceProp>(param), al::span{dvals}))
{
- double dvals[3];
- if(GetSourcedv(Source, context.get(), static_cast<SourceProp>(param), dvals))
- {
- *value1 = dvals[0];
- *value2 = dvals[1];
- *value3 = dvals[2];
- }
+ *value1 = dvals[0];
+ *value2 = dvals[1];
+ *value3 = dvals[2];
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alGetSourcedv,SOFT, ALuint, ALenum, ALdouble*)
+FORCE_ALIGN void AL_APIENTRY alGetSourcedvDirectSOFT(ALCcontext *context, ALuint source,
+ ALenum param, ALdouble *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
if(!values) UNLIKELY
return context->setError(AL_INVALID_VALUE, "NULL pointer");
const ALuint count{DoubleValsByProp(param)};
- GetSourcedv(Source, context.get(), static_cast<SourceProp>(param), {values, count});
+ std::ignore = GetProperty(Source, context, static_cast<SourceProp>(param),
+ al::span{values, count});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetSourcei, ALuint, ALenum, ALint*)
+FORCE_ALIGN void AL_APIENTRY alGetSourceiDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALint *value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!value) UNLIKELY
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else
- GetSourceiv(Source, context.get(), static_cast<SourceProp>(param), {value, 1u});
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+ if(!value) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ std::ignore = GetProperty(Source, context, static_cast<SourceProp>(param), al::span{value, 1});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3)
-START_API_FUNC
+AL_API DECL_FUNC5(void, alGetSource3i, ALuint, ALenum, ALint*, ALint*, ALint*)
+FORCE_ALIGN void AL_APIENTRY alGetSource3iDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALint *value1, ALint *value2, ALint *value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!(value1 && value2 && value3)) UNLIKELY
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+ if(!(value1 && value2 && value3)) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ int ivals[3];
+ if(GetProperty<int>(Source, context, static_cast<SourceProp>(param), al::span{ivals}))
{
- int ivals[3];
- if(GetSourceiv(Source, context.get(), static_cast<SourceProp>(param), ivals))
- {
- *value1 = ivals[0];
- *value2 = ivals[1];
- *value3 = ivals[2];
- }
+ *value1 = ivals[0];
+ *value2 = ivals[1];
+ *value3 = ivals[2];
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetSourceiv, ALuint, ALenum, ALint*)
+FORCE_ALIGN void AL_APIENTRY alGetSourceivDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALint *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
if(!values) UNLIKELY
return context->setError(AL_INVALID_VALUE, "NULL pointer");
const ALuint count{IntValsByProp(param)};
- GetSourceiv(Source, context.get(), static_cast<SourceProp>(param), {values, count});
+ std::ignore = GetProperty(Source, context, static_cast<SourceProp>(param),
+ al::span{values, count});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alGetSourcei64,SOFT, ALuint, ALenum, ALint64SOFT*)
+FORCE_ALIGN void AL_APIENTRY alGetSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!value) UNLIKELY
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else
- GetSourcei64v(Source, context.get(), static_cast<SourceProp>(param), {value, 1u});
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+ if(!value) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ std::ignore = GetProperty(Source, context, static_cast<SourceProp>(param), al::span{value, 1});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3)
-START_API_FUNC
+AL_API DECL_FUNCEXT5(void, alGetSource3i64,SOFT, ALuint, ALenum, ALint64SOFT*, ALint64SOFT*, ALint64SOFT*)
+FORCE_ALIGN void AL_APIENTRY alGetSource3i64DirectSOFT(ALCcontext *context, ALuint source,
+ ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!(value1 && value2 && value3)) UNLIKELY
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+ if(!(value1 && value2 && value3)) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ int64_t i64vals[3];
+ if(GetProperty<int64_t>(Source, context, static_cast<SourceProp>(param), al::span{i64vals}))
{
- int64_t i64vals[3];
- if(GetSourcei64v(Source, context.get(), static_cast<SourceProp>(param), i64vals))
- {
- *value1 = i64vals[0];
- *value2 = i64vals[1];
- *value3 = i64vals[2];
- }
+ *value1 = i64vals[0];
+ *value2 = i64vals[1];
+ *value3 = i64vals[2];
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alGetSourcei64v,SOFT, ALuint, ALenum, ALint64SOFT*)
+FORCE_ALIGN void AL_APIENTRY alGetSourcei64vDirectSOFT(ALCcontext *context, ALuint source,
+ ALenum param, ALint64SOFT *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
if(!values) UNLIKELY
return context->setError(AL_INVALID_VALUE, "NULL pointer");
const ALuint count{Int64ValsByProp(param)};
- GetSourcei64v(Source, context.get(), static_cast<SourceProp>(param), {values, count});
+ std::ignore = GetProperty(Source, context, static_cast<SourceProp>(param),
+ al::span{values, count});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcePlay(ALuint source)
-START_API_FUNC
+AL_API DECL_FUNC1(void, alSourcePlay, ALuint)
+FORCE_ALIGN void AL_APIENTRY alSourcePlayDirect(ALCcontext *context, ALuint source) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *srchandle{LookupSource(context.get(), source)};
+ ALsource *srchandle{LookupSource(context, source)};
if(!srchandle)
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- StartSources(context.get(), {&srchandle, 1});
+ StartSources(context, {&srchandle, 1});
}
-END_API_FUNC
-void AL_APIENTRY alSourcePlayAtTimeSOFT(ALuint source, ALint64SOFT start_time)
-START_API_FUNC
+FORCE_ALIGN DECL_FUNCEXT2(void, alSourcePlayAtTime,SOFT, ALuint, ALint64SOFT)
+FORCE_ALIGN void AL_APIENTRY alSourcePlayAtTimeDirectSOFT(ALCcontext *context, ALuint source,
+ ALint64SOFT start_time) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(start_time < 0) UNLIKELY
return context->setError(AL_INVALID_VALUE, "Invalid time point %" PRId64, start_time);
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *srchandle{LookupSource(context.get(), source)};
+ ALsource *srchandle{LookupSource(context, source)};
if(!srchandle)
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- StartSources(context.get(), {&srchandle, 1}, nanoseconds{start_time});
+ StartSources(context, {&srchandle, 1}, nanoseconds{start_time});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alSourcePlayv, ALsizei, const ALuint*)
+FORCE_ALIGN void AL_APIENTRY alSourcePlayvDirect(ALCcontext *context, ALsizei n,
+ const ALuint *sources) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Playing %d sources", n);
if(n <= 0) UNLIKELY return;
- al::vector<ALsource*> extra_sources;
+ std::vector<ALsource*> extra_sources;
std::array<ALsource*,8> source_storage;
al::span<ALsource*> srchandles;
if(static_cast<ALuint>(n) <= source_storage.size()) LIKELY
- srchandles = {source_storage.data(), static_cast<ALuint>(n)};
+ srchandles = al::span{source_storage}.first(static_cast<ALuint>(n));
else
{
extra_sources.resize(static_cast<ALuint>(n));
- srchandles = {extra_sources.data(), extra_sources.size()};
+ srchandles = extra_sources;
}
std::lock_guard<std::mutex> _{context->mSourceLock};
for(auto &srchdl : srchandles)
{
- srchdl = LookupSource(context.get(), *sources);
+ srchdl = LookupSource(context, *sources);
if(!srchdl) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", *sources);
++sources;
}
- StartSources(context.get(), srchandles);
+ StartSources(context, srchandles);
}
-END_API_FUNC
-void AL_APIENTRY alSourcePlayAtTimevSOFT(ALsizei n, const ALuint *sources, ALint64SOFT start_time)
-START_API_FUNC
+FORCE_ALIGN DECL_FUNCEXT3(void, alSourcePlayAtTimev,SOFT, ALsizei, const ALuint*, ALint64SOFT)
+FORCE_ALIGN void AL_APIENTRY alSourcePlayAtTimevDirectSOFT(ALCcontext *context, ALsizei n,
+ const ALuint *sources, ALint64SOFT start_time) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Playing %d sources", n);
if(n <= 0) UNLIKELY return;
@@ -3557,61 +3160,57 @@ START_API_FUNC
if(start_time < 0) UNLIKELY
return context->setError(AL_INVALID_VALUE, "Invalid time point %" PRId64, start_time);
- al::vector<ALsource*> extra_sources;
+ std::vector<ALsource*> extra_sources;
std::array<ALsource*,8> source_storage;
al::span<ALsource*> srchandles;
if(static_cast<ALuint>(n) <= source_storage.size()) LIKELY
- srchandles = {source_storage.data(), static_cast<ALuint>(n)};
+ srchandles = al::span{source_storage}.first(static_cast<ALuint>(n));
else
{
extra_sources.resize(static_cast<ALuint>(n));
- srchandles = {extra_sources.data(), extra_sources.size()};
+ srchandles = extra_sources;
}
std::lock_guard<std::mutex> _{context->mSourceLock};
for(auto &srchdl : srchandles)
{
- srchdl = LookupSource(context.get(), *sources);
+ srchdl = LookupSource(context, *sources);
if(!srchdl)
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", *sources);
++sources;
}
- StartSources(context.get(), srchandles, nanoseconds{start_time});
+ StartSources(context, srchandles, nanoseconds{start_time});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcePause(ALuint source)
-START_API_FUNC
-{ alSourcePausev(1, &source); }
-END_API_FUNC
+AL_API DECL_FUNC1(void, alSourcePause, ALuint)
+FORCE_ALIGN void AL_APIENTRY alSourcePauseDirect(ALCcontext *context, ALuint source) noexcept
+{ alSourcePausevDirect(context, 1, &source); }
-AL_API void AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alSourcePausev, ALsizei, const ALuint*)
+FORCE_ALIGN void AL_APIENTRY alSourcePausevDirect(ALCcontext *context, ALsizei n,
+ const ALuint *sources) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Pausing %d sources", n);
if(n <= 0) UNLIKELY return;
- al::vector<ALsource*> extra_sources;
+ std::vector<ALsource*> extra_sources;
std::array<ALsource*,8> source_storage;
al::span<ALsource*> srchandles;
if(static_cast<ALuint>(n) <= source_storage.size()) LIKELY
- srchandles = {source_storage.data(), static_cast<ALuint>(n)};
+ srchandles = al::span{source_storage}.first(static_cast<ALuint>(n));
else
{
extra_sources.resize(static_cast<ALuint>(n));
- srchandles = {extra_sources.data(), extra_sources.size()};
+ srchandles = extra_sources;
}
std::lock_guard<std::mutex> _{context->mSourceLock};
for(auto &srchdl : srchandles)
{
- srchdl = LookupSource(context.get(), *sources);
+ srchdl = LookupSource(context, *sources);
if(!srchdl)
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", *sources);
++sources;
@@ -3624,14 +3223,14 @@ START_API_FUNC
VoiceChange *tail{}, *cur{};
for(ALsource *source : srchandles)
{
- Voice *voice{GetSourceVoice(source, context.get())};
+ Voice *voice{GetSourceVoice(source, context)};
if(GetSourceState(source, voice) == AL_PLAYING)
{
if(!cur)
- cur = tail = GetVoiceChanger(context.get());
+ cur = tail = GetVoiceChanger(context);
else
{
- cur->mNext.store(GetVoiceChanger(context.get()), std::memory_order_relaxed);
+ cur->mNext.store(GetVoiceChanger(context), std::memory_order_relaxed);
cur = cur->mNext.load(std::memory_order_relaxed);
}
cur->mVoice = voice;
@@ -3641,7 +3240,7 @@ START_API_FUNC
}
if(tail) LIKELY
{
- SendVoiceChanges(context.get(), tail);
+ SendVoiceChanges(context, tail);
/* Second, now that the voice changes have been sent, because it's
* possible that the voice stopped after it was detected playing and
* before the voice got paused, recheck that the source is still
@@ -3649,45 +3248,41 @@ START_API_FUNC
*/
for(ALsource *source : srchandles)
{
- Voice *voice{GetSourceVoice(source, context.get())};
+ Voice *voice{GetSourceVoice(source, context)};
if(GetSourceState(source, voice) == AL_PLAYING)
source->state = AL_PAUSED;
}
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourceStop(ALuint source)
-START_API_FUNC
-{ alSourceStopv(1, &source); }
-END_API_FUNC
+AL_API DECL_FUNC1(void, alSourceStop, ALuint)
+FORCE_ALIGN void AL_APIENTRY alSourceStopDirect(ALCcontext *context, ALuint source) noexcept
+{ alSourceStopvDirect(context, 1, &source); }
-AL_API void AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alSourceStopv, ALsizei, const ALuint*)
+FORCE_ALIGN void AL_APIENTRY alSourceStopvDirect(ALCcontext *context, ALsizei n,
+ const ALuint *sources) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Stopping %d sources", n);
if(n <= 0) UNLIKELY return;
- al::vector<ALsource*> extra_sources;
+ std::vector<ALsource*> extra_sources;
std::array<ALsource*,8> source_storage;
al::span<ALsource*> srchandles;
if(static_cast<ALuint>(n) <= source_storage.size()) LIKELY
- srchandles = {source_storage.data(), static_cast<ALuint>(n)};
+ srchandles = al::span{source_storage}.first(static_cast<ALuint>(n));
else
{
extra_sources.resize(static_cast<ALuint>(n));
- srchandles = {extra_sources.data(), extra_sources.size()};
+ srchandles = extra_sources;
}
std::lock_guard<std::mutex> _{context->mSourceLock};
for(auto &srchdl : srchandles)
{
- srchdl = LookupSource(context.get(), *sources);
+ srchdl = LookupSource(context, *sources);
if(!srchdl)
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", *sources);
++sources;
@@ -3696,13 +3291,13 @@ START_API_FUNC
VoiceChange *tail{}, *cur{};
for(ALsource *source : srchandles)
{
- if(Voice *voice{GetSourceVoice(source, context.get())})
+ if(Voice *voice{GetSourceVoice(source, context)})
{
if(!cur)
- cur = tail = GetVoiceChanger(context.get());
+ cur = tail = GetVoiceChanger(context);
else
{
- cur->mNext.store(GetVoiceChanger(context.get()), std::memory_order_relaxed);
+ cur->mNext.store(GetVoiceChanger(context), std::memory_order_relaxed);
cur = cur->mNext.load(std::memory_order_relaxed);
}
voice->mPendingChange.store(true, std::memory_order_relaxed);
@@ -3713,44 +3308,40 @@ START_API_FUNC
}
source->Offset = 0.0;
source->OffsetType = AL_NONE;
- source->VoiceIdx = INVALID_VOICE_IDX;
+ source->VoiceIdx = InvalidVoiceIndex;
}
if(tail) LIKELY
- SendVoiceChanges(context.get(), tail);
+ SendVoiceChanges(context, tail);
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourceRewind(ALuint source)
-START_API_FUNC
-{ alSourceRewindv(1, &source); }
-END_API_FUNC
+AL_API DECL_FUNC1(void, alSourceRewind, ALuint)
+FORCE_ALIGN void AL_APIENTRY alSourceRewindDirect(ALCcontext *context, ALuint source) noexcept
+{ alSourceRewindvDirect(context, 1, &source); }
-AL_API void AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alSourceRewindv, ALsizei, const ALuint*)
+FORCE_ALIGN void AL_APIENTRY alSourceRewindvDirect(ALCcontext *context, ALsizei n,
+ const ALuint *sources) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Rewinding %d sources", n);
if(n <= 0) UNLIKELY return;
- al::vector<ALsource*> extra_sources;
+ std::vector<ALsource*> extra_sources;
std::array<ALsource*,8> source_storage;
al::span<ALsource*> srchandles;
if(static_cast<ALuint>(n) <= source_storage.size()) LIKELY
- srchandles = {source_storage.data(), static_cast<ALuint>(n)};
+ srchandles = al::span{source_storage}.first(static_cast<ALuint>(n));
else
{
extra_sources.resize(static_cast<ALuint>(n));
- srchandles = {extra_sources.data(), extra_sources.size()};
+ srchandles = extra_sources;
}
std::lock_guard<std::mutex> _{context->mSourceLock};
for(auto &srchdl : srchandles)
{
- srchdl = LookupSource(context.get(), *sources);
+ srchdl = LookupSource(context, *sources);
if(!srchdl)
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", *sources);
++sources;
@@ -3759,14 +3350,14 @@ START_API_FUNC
VoiceChange *tail{}, *cur{};
for(ALsource *source : srchandles)
{
- Voice *voice{GetSourceVoice(source, context.get())};
+ Voice *voice{GetSourceVoice(source, context)};
if(source->state != AL_INITIAL)
{
if(!cur)
- cur = tail = GetVoiceChanger(context.get());
+ cur = tail = GetVoiceChanger(context);
else
{
- cur->mNext.store(GetVoiceChanger(context.get()), std::memory_order_relaxed);
+ cur->mNext.store(GetVoiceChanger(context), std::memory_order_relaxed);
cur = cur->mNext.load(std::memory_order_relaxed);
}
if(voice)
@@ -3778,26 +3369,23 @@ START_API_FUNC
}
source->Offset = 0.0;
source->OffsetType = AL_NONE;
- source->VoiceIdx = INVALID_VOICE_IDX;
+ source->VoiceIdx = InvalidVoiceIndex;
}
if(tail) LIKELY
- SendVoiceChanges(context.get(), tail);
+ SendVoiceChanges(context, tail);
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALuint *buffers)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alSourceQueueBuffers, ALuint, ALsizei, const ALuint*)
+FORCE_ALIGN void AL_APIENTRY alSourceQueueBuffersDirect(ALCcontext *context, ALuint src,
+ ALsizei nb, const ALuint *buffers) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(nb < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Queueing %d buffers", nb);
if(nb <= 0) UNLIKELY return;
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *source{LookupSource(context.get(),src)};
+ ALsource *source{LookupSource(context,src)};
if(!source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", src);
@@ -3912,20 +3500,17 @@ START_API_FUNC
(iter-1)->mNext.store(al::to_address(iter), std::memory_order_release);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint *buffers)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alSourceUnqueueBuffers, ALuint, ALsizei, ALuint*)
+FORCE_ALIGN void AL_APIENTRY alSourceUnqueueBuffersDirect(ALCcontext *context, ALuint src,
+ ALsizei nb, ALuint *buffers) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(nb < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Unqueueing %d buffers", nb);
if(nb <= 0) UNLIKELY return;
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *source{LookupSource(context.get(),src)};
+ ALsource *source{LookupSource(context,src)};
if(!source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", src);
@@ -3940,7 +3525,7 @@ START_API_FUNC
if(source->state != AL_INITIAL) LIKELY
{
VoiceBufferItem *Current{nullptr};
- if(Voice *voice{GetSourceVoice(source, context.get())})
+ if(Voice *voice{GetSourceVoice(source, context)})
Current = voice->mCurrentBuffer.load(std::memory_order_relaxed);
for(auto &item : source->mQueue)
{
@@ -3965,18 +3550,15 @@ START_API_FUNC
source->mQueue.pop_front();
} while(--nb);
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourceQueueBufferLayersSOFT(ALuint, ALsizei, const ALuint*)
-START_API_FUNC
+AL_API void AL_APIENTRY alSourceQueueBufferLayersSOFT(ALuint, ALsizei, const ALuint*) noexcept
{
ContextRef context{GetContextRef()};
if(!context) UNLIKELY return;
context->setError(AL_INVALID_OPERATION, "alSourceQueueBufferLayersSOFT not supported");
}
-END_API_FUNC
ALsource::ALsource()
@@ -4028,14 +3610,29 @@ void UpdateAllSourceProps(ALCcontext *context)
}
}
+void ALsource::SetName(ALCcontext *context, ALuint id, std::string_view name)
+{
+ std::lock_guard<std::mutex> _{context->mSourceLock};
+
+ auto source = LookupSource(context, id);
+ if(!source) UNLIKELY
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", id);
+
+ context->mSourceNames.insert_or_assign(id, name);
+}
+
+
SourceSubList::~SourceSubList()
{
+ if(!Sources)
+ return;
+
uint64_t usemask{~FreeMask};
while(usemask)
{
const int idx{al::countr_zero(usemask)};
usemask &= ~(1_u64 << idx);
- al::destroy_at(Sources+idx);
+ std::destroy_at(Sources+idx);
}
FreeMask = ~usemask;
al_free(Sources);
@@ -4097,7 +3694,8 @@ ALsource* ALsource::EaxLookupSource(ALCcontext& al_context, ALuint source_id) no
void ALsource::eax_set_sends_defaults(EaxSends& sends, const EaxFxSlotIds& ids) noexcept
{
- for (auto i = size_t{}; i < EAX_MAX_FXSLOTS; ++i) {
+ for(size_t i{0};i < EAX_MAX_FXSLOTS;++i)
+ {
auto& send = sends[i];
send.guidReceivingFXSlotID = *(ids[i]);
send.lSend = EAXSOURCE_DEFAULTSEND;
@@ -4209,7 +3807,8 @@ void ALsource::eax5_set_active_fx_slots_defaults(EAX50ACTIVEFXSLOTS& slots) noex
void ALsource::eax5_set_speaker_levels_defaults(EaxSpeakerLevels& speaker_levels) noexcept
{
- for (auto i = size_t{}; i < eax_max_speakers; ++i) {
+ for(size_t i{0};i < eax_max_speakers;++i)
+ {
auto& speaker_level = speaker_levels[i];
speaker_level.lSpeakerID = static_cast<long>(EAXSPEAKER_FRONT_LEFT + i);
speaker_level.lLevel = EAXSOURCE_DEFAULTSPEAKERLEVEL;
@@ -4251,7 +3850,7 @@ void ALsource::eax1_translate(const Eax1Props& src, Eax5Props& dst) noexcept
else
{
dst.source.ulFlags &= ~EAXSOURCEFLAGS_ROOMAUTO;
- dst.sends[0].lSend = clamp(static_cast<long>(gain_to_level_mb(src.fMix)),
+ dst.sends[0].lSend = std::clamp(static_cast<long>(gain_to_level_mb(src.fMix)),
EAXSOURCE_MINSEND, EAXSOURCE_MAXSEND);
}
}
@@ -4280,7 +3879,7 @@ void ALsource::eax2_translate(const Eax2Props& src, Eax5Props& dst) noexcept
dst.source.ulFlags = src.dwFlags;
dst.source.flMacroFXFactor = EAXSOURCE_DEFAULTMACROFXFACTOR;
- // Set everyting else to defaults.
+ // Set everything else to defaults.
//
eax5_set_sends_defaults(dst.sends);
eax5_set_active_fx_slots_defaults(dst.active_fx_slots);
@@ -4294,7 +3893,7 @@ void ALsource::eax3_translate(const Eax3Props& src, Eax5Props& dst) noexcept
static_cast<Eax3Props&>(dst.source) = src;
dst.source.flMacroFXFactor = EAXSOURCE_DEFAULTMACROFXFACTOR;
- // Set everyting else to defaults.
+ // Set everything else to defaults.
//
eax5_set_sends_defaults(dst.sends);
eax5_set_active_fx_slots_defaults(dst.active_fx_slots);
@@ -4312,7 +3911,7 @@ void ALsource::eax4_translate(const Eax4Props& src, Eax5Props& dst) noexcept
//
dst.sends = src.sends;
- for (auto i = size_t{}; i < EAX_MAX_FXSLOTS; ++i)
+ for(size_t i{0};i < EAX_MAX_FXSLOTS;++i)
dst.sends[i].guidReceivingFXSlotID = *(eax5_fx_slot_ids[i]);
// Active FX slots.
@@ -4374,19 +3973,21 @@ EaxAlLowPassParam ALsource::eax_create_direct_filter_param() const noexcept
static_cast<float>(mEax.source.lDirectHF) +
static_cast<float>(mEax.source.lObstruction);
- for (auto i = std::size_t{}; i < EAX_MAX_FXSLOTS; ++i)
+ for(size_t i{0};i < EAX_MAX_FXSLOTS;++i)
{
if(!mEaxActiveFxSlots[i])
continue;
- if(has_source_occlusion) {
+ if(has_source_occlusion)
+ {
const auto& fx_slot = mEaxAlContext->eaxGetFxSlot(i);
const auto& fx_slot_eax = fx_slot.eax_get_eax_fx_slot();
const auto is_environmental_fx = ((fx_slot_eax.ulFlags & EAXFXSLOTFLAGS_ENVIRONMENT) != 0);
const auto is_primary = (mEaxPrimaryFxSlotId.value_or(-1) == fx_slot.eax_get_index());
const auto is_listener_environment = (is_environmental_fx && is_primary);
- if(is_listener_environment) {
+ if(is_listener_environment)
+ {
gain_mb += eax_calculate_dst_occlusion_mb(
mEax.source.lOcclusion,
mEax.source.flOcclusionDirectRatio,
@@ -4398,7 +3999,8 @@ EaxAlLowPassParam ALsource::eax_create_direct_filter_param() const noexcept
const auto& send = mEax.sends[i];
- if(send.lOcclusion != 0) {
+ if(send.lOcclusion != 0)
+ {
gain_mb += eax_calculate_dst_occlusion_mb(
send.lOcclusion,
send.flOcclusionDirectRatio,
@@ -4473,8 +4075,9 @@ void ALsource::eax_update_direct_filter()
void ALsource::eax_update_room_filters()
{
- for (auto i = size_t{}; i < EAX_MAX_FXSLOTS; ++i) {
- if (!mEaxActiveFxSlots[i])
+ for(size_t i{0};i < EAX_MAX_FXSLOTS;++i)
+ {
+ if(!mEaxActiveFxSlots[i])
continue;
auto& fx_slot = mEaxAlContext->eaxGetFxSlot(i);
@@ -4486,7 +4089,7 @@ void ALsource::eax_update_room_filters()
void ALsource::eax_set_efx_outer_gain_hf()
{
- OuterGainHF = clamp(
+ OuterGainHF = std::clamp(
level_mb_to_gain(static_cast<float>(mEax.source.lOutsideVolumeHF)),
AL_MIN_CONE_OUTER_GAINHF,
AL_MAX_CONE_OUTER_GAINHF);
@@ -5280,7 +4883,7 @@ void ALsource::eax_commit_active_fx_slots()
// Deactivate EFX auxiliary effect slots for inactive slots. Active slots
// will be updated with the room filters.
- for(auto i = size_t{}; i < EAX_MAX_FXSLOTS; ++i)
+ for(size_t i{0};i < EAX_MAX_FXSLOTS;++i)
{
if(!mEaxActiveFxSlots[i])
eax_set_al_source_send(nullptr, i, EaxAlLowPassParam{1.0f, 1.0f});