Use a normal vector for filter sublists
[openal-soft.git] / OpenAL32 / Include / alMain.h
blob226d39a948912c5915819c20e6f741e7ce05bf0a
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 <vector>
20 #include <string>
22 #include "AL/al.h"
23 #include "AL/alc.h"
24 #include "AL/alext.h"
26 #include "inprogext.h"
27 #include "logging.h"
28 #include "polymorphism.h"
29 #include "atomic.h"
30 #include "vector.h"
31 #include "almalloc.h"
32 #include "threads.h"
35 template<typename T, size_t N>
36 constexpr inline size_t countof(const T(&)[N]) noexcept
37 { return N; }
38 #define COUNTOF countof
40 #if defined(_WIN64)
41 #define SZFMT "%I64u"
42 #elif defined(_WIN32)
43 #define SZFMT "%u"
44 #else
45 #define SZFMT "%zu"
46 #endif
48 #ifdef __has_builtin
49 #define HAS_BUILTIN __has_builtin
50 #else
51 #define HAS_BUILTIN(x) (0)
52 #endif
54 #ifdef __GNUC__
55 /* LIKELY optimizes the case where the condition is true. The condition is not
56 * required to be true, but it can result in more optimal code for the true
57 * path at the expense of a less optimal false path.
59 #define LIKELY(x) __builtin_expect(!!(x), !0)
60 /* The opposite of LIKELY, optimizing the case where the condition is false. */
61 #define UNLIKELY(x) __builtin_expect(!!(x), 0)
62 /* Unlike LIKELY, ASSUME requires the condition to be true or else it invokes
63 * undefined behavior. It's essentially an assert without actually checking the
64 * condition at run-time, allowing for stronger optimizations than LIKELY.
66 #if HAS_BUILTIN(__builtin_assume)
67 #define ASSUME __builtin_assume
68 #else
69 #define ASSUME(x) do { if(!(x)) __builtin_unreachable(); } while(0)
70 #endif
72 #else
74 #define LIKELY(x) (!!(x))
75 #define UNLIKELY(x) (!!(x))
76 #ifdef _MSC_VER
77 #define ASSUME __assume
78 #else
79 #define ASSUME(x) ((void)0)
80 #endif
81 #endif
83 #ifndef UINT64_MAX
84 #define UINT64_MAX U64(18446744073709551615)
85 #endif
87 #ifndef UNUSED
88 #if defined(__cplusplus)
89 #define UNUSED(x)
90 #elif defined(__GNUC__)
91 #define UNUSED(x) UNUSED_##x __attribute__((unused))
92 #elif defined(__LCLINT__)
93 #define UNUSED(x) /*@unused@*/ x
94 #else
95 #define UNUSED(x) x
96 #endif
97 #endif
99 /* Calculates the size of a struct with N elements of a flexible array member.
100 * GCC and Clang allow offsetof(Type, fam[N]) for this, but MSVC seems to have
101 * trouble, so a bit more verbose workaround is needed.
103 #define FAM_SIZE(T, M, N) (offsetof(T, M) + sizeof(((T*)NULL)->M[0])*(N))
106 typedef ALint64SOFT ALint64;
107 typedef ALuint64SOFT ALuint64;
109 #ifndef U64
110 #if defined(_MSC_VER)
111 #define U64(x) ((ALuint64)(x##ui64))
112 #elif SIZEOF_LONG == 8
113 #define U64(x) ((ALuint64)(x##ul))
114 #elif SIZEOF_LONG_LONG == 8
115 #define U64(x) ((ALuint64)(x##ull))
116 #endif
117 #endif
119 #ifndef I64
120 #if defined(_MSC_VER)
121 #define I64(x) ((ALint64)(x##i64))
122 #elif SIZEOF_LONG == 8
123 #define I64(x) ((ALint64)(x##l))
124 #elif SIZEOF_LONG_LONG == 8
125 #define I64(x) ((ALint64)(x##ll))
126 #endif
127 #endif
129 /* Define a CTZ64 macro (count trailing zeros, for 64-bit integers). The result
130 * is *UNDEFINED* if the value is 0.
132 #ifdef __GNUC__
134 #if SIZEOF_LONG == 8
135 #define CTZ64 __builtin_ctzl
136 #else
137 #define CTZ64 __builtin_ctzll
138 #endif
140 #elif defined(HAVE_BITSCANFORWARD64_INTRINSIC)
142 inline int msvc64_ctz64(ALuint64 v)
144 unsigned long idx = 64;
145 _BitScanForward64(&idx, v);
146 return (int)idx;
148 #define CTZ64 msvc64_ctz64
150 #elif defined(HAVE_BITSCANFORWARD_INTRINSIC)
152 inline int msvc_ctz64(ALuint64 v)
154 unsigned long idx = 64;
155 if(!_BitScanForward(&idx, v&0xffffffff))
157 if(_BitScanForward(&idx, v>>32))
158 idx += 32;
160 return (int)idx;
162 #define CTZ64 msvc_ctz64
164 #else
166 /* There be black magics here. The popcnt64 method is derived from
167 * https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
168 * while the ctz-utilizing-popcnt algorithm is shown here
169 * http://www.hackersdelight.org/hdcodetxt/ntz.c.txt
170 * as the ntz2 variant. These likely aren't the most efficient methods, but
171 * they're good enough if the GCC or MSVC intrinsics aren't available.
173 inline int fallback_popcnt64(ALuint64 v)
175 v = v - ((v >> 1) & U64(0x5555555555555555));
176 v = (v & U64(0x3333333333333333)) + ((v >> 2) & U64(0x3333333333333333));
177 v = (v + (v >> 4)) & U64(0x0f0f0f0f0f0f0f0f);
178 return (int)((v * U64(0x0101010101010101)) >> 56);
181 inline int fallback_ctz64(ALuint64 value)
183 return fallback_popcnt64(~value & (value - 1));
185 #define CTZ64 fallback_ctz64
186 #endif
188 #if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__)
189 #define IS_LITTLE_ENDIAN (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
190 #else
191 static const union {
192 ALuint u;
193 ALubyte b[sizeof(ALuint)];
194 } EndianTest = { 1 };
195 #define IS_LITTLE_ENDIAN (EndianTest.b[0] == 1)
196 #endif
199 struct Hrtf;
200 struct HrtfEntry;
201 struct DirectHrtfState;
202 struct FrontStablizer;
203 struct Compressor;
204 struct ALCbackend;
205 struct ALbuffer;
206 struct ALeffect;
207 struct ALfilter;
210 #define DEFAULT_OUTPUT_RATE (44100)
211 #define MIN_OUTPUT_RATE (8000)
214 /* Find the next power-of-2 for non-power-of-2 numbers. */
215 inline ALuint NextPowerOf2(ALuint value)
217 if(value > 0)
219 value--;
220 value |= value>>1;
221 value |= value>>2;
222 value |= value>>4;
223 value |= value>>8;
224 value |= value>>16;
226 return value+1;
229 /** Round up a value to the next multiple. */
230 inline size_t RoundUp(size_t value, size_t r)
232 value += r-1;
233 return value - (value%r);
236 /* Fast float-to-int conversion. No particular rounding mode is assumed; the
237 * IEEE-754 default is round-to-nearest with ties-to-even, though an app could
238 * change it on its own threads. On some systems, a truncating conversion may
239 * always be the fastest method.
241 inline ALint fastf2i(ALfloat f)
243 #if defined(HAVE_INTRIN_H) && ((defined(_M_IX86_FP) && (_M_IX86_FP > 0)) || defined(_M_X64))
244 return _mm_cvt_ss2si(_mm_set1_ps(f));
246 #elif defined(_MSC_VER) && defined(_M_IX86_FP)
248 ALint i;
249 __asm fld f
250 __asm fistp i
251 return i;
253 #elif (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))
255 ALint i;
256 #ifdef __SSE_MATH__
257 __asm__("cvtss2si %1, %0" : "=r"(i) : "x"(f));
258 #else
259 __asm__ __volatile__("fistpl %0" : "=m"(i) : "t"(f) : "st");
260 #endif
261 return i;
263 /* On GCC when compiling with -fno-math-errno, lrintf can be inlined to
264 * some simple instructions. Clang does not inline it, always generating a
265 * libc call, while MSVC's implementation is horribly slow, so always fall
266 * back to a normal integer conversion for them.
268 #elif !defined(_MSC_VER) && !defined(__clang__)
270 return lrintf(f);
272 #else
274 return (ALint)f;
275 #endif
278 /* Converts float-to-int using standard behavior (truncation). */
279 inline int float2int(float f)
281 #if ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) && \
282 !defined(__SSE_MATH__)) || (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP == 0)
283 ALint sign, shift, mant;
284 union {
285 ALfloat f;
286 ALint i;
287 } conv;
289 conv.f = f;
290 sign = (conv.i>>31) | 1;
291 shift = ((conv.i>>23)&0xff) - (127+23);
293 /* Over/underflow */
294 if(UNLIKELY(shift >= 31 || shift < -23))
295 return 0;
297 mant = (conv.i&0x7fffff) | 0x800000;
298 if(LIKELY(shift < 0))
299 return (mant >> -shift) * sign;
300 return (mant << shift) * sign;
302 #else
304 return (ALint)f;
305 #endif
308 /* Rounds a float to the nearest integral value, according to the current
309 * rounding mode. This is essentially an inlined version of rintf, although
310 * makes fewer promises (e.g. -0 or -0.25 rounded to 0 may result in +0).
312 inline float fast_roundf(float f)
314 #if (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) && \
315 !defined(__SSE_MATH__)
317 float out;
318 __asm__ __volatile__("frndint" : "=t"(out) : "0"(f));
319 return out;
321 #else
323 /* Integral limit, where sub-integral precision is not available for
324 * floats.
326 static const float ilim[2] = {
327 8388608.0f /* 0x1.0p+23 */,
328 -8388608.0f /* -0x1.0p+23 */
330 ALuint sign, expo;
331 union {
332 ALfloat f;
333 ALuint i;
334 } conv;
336 conv.f = f;
337 sign = (conv.i>>31)&0x01;
338 expo = (conv.i>>23)&0xff;
340 if(UNLIKELY(expo >= 150/*+23*/))
342 /* An exponent (base-2) of 23 or higher is incapable of sub-integral
343 * precision, so it's already an integral value. We don't need to worry
344 * about infinity or NaN here.
346 return f;
348 /* Adding the integral limit to the value (with a matching sign) forces a
349 * result that has no sub-integral precision, and is consequently forced to
350 * round to an integral value. Removing the integral limit then restores
351 * the initial value rounded to the integral. The compiler should not
352 * optimize this out because of non-associative rules on floating-point
353 * math (as long as you don't use -fassociative-math,
354 * -funsafe-math-optimizations, -ffast-math, or -Ofast, in which case this
355 * may break).
357 f += ilim[sign];
358 return f - ilim[sign];
359 #endif
363 enum DevProbe {
364 ALL_DEVICE_PROBE,
365 CAPTURE_DEVICE_PROBE
369 enum Channel {
370 FrontLeft = 0,
371 FrontRight,
372 FrontCenter,
373 LFE,
374 BackLeft,
375 BackRight,
376 BackCenter,
377 SideLeft,
378 SideRight,
380 UpperFrontLeft,
381 UpperFrontRight,
382 UpperBackLeft,
383 UpperBackRight,
384 LowerFrontLeft,
385 LowerFrontRight,
386 LowerBackLeft,
387 LowerBackRight,
389 Aux0,
390 Aux1,
391 Aux2,
392 Aux3,
393 Aux4,
394 Aux5,
395 Aux6,
396 Aux7,
397 Aux8,
398 Aux9,
399 Aux10,
400 Aux11,
401 Aux12,
402 Aux13,
403 Aux14,
404 Aux15,
406 InvalidChannel
410 /* Device formats */
411 enum DevFmtType {
412 DevFmtByte = ALC_BYTE_SOFT,
413 DevFmtUByte = ALC_UNSIGNED_BYTE_SOFT,
414 DevFmtShort = ALC_SHORT_SOFT,
415 DevFmtUShort = ALC_UNSIGNED_SHORT_SOFT,
416 DevFmtInt = ALC_INT_SOFT,
417 DevFmtUInt = ALC_UNSIGNED_INT_SOFT,
418 DevFmtFloat = ALC_FLOAT_SOFT,
420 DevFmtTypeDefault = DevFmtFloat
422 enum DevFmtChannels {
423 DevFmtMono = ALC_MONO_SOFT,
424 DevFmtStereo = ALC_STEREO_SOFT,
425 DevFmtQuad = ALC_QUAD_SOFT,
426 DevFmtX51 = ALC_5POINT1_SOFT,
427 DevFmtX61 = ALC_6POINT1_SOFT,
428 DevFmtX71 = ALC_7POINT1_SOFT,
429 DevFmtAmbi3D = ALC_BFORMAT3D_SOFT,
431 /* Similar to 5.1, except using rear channels instead of sides */
432 DevFmtX51Rear = 0x80000000,
434 DevFmtChannelsDefault = DevFmtStereo
436 #define MAX_OUTPUT_CHANNELS (16)
438 ALsizei BytesFromDevFmt(enum DevFmtType type);
439 ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans, ALsizei ambiorder);
440 inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type, ALsizei ambiorder)
442 return ChannelsFromDevFmt(chans, ambiorder) * BytesFromDevFmt(type);
445 enum AmbiLayout {
446 AmbiLayout_FuMa = ALC_FUMA_SOFT, /* FuMa channel order */
447 AmbiLayout_ACN = ALC_ACN_SOFT, /* ACN channel order */
449 AmbiLayout_Default = AmbiLayout_ACN
452 enum AmbiNorm {
453 AmbiNorm_FuMa = ALC_FUMA_SOFT, /* FuMa normalization */
454 AmbiNorm_SN3D = ALC_SN3D_SOFT, /* SN3D normalization */
455 AmbiNorm_N3D = ALC_N3D_SOFT, /* N3D normalization */
457 AmbiNorm_Default = AmbiNorm_SN3D
461 enum DeviceType {
462 Playback,
463 Capture,
464 Loopback
468 enum RenderMode {
469 NormalRender,
470 StereoPair,
471 HrtfRender
475 /* The maximum number of Ambisonics coefficients. For a given order (o), the
476 * size needed will be (o+1)**2, thus zero-order has 1, first-order has 4,
477 * second-order has 9, third-order has 16, and fourth-order has 25.
479 #define MAX_AMBI_ORDER 3
480 #define MAX_AMBI_COEFFS ((MAX_AMBI_ORDER+1) * (MAX_AMBI_ORDER+1))
482 /* A bitmask of ambisonic channels with height information. If none of these
483 * channels are used/needed, there's no height (e.g. with most surround sound
484 * speaker setups). This only specifies up to 4th order, which is the highest
485 * order a 32-bit mask value can specify (a 64-bit mask could handle up to 7th
486 * order). This is ACN ordering, with bit 0 being ACN 0, etc.
488 #define AMBI_PERIPHONIC_MASK (0xfe7ce4)
490 /* The maximum number of Ambisonic coefficients for 2D (non-periphonic)
491 * representation. This is 2 per each order above zero-order, plus 1 for zero-
492 * order. Or simply, o*2 + 1.
494 #define MAX_AMBI2D_COEFFS (MAX_AMBI_ORDER*2 + 1)
497 typedef ALfloat ChannelConfig[MAX_AMBI_COEFFS];
498 typedef struct BFChannelConfig {
499 ALfloat Scale;
500 ALsizei Index;
501 } BFChannelConfig;
503 typedef union AmbiConfig {
504 /* Ambisonic coefficients for mixing to the dry buffer. */
505 ChannelConfig Coeffs[MAX_OUTPUT_CHANNELS];
506 /* Coefficient channel mapping for mixing to the dry buffer. */
507 BFChannelConfig Map[MAX_OUTPUT_CHANNELS];
508 } AmbiConfig;
511 typedef struct BufferSubList {
512 ALuint64 FreeMask{0u};
513 struct ALbuffer *Buffers{nullptr}; /* 64 */
514 } BufferSubList;
516 typedef struct EffectSubList {
517 ALuint64 FreeMask{0u};
518 struct ALeffect *Effects{nullptr}; /* 64 */
519 } EffectSubList;
521 typedef struct FilterSubList {
522 ALuint64 FreeMask{0u};
523 struct ALfilter *Filters{nullptr}; /* 64 */
524 } FilterSubList;
527 typedef struct EnumeratedHrtf {
528 std::string name;
530 struct HrtfEntry *hrtf;
531 } EnumeratedHrtf;
534 /* Maximum delay in samples for speaker distance compensation. */
535 #define MAX_DELAY_LENGTH 1024
537 typedef struct DistanceComp {
538 ALfloat Gain{1.0f};
539 ALsizei Length{0}; /* Valid range is [0...MAX_DELAY_LENGTH). */
540 ALfloat *Buffer{nullptr};
541 } DistanceComp;
543 /* Size for temporary storage of buffer data, in ALfloats. Larger values need
544 * more memory, while smaller values may need more iterations. The value needs
545 * to be a sensible size, however, as it constrains the max stepping value used
546 * for mixing, as well as the maximum number of samples per mixing iteration.
548 #define BUFFERSIZE 2048
550 typedef struct MixParams {
551 AmbiConfig Ambi{};
552 /* Number of coefficients in each Ambi.Coeffs to mix together (4 for first-
553 * order, 9 for second-order, etc). If the count is 0, Ambi.Map is used
554 * instead to map each output to a coefficient index.
556 ALsizei CoeffCount{0};
558 ALfloat (*Buffer)[BUFFERSIZE]{nullptr};
559 ALsizei NumChannels{0};
560 } MixParams;
562 typedef struct RealMixParams {
563 enum Channel ChannelName[MAX_OUTPUT_CHANNELS]{};
565 ALfloat (*Buffer)[BUFFERSIZE]{nullptr};
566 ALsizei NumChannels{0};
567 } RealMixParams;
569 typedef void (*POSTPROCESS)(ALCdevice *device, ALsizei SamplesToDo);
571 struct ALCdevice_struct {
572 RefCount ref{1u};
574 ATOMIC(ALenum) Connected{AL_TRUE};
575 DeviceType Type{};
577 ALuint Frequency{};
578 ALuint UpdateSize{};
579 ALuint NumUpdates{};
580 DevFmtChannels FmtChans{};
581 DevFmtType FmtType{};
582 ALboolean IsHeadphones{};
583 ALsizei mAmbiOrder{};
584 /* For DevFmtAmbi* output only, specifies the channel order and
585 * normalization.
587 AmbiLayout mAmbiLayout{};
588 AmbiNorm mAmbiScale{};
590 ALCenum LimiterState{ALC_DONT_CARE_SOFT};
592 std::string DeviceName;
594 ATOMIC(ALCenum) LastError{ALC_NO_ERROR};
596 // Maximum number of sources that can be created
597 ALuint SourcesMax{};
598 // Maximum number of slots that can be created
599 ALuint AuxiliaryEffectSlotMax{};
601 ALCuint NumMonoSources{};
602 ALCuint NumStereoSources{};
603 ALsizei NumAuxSends{};
605 // Map of Buffers for this device
606 al::vector<BufferSubList> BufferList;
607 almtx_t BufferLock;
609 // Map of Effects for this device
610 al::vector<EffectSubList> EffectList;
611 almtx_t EffectLock;
613 // Map of Filters for this device
614 al::vector<FilterSubList> FilterList;
615 almtx_t FilterLock;
617 POSTPROCESS PostProcess{};
619 /* HRTF state and info */
620 struct DirectHrtfState *Hrtf{nullptr};
621 std::string HrtfName;
622 struct Hrtf *HrtfHandle{nullptr};
623 al::vector<EnumeratedHrtf> HrtfList;
624 ALCenum HrtfStatus{ALC_FALSE};
626 /* UHJ encoder state */
627 struct Uhj2Encoder *Uhj_Encoder{nullptr};
629 /* High quality Ambisonic decoder */
630 struct BFormatDec *AmbiDecoder{nullptr};
632 /* Stereo-to-binaural filter */
633 struct bs2b *Bs2b{nullptr};
635 /* First-order ambisonic upsampler for higher-order output */
636 struct AmbiUpsampler *AmbiUp{nullptr};
638 /* Rendering mode. */
639 RenderMode Render_Mode{NormalRender};
641 // Device flags
642 ALuint Flags{0u};
644 ALuint64 ClockBase{0u};
645 ALuint SamplesDone{0u};
646 ALuint FixedLatency{0u};
648 /* Temp storage used for mixer processing. */
649 alignas(16) ALfloat TempBuffer[4][BUFFERSIZE];
651 /* The "dry" path corresponds to the main output. */
652 MixParams Dry;
653 ALsizei NumChannelsPerOrder[MAX_AMBI_ORDER+1]{};
655 /* First-order ambisonics output, to be upsampled to the dry buffer if different. */
656 MixParams FOAOut;
658 /* "Real" output, which will be written to the device buffer. May alias the
659 * dry buffer.
661 RealMixParams RealOut;
663 struct FrontStablizer *Stablizer{nullptr};
665 struct Compressor *Limiter{nullptr};
667 /* The average speaker distance as determined by the ambdec configuration
668 * (or alternatively, by the NFC-HOA reference delay). Only used for NFC.
670 ALfloat AvgSpeakerDist{0.0f};
672 /* Delay buffers used to compensate for speaker distances. */
673 DistanceComp ChannelDelay[MAX_OUTPUT_CHANNELS];
675 /* Dithering control. */
676 ALfloat DitherDepth{0.0f};
677 ALuint DitherSeed{0u};
679 /* Running count of the mixer invocations, in 31.1 fixed point. This
680 * actually increments *twice* when mixing, first at the start and then at
681 * the end, so the bottom bit indicates if the device is currently mixing
682 * and the upper bits indicates how many mixes have been done.
684 RefCount MixCount{0u};
686 // Contexts created on this device
687 ATOMIC(ALCcontext*) ContextList{nullptr};
689 almtx_t BackendLock;
690 struct ALCbackend *Backend{nullptr};
692 ATOMIC(ALCdevice*) next{nullptr};
695 ALCdevice_struct(DeviceType type);
696 ALCdevice_struct(const ALCdevice_struct&) = delete;
697 ALCdevice_struct& operator=(const ALCdevice_struct&) = delete;
698 ~ALCdevice_struct();
700 DEF_NEWDEL(ALCdevice)
703 // Frequency was requested by the app or config file
704 #define DEVICE_FREQUENCY_REQUEST (1u<<1)
705 // Channel configuration was requested by the config file
706 #define DEVICE_CHANNELS_REQUEST (1u<<2)
707 // Sample type was requested by the config file
708 #define DEVICE_SAMPLE_TYPE_REQUEST (1u<<3)
710 // Specifies if the DSP is paused at user request
711 #define DEVICE_PAUSED (1u<<30)
713 // Specifies if the device is currently running
714 #define DEVICE_RUNNING (1u<<31)
717 /* Nanosecond resolution for the device clock time. */
718 #define DEVICE_CLOCK_RES U64(1000000000)
721 /* Must be less than 15 characters (16 including terminating null) for
722 * compatibility with pthread_setname_np limitations. */
723 #define MIXER_THREAD_NAME "alsoft-mixer"
725 #define RECORD_THREAD_NAME "alsoft-record"
728 enum {
729 /* End event thread processing. */
730 EventType_KillThread = 0,
732 /* User event types. */
733 EventType_SourceStateChange = 1<<0,
734 EventType_BufferCompleted = 1<<1,
735 EventType_Error = 1<<2,
736 EventType_Performance = 1<<3,
737 EventType_Deprecated = 1<<4,
738 EventType_Disconnected = 1<<5,
740 /* Internal events. */
741 EventType_ReleaseEffectState = 65536,
744 typedef struct AsyncEvent {
745 unsigned int EnumType;
746 union {
747 char dummy;
748 struct {
749 ALenum type;
750 ALuint id;
751 ALuint param;
752 ALchar msg[1008];
753 } user;
754 struct ALeffectState *EffectState;
755 } u;
756 } AsyncEvent;
757 #define ASYNC_EVENT(t) { t, { 0 } }
760 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends);
763 extern ALint RTPrioLevel;
764 void SetRTPriority(void);
766 void SetDefaultChannelOrder(ALCdevice *device);
767 void SetDefaultWFXChannelOrder(ALCdevice *device);
769 const ALCchar *DevFmtTypeString(enum DevFmtType type);
770 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans);
772 inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan)
774 ALint i;
775 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
777 if(names[i] == chan)
778 return i;
780 return -1;
783 * GetChannelIdxByName
785 * Returns the index for the given channel name (e.g. FrontCenter), or -1 if it
786 * doesn't exist.
788 inline ALint GetChannelIdxByName(const RealMixParams *real, enum Channel chan)
789 { return GetChannelIndex(real->ChannelName, chan); }
792 inline void LockBufferList(ALCdevice *device) { almtx_lock(&device->BufferLock); }
793 inline void UnlockBufferList(ALCdevice *device) { almtx_unlock(&device->BufferLock); }
795 inline void LockEffectList(ALCdevice *device) { almtx_lock(&device->EffectLock); }
796 inline void UnlockEffectList(ALCdevice *device) { almtx_unlock(&device->EffectLock); }
798 inline void LockFilterList(ALCdevice *device) { almtx_lock(&device->FilterLock); }
799 inline void UnlockFilterList(ALCdevice *device) { almtx_unlock(&device->FilterLock); }
802 void StartEventThrd(ALCcontext *ctx);
803 void StopEventThrd(ALCcontext *ctx);
806 std::vector<std::string> SearchDataFiles(const char *match, const char *subdir);
808 #endif