Remove redundant void argument list in function def
[openal-soft.git] / OpenAL32 / Include / alMain.h
blob7f7013aaf37fed0877d3f39b6fe73b59f1020408
1 #ifndef AL_MAIN_H
2 #define AL_MAIN_H
4 #include <string.h>
5 #include <stdio.h>
6 #include <stddef.h>
7 #include <stdarg.h>
8 #include <assert.h>
9 #include <math.h>
10 #include <limits.h>
12 #ifdef HAVE_STRINGS_H
13 #include <strings.h>
14 #endif
15 #ifdef HAVE_INTRIN_H
16 #include <intrin.h>
17 #endif
19 #include <array>
20 #include <vector>
21 #include <string>
22 #include <chrono>
23 #include <algorithm>
25 #include "AL/al.h"
26 #include "AL/alc.h"
27 #include "AL/alext.h"
29 #include "inprogext.h"
30 #include "atomic.h"
31 #include "vector.h"
32 #include "almalloc.h"
33 #include "threads.h"
34 #include "ambidefs.h"
35 #include "opthelpers.h"
38 template<typename T, size_t N>
39 constexpr inline size_t countof(const T(&)[N]) noexcept
40 { return N; }
41 #define COUNTOF countof
44 #ifndef UNUSED
45 #if defined(__cplusplus)
46 #define UNUSED(x)
47 #elif defined(__GNUC__)
48 #define UNUSED(x) UNUSED_##x __attribute__((unused))
49 #elif defined(__LCLINT__)
50 #define UNUSED(x) /*@unused@*/ x
51 #else
52 #define UNUSED(x) x
53 #endif
54 #endif
56 /* Calculates the size of a struct with N elements of a flexible array member.
57 * GCC and Clang allow offsetof(Type, fam[N]) for this, but MSVC seems to have
58 * trouble, so a bit more verbose workaround is needed.
60 #define FAM_SIZE(T, M, N) (offsetof(T, M) + sizeof(((T*)NULL)->M[0])*(N))
63 using ALint64 = ALint64SOFT;
64 using ALuint64 = ALuint64SOFT;
66 inline constexpr int64_t operator "" _i64(unsigned long long int n) noexcept { return static_cast<int64_t>(n); }
67 inline constexpr uint64_t operator "" _u64(unsigned long long int n) noexcept { return static_cast<uint64_t>(n); }
69 /* Define CTZ macros (count trailing zeros), and POPCNT macros (population
70 * count/count 1 bits), for 32- and 64-bit integers. The CTZ macros' results
71 * are *UNDEFINED* if the value is 0.
73 #ifdef __GNUC__
75 #define POPCNT32 __builtin_popcount
76 #define CTZ32 __builtin_ctz
77 #if SIZEOF_LONG == 8
78 #define POPCNT64 __builtin_popcountl
79 #define CTZ64 __builtin_ctzl
80 #else
81 #define POPCNT64 __builtin_popcountll
82 #define CTZ64 __builtin_ctzll
83 #endif
85 #elif defined(HAVE_BITSCANFORWARD64_INTRINSIC)
87 inline int msvc64_popcnt32(ALuint v)
88 { return (int)__popcnt(v); }
89 #define POPCNT32 msvc64_popcnt32
90 inline int msvc64_ctz32(ALuint v)
92 unsigned long idx = 32;
93 _BitScanForward(&idx, v);
94 return (int)idx;
96 #define CTZ32 msvc64_ctz32
98 inline int msvc64_popcnt64(ALuint64 v)
99 { return (int)__popcnt64(v); }
100 #define POPCNT64 msvc64_popcnt64
101 inline int msvc64_ctz64(ALuint64 v)
103 unsigned long idx = 64;
104 _BitScanForward64(&idx, v);
105 return (int)idx;
107 #define CTZ64 msvc64_ctz64
109 #elif defined(HAVE_BITSCANFORWARD_INTRINSIC)
111 inline int msvc_popcnt32(ALuint v)
112 { return (int)__popcnt(v); }
113 #define POPCNT32 msvc_popcnt32
114 inline int msvc_ctz32(ALuint v)
116 unsigned long idx = 32;
117 _BitScanForward(&idx, v);
118 return (int)idx;
120 #define CTZ32 msvc_ctz32
122 inline int msvc_popcnt64(ALuint64 v)
123 { return (int)(__popcnt((ALuint)v) + __popcnt((ALuint)(v>>32))); }
124 #define POPCNT64 msvc_popcnt64
125 inline int msvc_ctz64(ALuint64 v)
127 unsigned long idx = 64;
128 if(!_BitScanForward(&idx, v&0xffffffff))
130 if(_BitScanForward(&idx, v>>32))
131 idx += 32;
133 return (int)idx;
135 #define CTZ64 msvc_ctz64
137 #else
139 /* There be black magics here. The popcnt method is derived from
140 * https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
141 * while the ctz-utilizing-popcnt algorithm is shown here
142 * http://www.hackersdelight.org/hdcodetxt/ntz.c.txt
143 * as the ntz2 variant. These likely aren't the most efficient methods, but
144 * they're good enough if the GCC or MSVC intrinsics aren't available.
146 inline int fallback_popcnt32(ALuint v)
148 v = v - ((v >> 1) & 0x55555555u);
149 v = (v & 0x33333333u) + ((v >> 2) & 0x33333333u);
150 v = (v + (v >> 4)) & 0x0f0f0f0fu;
151 return (int)((v * 0x01010101u) >> 24);
153 #define POPCNT32 fallback_popcnt32
154 inline int fallback_ctz32(ALuint value)
155 { return fallback_popcnt32(~value & (value - 1)); }
156 #define CTZ32 fallback_ctz32
158 inline int fallback_popcnt64(ALuint64 v)
160 v = v - ((v >> 1) & 0x5555555555555555_u64);
161 v = (v & 0x3333333333333333_u64) + ((v >> 2) & 0x3333333333333333_u64);
162 v = (v + (v >> 4)) & 0x0f0f0f0f0f0f0f0f_u64;
163 return (int)((v * 0x0101010101010101_u64) >> 56);
165 #define POPCNT64 fallback_popcnt64
166 inline int fallback_ctz64(ALuint64 value)
167 { return fallback_popcnt64(~value & (value - 1)); }
168 #define CTZ64 fallback_ctz64
169 #endif
171 #if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__)
172 #define IS_LITTLE_ENDIAN (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
173 #else
174 static const union {
175 ALuint u;
176 ALubyte b[sizeof(ALuint)];
177 } EndianTest = { 1 };
178 #define IS_LITTLE_ENDIAN (EndianTest.b[0] == 1)
179 #endif
182 struct HrtfEntry;
183 struct HrtfHandle;
184 struct EnumeratedHrtf;
185 struct DirectHrtfState;
186 struct FrontStablizer;
187 struct Compressor;
188 struct BackendBase;
189 struct ALbuffer;
190 struct ALeffect;
191 struct ALfilter;
192 struct EffectState;
193 struct Uhj2Encoder;
194 class BFormatDec;
195 class AmbiUpsampler;
196 struct bs2b;
199 #define DEFAULT_UPDATE_SIZE (1024)
200 #define DEFAULT_NUM_UPDATES (3)
201 #define DEFAULT_OUTPUT_RATE (44100)
202 #define MIN_OUTPUT_RATE (8000)
205 /* Find the next power-of-2 for non-power-of-2 numbers. */
206 inline ALuint NextPowerOf2(ALuint value) noexcept
208 if(value > 0)
210 value--;
211 value |= value>>1;
212 value |= value>>2;
213 value |= value>>4;
214 value |= value>>8;
215 value |= value>>16;
217 return value+1;
220 /** Round up a value to the next multiple. */
221 inline size_t RoundUp(size_t value, size_t r) noexcept
223 value += r-1;
224 return value - (value%r);
227 /* Fast float-to-int conversion. No particular rounding mode is assumed; the
228 * IEEE-754 default is round-to-nearest with ties-to-even, though an app could
229 * change it on its own threads. On some systems, a truncating conversion may
230 * always be the fastest method.
232 inline ALint fastf2i(ALfloat f) noexcept
234 #if defined(HAVE_INTRIN_H) && ((defined(_M_IX86_FP) && (_M_IX86_FP > 0)) || defined(_M_X64))
235 return _mm_cvt_ss2si(_mm_set1_ps(f));
237 #elif defined(_MSC_VER) && defined(_M_IX86_FP)
239 ALint i;
240 __asm fld f
241 __asm fistp i
242 return i;
244 #elif (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))
246 ALint i;
247 #ifdef __SSE_MATH__
248 __asm__("cvtss2si %1, %0" : "=r"(i) : "x"(f));
249 #else
250 __asm__ __volatile__("fistpl %0" : "=m"(i) : "t"(f) : "st");
251 #endif
252 return i;
254 /* On GCC when compiling with -fno-math-errno, lrintf can be inlined to
255 * some simple instructions. Clang does not inline it, always generating a
256 * libc call, while MSVC's implementation is horribly slow, so always fall
257 * back to a normal integer conversion for them.
259 #elif !defined(_MSC_VER) && !defined(__clang__)
261 return lrintf(f);
263 #else
265 return (ALint)f;
266 #endif
269 /* Converts float-to-int using standard behavior (truncation). */
270 inline int float2int(float f) noexcept
272 #if ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) && \
273 !defined(__SSE_MATH__)) || (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP == 0)
274 ALint sign, shift, mant;
275 union {
276 ALfloat f;
277 ALint i;
278 } conv;
280 conv.f = f;
281 sign = (conv.i>>31) | 1;
282 shift = ((conv.i>>23)&0xff) - (127+23);
284 /* Over/underflow */
285 if(UNLIKELY(shift >= 31 || shift < -23))
286 return 0;
288 mant = (conv.i&0x7fffff) | 0x800000;
289 if(LIKELY(shift < 0))
290 return (mant >> -shift) * sign;
291 return (mant << shift) * sign;
293 #else
295 return static_cast<ALint>(f);
296 #endif
299 /* Rounds a float to the nearest integral value, according to the current
300 * rounding mode. This is essentially an inlined version of rintf, although
301 * makes fewer promises (e.g. -0 or -0.25 rounded to 0 may result in +0).
303 inline float fast_roundf(float f) noexcept
305 #if (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) && \
306 !defined(__SSE_MATH__)
308 float out;
309 __asm__ __volatile__("frndint" : "=t"(out) : "0"(f));
310 return out;
312 #else
314 /* Integral limit, where sub-integral precision is not available for
315 * floats.
317 static const float ilim[2] = {
318 8388608.0f /* 0x1.0p+23 */,
319 -8388608.0f /* -0x1.0p+23 */
321 ALuint sign, expo;
322 union {
323 ALfloat f;
324 ALuint i;
325 } conv;
327 conv.f = f;
328 sign = (conv.i>>31)&0x01;
329 expo = (conv.i>>23)&0xff;
331 if(UNLIKELY(expo >= 150/*+23*/))
333 /* An exponent (base-2) of 23 or higher is incapable of sub-integral
334 * precision, so it's already an integral value. We don't need to worry
335 * about infinity or NaN here.
337 return f;
339 /* Adding the integral limit to the value (with a matching sign) forces a
340 * result that has no sub-integral precision, and is consequently forced to
341 * round to an integral value. Removing the integral limit then restores
342 * the initial value rounded to the integral. The compiler should not
343 * optimize this out because of non-associative rules on floating-point
344 * math (as long as you don't use -fassociative-math,
345 * -funsafe-math-optimizations, -ffast-math, or -Ofast, in which case this
346 * may break).
348 f += ilim[sign];
349 return f - ilim[sign];
350 #endif
354 enum DevProbe {
355 ALL_DEVICE_PROBE,
356 CAPTURE_DEVICE_PROBE
360 enum Channel {
361 FrontLeft = 0,
362 FrontRight,
363 FrontCenter,
364 LFE,
365 BackLeft,
366 BackRight,
367 BackCenter,
368 SideLeft,
369 SideRight,
371 UpperFrontLeft,
372 UpperFrontRight,
373 UpperBackLeft,
374 UpperBackRight,
375 LowerFrontLeft,
376 LowerFrontRight,
377 LowerBackLeft,
378 LowerBackRight,
380 Aux0,
381 Aux1,
382 Aux2,
383 Aux3,
384 Aux4,
385 Aux5,
386 Aux6,
387 Aux7,
388 Aux8,
389 Aux9,
390 Aux10,
391 Aux11,
392 Aux12,
393 Aux13,
394 Aux14,
395 Aux15,
397 InvalidChannel
401 /* Device formats */
402 enum DevFmtType {
403 DevFmtByte = ALC_BYTE_SOFT,
404 DevFmtUByte = ALC_UNSIGNED_BYTE_SOFT,
405 DevFmtShort = ALC_SHORT_SOFT,
406 DevFmtUShort = ALC_UNSIGNED_SHORT_SOFT,
407 DevFmtInt = ALC_INT_SOFT,
408 DevFmtUInt = ALC_UNSIGNED_INT_SOFT,
409 DevFmtFloat = ALC_FLOAT_SOFT,
411 DevFmtTypeDefault = DevFmtFloat
413 enum DevFmtChannels {
414 DevFmtMono = ALC_MONO_SOFT,
415 DevFmtStereo = ALC_STEREO_SOFT,
416 DevFmtQuad = ALC_QUAD_SOFT,
417 DevFmtX51 = ALC_5POINT1_SOFT,
418 DevFmtX61 = ALC_6POINT1_SOFT,
419 DevFmtX71 = ALC_7POINT1_SOFT,
420 DevFmtAmbi3D = ALC_BFORMAT3D_SOFT,
422 /* Similar to 5.1, except using rear channels instead of sides */
423 DevFmtX51Rear = 0x80000000,
425 DevFmtChannelsDefault = DevFmtStereo
427 #define MAX_OUTPUT_CHANNELS (16)
429 /* DevFmtType traits, providing the type, etc given a DevFmtType. */
430 template<DevFmtType T>
431 struct DevFmtTypeTraits { };
433 template<>
434 struct DevFmtTypeTraits<DevFmtByte> { using Type = ALbyte; };
435 template<>
436 struct DevFmtTypeTraits<DevFmtUByte> { using Type = ALubyte; };
437 template<>
438 struct DevFmtTypeTraits<DevFmtShort> { using Type = ALshort; };
439 template<>
440 struct DevFmtTypeTraits<DevFmtUShort> { using Type = ALushort; };
441 template<>
442 struct DevFmtTypeTraits<DevFmtInt> { using Type = ALint; };
443 template<>
444 struct DevFmtTypeTraits<DevFmtUInt> { using Type = ALuint; };
445 template<>
446 struct DevFmtTypeTraits<DevFmtFloat> { using Type = ALfloat; };
449 ALsizei BytesFromDevFmt(DevFmtType type) noexcept;
450 ALsizei ChannelsFromDevFmt(DevFmtChannels chans, ALsizei ambiorder) noexcept;
451 inline ALsizei FrameSizeFromDevFmt(DevFmtChannels chans, DevFmtType type, ALsizei ambiorder) noexcept
452 { return ChannelsFromDevFmt(chans, ambiorder) * BytesFromDevFmt(type); }
454 enum class AmbiLayout {
455 FuMa = ALC_FUMA_SOFT, /* FuMa channel order */
456 ACN = ALC_ACN_SOFT, /* ACN channel order */
458 Default = ACN
461 enum class AmbiNorm {
462 FuMa = ALC_FUMA_SOFT, /* FuMa normalization */
463 SN3D = ALC_SN3D_SOFT, /* SN3D normalization */
464 N3D = ALC_N3D_SOFT, /* N3D normalization */
466 Default = SN3D
470 enum DeviceType {
471 Playback,
472 Capture,
473 Loopback
477 enum RenderMode {
478 NormalRender,
479 StereoPair,
480 HrtfRender
484 struct BufferSubList {
485 uint64_t FreeMask{~uint64_t{}};
486 ALbuffer *Buffers{nullptr}; /* 64 */
488 BufferSubList() noexcept = default;
489 BufferSubList(const BufferSubList&) = delete;
490 BufferSubList(BufferSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Buffers{rhs.Buffers}
491 { rhs.FreeMask = ~uint64_t{}; rhs.Buffers = nullptr; }
492 ~BufferSubList();
494 BufferSubList& operator=(const BufferSubList&) = delete;
495 BufferSubList& operator=(BufferSubList&& rhs) noexcept
496 { std::swap(FreeMask, rhs.FreeMask); std::swap(Buffers, rhs.Buffers); return *this; }
499 struct EffectSubList {
500 uint64_t FreeMask{~uint64_t{}};
501 ALeffect *Effects{nullptr}; /* 64 */
503 EffectSubList() noexcept = default;
504 EffectSubList(const EffectSubList&) = delete;
505 EffectSubList(EffectSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Effects{rhs.Effects}
506 { rhs.FreeMask = ~uint64_t{}; rhs.Effects = nullptr; }
507 ~EffectSubList();
509 EffectSubList& operator=(const EffectSubList&) = delete;
510 EffectSubList& operator=(EffectSubList&& rhs) noexcept
511 { std::swap(FreeMask, rhs.FreeMask); std::swap(Effects, rhs.Effects); return *this; }
514 struct FilterSubList {
515 uint64_t FreeMask{~uint64_t{}};
516 ALfilter *Filters{nullptr}; /* 64 */
518 FilterSubList() noexcept = default;
519 FilterSubList(const FilterSubList&) = delete;
520 FilterSubList(FilterSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Filters{rhs.Filters}
521 { rhs.FreeMask = ~uint64_t{}; rhs.Filters = nullptr; }
522 ~FilterSubList();
524 FilterSubList& operator=(const FilterSubList&) = delete;
525 FilterSubList& operator=(FilterSubList&& rhs) noexcept
526 { std::swap(FreeMask, rhs.FreeMask); std::swap(Filters, rhs.Filters); return *this; }
530 /* Maximum delay in samples for speaker distance compensation. */
531 #define MAX_DELAY_LENGTH 1024
533 class DistanceComp {
534 public:
535 struct DistData {
536 ALfloat Gain{1.0f};
537 ALsizei Length{0}; /* Valid range is [0...MAX_DELAY_LENGTH). */
538 ALfloat *Buffer{nullptr};
541 private:
542 DistData mChannel[MAX_OUTPUT_CHANNELS];
543 al::vector<ALfloat,16> mSamples;
545 public:
546 void resize(size_t new_size) { mSamples.resize(new_size); }
547 void shrink_to_fit() { mSamples.shrink_to_fit(); }
548 void clear() noexcept
550 for(auto &chan : mChannel)
552 chan.Gain = 1.0f;
553 chan.Length = 0;
554 chan.Buffer = nullptr;
556 mSamples.clear();
559 DistData *begin() noexcept { return std::begin(mChannel); }
560 const DistData *begin() const noexcept { return std::begin(mChannel); }
561 const DistData *cbegin() const noexcept { return std::begin(mChannel); }
562 DistData *end() noexcept { return std::end(mChannel); }
563 const DistData *end() const noexcept { return std::end(mChannel); }
564 const DistData *cend() const noexcept { return std::end(mChannel); }
566 ALfloat *data() noexcept { return mSamples.data(); }
567 const ALfloat *data() const noexcept { return mSamples.data(); }
569 DistData& operator[](size_t o) noexcept { return mChannel[o]; }
570 const DistData& operator[](size_t o) const noexcept { return mChannel[o]; }
573 struct BFChannelConfig {
574 ALfloat Scale;
575 ALsizei Index;
578 /* Size for temporary storage of buffer data, in ALfloats. Larger values need
579 * more memory, while smaller values may need more iterations. The value needs
580 * to be a sensible size, however, as it constrains the max stepping value used
581 * for mixing, as well as the maximum number of samples per mixing iteration.
583 #define BUFFERSIZE 2048
585 struct MixParams {
586 /* Coefficient channel mapping for mixing to the buffer. */
587 std::array<BFChannelConfig,MAX_OUTPUT_CHANNELS> AmbiMap;
589 ALfloat (*Buffer)[BUFFERSIZE]{nullptr};
590 ALsizei NumChannels{0};
593 struct RealMixParams {
594 Channel ChannelName[MAX_OUTPUT_CHANNELS]{};
596 ALfloat (*Buffer)[BUFFERSIZE]{nullptr};
597 ALsizei NumChannels{0};
600 using POSTPROCESS = void(*)(ALCdevice *device, ALsizei SamplesToDo);
602 struct ALCdevice {
603 RefCount ref{1u};
605 std::atomic<bool> Connected{true};
606 const DeviceType Type{};
608 ALuint Frequency{};
609 ALuint UpdateSize{};
610 ALuint NumUpdates{};
611 DevFmtChannels FmtChans{};
612 DevFmtType FmtType{};
613 ALboolean IsHeadphones{AL_FALSE};
614 ALsizei mAmbiOrder{0};
615 /* For DevFmtAmbi* output only, specifies the channel order and
616 * normalization.
618 AmbiLayout mAmbiLayout{AmbiLayout::Default};
619 AmbiNorm mAmbiScale{AmbiNorm::Default};
621 ALCenum LimiterState{ALC_DONT_CARE_SOFT};
623 std::string DeviceName;
625 // Device flags
626 ALuint Flags{0u};
628 std::string HrtfName;
629 al::vector<EnumeratedHrtf> HrtfList;
630 ALCenum HrtfStatus{ALC_FALSE};
632 std::atomic<ALCenum> LastError{ALC_NO_ERROR};
634 // Maximum number of sources that can be created
635 ALuint SourcesMax{};
636 // Maximum number of slots that can be created
637 ALuint AuxiliaryEffectSlotMax{};
639 ALCuint NumMonoSources{};
640 ALCuint NumStereoSources{};
641 ALsizei NumAuxSends{};
643 // Map of Buffers for this device
644 std::mutex BufferLock;
645 al::vector<BufferSubList> BufferList;
647 // Map of Effects for this device
648 std::mutex EffectLock;
649 al::vector<EffectSubList> EffectList;
651 // Map of Filters for this device
652 std::mutex FilterLock;
653 al::vector<FilterSubList> FilterList;
655 /* Rendering mode. */
656 RenderMode mRenderMode{NormalRender};
658 /* The average speaker distance as determined by the ambdec configuration
659 * (or alternatively, by the NFC-HOA reference delay). Only used for NFC.
661 ALfloat AvgSpeakerDist{0.0f};
663 ALuint SamplesDone{0u};
664 std::chrono::nanoseconds ClockBase{0};
665 std::chrono::nanoseconds FixedLatency{0};
667 /* Temp storage used for mixer processing. */
668 alignas(16) ALfloat TempBuffer[4][BUFFERSIZE];
670 /* Mixing buffer used by the Dry mix, FOAOut, and Real out. */
671 al::vector<std::array<ALfloat,BUFFERSIZE>, 16> MixBuffer;
673 /* The "dry" path corresponds to the main output. */
674 MixParams Dry;
675 ALsizei NumChannelsPerOrder[MAX_AMBI_ORDER+1]{};
677 /* First-order ambisonics output, to be upsampled to the dry buffer if different. */
678 MixParams FOAOut;
680 /* "Real" output, which will be written to the device buffer. May alias the
681 * dry buffer.
683 RealMixParams RealOut;
685 /* HRTF state and info */
686 std::unique_ptr<DirectHrtfState> mHrtfState;
687 HrtfEntry *mHrtf{nullptr};
689 /* UHJ encoder state */
690 std::unique_ptr<Uhj2Encoder> Uhj_Encoder;
692 /* High quality Ambisonic decoder */
693 std::unique_ptr<BFormatDec> AmbiDecoder;
695 /* Stereo-to-binaural filter */
696 std::unique_ptr<bs2b> Bs2b;
698 /* First-order ambisonic upsampler for higher-order output */
699 std::unique_ptr<AmbiUpsampler> AmbiUp;
701 POSTPROCESS PostProcess{};
703 std::unique_ptr<FrontStablizer> Stablizer;
705 std::unique_ptr<Compressor> Limiter;
707 /* Delay buffers used to compensate for speaker distances. */
708 DistanceComp ChannelDelay;
710 /* Dithering control. */
711 ALfloat DitherDepth{0.0f};
712 ALuint DitherSeed{0u};
714 /* Running count of the mixer invocations, in 31.1 fixed point. This
715 * actually increments *twice* when mixing, first at the start and then at
716 * the end, so the bottom bit indicates if the device is currently mixing
717 * and the upper bits indicates how many mixes have been done.
719 RefCount MixCount{0u};
721 // Contexts created on this device
722 std::atomic<ALCcontext*> ContextList{nullptr};
724 /* This lock protects the device state (format, update size, etc) from
725 * being from being changed in multiple threads, or being accessed while
726 * being changed. It's also used to serialize calls to the backend.
728 std::mutex StateLock;
729 std::unique_ptr<BackendBase> Backend;
731 std::atomic<ALCdevice*> next{nullptr};
734 ALCdevice(DeviceType type);
735 ALCdevice(const ALCdevice&) = delete;
736 ALCdevice& operator=(const ALCdevice&) = delete;
737 ~ALCdevice();
739 ALsizei bytesFromFmt() const noexcept { return BytesFromDevFmt(FmtType); }
740 ALsizei channelsFromFmt() const noexcept { return ChannelsFromDevFmt(FmtChans, mAmbiOrder); }
741 ALsizei frameSizeFromFmt() const noexcept { return bytesFromFmt() * channelsFromFmt(); }
743 static constexpr inline const char *CurrentPrefix() noexcept { return "ALCdevice::"; }
744 DEF_NEWDEL(ALCdevice)
747 // Frequency was requested by the app or config file
748 #define DEVICE_FREQUENCY_REQUEST (1u<<1)
749 // Channel configuration was requested by the config file
750 #define DEVICE_CHANNELS_REQUEST (1u<<2)
751 // Sample type was requested by the config file
752 #define DEVICE_SAMPLE_TYPE_REQUEST (1u<<3)
754 // Specifies if the DSP is paused at user request
755 #define DEVICE_PAUSED (1u<<30)
757 // Specifies if the device is currently running
758 #define DEVICE_RUNNING (1u<<31)
761 /* Must be less than 15 characters (16 including terminating null) for
762 * compatibility with pthread_setname_np limitations. */
763 #define MIXER_THREAD_NAME "alsoft-mixer"
765 #define RECORD_THREAD_NAME "alsoft-record"
768 enum {
769 /* End event thread processing. */
770 EventType_KillThread = 0,
772 /* User event types. */
773 EventType_SourceStateChange = 1<<0,
774 EventType_BufferCompleted = 1<<1,
775 EventType_Error = 1<<2,
776 EventType_Performance = 1<<3,
777 EventType_Deprecated = 1<<4,
778 EventType_Disconnected = 1<<5,
780 /* Internal events. */
781 EventType_ReleaseEffectState = 65536,
784 struct AsyncEvent {
785 unsigned int EnumType{0u};
786 union {
787 char dummy;
788 struct {
789 ALuint id;
790 ALenum state;
791 } srcstate;
792 struct {
793 ALuint id;
794 ALsizei count;
795 } bufcomp;
796 struct {
797 ALenum type;
798 ALuint id;
799 ALuint param;
800 ALchar msg[1008];
801 } user;
802 EffectState *mEffectState;
803 } u{};
805 AsyncEvent() noexcept = default;
806 constexpr AsyncEvent(unsigned int type) noexcept : EnumType{type} { }
810 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends);
813 extern ALint RTPrioLevel;
814 void SetRTPriority(void);
816 void SetDefaultChannelOrder(ALCdevice *device);
817 void SetDefaultWFXChannelOrder(ALCdevice *device);
819 const ALCchar *DevFmtTypeString(DevFmtType type) noexcept;
820 const ALCchar *DevFmtChannelsString(DevFmtChannels chans) noexcept;
822 inline ALint GetChannelIndex(const Channel (&names)[MAX_OUTPUT_CHANNELS], Channel chan)
824 auto iter = std::find(std::begin(names), std::end(names), chan);
825 if(iter == std::end(names)) return -1;
826 return static_cast<ALint>(std::distance(std::begin(names), iter));
829 * GetChannelIdxByName
831 * Returns the index for the given channel name (e.g. FrontCenter), or -1 if it
832 * doesn't exist.
834 inline ALint GetChannelIdxByName(const RealMixParams &real, Channel chan)
835 { return GetChannelIndex(real.ChannelName, chan); }
838 void StartEventThrd(ALCcontext *ctx);
839 void StopEventThrd(ALCcontext *ctx);
842 al::vector<std::string> SearchDataFiles(const char *match, const char *subdir);
844 #endif