🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

214 lines
5.7 KiB

#ifndef ALCONTEXT_H
#define ALCONTEXT_H
#include <mutex>
#include <atomic>
#include <memory>
#include <thread>
#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alext.h"
#include "inprogext.h"
#include "atomic.h"
#include "vector.h"
#include "threads.h"
#include "almalloc.h"
#include "alnumeric.h"
#include "alListener.h"
struct ALsource;
struct ALeffectslot;
struct ALcontextProps;
struct ALlistenerProps;
struct ALvoiceProps;
struct ALeffectslotProps;
struct ALvoice;
struct RingBuffer;
enum class DistanceModel {
InverseClamped = AL_INVERSE_DISTANCE_CLAMPED,
LinearClamped = AL_LINEAR_DISTANCE_CLAMPED,
ExponentClamped = AL_EXPONENT_DISTANCE_CLAMPED,
Inverse = AL_INVERSE_DISTANCE,
Linear = AL_LINEAR_DISTANCE,
Exponent = AL_EXPONENT_DISTANCE,
Disable = AL_NONE,
Default = InverseClamped
};
struct SourceSubList {
uint64_t FreeMask{~0_u64};
ALsource *Sources{nullptr}; /* 64 */
SourceSubList() noexcept = default;
SourceSubList(const SourceSubList&) = delete;
SourceSubList(SourceSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Sources{rhs.Sources}
{ rhs.FreeMask = ~0_u64; rhs.Sources = nullptr; }
~SourceSubList();
SourceSubList& operator=(const SourceSubList&) = delete;
SourceSubList& operator=(SourceSubList&& rhs) noexcept
{ std::swap(FreeMask, rhs.FreeMask); std::swap(Sources, rhs.Sources); return *this; }
};
struct EffectSlotSubList {
uint64_t FreeMask{~0_u64};
ALeffectslot *EffectSlots{nullptr}; /* 64 */
EffectSlotSubList() noexcept = default;
EffectSlotSubList(const EffectSlotSubList&) = delete;
EffectSlotSubList(EffectSlotSubList&& rhs) noexcept
: FreeMask{rhs.FreeMask}, EffectSlots{rhs.EffectSlots}
{ rhs.FreeMask = ~0_u64; rhs.EffectSlots = nullptr; }
~EffectSlotSubList();
EffectSlotSubList& operator=(const EffectSlotSubList&) = delete;
EffectSlotSubList& operator=(EffectSlotSubList&& rhs) noexcept
{ std::swap(FreeMask, rhs.FreeMask); std::swap(EffectSlots, rhs.EffectSlots); return *this; }
};
struct ALCcontext {
RefCount ref{1u};
al::vector<SourceSubList> SourceList;
ALuint NumSources{0};
std::mutex SourceLock;
al::vector<EffectSlotSubList> EffectSlotList;
ALuint NumEffectSlots{0u};
std::mutex EffectSlotLock;
std::atomic<ALenum> LastError{AL_NO_ERROR};
DistanceModel mDistanceModel{DistanceModel::Default};
ALboolean SourceDistanceModel{AL_FALSE};
ALfloat DopplerFactor{1.0f};
ALfloat DopplerVelocity{1.0f};
ALfloat SpeedOfSound{};
ALfloat MetersPerUnit{1.0f};
std::atomic_flag PropsClean;
std::atomic<bool> DeferUpdates{false};
std::mutex PropLock;
/* Counter for the pre-mixing updates, in 31.1 fixed point (lowest bit
* indicates if updates are currently happening).
*/
RefCount UpdateCount{0u};
std::atomic<bool> HoldUpdates{false};
ALfloat GainBoost{1.0f};
std::atomic<ALcontextProps*> Update{nullptr};
/* Linked lists of unused property containers, free to use for future
* updates.
*/
std::atomic<ALcontextProps*> FreeContextProps{nullptr};
std::atomic<ALlistenerProps*> FreeListenerProps{nullptr};
std::atomic<ALvoiceProps*> FreeVoiceProps{nullptr};
std::atomic<ALeffectslotProps*> FreeEffectslotProps{nullptr};
ALvoice **Voices{nullptr};
std::atomic<ALsizei> VoiceCount{0};
ALsizei MaxVoices{0};
using ALeffectslotArray = al::FlexArray<ALeffectslot*>;
std::atomic<ALeffectslotArray*> ActiveAuxSlots{nullptr};
std::thread EventThread;
al::semaphore EventSem;
std::unique_ptr<RingBuffer> AsyncEvents;
std::atomic<ALbitfieldSOFT> EnabledEvts{0u};
std::mutex EventCbLock;
ALEVENTPROCSOFT EventCb{};
void *EventParam{nullptr};
/* Default effect slot */
std::unique_ptr<ALeffectslot> DefaultSlot;
ALCdevice *const Device;
const ALCchar *ExtensionList{nullptr};
std::atomic<ALCcontext*> next{nullptr};
ALlistener Listener{};
ALCcontext(ALCdevice *device);
ALCcontext(const ALCcontext&) = delete;
ALCcontext& operator=(const ALCcontext&) = delete;
~ALCcontext();
static constexpr inline const char *CurrentPrefix() noexcept { return "ALCcontext::"; }
DEF_NEWDEL(ALCcontext)
};
void ALCcontext_DecRef(ALCcontext *context);
void UpdateContextProps(ALCcontext *context);
void ALCcontext_DeferUpdates(ALCcontext *context);
void ALCcontext_ProcessUpdates(ALCcontext *context);
/* Simple RAII context reference. Takes the reference of the provided
* ALCcontext, and decrements it when leaving scope. Movable (transfer
* reference) but not copyable (no new references).
*/
class ContextRef {
ALCcontext *mCtx{nullptr};
void reset() noexcept
{
if(mCtx)
ALCcontext_DecRef(mCtx);
mCtx = nullptr;
}
public:
ContextRef() noexcept = default;
ContextRef(ContextRef&& rhs) noexcept : mCtx{rhs.mCtx}
{ rhs.mCtx = nullptr; }
explicit ContextRef(ALCcontext *ctx) noexcept : mCtx(ctx) { }
~ContextRef() { reset(); }
ContextRef& operator=(const ContextRef&) = delete;
ContextRef& operator=(ContextRef&& rhs) noexcept
{ std::swap(mCtx, rhs.mCtx); return *this; }
operator bool() const noexcept { return mCtx != nullptr; }
ALCcontext* operator->() noexcept { return mCtx; }
ALCcontext* get() noexcept { return mCtx; }
ALCcontext* release() noexcept
{
ALCcontext *ret{mCtx};
mCtx = nullptr;
return ret;
}
};
ContextRef GetContextRef(void);
struct ALcontextProps {
ALfloat DopplerFactor;
ALfloat DopplerVelocity;
ALfloat SpeedOfSound;
ALboolean SourceDistanceModel;
DistanceModel mDistanceModel;
ALfloat MetersPerUnit;
std::atomic<ALcontextProps*> next;
};
#endif /* ALCONTEXT_H */