Use a plain mutex for the property lock
[openal-soft.git] / OpenAL32 / Include / alMain.h
blob6d6d661fdff19a9473ecca526593a4eb91426200
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 "vector.h"
30 #include "alstring.h"
31 #include "almalloc.h"
32 #include "threads.h"
35 #if defined(_WIN64)
36 #define SZFMT "%I64u"
37 #elif defined(_WIN32)
38 #define SZFMT "%u"
39 #else
40 #define SZFMT "%zu"
41 #endif
44 #ifdef __GNUC__
45 #define LIKELY(x) __builtin_expect(!!(x), !0)
46 #define UNLIKELY(x) __builtin_expect(!!(x), 0)
47 #else
48 #define LIKELY(x) (!!(x))
49 #define UNLIKELY(x) (!!(x))
50 #endif
52 typedef ALint64SOFT ALint64;
53 typedef ALuint64SOFT ALuint64;
55 #ifndef U64
56 #if defined(_MSC_VER)
57 #define U64(x) ((ALuint64)(x##ui64))
58 #elif SIZEOF_LONG == 8
59 #define U64(x) ((ALuint64)(x##ul))
60 #elif SIZEOF_LONG_LONG == 8
61 #define U64(x) ((ALuint64)(x##ull))
62 #endif
63 #endif
65 #ifndef UINT64_MAX
66 #define UINT64_MAX U64(18446744073709551615)
67 #endif
69 #ifndef UNUSED
70 #if defined(__cplusplus)
71 #define UNUSED(x)
72 #elif defined(__GNUC__)
73 #define UNUSED(x) UNUSED_##x __attribute__((unused))
74 #elif defined(__LCLINT__)
75 #define UNUSED(x) /*@unused@*/ x
76 #else
77 #define UNUSED(x) x
78 #endif
79 #endif
81 /* Calculates the size of a struct with N elements of a flexible array member.
82 * GCC and Clang allow offsetof(Type, fam[N]) for this, but MSVC seems to have
83 * trouble, so a bit more verbose workaround is needed.
85 #define FAM_SIZE(T, M, N) (offsetof(T, M) + sizeof(((T*)NULL)->M[0])*(N))
88 /* Define a CTZ64 macro (count trailing zeros, for 64-bit integers). The result
89 * is *UNDEFINED* if the value is 0.
91 #ifdef __GNUC__
93 #if SIZEOF_LONG == 8
94 #define CTZ64(x) __builtin_ctzl(x)
95 #else
96 #define CTZ64(x) __builtin_ctzll(x)
97 #endif
99 #elif defined(HAVE_BITSCANFORWARD64_INTRINSIC)
101 inline int msvc64_ctz64(ALuint64 v)
103 unsigned long idx = 64;
104 _BitScanForward64(&idx, v);
105 return (int)idx;
107 #define CTZ64(x) msvc64_ctz64(x)
109 #elif defined(HAVE_BITSCANFORWARD_INTRINSIC)
111 inline int msvc_ctz64(ALuint64 v)
113 unsigned long idx = 64;
114 if(!_BitScanForward(&idx, v&0xffffffff))
116 if(_BitScanForward(&idx, v>>32))
117 idx += 32;
119 return (int)idx;
121 #define CTZ64(x) msvc_ctz64(x)
123 #else
125 /* There be black magics here. The popcnt64 method is derived from
126 * https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
127 * while the ctz-utilizing-popcnt algorithm is shown here
128 * http://www.hackersdelight.org/hdcodetxt/ntz.c.txt
129 * as the ntz2 variant. These likely aren't the most efficient methods, but
130 * they're good enough if the GCC or MSVC intrinsics aren't available.
132 inline int fallback_popcnt64(ALuint64 v)
134 v = v - ((v >> 1) & U64(0x5555555555555555));
135 v = (v & U64(0x3333333333333333)) + ((v >> 2) & U64(0x3333333333333333));
136 v = (v + (v >> 4)) & U64(0x0f0f0f0f0f0f0f0f);
137 return (int)((v * U64(0x0101010101010101)) >> 56);
140 inline int fallback_ctz64(ALuint64 value)
142 return fallback_popcnt64(~value & (value - 1));
144 #define CTZ64(x) fallback_ctz64(x)
145 #endif
147 static const union {
148 ALuint u;
149 ALubyte b[sizeof(ALuint)];
150 } EndianTest = { 1 };
151 #define IS_LITTLE_ENDIAN (EndianTest.b[0] == 1)
153 #define COUNTOF(x) (sizeof(x) / sizeof(0[x]))
156 #ifdef __cplusplus
157 extern "C" {
158 #endif
160 struct ll_ringbuffer;
161 struct Hrtf;
162 struct HrtfEntry;
163 struct DirectHrtfState;
164 struct FrontStablizer;
165 struct Compressor;
166 struct ALCbackend;
167 struct ALbuffer;
168 struct ALeffect;
169 struct ALfilter;
170 struct ALsource;
171 struct ALcontextProps;
172 struct ALlistenerProps;
173 struct ALvoiceProps;
174 struct ALeffectslotProps;
177 #define DEFAULT_OUTPUT_RATE (44100)
178 #define MIN_OUTPUT_RATE (8000)
181 /* Find the next power-of-2 for non-power-of-2 numbers. */
182 inline ALuint NextPowerOf2(ALuint value)
184 if(value > 0)
186 value--;
187 value |= value>>1;
188 value |= value>>2;
189 value |= value>>4;
190 value |= value>>8;
191 value |= value>>16;
193 return value+1;
196 /** Round up a value to the next multiple. */
197 inline size_t RoundUp(size_t value, size_t r)
199 value += r-1;
200 return value - (value%r);
203 /* Fast float-to-int conversion. Assumes the FPU is already in round-to-zero
204 * mode. */
205 inline ALint fastf2i(ALfloat f)
207 #ifdef HAVE_LRINTF
208 return lrintf(f);
209 #elif defined(_MSC_VER) && defined(_M_IX86)
210 ALint i;
211 __asm fld f
212 __asm fistp i
213 return i;
214 #else
215 return (ALint)f;
216 #endif
220 enum DevProbe {
221 ALL_DEVICE_PROBE,
222 CAPTURE_DEVICE_PROBE
226 enum DistanceModel {
227 InverseDistanceClamped = AL_INVERSE_DISTANCE_CLAMPED,
228 LinearDistanceClamped = AL_LINEAR_DISTANCE_CLAMPED,
229 ExponentDistanceClamped = AL_EXPONENT_DISTANCE_CLAMPED,
230 InverseDistance = AL_INVERSE_DISTANCE,
231 LinearDistance = AL_LINEAR_DISTANCE,
232 ExponentDistance = AL_EXPONENT_DISTANCE,
233 DisableDistance = AL_NONE,
235 DefaultDistanceModel = InverseDistanceClamped
238 enum Channel {
239 FrontLeft = 0,
240 FrontRight,
241 FrontCenter,
242 LFE,
243 BackLeft,
244 BackRight,
245 BackCenter,
246 SideLeft,
247 SideRight,
249 UpperFrontLeft,
250 UpperFrontRight,
251 UpperBackLeft,
252 UpperBackRight,
253 LowerFrontLeft,
254 LowerFrontRight,
255 LowerBackLeft,
256 LowerBackRight,
258 Aux0,
259 Aux1,
260 Aux2,
261 Aux3,
262 Aux4,
263 Aux5,
264 Aux6,
265 Aux7,
266 Aux8,
267 Aux9,
268 Aux10,
269 Aux11,
270 Aux12,
271 Aux13,
272 Aux14,
273 Aux15,
275 InvalidChannel
279 /* Device formats */
280 enum DevFmtType {
281 DevFmtByte = ALC_BYTE_SOFT,
282 DevFmtUByte = ALC_UNSIGNED_BYTE_SOFT,
283 DevFmtShort = ALC_SHORT_SOFT,
284 DevFmtUShort = ALC_UNSIGNED_SHORT_SOFT,
285 DevFmtInt = ALC_INT_SOFT,
286 DevFmtUInt = ALC_UNSIGNED_INT_SOFT,
287 DevFmtFloat = ALC_FLOAT_SOFT,
289 DevFmtTypeDefault = DevFmtFloat
291 enum DevFmtChannels {
292 DevFmtMono = ALC_MONO_SOFT,
293 DevFmtStereo = ALC_STEREO_SOFT,
294 DevFmtQuad = ALC_QUAD_SOFT,
295 DevFmtX51 = ALC_5POINT1_SOFT,
296 DevFmtX61 = ALC_6POINT1_SOFT,
297 DevFmtX71 = ALC_7POINT1_SOFT,
298 DevFmtAmbi3D = ALC_BFORMAT3D_SOFT,
300 /* Similar to 5.1, except using rear channels instead of sides */
301 DevFmtX51Rear = 0x80000000,
303 DevFmtChannelsDefault = DevFmtStereo
305 #define MAX_OUTPUT_CHANNELS (16)
307 ALsizei BytesFromDevFmt(enum DevFmtType type);
308 ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans, ALsizei ambiorder);
309 inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type, ALsizei ambiorder)
311 return ChannelsFromDevFmt(chans, ambiorder) * BytesFromDevFmt(type);
314 enum AmbiLayout {
315 AmbiLayout_FuMa = ALC_FUMA_SOFT, /* FuMa channel order */
316 AmbiLayout_ACN = ALC_ACN_SOFT, /* ACN channel order */
318 AmbiLayout_Default = AmbiLayout_ACN
321 enum AmbiNorm {
322 AmbiNorm_FuMa = ALC_FUMA_SOFT, /* FuMa normalization */
323 AmbiNorm_SN3D = ALC_SN3D_SOFT, /* SN3D normalization */
324 AmbiNorm_N3D = ALC_N3D_SOFT, /* N3D normalization */
326 AmbiNorm_Default = AmbiNorm_SN3D
330 enum DeviceType {
331 Playback,
332 Capture,
333 Loopback
337 enum RenderMode {
338 NormalRender,
339 StereoPair,
340 HrtfRender
344 /* The maximum number of Ambisonics coefficients. For a given order (o), the
345 * size needed will be (o+1)**2, thus zero-order has 1, first-order has 4,
346 * second-order has 9, third-order has 16, and fourth-order has 25.
348 #define MAX_AMBI_ORDER 3
349 #define MAX_AMBI_COEFFS ((MAX_AMBI_ORDER+1) * (MAX_AMBI_ORDER+1))
351 /* A bitmask of ambisonic channels with height information. If none of these
352 * channels are used/needed, there's no height (e.g. with most surround sound
353 * speaker setups). This only specifies up to 4th order, which is the highest
354 * order a 32-bit mask value can specify (a 64-bit mask could handle up to 7th
355 * order). This is ACN ordering, with bit 0 being ACN 0, etc.
357 #define AMBI_PERIPHONIC_MASK (0xfe7ce4)
359 /* The maximum number of Ambisonic coefficients for 2D (non-periphonic)
360 * representation. This is 2 per each order above zero-order, plus 1 for zero-
361 * order. Or simply, o*2 + 1.
363 #define MAX_AMBI2D_COEFFS (MAX_AMBI_ORDER*2 + 1)
366 typedef ALfloat ChannelConfig[MAX_AMBI_COEFFS];
367 typedef struct BFChannelConfig {
368 ALfloat Scale;
369 ALsizei Index;
370 } BFChannelConfig;
372 typedef union AmbiConfig {
373 /* Ambisonic coefficients for mixing to the dry buffer. */
374 ChannelConfig Coeffs[MAX_OUTPUT_CHANNELS];
375 /* Coefficient channel mapping for mixing to the dry buffer. */
376 BFChannelConfig Map[MAX_OUTPUT_CHANNELS];
377 } AmbiConfig;
380 typedef struct BufferSubList {
381 ALuint64 FreeMask;
382 struct ALbuffer *Buffers; /* 64 */
383 } BufferSubList;
384 TYPEDEF_VECTOR(BufferSubList, vector_BufferSubList)
386 typedef struct EffectSubList {
387 ALuint64 FreeMask;
388 struct ALeffect *Effects; /* 64 */
389 } EffectSubList;
390 TYPEDEF_VECTOR(EffectSubList, vector_EffectSubList)
392 typedef struct FilterSubList {
393 ALuint64 FreeMask;
394 struct ALfilter *Filters; /* 64 */
395 } FilterSubList;
396 TYPEDEF_VECTOR(FilterSubList, vector_FilterSubList)
398 typedef struct SourceSubList {
399 ALuint64 FreeMask;
400 struct ALsource *Sources; /* 64 */
401 } SourceSubList;
402 TYPEDEF_VECTOR(SourceSubList, vector_SourceSubList)
404 /* Effect slots are rather large, and apps aren't likely to have more than one
405 * or two (let alone 64), so hold them individually.
407 typedef struct ALeffectslot *ALeffectslotPtr;
408 TYPEDEF_VECTOR(ALeffectslotPtr, vector_ALeffectslotPtr)
411 typedef struct EnumeratedHrtf {
412 al_string name;
414 struct HrtfEntry *hrtf;
415 } EnumeratedHrtf;
416 TYPEDEF_VECTOR(EnumeratedHrtf, vector_EnumeratedHrtf)
419 /* Maximum delay in samples for speaker distance compensation. */
420 #define MAX_DELAY_LENGTH 1024
422 typedef struct DistanceComp {
423 ALfloat Gain;
424 ALsizei Length; /* Valid range is [0...MAX_DELAY_LENGTH). */
425 ALfloat *Buffer;
426 } DistanceComp;
428 /* Size for temporary storage of buffer data, in ALfloats. Larger values need
429 * more memory, while smaller values may need more iterations. The value needs
430 * to be a sensible size, however, as it constrains the max stepping value used
431 * for mixing, as well as the maximum number of samples per mixing iteration.
433 #define BUFFERSIZE 2048
435 typedef struct DryMixParams {
436 AmbiConfig Ambi;
437 /* Number of coefficients in each Ambi.Coeffs to mix together (4 for first-
438 * order, 9 for second-order, etc). If the count is 0, Ambi.Map is used
439 * instead to map each output to a coefficient index.
441 ALsizei CoeffCount;
443 ALfloat (*Buffer)[BUFFERSIZE];
444 ALsizei NumChannels;
445 ALsizei NumChannelsPerOrder[MAX_AMBI_ORDER+1];
446 } DryMixParams;
448 typedef struct BFMixParams {
449 AmbiConfig Ambi;
450 /* Will only be 4 or 0. */
451 ALsizei CoeffCount;
453 ALfloat (*Buffer)[BUFFERSIZE];
454 ALsizei NumChannels;
455 } BFMixParams;
457 typedef struct RealMixParams {
458 enum Channel ChannelName[MAX_OUTPUT_CHANNELS];
460 ALfloat (*Buffer)[BUFFERSIZE];
461 ALsizei NumChannels;
462 } RealMixParams;
464 typedef void (*POSTPROCESS)(ALCdevice *device, ALsizei SamplesToDo);
466 struct ALCdevice_struct {
467 RefCount ref;
469 ATOMIC(ALenum) Connected;
470 enum DeviceType Type;
472 ALuint Frequency;
473 ALuint UpdateSize;
474 ALuint NumUpdates;
475 enum DevFmtChannels FmtChans;
476 enum DevFmtType FmtType;
477 ALboolean IsHeadphones;
478 ALsizei AmbiOrder;
479 /* For DevFmtAmbi* output only, specifies the channel order and
480 * normalization.
482 enum AmbiLayout AmbiLayout;
483 enum AmbiNorm AmbiScale;
485 al_string DeviceName;
487 ATOMIC(ALCenum) LastError;
489 // Maximum number of sources that can be created
490 ALuint SourcesMax;
491 // Maximum number of slots that can be created
492 ALuint AuxiliaryEffectSlotMax;
494 ALCuint NumMonoSources;
495 ALCuint NumStereoSources;
496 ALsizei NumAuxSends;
498 // Map of Buffers for this device
499 vector_BufferSubList BufferList;
500 almtx_t BufferLock;
502 // Map of Effects for this device
503 vector_EffectSubList EffectList;
504 almtx_t EffectLock;
506 // Map of Filters for this device
507 vector_FilterSubList FilterList;
508 almtx_t FilterLock;
510 POSTPROCESS PostProcess;
512 /* HRTF state and info */
513 struct DirectHrtfState *Hrtf;
514 al_string HrtfName;
515 struct Hrtf *HrtfHandle;
516 vector_EnumeratedHrtf HrtfList;
517 ALCenum HrtfStatus;
519 /* UHJ encoder state */
520 struct Uhj2Encoder *Uhj_Encoder;
522 /* High quality Ambisonic decoder */
523 struct BFormatDec *AmbiDecoder;
525 /* Stereo-to-binaural filter */
526 struct bs2b *Bs2b;
528 /* First-order ambisonic upsampler for higher-order output */
529 struct AmbiUpsampler *AmbiUp;
531 /* Rendering mode. */
532 enum RenderMode Render_Mode;
534 // Device flags
535 ALuint Flags;
537 ALuint64 ClockBase;
538 ALuint SamplesDone;
540 /* Temp storage used for mixer processing. */
541 alignas(16) ALfloat TempBuffer[4][BUFFERSIZE];
543 /* The "dry" path corresponds to the main output. */
544 DryMixParams Dry;
546 /* First-order ambisonics output, to be upsampled to the dry buffer if different. */
547 BFMixParams FOAOut;
549 /* "Real" output, which will be written to the device buffer. May alias the
550 * dry buffer.
552 RealMixParams RealOut;
554 struct FrontStablizer *Stablizer;
556 struct Compressor *Limiter;
558 /* The average speaker distance as determined by the ambdec configuration
559 * (or alternatively, by the NFC-HOA reference delay). Only used for NFC.
561 ALfloat AvgSpeakerDist;
563 /* Delay buffers used to compensate for speaker distances. */
564 DistanceComp ChannelDelay[MAX_OUTPUT_CHANNELS];
566 /* Dithering control. */
567 ALfloat DitherDepth;
568 ALuint DitherSeed;
570 /* Running count of the mixer invocations, in 31.1 fixed point. This
571 * actually increments *twice* when mixing, first at the start and then at
572 * the end, so the bottom bit indicates if the device is currently mixing
573 * and the upper bits indicates how many mixes have been done.
575 RefCount MixCount;
577 // Contexts created on this device
578 ATOMIC(ALCcontext*) ContextList;
580 almtx_t BackendLock;
581 struct ALCbackend *Backend;
583 ATOMIC(ALCdevice*) next;
586 // Frequency was requested by the app or config file
587 #define DEVICE_FREQUENCY_REQUEST (1u<<1)
588 // Channel configuration was requested by the config file
589 #define DEVICE_CHANNELS_REQUEST (1u<<2)
590 // Sample type was requested by the config file
591 #define DEVICE_SAMPLE_TYPE_REQUEST (1u<<3)
593 // Specifies if the DSP is paused at user request
594 #define DEVICE_PAUSED (1u<<30)
596 // Specifies if the device is currently running
597 #define DEVICE_RUNNING (1u<<31)
600 /* Nanosecond resolution for the device clock time. */
601 #define DEVICE_CLOCK_RES U64(1000000000)
604 /* Must be less than 15 characters (16 including terminating null) for
605 * compatibility with pthread_setname_np limitations. */
606 #define MIXER_THREAD_NAME "alsoft-mixer"
608 #define RECORD_THREAD_NAME "alsoft-record"
611 enum {
612 EventType_SourceStateChange = 1<<0,
613 EventType_BufferCompleted = 1<<1,
614 EventType_Error = 1<<2,
615 EventType_Performance = 1<<3,
616 EventType_Deprecated = 1<<4,
617 EventType_Disconnected = 1<<5,
620 typedef struct AsyncEvent {
621 unsigned int EnumType;
622 ALenum Type;
623 ALuint ObjectId;
624 ALuint Param;
625 ALchar Message[1008];
626 } AsyncEvent;
628 struct ALCcontext_struct {
629 RefCount ref;
631 struct ALlistener *Listener;
633 vector_SourceSubList SourceList;
634 ALuint NumSources;
635 almtx_t SourceLock;
637 vector_ALeffectslotPtr EffectSlotList;
638 almtx_t EffectSlotLock;
640 ATOMIC(ALenum) LastError;
642 enum DistanceModel DistanceModel;
643 ALboolean SourceDistanceModel;
645 ALfloat DopplerFactor;
646 ALfloat DopplerVelocity;
647 ALfloat SpeedOfSound;
648 ALfloat MetersPerUnit;
650 ATOMIC_FLAG PropsClean;
651 ATOMIC(ALenum) DeferUpdates;
653 almtx_t PropLock;
655 /* Counter for the pre-mixing updates, in 31.1 fixed point (lowest bit
656 * indicates if updates are currently happening).
658 RefCount UpdateCount;
659 ATOMIC(ALenum) HoldUpdates;
661 ALfloat GainBoost;
663 ATOMIC(struct ALcontextProps*) Update;
665 /* Linked lists of unused property containers, free to use for future
666 * updates.
668 ATOMIC(struct ALcontextProps*) FreeContextProps;
669 ATOMIC(struct ALlistenerProps*) FreeListenerProps;
670 ATOMIC(struct ALvoiceProps*) FreeVoiceProps;
671 ATOMIC(struct ALeffectslotProps*) FreeEffectslotProps;
673 struct ALvoice **Voices;
674 ALsizei VoiceCount;
675 ALsizei MaxVoices;
677 ATOMIC(struct ALeffectslotArray*) ActiveAuxSlots;
679 almtx_t EventThrdLock;
680 althrd_t EventThread;
681 alsem_t EventSem;
682 struct ll_ringbuffer *AsyncEvents;
683 ATOMIC(ALbitfieldSOFT) EnabledEvts;
684 almtx_t EventCbLock;
685 ALEVENTPROCSOFT EventCb;
686 void *EventParam;
688 /* Default effect slot */
689 struct ALeffectslot *DefaultSlot;
691 ALCdevice *Device;
692 const ALCchar *ExtensionList;
694 ATOMIC(ALCcontext*) next;
696 /* Memory space used by the listener (and possibly default effect slot) */
697 alignas(16) ALCbyte _listener_mem[];
700 ALCcontext *GetContextRef(void);
702 void ALCcontext_DecRef(ALCcontext *context);
704 void ALCcontext_DeferUpdates(ALCcontext *context);
705 void ALCcontext_ProcessUpdates(ALCcontext *context);
707 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends);
709 void AppendAllDevicesList(const ALCchar *name);
710 void AppendCaptureDeviceList(const ALCchar *name);
713 extern ALint RTPrioLevel;
714 void SetRTPriority(void);
716 void SetDefaultChannelOrder(ALCdevice *device);
717 void SetDefaultWFXChannelOrder(ALCdevice *device);
719 const ALCchar *DevFmtTypeString(enum DevFmtType type);
720 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans);
722 inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan)
724 ALint i;
725 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
727 if(names[i] == chan)
728 return i;
730 return -1;
733 * GetChannelIdxByName
735 * Returns the index for the given channel name (e.g. FrontCenter), or -1 if it
736 * doesn't exist.
738 inline ALint GetChannelIdxByName(const RealMixParams *real, enum Channel chan)
739 { return GetChannelIndex(real->ChannelName, chan); }
742 inline void LockBufferList(ALCdevice *device) { almtx_lock(&device->BufferLock); }
743 inline void UnlockBufferList(ALCdevice *device) { almtx_unlock(&device->BufferLock); }
745 inline void LockEffectList(ALCdevice *device) { almtx_lock(&device->EffectLock); }
746 inline void UnlockEffectList(ALCdevice *device) { almtx_unlock(&device->EffectLock); }
748 inline void LockFilterList(ALCdevice *device) { almtx_lock(&device->FilterLock); }
749 inline void UnlockFilterList(ALCdevice *device) { almtx_unlock(&device->FilterLock); }
751 inline void LockEffectSlotList(ALCcontext *context)
752 { almtx_lock(&context->EffectSlotLock); }
753 inline void UnlockEffectSlotList(ALCcontext *context)
754 { almtx_unlock(&context->EffectSlotLock); }
757 vector_al_string SearchDataFiles(const char *match, const char *subdir);
759 #ifdef __cplusplus
761 #endif
763 #endif