Make a couple more operator bools explicit
[openal-soft.git] / core / context.h
blobf5768629cb95bd7654649d84df277937733004f0
1 #ifndef CORE_CONTEXT_H
2 #define CORE_CONTEXT_H
4 #include <array>
5 #include <atomic>
6 #include <cstddef>
7 #include <memory>
8 #include <thread>
10 #include "almalloc.h"
11 #include "alspan.h"
12 #include "atomic.h"
13 #include "bufferline.h"
14 #include "threads.h"
15 #include "vecmat.h"
16 #include "vector.h"
18 struct DeviceBase;
19 struct EffectSlot;
20 struct EffectSlotProps;
21 struct RingBuffer;
22 struct Voice;
23 struct VoiceChange;
24 struct VoicePropsItem;
26 using uint = unsigned int;
29 constexpr float SpeedOfSoundMetersPerSec{343.3f};
31 constexpr float AirAbsorbGainHF{0.99426f}; /* -0.05dB */
33 enum class DistanceModel : unsigned char {
34 Disable,
35 Inverse, InverseClamped,
36 Linear, LinearClamped,
37 Exponent, ExponentClamped,
39 Default = InverseClamped
43 struct WetBuffer {
44 bool mInUse;
45 al::FlexArray<FloatBufferLine, 16> mBuffer;
47 WetBuffer(size_t count) : mBuffer{count} { }
49 DEF_FAM_NEWDEL(WetBuffer, mBuffer)
51 using WetBufferPtr = std::unique_ptr<WetBuffer>;
54 struct ContextProps {
55 std::array<float,3> Position;
56 std::array<float,3> Velocity;
57 std::array<float,3> OrientAt;
58 std::array<float,3> OrientUp;
59 float Gain;
60 float MetersPerUnit;
61 float AirAbsorptionGainHF;
63 float DopplerFactor;
64 float DopplerVelocity;
65 float SpeedOfSound;
66 bool SourceDistanceModel;
67 DistanceModel mDistanceModel;
69 std::atomic<ContextProps*> next;
71 DEF_NEWDEL(ContextProps)
74 struct ContextParams {
75 /* Pointer to the most recent property values that are awaiting an update. */
76 std::atomic<ContextProps*> ContextUpdate{nullptr};
78 alu::Vector Position{};
79 alu::Matrix Matrix{alu::Matrix::Identity()};
80 alu::Vector Velocity{};
82 float Gain{1.0f};
83 float MetersPerUnit{1.0f};
84 float AirAbsorptionGainHF{AirAbsorbGainHF};
86 float DopplerFactor{1.0f};
87 float SpeedOfSound{SpeedOfSoundMetersPerSec}; /* in units per sec! */
89 bool SourceDistanceModel{false};
90 DistanceModel mDistanceModel{};
93 struct ContextBase {
94 DeviceBase *const mDevice;
96 /* Counter for the pre-mixing updates, in 31.1 fixed point (lowest bit
97 * indicates if updates are currently happening).
99 RefCount mUpdateCount{0u};
100 std::atomic<bool> mHoldUpdates{false};
101 std::atomic<bool> mStopVoicesOnDisconnect{true};
103 float mGainBoost{1.0f};
105 /* Linked lists of unused property containers, free to use for future
106 * updates.
108 std::atomic<ContextProps*> mFreeContextProps{nullptr};
109 std::atomic<VoicePropsItem*> mFreeVoiceProps{nullptr};
110 std::atomic<EffectSlotProps*> mFreeEffectslotProps{nullptr};
112 /* The voice change tail is the beginning of the "free" elements, up to and
113 * *excluding* the current. If tail==current, there's no free elements and
114 * new ones need to be allocated. The current voice change is the element
115 * last processed, and any after are pending.
117 VoiceChange *mVoiceChangeTail{};
118 std::atomic<VoiceChange*> mCurrentVoiceChange{};
120 void allocVoiceChanges();
121 void allocVoiceProps();
124 ContextParams mParams;
126 using VoiceArray = al::FlexArray<Voice*>;
127 std::atomic<VoiceArray*> mVoices{};
128 std::atomic<size_t> mActiveVoiceCount{};
130 void allocVoices(size_t addcount);
131 al::span<Voice*> getVoicesSpan() const noexcept
133 return {mVoices.load(std::memory_order_relaxed)->data(),
134 mActiveVoiceCount.load(std::memory_order_relaxed)};
136 al::span<Voice*> getVoicesSpanAcquired() const noexcept
138 return {mVoices.load(std::memory_order_acquire)->data(),
139 mActiveVoiceCount.load(std::memory_order_acquire)};
143 using EffectSlotArray = al::FlexArray<EffectSlot*>;
144 std::atomic<EffectSlotArray*> mActiveAuxSlots{nullptr};
146 std::thread mEventThread;
147 al::semaphore mEventSem;
148 std::unique_ptr<RingBuffer> mAsyncEvents;
149 std::atomic<uint> mEnabledEvts{0u};
151 /* Asynchronous voice change actions are processed as a linked list of
152 * VoiceChange objects by the mixer, which is atomically appended to.
153 * However, to avoid allocating each object individually, they're allocated
154 * in clusters that are stored in a vector for easy automatic cleanup.
156 using VoiceChangeCluster = std::unique_ptr<VoiceChange[]>;
157 al::vector<VoiceChangeCluster> mVoiceChangeClusters;
159 using VoiceCluster = std::unique_ptr<Voice[]>;
160 al::vector<VoiceCluster> mVoiceClusters;
162 using VoicePropsCluster = std::unique_ptr<VoicePropsItem[]>;
163 al::vector<VoicePropsCluster> mVoicePropClusters;
166 ContextBase(DeviceBase *device);
167 ContextBase(const ContextBase&) = delete;
168 ContextBase& operator=(const ContextBase&) = delete;
169 ~ContextBase();
172 #endif /* CORE_CONTEXT_H */