Use a function pointer for applying the dry mix post-process
[openal-soft.git] / OpenAL32 / Include / alMain.h
blob8c2615cf2242e89a554dcc1404fd519901282eae
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 "AL/al.h"
20 #include "AL/alc.h"
21 #include "AL/alext.h"
23 #include "inprogext.h"
24 #include "logging.h"
25 #include "polymorphism.h"
26 #include "static_assert.h"
27 #include "align.h"
28 #include "atomic.h"
29 #include "uintmap.h"
30 #include "vector.h"
31 #include "alstring.h"
32 #include "almalloc.h"
33 #include "threads.h"
36 #if defined(_WIN64)
37 #define SZFMT "%I64u"
38 #elif defined(_WIN32)
39 #define SZFMT "%u"
40 #else
41 #define SZFMT "%zu"
42 #endif
45 #ifdef __GNUC__
46 #define LIKELY(x) __builtin_expect(!!(x), !0)
47 #define UNLIKELY(x) __builtin_expect(!!(x), 0)
48 #else
49 #define LIKELY(x) (!!(x))
50 #define UNLIKELY(x) (!!(x))
51 #endif
53 typedef ALint64SOFT ALint64;
54 typedef ALuint64SOFT ALuint64;
56 #ifndef U64
57 #if defined(_MSC_VER)
58 #define U64(x) ((ALuint64)(x##ui64))
59 #elif SIZEOF_LONG == 8
60 #define U64(x) ((ALuint64)(x##ul))
61 #elif SIZEOF_LONG_LONG == 8
62 #define U64(x) ((ALuint64)(x##ull))
63 #endif
64 #endif
66 #ifndef UINT64_MAX
67 #define UINT64_MAX U64(18446744073709551615)
68 #endif
70 #ifndef UNUSED
71 #if defined(__cplusplus)
72 #define UNUSED(x)
73 #elif defined(__GNUC__)
74 #define UNUSED(x) UNUSED_##x __attribute__((unused))
75 #elif defined(__LCLINT__)
76 #define UNUSED(x) /*@unused@*/ x
77 #else
78 #define UNUSED(x) x
79 #endif
80 #endif
82 /* Calculates the size of a struct with N elements of a flexible array member.
83 * GCC and Clang allow offsetof(Type, fam[N]) for this, but MSVC seems to have
84 * trouble, so a bit more verbose workaround is needed.
86 #define FAM_SIZE(T, M, N) (offsetof(T, M) + sizeof(((T*)NULL)->M[0])*(N))
89 /* Define a CTZ64 macro (count trailing zeros, for 64-bit integers). The result
90 * is *UNDEFINED* if the value is 0.
92 #ifdef __GNUC__
94 #if SIZEOF_LONG == 8
95 #define CTZ64(x) __builtin_ctzl(x)
96 #else
97 #define CTZ64(x) __builtin_ctzll(x)
98 #endif
100 #elif defined(HAVE_BITSCANFORWARD64_INTRINSIC)
102 static inline int msvc64_ctz64(ALuint64 v)
104 unsigned long idx = 64;
105 _BitScanForward64(&idx, v);
106 return (int)idx;
108 #define CTZ64(x) msvc64_ctz64(x)
110 #elif defined(HAVE_BITSCANFORWARD_INTRINSIC)
112 static inline int msvc_ctz64(ALuint64 v)
114 unsigned long idx = 64;
115 if(!_BitScanForward(&idx, v&0xffffffff))
117 if(_BitScanForward(&idx, v>>32))
118 idx += 32;
120 return (int)idx;
122 #define CTZ64(x) msvc_ctz64(x)
124 #else
126 /* There be black magics here. The popcnt64 method is derived from
127 * https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
128 * while the ctz-utilizing-popcnt algorithm is shown here
129 * http://www.hackersdelight.org/hdcodetxt/ntz.c.txt
130 * as the ntz2 variant. These likely aren't the most efficient methods, but
131 * they're good enough if the GCC or MSVC intrinsics aren't available.
133 static inline int fallback_popcnt64(ALuint64 v)
135 v = v - ((v >> 1) & U64(0x5555555555555555));
136 v = (v & U64(0x3333333333333333)) + ((v >> 2) & U64(0x3333333333333333));
137 v = (v + (v >> 4)) & U64(0x0f0f0f0f0f0f0f0f);
138 return (int)((v * U64(0x0101010101010101)) >> 56);
141 static inline int fallback_ctz64(ALuint64 value)
143 return fallback_popcnt64(~value & (value - 1));
145 #define CTZ64(x) fallback_ctz64(x)
146 #endif
148 static const union {
149 ALuint u;
150 ALubyte b[sizeof(ALuint)];
151 } EndianTest = { 1 };
152 #define IS_LITTLE_ENDIAN (EndianTest.b[0] == 1)
154 #define COUNTOF(x) (sizeof(x) / sizeof(0[x]))
157 #ifdef __cplusplus
158 extern "C" {
159 #endif
161 struct ll_ringbuffer;
162 struct Hrtf;
163 struct HrtfEntry;
164 struct DirectHrtfState;
165 struct FrontStablizer;
166 struct Compressor;
167 struct ALCbackend;
168 struct ALbuffer;
169 struct ALeffect;
170 struct ALfilter;
171 struct ALsource;
172 struct ALcontextProps;
173 struct ALlistenerProps;
174 struct ALvoiceProps;
175 struct ALeffectslotProps;
178 #define DEFAULT_OUTPUT_RATE (44100)
179 #define MIN_OUTPUT_RATE (8000)
182 /* Find the next power-of-2 for non-power-of-2 numbers. */
183 inline ALuint NextPowerOf2(ALuint value)
185 if(value > 0)
187 value--;
188 value |= value>>1;
189 value |= value>>2;
190 value |= value>>4;
191 value |= value>>8;
192 value |= value>>16;
194 return value+1;
197 /** Round up a value to the next multiple. */
198 inline size_t RoundUp(size_t value, size_t r)
200 value += r-1;
201 return value - (value%r);
204 /* Fast float-to-int conversion. Assumes the FPU is already in round-to-zero
205 * mode. */
206 inline ALint fastf2i(ALfloat f)
208 #ifdef HAVE_LRINTF
209 return lrintf(f);
210 #elif defined(_MSC_VER) && defined(_M_IX86)
211 ALint i;
212 __asm fld f
213 __asm fistp i
214 return i;
215 #else
216 return (ALint)f;
217 #endif
221 enum DevProbe {
222 ALL_DEVICE_PROBE,
223 CAPTURE_DEVICE_PROBE
227 enum DistanceModel {
228 InverseDistanceClamped = AL_INVERSE_DISTANCE_CLAMPED,
229 LinearDistanceClamped = AL_LINEAR_DISTANCE_CLAMPED,
230 ExponentDistanceClamped = AL_EXPONENT_DISTANCE_CLAMPED,
231 InverseDistance = AL_INVERSE_DISTANCE,
232 LinearDistance = AL_LINEAR_DISTANCE,
233 ExponentDistance = AL_EXPONENT_DISTANCE,
234 DisableDistance = AL_NONE,
236 DefaultDistanceModel = InverseDistanceClamped
239 enum Channel {
240 FrontLeft = 0,
241 FrontRight,
242 FrontCenter,
243 LFE,
244 BackLeft,
245 BackRight,
246 BackCenter,
247 SideLeft,
248 SideRight,
250 UpperFrontLeft,
251 UpperFrontRight,
252 UpperBackLeft,
253 UpperBackRight,
254 LowerFrontLeft,
255 LowerFrontRight,
256 LowerBackLeft,
257 LowerBackRight,
259 Aux0,
260 Aux1,
261 Aux2,
262 Aux3,
263 Aux4,
264 Aux5,
265 Aux6,
266 Aux7,
267 Aux8,
268 Aux9,
269 Aux10,
270 Aux11,
271 Aux12,
272 Aux13,
273 Aux14,
274 Aux15,
276 InvalidChannel
280 /* Device formats */
281 enum DevFmtType {
282 DevFmtByte = ALC_BYTE_SOFT,
283 DevFmtUByte = ALC_UNSIGNED_BYTE_SOFT,
284 DevFmtShort = ALC_SHORT_SOFT,
285 DevFmtUShort = ALC_UNSIGNED_SHORT_SOFT,
286 DevFmtInt = ALC_INT_SOFT,
287 DevFmtUInt = ALC_UNSIGNED_INT_SOFT,
288 DevFmtFloat = ALC_FLOAT_SOFT,
290 DevFmtTypeDefault = DevFmtFloat
292 enum DevFmtChannels {
293 DevFmtMono = ALC_MONO_SOFT,
294 DevFmtStereo = ALC_STEREO_SOFT,
295 DevFmtQuad = ALC_QUAD_SOFT,
296 DevFmtX51 = ALC_5POINT1_SOFT,
297 DevFmtX61 = ALC_6POINT1_SOFT,
298 DevFmtX71 = ALC_7POINT1_SOFT,
299 DevFmtAmbi3D = ALC_BFORMAT3D_SOFT,
301 /* Similar to 5.1, except using rear channels instead of sides */
302 DevFmtX51Rear = 0x80000000,
304 DevFmtChannelsDefault = DevFmtStereo
306 #define MAX_OUTPUT_CHANNELS (16)
308 ALsizei BytesFromDevFmt(enum DevFmtType type);
309 ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans, ALsizei ambiorder);
310 inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type, ALsizei ambiorder)
312 return ChannelsFromDevFmt(chans, ambiorder) * BytesFromDevFmt(type);
315 enum AmbiLayout {
316 AmbiLayout_FuMa = ALC_FUMA_SOFT, /* FuMa channel order */
317 AmbiLayout_ACN = ALC_ACN_SOFT, /* ACN channel order */
319 AmbiLayout_Default = AmbiLayout_ACN
322 enum AmbiNorm {
323 AmbiNorm_FuMa = ALC_FUMA_SOFT, /* FuMa normalization */
324 AmbiNorm_SN3D = ALC_SN3D_SOFT, /* SN3D normalization */
325 AmbiNorm_N3D = ALC_N3D_SOFT, /* N3D normalization */
327 AmbiNorm_Default = AmbiNorm_SN3D
331 enum DeviceType {
332 Playback,
333 Capture,
334 Loopback
338 enum RenderMode {
339 NormalRender,
340 StereoPair,
341 HrtfRender
345 /* The maximum number of Ambisonics coefficients. For a given order (o), the
346 * size needed will be (o+1)**2, thus zero-order has 1, first-order has 4,
347 * second-order has 9, third-order has 16, and fourth-order has 25.
349 #define MAX_AMBI_ORDER 3
350 #define MAX_AMBI_COEFFS ((MAX_AMBI_ORDER+1) * (MAX_AMBI_ORDER+1))
352 /* A bitmask of ambisonic channels with height information. If none of these
353 * channels are used/needed, there's no height (e.g. with most surround sound
354 * speaker setups). This only specifies up to 4th order, which is the highest
355 * order a 32-bit mask value can specify (a 64-bit mask could handle up to 7th
356 * order). This is ACN ordering, with bit 0 being ACN 0, etc.
358 #define AMBI_PERIPHONIC_MASK (0xfe7ce4)
360 /* The maximum number of Ambisonic coefficients for 2D (non-periphonic)
361 * representation. This is 2 per each order above zero-order, plus 1 for zero-
362 * order. Or simply, o*2 + 1.
364 #define MAX_AMBI2D_COEFFS (MAX_AMBI_ORDER*2 + 1)
367 typedef ALfloat ChannelConfig[MAX_AMBI_COEFFS];
368 typedef struct BFChannelConfig {
369 ALfloat Scale;
370 ALsizei Index;
371 } BFChannelConfig;
373 typedef union AmbiConfig {
374 /* Ambisonic coefficients for mixing to the dry buffer. */
375 ChannelConfig Coeffs[MAX_OUTPUT_CHANNELS];
376 /* Coefficient channel mapping for mixing to the dry buffer. */
377 BFChannelConfig Map[MAX_OUTPUT_CHANNELS];
378 } AmbiConfig;
381 typedef struct BufferSubList {
382 ALuint64 FreeMask;
383 struct ALbuffer *Buffers; /* 64 */
384 } BufferSubList;
385 TYPEDEF_VECTOR(BufferSubList, vector_BufferSubList)
387 typedef struct EffectSubList {
388 ALuint64 FreeMask;
389 struct ALeffect *Effects; /* 64 */
390 } EffectSubList;
391 TYPEDEF_VECTOR(EffectSubList, vector_EffectSubList)
393 typedef struct FilterSubList {
394 ALuint64 FreeMask;
395 struct ALfilter *Filters; /* 64 */
396 } FilterSubList;
397 TYPEDEF_VECTOR(FilterSubList, vector_FilterSubList)
399 typedef struct SourceSubList {
400 ALuint64 FreeMask;
401 struct ALsource *Sources; /* 64 */
402 } SourceSubList;
403 TYPEDEF_VECTOR(SourceSubList, vector_SourceSubList)
405 /* Effect slots are rather large, and apps aren't likely to have more than one
406 * or two (let alone 64), so hold them individually.
408 typedef struct ALeffectslot *ALeffectslotPtr;
409 TYPEDEF_VECTOR(ALeffectslotPtr, vector_ALeffectslotPtr)
412 typedef struct EnumeratedHrtf {
413 al_string name;
415 struct HrtfEntry *hrtf;
416 } EnumeratedHrtf;
417 TYPEDEF_VECTOR(EnumeratedHrtf, vector_EnumeratedHrtf)
420 /* Maximum delay in samples for speaker distance compensation. */
421 #define MAX_DELAY_LENGTH 1024
423 typedef struct DistanceComp {
424 ALfloat Gain;
425 ALsizei Length; /* Valid range is [0...MAX_DELAY_LENGTH). */
426 ALfloat *Buffer;
427 } DistanceComp;
429 /* Size for temporary storage of buffer data, in ALfloats. Larger values need
430 * more memory, while smaller values may need more iterations. The value needs
431 * to be a sensible size, however, as it constrains the max stepping value used
432 * for mixing, as well as the maximum number of samples per mixing iteration.
434 #define BUFFERSIZE 2048
436 typedef struct DryMixParams {
437 AmbiConfig Ambi;
438 /* Number of coefficients in each Ambi.Coeffs to mix together (4 for first-
439 * order, 9 for second-order, etc). If the count is 0, Ambi.Map is used
440 * instead to map each output to a coefficient index.
442 ALsizei CoeffCount;
444 ALfloat (*Buffer)[BUFFERSIZE];
445 ALsizei NumChannels;
446 ALsizei NumChannelsPerOrder[MAX_AMBI_ORDER+1];
447 } DryMixParams;
449 typedef struct BFMixParams {
450 AmbiConfig Ambi;
451 /* Will only be 4 or 0. */
452 ALsizei CoeffCount;
454 ALfloat (*Buffer)[BUFFERSIZE];
455 ALsizei NumChannels;
456 } BFMixParams;
458 typedef struct RealMixParams {
459 enum Channel ChannelName[MAX_OUTPUT_CHANNELS];
461 ALfloat (*Buffer)[BUFFERSIZE];
462 ALsizei NumChannels;
463 } RealMixParams;
465 typedef void (*POSTPROCESS)(ALCdevice *device, ALsizei SamplesToDo);
467 struct ALCdevice_struct {
468 RefCount ref;
470 ATOMIC(ALenum) Connected;
471 enum DeviceType Type;
473 ALuint Frequency;
474 ALuint UpdateSize;
475 ALuint NumUpdates;
476 enum DevFmtChannels FmtChans;
477 enum DevFmtType FmtType;
478 ALboolean IsHeadphones;
479 ALsizei AmbiOrder;
480 /* For DevFmtAmbi* output only, specifies the channel order and
481 * normalization.
483 enum AmbiLayout AmbiLayout;
484 enum AmbiNorm AmbiScale;
486 al_string DeviceName;
488 ATOMIC(ALCenum) LastError;
490 // Maximum number of sources that can be created
491 ALuint SourcesMax;
492 // Maximum number of slots that can be created
493 ALuint AuxiliaryEffectSlotMax;
495 ALCuint NumMonoSources;
496 ALCuint NumStereoSources;
497 ALsizei NumAuxSends;
499 // Map of Buffers for this device
500 vector_BufferSubList BufferList;
501 almtx_t BufferLock;
503 // Map of Effects for this device
504 vector_EffectSubList EffectList;
505 almtx_t EffectLock;
507 // Map of Filters for this device
508 vector_FilterSubList FilterList;
509 almtx_t FilterLock;
511 POSTPROCESS PostProcess;
513 /* HRTF state and info */
514 struct DirectHrtfState *Hrtf;
515 al_string HrtfName;
516 struct Hrtf *HrtfHandle;
517 vector_EnumeratedHrtf HrtfList;
518 ALCenum HrtfStatus;
520 /* UHJ encoder state */
521 struct Uhj2Encoder *Uhj_Encoder;
523 /* High quality Ambisonic decoder */
524 struct BFormatDec *AmbiDecoder;
526 /* Stereo-to-binaural filter */
527 struct bs2b *Bs2b;
529 /* First-order ambisonic upsampler for higher-order output */
530 struct AmbiUpsampler *AmbiUp;
532 /* Rendering mode. */
533 enum RenderMode Render_Mode;
535 // Device flags
536 ALuint Flags;
538 ALuint64 ClockBase;
539 ALuint SamplesDone;
541 /* Temp storage used for mixer processing. */
542 alignas(16) ALfloat TempBuffer[4][BUFFERSIZE];
544 /* The "dry" path corresponds to the main output. */
545 DryMixParams Dry;
547 /* First-order ambisonics output, to be upsampled to the dry buffer if different. */
548 BFMixParams FOAOut;
550 /* "Real" output, which will be written to the device buffer. May alias the
551 * dry buffer.
553 RealMixParams RealOut;
555 struct FrontStablizer *Stablizer;
557 struct Compressor *Limiter;
559 /* The average speaker distance as determined by the ambdec configuration
560 * (or alternatively, by the NFC-HOA reference delay). Only used for NFC.
562 ALfloat AvgSpeakerDist;
564 /* Delay buffers used to compensate for speaker distances. */
565 DistanceComp ChannelDelay[MAX_OUTPUT_CHANNELS];
567 /* Dithering control. */
568 ALfloat DitherDepth;
569 ALuint DitherSeed;
571 /* Running count of the mixer invocations, in 31.1 fixed point. This
572 * actually increments *twice* when mixing, first at the start and then at
573 * the end, so the bottom bit indicates if the device is currently mixing
574 * and the upper bits indicates how many mixes have been done.
576 RefCount MixCount;
578 // Contexts created on this device
579 ATOMIC(ALCcontext*) ContextList;
581 almtx_t BackendLock;
582 struct ALCbackend *Backend;
584 ALCdevice *volatile next;
587 // Frequency was requested by the app or config file
588 #define DEVICE_FREQUENCY_REQUEST (1u<<1)
589 // Channel configuration was requested by the config file
590 #define DEVICE_CHANNELS_REQUEST (1u<<2)
591 // Sample type was requested by the config file
592 #define DEVICE_SAMPLE_TYPE_REQUEST (1u<<3)
594 // Specifies if the DSP is paused at user request
595 #define DEVICE_PAUSED (1u<<30)
597 // Specifies if the device is currently running
598 #define DEVICE_RUNNING (1u<<31)
601 /* Nanosecond resolution for the device clock time. */
602 #define DEVICE_CLOCK_RES U64(1000000000)
605 /* Must be less than 15 characters (16 including terminating null) for
606 * compatibility with pthread_setname_np limitations. */
607 #define MIXER_THREAD_NAME "alsoft-mixer"
609 #define RECORD_THREAD_NAME "alsoft-record"
612 enum {
613 EventType_SourceStateChange = 1<<0,
614 EventType_BufferCompleted = 1<<1,
615 EventType_Error = 1<<2,
616 EventType_Performance = 1<<3,
617 EventType_Deprecated = 1<<4,
618 EventType_Disconnected = 1<<5,
621 typedef struct AsyncEvent {
622 unsigned int EnumType;
623 ALenum Type;
624 ALuint ObjectId;
625 ALuint Param;
626 ALchar Message[1008];
627 } AsyncEvent;
629 struct ALCcontext_struct {
630 RefCount ref;
632 struct ALlistener *Listener;
634 vector_SourceSubList SourceList;
635 ALuint NumSources;
636 almtx_t SourceLock;
638 vector_ALeffectslotPtr EffectSlotList;
639 almtx_t EffectSlotLock;
641 ATOMIC(ALenum) LastError;
643 enum DistanceModel DistanceModel;
644 ALboolean SourceDistanceModel;
646 ALfloat DopplerFactor;
647 ALfloat DopplerVelocity;
648 ALfloat SpeedOfSound;
649 ALfloat MetersPerUnit;
651 ATOMIC_FLAG PropsClean;
652 ATOMIC(ALenum) DeferUpdates;
654 RWLock PropLock;
656 /* Counter for the pre-mixing updates, in 31.1 fixed point (lowest bit
657 * indicates if updates are currently happening).
659 RefCount UpdateCount;
660 ATOMIC(ALenum) HoldUpdates;
662 ALfloat GainBoost;
664 ATOMIC(struct ALcontextProps*) Update;
666 /* Linked lists of unused property containers, free to use for future
667 * updates.
669 ATOMIC(struct ALcontextProps*) FreeContextProps;
670 ATOMIC(struct ALlistenerProps*) FreeListenerProps;
671 ATOMIC(struct ALvoiceProps*) FreeVoiceProps;
672 ATOMIC(struct ALeffectslotProps*) FreeEffectslotProps;
674 struct ALvoice **Voices;
675 ALsizei VoiceCount;
676 ALsizei MaxVoices;
678 ATOMIC(struct ALeffectslotArray*) ActiveAuxSlots;
680 almtx_t EventThrdLock;
681 althrd_t EventThread;
682 alsem_t EventSem;
683 struct ll_ringbuffer *AsyncEvents;
684 ATOMIC(ALbitfieldSOFT) EnabledEvts;
685 almtx_t EventCbLock;
686 ALEVENTPROCSOFT EventCb;
687 void *EventParam;
689 /* Default effect slot */
690 struct ALeffectslot *DefaultSlot;
692 ALCdevice *Device;
693 const ALCchar *ExtensionList;
695 ALCcontext *volatile next;
697 /* Memory space used by the listener (and possibly default effect slot) */
698 alignas(16) ALCbyte _listener_mem[];
701 ALCcontext *GetContextRef(void);
703 void ALCcontext_DecRef(ALCcontext *context);
705 void ALCcontext_DeferUpdates(ALCcontext *context);
706 void ALCcontext_ProcessUpdates(ALCcontext *context);
708 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends);
710 void AppendAllDevicesList(const ALCchar *name);
711 void AppendCaptureDeviceList(const ALCchar *name);
714 extern ALint RTPrioLevel;
715 void SetRTPriority(void);
717 void SetDefaultChannelOrder(ALCdevice *device);
718 void SetDefaultWFXChannelOrder(ALCdevice *device);
720 const ALCchar *DevFmtTypeString(enum DevFmtType type);
721 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans);
723 inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan)
725 ALint i;
726 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
728 if(names[i] == chan)
729 return i;
731 return -1;
734 * GetChannelIdxByName
736 * Returns the index for the given channel name (e.g. FrontCenter), or -1 if it
737 * doesn't exist.
739 inline ALint GetChannelIdxByName(const RealMixParams *real, enum Channel chan)
740 { return GetChannelIndex(real->ChannelName, chan); }
743 inline void LockBufferList(ALCdevice *device) { almtx_lock(&device->BufferLock); }
744 inline void UnlockBufferList(ALCdevice *device) { almtx_unlock(&device->BufferLock); }
746 inline void LockEffectList(ALCdevice *device) { almtx_lock(&device->EffectLock); }
747 inline void UnlockEffectList(ALCdevice *device) { almtx_unlock(&device->EffectLock); }
749 inline void LockFilterList(ALCdevice *device) { almtx_lock(&device->FilterLock); }
750 inline void UnlockFilterList(ALCdevice *device) { almtx_unlock(&device->FilterLock); }
752 inline void LockEffectSlotList(ALCcontext *context)
753 { almtx_lock(&context->EffectSlotLock); }
754 inline void UnlockEffectSlotList(ALCcontext *context)
755 { almtx_unlock(&context->EffectSlotLock); }
758 vector_al_string SearchDataFiles(const char *match, const char *subdir);
760 #ifdef __cplusplus
762 #endif
764 #endif