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()};
112 struct ContextDeleter
{
113 void operator()(ALCcontext
*ptr
) const { alcDestroyContext(ptr
); }
115 using ContextPtr
= UniquePtr
<ALCcontext
,ContextDeleter
>;
118 ListenerImpl mListener
;
121 Vector
<ALuint
> mSourceIds
;
123 struct PendingBuffer
{ BufferImpl
*mBuffer
; SharedFuture
<Buffer
> mFuture
; };
124 struct PendingSource
{ SourceImpl
*mSource
; SharedFuture
<Buffer
> mFuture
; };
125 using BufferListT
= Vector
<UniquePtr
<BufferImpl
>>;
126 using FutureBufferListT
= Vector
<PendingBuffer
>;
129 FutureBufferListT mFutureBuffers
;
130 BufferListT mBuffers
;
131 Vector
<UniquePtr
<SourceGroupImpl
>> mSourceGroups
;
132 Vector
<UniquePtr
<AuxiliaryEffectSlotImpl
>> mEffectSlots
;
133 Vector
<UniquePtr
<EffectImpl
>> mEffects
;
134 std::deque
<SourceImpl
> mAllSources
;
135 Vector
<SourceImpl
*> mFreeSources
;
137 Vector
<PendingSource
> mPendingSources
;
138 Vector
<SourceFadeUpdateEntry
> mFadingSources
;
139 Vector
<SourceBufferUpdateEntry
> mPlaySources
;
140 Vector
<SourceStreamUpdateEntry
> mStreamSources
;
142 Vector
<SourceImpl
*> mStreamingSources
;
143 std::mutex mSourceStreamMutex
;
145 std::atomic
<std::chrono::milliseconds
> mWakeInterval
{std::chrono::milliseconds::zero()};
146 std::mutex mWakeMutex
;
147 std::condition_variable mWakeThread
;
149 SharedPtr
<MessageHandler
> mMessage
;
151 struct PendingPromise
{
152 BufferImpl
*mBuffer
{nullptr};
153 SharedPtr
<Decoder
> mDecoder
;
154 ALenum mFormat
{AL_NONE
};
156 Promise
<Buffer
> mPromise
;
158 std::atomic
<PendingPromise
*> mNext
{nullptr};
160 PendingPromise() = default;
161 PendingPromise(BufferImpl
*buffer
, SharedPtr
<Decoder
> decoder
, ALenum format
,
162 ALuint frames
, Promise
<Buffer
> promise
)
163 : mBuffer(buffer
), mDecoder(std::move(decoder
)), mFormat(format
), mFrames(frames
)
164 , mPromise(std::move(promise
))
167 std::atomic
<PendingPromise
*> mPendingCurrent
{nullptr};
168 PendingPromise
*mPendingTail
{nullptr};
169 PendingPromise
*mPendingHead
{nullptr};
171 std::atomic
<bool> mQuitThread
{false};
173 void backgroundProc();
177 Vector
<String
> mResamplers
;
179 Bitfield
<static_cast<size_t>(AL::EXTENSION_MAX
)> mHasExt
;
181 std::once_flag mSetExts
;
184 DecoderOrExceptT
findDecoder(StringView name
);
185 BufferOrExceptT
doCreateBuffer(StringView name
, size_t name_hash
, BufferListT::const_iterator iter
, SharedPtr
<Decoder
> decoder
);
186 BufferOrExceptT
doCreateBufferAsync(StringView name
, size_t name_hash
, BufferListT::const_iterator iter
, SharedPtr
<Decoder
> decoder
, Promise
<Buffer
> promise
);
188 bool mIsConnected
: 1;
189 bool mIsBatching
: 1;
192 ContextImpl(DeviceImpl
&device
, ArrayView
<AttributePair
> attrs
);
195 ALCcontext
*getALCcontext() const { return mContext
.get(); }
196 size_t addRef() { return ++mRefs
; }
197 size_t decRef() { return --mRefs
; }
199 bool hasExtension(AL ext
) const { return mHasExt
[static_cast<size_t>(ext
)]; }
201 LPALGETSTRINGISOFT alGetStringiSOFT
{nullptr};
202 LPALGETSOURCEI64VSOFT alGetSourcei64vSOFT
{nullptr};
203 LPALGETSOURCEDVSOFT alGetSourcedvSOFT
{nullptr};
205 LPALGENEFFECTS alGenEffects
{nullptr};
206 LPALDELETEEFFECTS alDeleteEffects
{nullptr};
207 LPALISEFFECT alIsEffect
{nullptr};
208 LPALEFFECTI alEffecti
{nullptr};
209 LPALEFFECTIV alEffectiv
{nullptr};
210 LPALEFFECTF alEffectf
{nullptr};
211 LPALEFFECTFV alEffectfv
{nullptr};
212 LPALGETEFFECTI alGetEffecti
{nullptr};
213 LPALGETEFFECTIV alGetEffectiv
{nullptr};
214 LPALGETEFFECTF alGetEffectf
{nullptr};
215 LPALGETEFFECTFV alGetEffectfv
{nullptr};
217 LPALGENFILTERS alGenFilters
{nullptr};
218 LPALDELETEFILTERS alDeleteFilters
{nullptr};
219 LPALISFILTER alIsFilter
{nullptr};
220 LPALFILTERI alFilteri
{nullptr};
221 LPALFILTERIV alFilteriv
{nullptr};
222 LPALFILTERF alFilterf
{nullptr};
223 LPALFILTERFV alFilterfv
{nullptr};
224 LPALGETFILTERI alGetFilteri
{nullptr};
225 LPALGETFILTERIV alGetFilteriv
{nullptr};
226 LPALGETFILTERF alGetFilterf
{nullptr};
227 LPALGETFILTERFV alGetFilterfv
{nullptr};
229 LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots
{nullptr};
230 LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots
{nullptr};
231 LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot
{nullptr};
232 LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti
{nullptr};
233 LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv
{nullptr};
234 LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf
{nullptr};
235 LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv
{nullptr};
236 LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti
{nullptr};
237 LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv
{nullptr};
238 LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf
{nullptr};
239 LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv
{nullptr};
241 FutureBufferListT::const_iterator
findFutureBufferName(StringView name
, size_t name_hash
) const;
242 BufferListT::const_iterator
findBufferName(StringView name
, size_t name_hash
) const;
244 ALuint
getSourceId(ALuint maxprio
);
245 void insertSourceId(ALuint id
) { mSourceIds
.push_back(id
); }
247 void addPendingSource(SourceImpl
*source
, SharedFuture
<Buffer
> future
);
248 void removePendingSource(SourceImpl
*source
);
249 bool isPendingSource(const SourceImpl
*source
) const;
250 void addFadingSource(SourceImpl
*source
, std::chrono::nanoseconds duration
, ALfloat gain
);
251 void removeFadingSource(SourceImpl
*source
);
252 void addPlayingSource(SourceImpl
*source
, ALuint id
);
253 void addPlayingSource(SourceImpl
*source
);
254 void removePlayingSource(SourceImpl
*source
);
256 void addStream(SourceImpl
*source
);
257 void removeStream(SourceImpl
*source
);
258 void removeStreamNoLock(SourceImpl
*source
);
260 void freeSource(SourceImpl
*source
) { mFreeSources
.push_back(source
); }
261 void freeSourceGroup(SourceGroupImpl
*group
);
262 void freeEffectSlot(AuxiliaryEffectSlotImpl
*slot
);
263 void freeEffect(EffectImpl
*effect
);
268 return Batcher(nullptr);
269 alcSuspendContext(mContext
.get());
270 return Batcher(mContext
.get());
273 std::unique_lock
<std::mutex
> getSourceStreamLock()
274 { return std::unique_lock
<std::mutex
>(mSourceStreamMutex
); }
276 template<typename R
, typename
... Args
>
277 void send(R
MessageHandler::* func
, Args
&&... args
)
278 { if(mMessage
.get()) (mMessage
.get()->*func
)(std::forward
<Args
>(args
)...); }
280 Device
getDevice() { return Device(&mDevice
); }
287 Listener
getListener() { return Listener(&mListener
); }
289 SharedPtr
<MessageHandler
> setMessageHandler(SharedPtr
<MessageHandler
>&& handler
);
290 SharedPtr
<MessageHandler
> getMessageHandler() const { return mMessage
; }
292 void setAsyncWakeInterval(std::chrono::milliseconds interval
);
293 std::chrono::milliseconds
getAsyncWakeInterval() const { return mWakeInterval
.load(); }
295 SharedPtr
<Decoder
> createDecoder(StringView name
);
297 bool isSupported(ChannelConfig channels
, SampleType type
) const;
299 ArrayView
<String
> getAvailableResamplers();
300 ALsizei
getDefaultResamplerIndex() const;
302 Buffer
getBuffer(StringView name
);
303 SharedFuture
<Buffer
> getBufferAsync(StringView name
);
304 void precacheBuffersAsync(ArrayView
<StringView
> names
);
305 Buffer
createBufferFrom(StringView name
, SharedPtr
<Decoder
>&& decoder
);
306 SharedFuture
<Buffer
> createBufferAsyncFrom(StringView name
, SharedPtr
<Decoder
>&& decoder
);
307 Buffer
findBuffer(StringView name
);
308 SharedFuture
<Buffer
> findBufferAsync(StringView name
);
309 void removeBuffer(StringView name
);
310 void removeBuffer(Buffer buffer
) { removeBuffer(buffer
.getName()); }
312 Source
createSource();
314 AuxiliaryEffectSlot
createAuxiliaryEffectSlot();
316 Effect
createEffect();
318 SourceGroup
createSourceGroup();
320 void setDopplerFactor(ALfloat factor
);
322 void setSpeedOfSound(ALfloat speed
);
324 void setDistanceModel(DistanceModel model
);
330 inline void CheckContext(const ContextImpl
&ctx
)
332 auto count
= ContextImpl::sContextSetCount
.load(std::memory_order_acquire
);
333 if(UNLIKELY(count
!= ctx
.mContextSetCounter
))
335 if(UNLIKELY(&ctx
!= ContextImpl::GetCurrent()))
336 throw std::runtime_error("Called context is not current");
337 ctx
.mContextSetCounter
= count
;
341 inline void CheckContexts(const ContextImpl
&ctx0
, const ContextImpl
&ctx1
)
343 if(UNLIKELY(&ctx0
!= &ctx1
))
344 throw std::runtime_error("Mismatched object contexts");
350 #endif /* CONTEXT_H */