4 #include <condition_variable>
5 #include <unordered_map>
19 #define F_PI (3.14159265358979323846f)
36 SOFT_source_resampler
,
37 SOFT_source_spatialize
,
47 // Batches OpenAL updates while the object is alive, if batching isn't already
53 Batcher(ALCcontext
*context
) : mContext(context
) { }
54 Batcher(Batcher
&& rhs
) : mContext(rhs
.mContext
) { rhs
.mContext
= nullptr; }
55 Batcher(const Batcher
&) = delete;
59 alcProcessContext(mContext
);
62 Batcher
& operator=(Batcher
&&) = delete;
63 Batcher
& operator=(const Batcher
&) = delete;
68 ContextImpl
*const mContext
;
71 ListenerImpl(ContextImpl
*ctx
) : mContext(ctx
) { }
73 void setGain(ALfloat gain
);
75 void set3DParameters(const Vector3
&position
, const Vector3
&velocity
, const std::pair
<Vector3
,Vector3
> &orientation
);
77 void setPosition(const Vector3
&position
);
78 void setPosition(const ALfloat
*pos
);
80 void setVelocity(const Vector3
&velocity
);
81 void setVelocity(const ALfloat
*vel
);
83 void setOrientation(const std::pair
<Vector3
,Vector3
> &orientation
);
84 void setOrientation(const ALfloat
*at
, const ALfloat
*up
);
85 void setOrientation(const ALfloat
*ori
);
87 void setMetersPerUnit(ALfloat m_u
);
91 using DecoderOrExceptT
= std::variant
<SharedPtr
<Decoder
>,std::exception_ptr
>;
92 using BufferOrExceptT
= std::variant
<Buffer
,std::exception_ptr
>;
95 static ContextImpl
*sCurrentCtx
;
96 static thread_local ContextImpl
*sThreadCurrentCtx
;
99 static void MakeCurrent(ContextImpl
*context
);
100 static ContextImpl
*GetCurrent()
102 auto thrd_ctx
= sThreadCurrentCtx
;
103 return thrd_ctx
? thrd_ctx
: sCurrentCtx
;
106 static void MakeThreadCurrent(ContextImpl
*context
);
107 static ContextImpl
*GetThreadCurrent() { return sThreadCurrentCtx
; }
109 static std::atomic
<uint64_t> sContextSetCount
;
110 mutable uint64_t mContextSetCounter
{std::numeric_limits
<uint64_t>::max()};
113 ListenerImpl mListener
;
114 ALCcontext
*mContext
{nullptr};
115 Vector
<ALuint
> mSourceIds
;
117 struct PendingBuffer
{ BufferImpl
*mBuffer
; SharedFuture
<Buffer
> mFuture
; };
118 struct PendingSource
{ SourceImpl
*mSource
; SharedFuture
<Buffer
> mFuture
; };
121 Vector
<PendingBuffer
> mFutureBuffers
;
122 Vector
<UniquePtr
<BufferImpl
>> mBuffers
;
123 Vector
<UniquePtr
<SourceGroupImpl
>> mSourceGroups
;
124 Vector
<UniquePtr
<AuxiliaryEffectSlotImpl
>> mEffectSlots
;
125 Vector
<UniquePtr
<EffectImpl
>> mEffects
;
126 std::deque
<SourceImpl
> mAllSources
;
127 Vector
<SourceImpl
*> mFreeSources
;
129 Vector
<PendingSource
> mPendingSources
;
130 Vector
<SourceImpl
*> mFadingSources
;
131 Vector
<SourceBufferUpdateEntry
> mPlaySources
;
132 Vector
<SourceStreamUpdateEntry
> mStreamSources
;
134 Vector
<SourceImpl
*> mStreamingSources
;
135 std::mutex mSourceStreamMutex
;
137 std::atomic
<std::chrono::milliseconds
> mWakeInterval
{std::chrono::milliseconds::zero()};
138 std::mutex mWakeMutex
;
139 std::condition_variable mWakeThread
;
141 SharedPtr
<MessageHandler
> mMessage
;
143 struct PendingPromise
{
145 SharedPtr
<Decoder
> mDecoder
;
148 Promise
<Buffer
> mPromise
;
150 std::atomic
<PendingPromise
*> mNext
;
152 std::atomic
<PendingPromise
*> mPendingCurrent
{nullptr};
153 PendingPromise
*mPendingTail
{nullptr};
154 PendingPromise
*mPendingHead
{nullptr};
156 std::atomic
<bool> mQuitThread
{false};
158 void backgroundProc();
162 Vector
<String
> mResamplers
;
164 Bitfield
<static_cast<size_t>(AL::EXTENSION_MAX
)> mHasExt
;
166 std::once_flag mSetExts
;
169 DecoderOrExceptT
findDecoder(StringView name
);
170 BufferOrExceptT
doCreateBuffer(StringView name
, Vector
<UniquePtr
<BufferImpl
>>::iterator iter
, SharedPtr
<Decoder
> decoder
);
171 BufferOrExceptT
doCreateBufferAsync(StringView name
, Vector
<UniquePtr
<BufferImpl
>>::iterator iter
, SharedPtr
<Decoder
> decoder
, Promise
<Buffer
> promise
);
173 bool mIsConnected
: 1;
174 bool mIsBatching
: 1;
177 ContextImpl(DeviceImpl
&device
, ArrayView
<AttributePair
> attrs
);
180 ALCcontext
*getALCcontext() const { return mContext
; }
181 size_t addRef() { return ++mRefs
; }
182 size_t decRef() { return --mRefs
; }
184 bool hasExtension(AL ext
) const { return mHasExt
[static_cast<size_t>(ext
)]; }
186 LPALGETSTRINGISOFT alGetStringiSOFT
{nullptr};
187 LPALGETSOURCEI64VSOFT alGetSourcei64vSOFT
{nullptr};
188 LPALGETSOURCEDVSOFT alGetSourcedvSOFT
{nullptr};
190 LPALGENEFFECTS alGenEffects
{nullptr};
191 LPALDELETEEFFECTS alDeleteEffects
{nullptr};
192 LPALISEFFECT alIsEffect
{nullptr};
193 LPALEFFECTI alEffecti
{nullptr};
194 LPALEFFECTIV alEffectiv
{nullptr};
195 LPALEFFECTF alEffectf
{nullptr};
196 LPALEFFECTFV alEffectfv
{nullptr};
197 LPALGETEFFECTI alGetEffecti
{nullptr};
198 LPALGETEFFECTIV alGetEffectiv
{nullptr};
199 LPALGETEFFECTF alGetEffectf
{nullptr};
200 LPALGETEFFECTFV alGetEffectfv
{nullptr};
202 LPALGENFILTERS alGenFilters
{nullptr};
203 LPALDELETEFILTERS alDeleteFilters
{nullptr};
204 LPALISFILTER alIsFilter
{nullptr};
205 LPALFILTERI alFilteri
{nullptr};
206 LPALFILTERIV alFilteriv
{nullptr};
207 LPALFILTERF alFilterf
{nullptr};
208 LPALFILTERFV alFilterfv
{nullptr};
209 LPALGETFILTERI alGetFilteri
{nullptr};
210 LPALGETFILTERIV alGetFilteriv
{nullptr};
211 LPALGETFILTERF alGetFilterf
{nullptr};
212 LPALGETFILTERFV alGetFilterfv
{nullptr};
214 LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots
{nullptr};
215 LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots
{nullptr};
216 LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot
{nullptr};
217 LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti
{nullptr};
218 LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv
{nullptr};
219 LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf
{nullptr};
220 LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv
{nullptr};
221 LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti
{nullptr};
222 LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv
{nullptr};
223 LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf
{nullptr};
224 LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv
{nullptr};
226 ALuint
getSourceId(ALuint maxprio
);
227 void insertSourceId(ALuint id
) { mSourceIds
.push_back(id
); }
229 void addPendingSource(SourceImpl
*source
, SharedFuture
<Buffer
> future
);
230 void removePendingSource(SourceImpl
*source
);
231 bool isPendingSource(const SourceImpl
*source
) const;
232 void addFadingSource(SourceImpl
*source
);
233 void removeFadingSource(SourceImpl
*source
);
234 void addPlayingSource(SourceImpl
*source
, ALuint id
);
235 void addPlayingSource(SourceImpl
*source
);
236 void removePlayingSource(SourceImpl
*source
);
238 void addStream(SourceImpl
*source
);
239 void removeStream(SourceImpl
*source
);
240 void removeStreamNoLock(SourceImpl
*source
);
242 void freeSource(SourceImpl
*source
) { mFreeSources
.push_back(source
); }
243 void freeSourceGroup(SourceGroupImpl
*group
);
244 void freeEffectSlot(AuxiliaryEffectSlotImpl
*slot
);
245 void freeEffect(EffectImpl
*effect
);
250 return Batcher(nullptr);
251 alcSuspendContext(mContext
);
252 return Batcher(mContext
);
255 std::unique_lock
<std::mutex
> getSourceStreamLock()
256 { return std::unique_lock
<std::mutex
>(mSourceStreamMutex
); }
258 template<typename R
, typename
... Args
>
259 void send(R
MessageHandler::* func
, Args
&&... args
)
260 { if(mMessage
.get()) (mMessage
.get()->*func
)(std::forward
<Args
>(args
)...); }
262 Device
getDevice() { return Device(&mDevice
); }
269 Listener
getListener() { return Listener(&mListener
); }
271 SharedPtr
<MessageHandler
> setMessageHandler(SharedPtr
<MessageHandler
>&& handler
);
272 SharedPtr
<MessageHandler
> getMessageHandler() const { return mMessage
; }
274 void setAsyncWakeInterval(std::chrono::milliseconds interval
);
275 std::chrono::milliseconds
getAsyncWakeInterval() const { return mWakeInterval
.load(); }
277 SharedPtr
<Decoder
> createDecoder(StringView name
);
279 bool isSupported(ChannelConfig channels
, SampleType type
) const;
281 ArrayView
<String
> getAvailableResamplers();
282 ALsizei
getDefaultResamplerIndex() const;
284 Buffer
getBuffer(StringView name
);
285 SharedFuture
<Buffer
> getBufferAsync(StringView name
);
286 void precacheBuffersAsync(ArrayView
<StringView
> names
);
287 Buffer
createBufferFrom(StringView name
, SharedPtr
<Decoder
>&& decoder
);
288 SharedFuture
<Buffer
> createBufferAsyncFrom(StringView name
, SharedPtr
<Decoder
>&& decoder
);
289 Buffer
findBuffer(StringView name
);
290 SharedFuture
<Buffer
> findBufferAsync(StringView name
);
291 void removeBuffer(StringView name
);
292 void removeBuffer(Buffer buffer
) { removeBuffer(buffer
.getName()); }
294 Source
createSource();
296 AuxiliaryEffectSlot
createAuxiliaryEffectSlot();
298 Effect
createEffect();
300 SourceGroup
createSourceGroup();
302 void setDopplerFactor(ALfloat factor
);
304 void setSpeedOfSound(ALfloat speed
);
306 void setDistanceModel(DistanceModel model
);
312 inline void CheckContext(const ContextImpl
&ctx
)
314 auto count
= ContextImpl::sContextSetCount
.load(std::memory_order_acquire
);
315 if(UNLIKELY(count
!= ctx
.mContextSetCounter
))
317 if(UNLIKELY(&ctx
!= ContextImpl::GetCurrent()))
318 throw std::runtime_error("Called context is not current");
319 ctx
.mContextSetCounter
= count
;
323 inline void CheckContexts(const ContextImpl
&ctx0
, const ContextImpl
&ctx1
)
325 if(UNLIKELY(&ctx0
!= &ctx1
))
326 throw std::runtime_error("Mismatched object contexts");
332 #endif /* CONTEXT_H */