6 #include <condition_variable>
7 #include <unordered_map>
14 #if __cplusplus >= 201703L
17 #include "mpark/variant.hpp"
28 #ifndef AL_SOFT_source_latency
29 #define AL_SOFT_source_latency 1
30 #define AL_SAMPLE_OFFSET_LATENCY_SOFT 0x1200
31 #define AL_SEC_OFFSET_LATENCY_SOFT 0x1201
32 typedef int64_t ALint64SOFT
;
33 typedef uint64_t ALuint64SOFT
;
34 typedef void (AL_APIENTRY
*LPALSOURCEDSOFT
)(ALuint
,ALenum
,ALdouble
);
35 typedef void (AL_APIENTRY
*LPALSOURCE3DSOFT
)(ALuint
,ALenum
,ALdouble
,ALdouble
,ALdouble
);
36 typedef void (AL_APIENTRY
*LPALSOURCEDVSOFT
)(ALuint
,ALenum
,const ALdouble
*);
37 typedef void (AL_APIENTRY
*LPALGETSOURCEDSOFT
)(ALuint
,ALenum
,ALdouble
*);
38 typedef void (AL_APIENTRY
*LPALGETSOURCE3DSOFT
)(ALuint
,ALenum
,ALdouble
*,ALdouble
*,ALdouble
*);
39 typedef void (AL_APIENTRY
*LPALGETSOURCEDVSOFT
)(ALuint
,ALenum
,ALdouble
*);
40 typedef void (AL_APIENTRY
*LPALSOURCEI64SOFT
)(ALuint
,ALenum
,ALint64SOFT
);
41 typedef void (AL_APIENTRY
*LPALSOURCE3I64SOFT
)(ALuint
,ALenum
,ALint64SOFT
,ALint64SOFT
,ALint64SOFT
);
42 typedef void (AL_APIENTRY
*LPALSOURCEI64VSOFT
)(ALuint
,ALenum
,const ALint64SOFT
*);
43 typedef void (AL_APIENTRY
*LPALGETSOURCEI64SOFT
)(ALuint
,ALenum
,ALint64SOFT
*);
44 typedef void (AL_APIENTRY
*LPALGETSOURCE3I64SOFT
)(ALuint
,ALenum
,ALint64SOFT
*,ALint64SOFT
*,ALint64SOFT
*);
45 typedef void (AL_APIENTRY
*LPALGETSOURCEI64VSOFT
)(ALuint
,ALenum
,ALint64SOFT
*);
48 #ifndef AL_SOFT_source_resampler
49 #define AL_SOFT_source_resampler
50 #define AL_NUM_RESAMPLERS_SOFT 0x1210
51 #define AL_DEFAULT_RESAMPLER_SOFT 0x1211
52 #define AL_SOURCE_RESAMPLER_SOFT 0x1212
53 #define AL_RESAMPLER_NAME_SOFT 0x1213
54 typedef const ALchar
* (AL_APIENTRY
*LPALGETSTRINGISOFT
)(ALenum pname
, ALsizei index
);
57 #ifndef AL_SOFT_source_spatialize
58 #define AL_SOFT_source_spatialize
59 #define AL_SOURCE_SPATIALIZE_SOFT 0x1214
60 #define AL_AUTO_SOFT 0x0002
64 #define F_PI (3.14159265358979323846f)
66 #if !(__cplusplus >= 201703L)
71 using mpark::holds_alternative
;
90 SOFT_source_resampler
,
91 SOFT_source_spatialize
,
101 // Batches OpenAL updates while the object is alive, if batching isn't already
104 ALCcontext
*mContext
;
107 Batcher(ALCcontext
*context
) : mContext(context
) { }
108 Batcher(Batcher
&& rhs
) : mContext(rhs
.mContext
) { rhs
.mContext
= nullptr; }
109 Batcher(const Batcher
&) = delete;
113 alcProcessContext(mContext
);
116 Batcher
& operator=(Batcher
&&) = delete;
117 Batcher
& operator=(const Batcher
&) = delete;
122 ContextImpl
*const mContext
;
125 ListenerImpl(ContextImpl
*ctx
) : mContext(ctx
) { }
127 void setGain(ALfloat gain
);
129 void set3DParameters(const Vector3
&position
, const Vector3
&velocity
, const std::pair
<Vector3
,Vector3
> &orientation
);
131 void setPosition(ALfloat x
, ALfloat y
, ALfloat z
);
132 void setPosition(const ALfloat
*pos
);
134 void setVelocity(ALfloat x
, ALfloat y
, ALfloat z
);
135 void setVelocity(const ALfloat
*vel
);
137 void setOrientation(ALfloat x1
, ALfloat y1
, ALfloat z1
, ALfloat x2
, ALfloat y2
, ALfloat z2
);
138 void setOrientation(const ALfloat
*at
, const ALfloat
*up
);
139 void setOrientation(const ALfloat
*ori
);
141 void setMetersPerUnit(ALfloat m_u
);
145 using DecoderOrExceptT
= std::variant
<SharedPtr
<Decoder
>,std::runtime_error
>;
146 using BufferOrExceptT
= std::variant
<Buffer
,std::runtime_error
>;
149 static ContextImpl
*sCurrentCtx
;
150 static thread_local ContextImpl
*sThreadCurrentCtx
;
153 static void MakeCurrent(ContextImpl
*context
);
154 static ContextImpl
*GetCurrent()
156 auto thrd_ctx
= sThreadCurrentCtx
;
157 return thrd_ctx
? thrd_ctx
: sCurrentCtx
;
160 static void MakeThreadCurrent(ContextImpl
*context
);
161 static ContextImpl
*GetThreadCurrent() { return sThreadCurrentCtx
; }
163 static std::atomic
<uint64_t> sContextSetCount
;
164 mutable uint64_t mContextSetCounter
;
167 ListenerImpl mListener
;
168 ALCcontext
*mContext
;
169 std::stack
<ALuint
> mSourceIds
;
171 struct PendingFuture
{ BufferImpl
*mBuffer
; SharedFuture
<Buffer
> mFuture
; };
172 struct PendingSource
{ SourceImpl
*mSource
; SharedFuture
<Buffer
> mFuture
; };
174 DeviceImpl
*const mDevice
;
175 Vector
<PendingFuture
> mFutureBuffers
;
176 Vector
<UniquePtr
<BufferImpl
>> mBuffers
;
177 Vector
<UniquePtr
<SourceGroupImpl
>> mSourceGroups
;
178 std::deque
<SourceImpl
> mAllSources
;
179 Vector
<SourceImpl
*> mFreeSources
;
181 Vector
<PendingSource
> mPendingSources
;
182 Vector
<SourceImpl
*> mFadingSources
;
183 Vector
<SourceBufferUpdateEntry
> mPlaySources
;
184 Vector
<SourceStreamUpdateEntry
> mStreamSources
;
186 Vector
<SourceImpl
*> mStreamingSources
;
187 std::mutex mSourceStreamMutex
;
189 std::atomic
<std::chrono::milliseconds
> mWakeInterval
;
190 std::mutex mWakeMutex
;
191 std::condition_variable mWakeThread
;
193 SharedPtr
<MessageHandler
> mMessage
;
195 struct PendingBuffer
{
196 BufferImpl
*mBuffer
{nullptr};
197 SharedPtr
<Decoder
> mDecoder
;
200 Promise
<Buffer
> mPromise
;
202 std::atomic
<PendingBuffer
*> mNext
{nullptr};
204 PendingBuffer() = default;
205 PendingBuffer(BufferImpl
*buffer
, SharedPtr
<Decoder
> decoder
, ALenum format
, ALuint frames
,
206 Promise
<Buffer
> promise
)
207 : mBuffer(buffer
), mDecoder(std::move(decoder
)), mFormat(format
), mFrames(frames
)
208 , mPromise(std::move(promise
)), mNext(nullptr)
211 std::atomic
<PendingBuffer
*> mPendingCurrent
;
212 PendingBuffer
*mPendingTail
;
213 PendingBuffer
*mPendingHead
;
215 std::atomic
<bool> mQuitThread
;
217 void backgroundProc();
221 Vector
<String
> mResamplers
;
223 Bitfield
<static_cast<size_t>(AL::EXTENSION_MAX
)> mHasExt
;
225 std::once_flag mSetExts
;
228 DecoderOrExceptT
findDecoder(StringView name
);
229 BufferOrExceptT
doCreateBuffer(StringView name
, Vector
<UniquePtr
<BufferImpl
>>::iterator iter
, SharedPtr
<Decoder
> decoder
);
230 BufferOrExceptT
doCreateBufferAsync(StringView name
, Vector
<UniquePtr
<BufferImpl
>>::iterator iter
, SharedPtr
<Decoder
> decoder
, Promise
<Buffer
> promise
);
232 bool mIsConnected
: 1;
233 bool mIsBatching
: 1;
236 ContextImpl(ALCcontext
*context
, DeviceImpl
*device
);
239 ALCcontext
*getALCcontext() const { return mContext
; }
240 long addRef() { return ++mRefs
; }
241 long decRef() { return --mRefs
; }
243 bool hasExtension(AL ext
) const { return mHasExt
[static_cast<size_t>(ext
)]; }
245 LPALGETSTRINGISOFT alGetStringiSOFT
;
246 LPALGETSOURCEI64VSOFT alGetSourcei64vSOFT
;
247 LPALGETSOURCEDVSOFT alGetSourcedvSOFT
;
249 LPALGENEFFECTS alGenEffects
;
250 LPALDELETEEFFECTS alDeleteEffects
;
251 LPALISEFFECT alIsEffect
;
252 LPALEFFECTI alEffecti
;
253 LPALEFFECTIV alEffectiv
;
254 LPALEFFECTF alEffectf
;
255 LPALEFFECTFV alEffectfv
;
256 LPALGETEFFECTI alGetEffecti
;
257 LPALGETEFFECTIV alGetEffectiv
;
258 LPALGETEFFECTF alGetEffectf
;
259 LPALGETEFFECTFV alGetEffectfv
;
261 LPALGENFILTERS alGenFilters
;
262 LPALDELETEFILTERS alDeleteFilters
;
263 LPALISFILTER alIsFilter
;
264 LPALFILTERI alFilteri
;
265 LPALFILTERIV alFilteriv
;
266 LPALFILTERF alFilterf
;
267 LPALFILTERFV alFilterfv
;
268 LPALGETFILTERI alGetFilteri
;
269 LPALGETFILTERIV alGetFilteriv
;
270 LPALGETFILTERF alGetFilterf
;
271 LPALGETFILTERFV alGetFilterfv
;
273 LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots
;
274 LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots
;
275 LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot
;
276 LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti
;
277 LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv
;
278 LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf
;
279 LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv
;
280 LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti
;
281 LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv
;
282 LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf
;
283 LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv
;
285 ALuint
getSourceId(ALuint maxprio
);
286 void insertSourceId(ALuint id
) { mSourceIds
.push(id
); }
288 void addPendingSource(SourceImpl
*source
, SharedFuture
<Buffer
> future
);
289 void removePendingSource(SourceImpl
*source
);
290 bool isPendingSource(const SourceImpl
*source
) const;
291 void addFadingSource(SourceImpl
*source
);
292 void removeFadingSource(SourceImpl
*source
);
293 void addPlayingSource(SourceImpl
*source
, ALuint id
);
294 void addPlayingSource(SourceImpl
*source
);
295 void removePlayingSource(SourceImpl
*source
);
297 void addStream(SourceImpl
*source
);
298 void removeStream(SourceImpl
*source
);
299 void removeStreamNoLock(SourceImpl
*source
);
301 void freeSource(SourceImpl
*source
) { mFreeSources
.push_back(source
); }
302 void freeSourceGroup(SourceGroupImpl
*group
);
307 return Batcher(nullptr);
308 alcSuspendContext(mContext
);
309 return Batcher(mContext
);
312 std::unique_lock
<std::mutex
> getSourceStreamLock()
313 { return std::unique_lock
<std::mutex
>(mSourceStreamMutex
); }
315 template<typename R
, typename
... Args
>
316 void send(R
MessageHandler::* func
, Args
&&... args
)
317 { if(mMessage
.get()) (mMessage
.get()->*func
)(std::forward
<Args
>(args
)...); }
319 Device
getDevice() { return Device(mDevice
); }
326 Listener
getListener() { return Listener(&mListener
); }
328 SharedPtr
<MessageHandler
> setMessageHandler(SharedPtr
<MessageHandler
>&& handler
);
329 SharedPtr
<MessageHandler
> getMessageHandler() const { return mMessage
; }
331 void setAsyncWakeInterval(std::chrono::milliseconds interval
);
332 std::chrono::milliseconds
getAsyncWakeInterval() const { return mWakeInterval
.load(); }
334 SharedPtr
<Decoder
> createDecoder(StringView name
);
336 bool isSupported(ChannelConfig channels
, SampleType type
) const;
338 ArrayView
<String
> getAvailableResamplers();
339 ALsizei
getDefaultResamplerIndex() const;
341 Buffer
getBuffer(StringView name
);
342 SharedFuture
<Buffer
> getBufferAsync(StringView name
);
343 void precacheBuffersAsync(ArrayView
<StringView
> names
);
344 Buffer
createBufferFrom(StringView name
, SharedPtr
<Decoder
>&& decoder
);
345 SharedFuture
<Buffer
> createBufferAsyncFrom(StringView name
, SharedPtr
<Decoder
>&& decoder
);
346 void removeBuffer(StringView name
);
347 void removeBuffer(Buffer buffer
) { removeBuffer(buffer
.getName()); }
349 Source
createSource();
351 AuxiliaryEffectSlot
createAuxiliaryEffectSlot();
353 Effect
createEffect();
355 SourceGroup
createSourceGroup(StringView name
);
356 SourceGroup
getSourceGroup(StringView name
);
358 void setDopplerFactor(ALfloat factor
);
360 void setSpeedOfSound(ALfloat speed
);
362 void setDistanceModel(DistanceModel model
);
368 inline void CheckContext(const ContextImpl
*ctx
)
370 auto count
= ContextImpl::sContextSetCount
.load(std::memory_order_acquire
);
371 if(UNLIKELY(count
!= ctx
->mContextSetCounter
))
373 if(UNLIKELY(ctx
!= ContextImpl::GetCurrent()))
374 throw std::runtime_error("Called context is not current");
375 ctx
->mContextSetCounter
= count
;
379 inline void CheckContexts(const ContextImpl
*ctx0
, const ContextImpl
*ctx1
)
381 if(UNLIKELY(ctx0
!= ctx1
))
382 throw std::runtime_error("Mismatched object contexts");
388 #endif /* CONTEXT_H */