13 #include "async_event.h"
15 #include "bufferline.h"
22 struct EffectSlotProps
;
26 struct VoicePropsItem
;
28 using uint
= unsigned int;
31 constexpr float SpeedOfSoundMetersPerSec
{343.3f
};
33 constexpr float AirAbsorbGainHF
{0.99426f
}; /* -0.05dB */
35 enum class DistanceModel
: unsigned char {
37 Inverse
, InverseClamped
,
38 Linear
, LinearClamped
,
39 Exponent
, ExponentClamped
,
41 Default
= InverseClamped
46 std::array
<float,3> Position
;
47 std::array
<float,3> Velocity
;
48 std::array
<float,3> OrientAt
;
49 std::array
<float,3> OrientUp
;
52 float AirAbsorptionGainHF
;
55 float DopplerVelocity
;
57 bool SourceDistanceModel
;
58 DistanceModel mDistanceModel
;
60 std::atomic
<ContextProps
*> next
;
62 DEF_NEWDEL(ContextProps
)
65 struct ContextParams
{
66 /* Pointer to the most recent property values that are awaiting an update. */
67 std::atomic
<ContextProps
*> ContextUpdate
{nullptr};
69 alu::Vector Position
{};
70 alu::Matrix Matrix
{alu::Matrix::Identity()};
71 alu::Vector Velocity
{};
74 float MetersPerUnit
{1.0f
};
75 float AirAbsorptionGainHF
{AirAbsorbGainHF
};
77 float DopplerFactor
{1.0f
};
78 float SpeedOfSound
{SpeedOfSoundMetersPerSec
}; /* in units per sec! */
80 bool SourceDistanceModel
{false};
81 DistanceModel mDistanceModel
{};
85 DeviceBase
*const mDevice
;
87 /* Counter for the pre-mixing updates, in 31.1 fixed point (lowest bit
88 * indicates if updates are currently happening).
90 RefCount mUpdateCount
{0u};
91 std::atomic
<bool> mHoldUpdates
{false};
92 std::atomic
<bool> mStopVoicesOnDisconnect
{true};
94 float mGainBoost
{1.0f
};
96 /* Linked lists of unused property containers, free to use for future
99 std::atomic
<ContextProps
*> mFreeContextProps
{nullptr};
100 std::atomic
<VoicePropsItem
*> mFreeVoiceProps
{nullptr};
101 std::atomic
<EffectSlotProps
*> mFreeEffectslotProps
{nullptr};
103 /* The voice change tail is the beginning of the "free" elements, up to and
104 * *excluding* the current. If tail==current, there's no free elements and
105 * new ones need to be allocated. The current voice change is the element
106 * last processed, and any after are pending.
108 VoiceChange
*mVoiceChangeTail
{};
109 std::atomic
<VoiceChange
*> mCurrentVoiceChange
{};
111 void allocVoiceChanges();
112 void allocVoiceProps();
115 ContextParams mParams
;
117 using VoiceArray
= al::FlexArray
<Voice
*>;
118 std::atomic
<VoiceArray
*> mVoices
{};
119 std::atomic
<size_t> mActiveVoiceCount
{};
121 void allocVoices(size_t addcount
);
122 al::span
<Voice
*> getVoicesSpan() const noexcept
124 return {mVoices
.load(std::memory_order_relaxed
)->data(),
125 mActiveVoiceCount
.load(std::memory_order_relaxed
)};
127 al::span
<Voice
*> getVoicesSpanAcquired() const noexcept
129 return {mVoices
.load(std::memory_order_acquire
)->data(),
130 mActiveVoiceCount
.load(std::memory_order_acquire
)};
134 using EffectSlotArray
= al::FlexArray
<EffectSlot
*>;
135 std::atomic
<EffectSlotArray
*> mActiveAuxSlots
{nullptr};
137 std::thread mEventThread
;
138 al::semaphore mEventSem
;
139 std::unique_ptr
<RingBuffer
> mAsyncEvents
;
140 using AsyncEventBitset
= std::bitset
<AsyncEvent::UserEventCount
>;
141 std::atomic
<AsyncEventBitset
> mEnabledEvts
{0u};
143 /* Asynchronous voice change actions are processed as a linked list of
144 * VoiceChange objects by the mixer, which is atomically appended to.
145 * However, to avoid allocating each object individually, they're allocated
146 * in clusters that are stored in a vector for easy automatic cleanup.
148 using VoiceChangeCluster
= std::unique_ptr
<VoiceChange
[]>;
149 al::vector
<VoiceChangeCluster
> mVoiceChangeClusters
;
151 using VoiceCluster
= std::unique_ptr
<Voice
[]>;
152 al::vector
<VoiceCluster
> mVoiceClusters
;
154 using VoicePropsCluster
= std::unique_ptr
<VoicePropsItem
[]>;
155 al::vector
<VoicePropsCluster
> mVoicePropClusters
;
158 static constexpr size_t EffectSlotClusterSize
{4};
159 EffectSlot
*getEffectSlot();
161 using EffectSlotCluster
= std::unique_ptr
<EffectSlot
[]>;
162 al::vector
<EffectSlotCluster
> mEffectSlotClusters
;
165 ContextBase(DeviceBase
*device
);
166 ContextBase(const ContextBase
&) = delete;
167 ContextBase
& operator=(const ContextBase
&) = delete;
171 #endif /* CORE_CONTEXT_H */