1 /**
2  * OpenAL cross platform audio library
3  * Copyright (C) 1999-2007 by authors.
4  * This library is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU Library General Public
6  *  License as published by the Free Software Foundation; either
7  *  version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  *  License along with this library; if not, write to the
16  *  Free Software Foundation, Inc.,
17  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  * Or go to http://www.gnu.org/copyleft/lgpl.html
19  */
20 
21 #include "config.h"
22 
23 #include "version.h"
24 
25 #ifdef _WIN32
26 #define WIN32_LEAN_AND_MEAN
27 #include <windows.h>
28 #endif
29 
30 #include <exception>
31 #include <algorithm>
32 #include <array>
33 #include <atomic>
34 #include <cctype>
35 #include <chrono>
36 #include <cinttypes>
37 #include <climits>
38 #include <cmath>
39 #include <csignal>
40 #include <cstdint>
41 #include <cstdio>
42 #include <cstdlib>
43 #include <cstring>
44 #include <functional>
45 #include <iterator>
46 #include <limits>
47 #include <memory>
48 #include <mutex>
49 #include <new>
50 #include <numeric>
51 #include <string>
52 #include <thread>
53 #include <utility>
54 
55 #include "AL/al.h"
56 #include "AL/alc.h"
57 #include "AL/alext.h"
58 #include "AL/efx.h"
59 
60 #include "al/auxeffectslot.h"
61 #include "al/buffer.h"
62 #include "al/effect.h"
63 #include "al/event.h"
64 #include "al/filter.h"
65 #include "al/listener.h"
66 #include "al/source.h"
67 #include "albit.h"
68 #include "alcmain.h"
69 #include "albyte.h"
70 #include "alconfig.h"
71 #include "alcontext.h"
72 #include "almalloc.h"
73 #include "alnumeric.h"
74 #include "aloptional.h"
75 #include "alspan.h"
76 #include "alstring.h"
77 #include "alu.h"
78 #include "async_event.h"
79 #include "atomic.h"
80 #include "bformatdec.h"
81 #include "compat.h"
82 #include "core/ambidefs.h"
83 #include "core/bs2b.h"
84 #include "core/cpu_caps.h"
85 #include "core/devformat.h"
86 #include "core/except.h"
87 #include "core/mastering.h"
88 #include "core/filters/nfc.h"
89 #include "core/filters/splitter.h"
90 #include "core/fpu_ctrl.h"
91 #include "core/logging.h"
92 #include "core/uhjfilter.h"
93 #include "effects/base.h"
94 #include "front_stablizer.h"
95 #include "hrtf.h"
96 #include "inprogext.h"
97 #include "intrusive_ptr.h"
98 #include "opthelpers.h"
99 #include "pragmadefs.h"
100 #include "ringbuffer.h"
101 #include "strutils.h"
102 #include "threads.h"
103 #include "vecmat.h"
104 #include "vector.h"
105 #include "voice_change.h"
106 
107 #include "backends/base.h"
108 #include "backends/null.h"
109 #include "backends/loopback.h"
110 #ifdef HAVE_JACK
111 #include "backends/jack.h"
112 #endif
113 #ifdef HAVE_PULSEAUDIO
114 #include "backends/pulseaudio.h"
115 #endif
116 #ifdef HAVE_ALSA
117 #include "backends/alsa.h"
118 #endif
119 #ifdef HAVE_WASAPI
120 #include "backends/wasapi.h"
121 #endif
122 #ifdef HAVE_COREAUDIO
123 #include "backends/coreaudio.h"
124 #endif
125 #ifdef HAVE_OPENSL
126 #include "backends/opensl.h"
127 #endif
128 #ifdef HAVE_OBOE
129 #include "backends/oboe.h"
130 #endif
131 #ifdef HAVE_SOLARIS
132 #include "backends/solaris.h"
133 #endif
134 #ifdef HAVE_SNDIO
135 #include "backends/sndio.h"
136 #endif
137 #ifdef HAVE_OSS
138 #include "backends/oss.h"
139 #endif
140 #ifdef HAVE_DSOUND
141 #include "backends/dsound.h"
142 #endif
143 #ifdef HAVE_WINMM
144 #include "backends/winmm.h"
145 #endif
146 #ifdef HAVE_PORTAUDIO
147 #include "backends/portaudio.h"
148 #endif
149 #ifdef HAVE_SDL2
150 #include "backends/sdl2.h"
151 #endif
152 #ifdef HAVE_WAVE
153 #include "backends/wave.h"
154 #endif
155 
156 
157 namespace {
158 
159 using namespace std::placeholders;
160 using std::chrono::seconds;
161 using std::chrono::nanoseconds;
162 
163 using voidp = void*;
164 
165 
166 /************************************************
167  * Backends
168  ************************************************/
169 struct BackendInfo {
170     const char *name;
171     BackendFactory& (*getFactory)(void);
172 };
173 
174 BackendInfo BackendList[] = {
175 #ifdef HAVE_JACK
176     { "jack", JackBackendFactory::getFactory },
177 #endif
178 #ifdef HAVE_PULSEAUDIO
179     { "pulse", PulseBackendFactory::getFactory },
180 #endif
181 #ifdef HAVE_ALSA
182     { "alsa", AlsaBackendFactory::getFactory },
183 #endif
184 #ifdef HAVE_WASAPI
185     { "wasapi", WasapiBackendFactory::getFactory },
186 #endif
187 #ifdef HAVE_COREAUDIO
188     { "core", CoreAudioBackendFactory::getFactory },
189 #endif
190 #ifdef HAVE_OBOE
191     { "oboe", OboeBackendFactory::getFactory },
192 #endif
193 #ifdef HAVE_OPENSL
194     { "opensl", OSLBackendFactory::getFactory },
195 #endif
196 #ifdef HAVE_SOLARIS
197     { "solaris", SolarisBackendFactory::getFactory },
198 #endif
199 #ifdef HAVE_SNDIO
200     { "sndio", SndIOBackendFactory::getFactory },
201 #endif
202 #ifdef HAVE_OSS
203     { "oss", OSSBackendFactory::getFactory },
204 #endif
205 #ifdef HAVE_DSOUND
206     { "dsound", DSoundBackendFactory::getFactory },
207 #endif
208 #ifdef HAVE_WINMM
209     { "winmm", WinMMBackendFactory::getFactory },
210 #endif
211 #ifdef HAVE_PORTAUDIO
212     { "port", PortBackendFactory::getFactory },
213 #endif
214 #ifdef HAVE_SDL2
215     { "sdl2", SDL2BackendFactory::getFactory },
216 #endif
217 
218     { "null", NullBackendFactory::getFactory },
219 #ifdef HAVE_WAVE
220     { "wave", WaveBackendFactory::getFactory },
221 #endif
222 };
223 
224 BackendFactory *PlaybackFactory{};
225 BackendFactory *CaptureFactory{};
226 
227 
228 /************************************************
229  * Functions, enums, and errors
230  ************************************************/
231 #define DECL(x) { #x, reinterpret_cast<void*>(x) }
232 const struct {
233     const char *funcName;
234     void *address;
235 } alcFunctions[] = {
236     DECL(alcCreateContext),
237     DECL(alcMakeContextCurrent),
238     DECL(alcProcessContext),
239     DECL(alcSuspendContext),
240     DECL(alcDestroyContext),
241     DECL(alcGetCurrentContext),
242     DECL(alcGetContextsDevice),
243     DECL(alcOpenDevice),
244     DECL(alcCloseDevice),
245     DECL(alcGetError),
246     DECL(alcIsExtensionPresent),
247     DECL(alcGetProcAddress),
248     DECL(alcGetEnumValue),
249     DECL(alcGetString),
250     DECL(alcGetIntegerv),
251     DECL(alcCaptureOpenDevice),
252     DECL(alcCaptureCloseDevice),
253     DECL(alcCaptureStart),
254     DECL(alcCaptureStop),
255     DECL(alcCaptureSamples),
256 
257     DECL(alcSetThreadContext),
258     DECL(alcGetThreadContext),
259 
260     DECL(alcLoopbackOpenDeviceSOFT),
261     DECL(alcIsRenderFormatSupportedSOFT),
262     DECL(alcRenderSamplesSOFT),
263 
264     DECL(alcDevicePauseSOFT),
265     DECL(alcDeviceResumeSOFT),
266 
267     DECL(alcGetStringiSOFT),
268     DECL(alcResetDeviceSOFT),
269 
270     DECL(alcGetInteger64vSOFT),
271 
272     DECL(alEnable),
273     DECL(alDisable),
274     DECL(alIsEnabled),
275     DECL(alGetString),
276     DECL(alGetBooleanv),
277     DECL(alGetIntegerv),
278     DECL(alGetFloatv),
279     DECL(alGetDoublev),
280     DECL(alGetBoolean),
281     DECL(alGetInteger),
282     DECL(alGetFloat),
283     DECL(alGetDouble),
284     DECL(alGetError),
285     DECL(alIsExtensionPresent),
286     DECL(alGetProcAddress),
287     DECL(alGetEnumValue),
288     DECL(alListenerf),
289     DECL(alListener3f),
290     DECL(alListenerfv),
291     DECL(alListeneri),
292     DECL(alListener3i),
293     DECL(alListeneriv),
294     DECL(alGetListenerf),
295     DECL(alGetListener3f),
296     DECL(alGetListenerfv),
297     DECL(alGetListeneri),
298     DECL(alGetListener3i),
299     DECL(alGetListeneriv),
300     DECL(alGenSources),
301     DECL(alDeleteSources),
302     DECL(alIsSource),
303     DECL(alSourcef),
304     DECL(alSource3f),
305     DECL(alSourcefv),
306     DECL(alSourcei),
307     DECL(alSource3i),
308     DECL(alSourceiv),
309     DECL(alGetSourcef),
310     DECL(alGetSource3f),
311     DECL(alGetSourcefv),
312     DECL(alGetSourcei),
313     DECL(alGetSource3i),
314     DECL(alGetSourceiv),
315     DECL(alSourcePlayv),
316     DECL(alSourceStopv),
317     DECL(alSourceRewindv),
318     DECL(alSourcePausev),
319     DECL(alSourcePlay),
320     DECL(alSourceStop),
321     DECL(alSourceRewind),
322     DECL(alSourcePause),
323     DECL(alSourceQueueBuffers),
324     DECL(alSourceUnqueueBuffers),
325     DECL(alGenBuffers),
326     DECL(alDeleteBuffers),
327     DECL(alIsBuffer),
328     DECL(alBufferData),
329     DECL(alBufferf),
330     DECL(alBuffer3f),
331     DECL(alBufferfv),
332     DECL(alBufferi),
333     DECL(alBuffer3i),
334     DECL(alBufferiv),
335     DECL(alGetBufferf),
336     DECL(alGetBuffer3f),
337     DECL(alGetBufferfv),
338     DECL(alGetBufferi),
339     DECL(alGetBuffer3i),
340     DECL(alGetBufferiv),
341     DECL(alDopplerFactor),
342     DECL(alDopplerVelocity),
343     DECL(alSpeedOfSound),
344     DECL(alDistanceModel),
345 
346     DECL(alGenFilters),
347     DECL(alDeleteFilters),
348     DECL(alIsFilter),
349     DECL(alFilteri),
350     DECL(alFilteriv),
351     DECL(alFilterf),
352     DECL(alFilterfv),
353     DECL(alGetFilteri),
354     DECL(alGetFilteriv),
355     DECL(alGetFilterf),
356     DECL(alGetFilterfv),
357     DECL(alGenEffects),
358     DECL(alDeleteEffects),
359     DECL(alIsEffect),
360     DECL(alEffecti),
361     DECL(alEffectiv),
362     DECL(alEffectf),
363     DECL(alEffectfv),
364     DECL(alGetEffecti),
365     DECL(alGetEffectiv),
366     DECL(alGetEffectf),
367     DECL(alGetEffectfv),
368     DECL(alGenAuxiliaryEffectSlots),
369     DECL(alDeleteAuxiliaryEffectSlots),
370     DECL(alIsAuxiliaryEffectSlot),
371     DECL(alAuxiliaryEffectSloti),
372     DECL(alAuxiliaryEffectSlotiv),
373     DECL(alAuxiliaryEffectSlotf),
374     DECL(alAuxiliaryEffectSlotfv),
375     DECL(alGetAuxiliaryEffectSloti),
376     DECL(alGetAuxiliaryEffectSlotiv),
377     DECL(alGetAuxiliaryEffectSlotf),
378     DECL(alGetAuxiliaryEffectSlotfv),
379 
380     DECL(alDeferUpdatesSOFT),
381     DECL(alProcessUpdatesSOFT),
382 
383     DECL(alSourcedSOFT),
384     DECL(alSource3dSOFT),
385     DECL(alSourcedvSOFT),
386     DECL(alGetSourcedSOFT),
387     DECL(alGetSource3dSOFT),
388     DECL(alGetSourcedvSOFT),
389     DECL(alSourcei64SOFT),
390     DECL(alSource3i64SOFT),
391     DECL(alSourcei64vSOFT),
392     DECL(alGetSourcei64SOFT),
393     DECL(alGetSource3i64SOFT),
394     DECL(alGetSourcei64vSOFT),
395 
396     DECL(alGetStringiSOFT),
397 
398     DECL(alBufferStorageSOFT),
399     DECL(alMapBufferSOFT),
400     DECL(alUnmapBufferSOFT),
401     DECL(alFlushMappedBufferSOFT),
402 
403     DECL(alEventControlSOFT),
404     DECL(alEventCallbackSOFT),
405     DECL(alGetPointerSOFT),
406     DECL(alGetPointervSOFT),
407 
408     DECL(alBufferCallbackSOFT),
409     DECL(alGetBufferPtrSOFT),
410     DECL(alGetBuffer3PtrSOFT),
411     DECL(alGetBufferPtrvSOFT),
412 
413     DECL(alAuxiliaryEffectSlotPlaySOFT),
414     DECL(alAuxiliaryEffectSlotPlayvSOFT),
415     DECL(alAuxiliaryEffectSlotStopSOFT),
416     DECL(alAuxiliaryEffectSlotStopvSOFT),
417 };
418 #undef DECL
419 
420 #define DECL(x) { #x, (x) }
421 constexpr struct {
422     const ALCchar *enumName;
423     ALCenum value;
424 } alcEnumerations[] = {
425     DECL(ALC_INVALID),
426     DECL(ALC_FALSE),
427     DECL(ALC_TRUE),
428 
429     DECL(ALC_MAJOR_VERSION),
430     DECL(ALC_MINOR_VERSION),
431     DECL(ALC_ATTRIBUTES_SIZE),
432     DECL(ALC_ALL_ATTRIBUTES),
433     DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
434     DECL(ALC_DEVICE_SPECIFIER),
435     DECL(ALC_ALL_DEVICES_SPECIFIER),
436     DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
437     DECL(ALC_EXTENSIONS),
438     DECL(ALC_FREQUENCY),
439     DECL(ALC_REFRESH),
440     DECL(ALC_SYNC),
441     DECL(ALC_MONO_SOURCES),
442     DECL(ALC_STEREO_SOURCES),
443     DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
444     DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
445     DECL(ALC_CAPTURE_SAMPLES),
446     DECL(ALC_CONNECTED),
447 
448     DECL(ALC_EFX_MAJOR_VERSION),
449     DECL(ALC_EFX_MINOR_VERSION),
450     DECL(ALC_MAX_AUXILIARY_SENDS),
451 
452     DECL(ALC_FORMAT_CHANNELS_SOFT),
453     DECL(ALC_FORMAT_TYPE_SOFT),
454 
455     DECL(ALC_MONO_SOFT),
456     DECL(ALC_STEREO_SOFT),
457     DECL(ALC_QUAD_SOFT),
458     DECL(ALC_5POINT1_SOFT),
459     DECL(ALC_6POINT1_SOFT),
460     DECL(ALC_7POINT1_SOFT),
461     DECL(ALC_BFORMAT3D_SOFT),
462 
463     DECL(ALC_BYTE_SOFT),
464     DECL(ALC_UNSIGNED_BYTE_SOFT),
465     DECL(ALC_SHORT_SOFT),
466     DECL(ALC_UNSIGNED_SHORT_SOFT),
467     DECL(ALC_INT_SOFT),
468     DECL(ALC_UNSIGNED_INT_SOFT),
469     DECL(ALC_FLOAT_SOFT),
470 
471     DECL(ALC_HRTF_SOFT),
472     DECL(ALC_DONT_CARE_SOFT),
473     DECL(ALC_HRTF_STATUS_SOFT),
474     DECL(ALC_HRTF_DISABLED_SOFT),
475     DECL(ALC_HRTF_ENABLED_SOFT),
476     DECL(ALC_HRTF_DENIED_SOFT),
477     DECL(ALC_HRTF_REQUIRED_SOFT),
478     DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
479     DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
480     DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
481     DECL(ALC_HRTF_SPECIFIER_SOFT),
482     DECL(ALC_HRTF_ID_SOFT),
483 
484     DECL(ALC_AMBISONIC_LAYOUT_SOFT),
485     DECL(ALC_AMBISONIC_SCALING_SOFT),
486     DECL(ALC_AMBISONIC_ORDER_SOFT),
487     DECL(ALC_ACN_SOFT),
488     DECL(ALC_FUMA_SOFT),
489     DECL(ALC_N3D_SOFT),
490     DECL(ALC_SN3D_SOFT),
491 
492     DECL(ALC_OUTPUT_LIMITER_SOFT),
493 
494     DECL(ALC_NO_ERROR),
495     DECL(ALC_INVALID_DEVICE),
496     DECL(ALC_INVALID_CONTEXT),
497     DECL(ALC_INVALID_ENUM),
498     DECL(ALC_INVALID_VALUE),
499     DECL(ALC_OUT_OF_MEMORY),
500 
501 
502     DECL(AL_INVALID),
503     DECL(AL_NONE),
504     DECL(AL_FALSE),
505     DECL(AL_TRUE),
506 
507     DECL(AL_SOURCE_RELATIVE),
508     DECL(AL_CONE_INNER_ANGLE),
509     DECL(AL_CONE_OUTER_ANGLE),
510     DECL(AL_PITCH),
511     DECL(AL_POSITION),
512     DECL(AL_DIRECTION),
513     DECL(AL_VELOCITY),
514     DECL(AL_LOOPING),
515     DECL(AL_BUFFER),
516     DECL(AL_GAIN),
517     DECL(AL_MIN_GAIN),
518     DECL(AL_MAX_GAIN),
519     DECL(AL_ORIENTATION),
520     DECL(AL_REFERENCE_DISTANCE),
521     DECL(AL_ROLLOFF_FACTOR),
522     DECL(AL_CONE_OUTER_GAIN),
523     DECL(AL_MAX_DISTANCE),
524     DECL(AL_SEC_OFFSET),
525     DECL(AL_SAMPLE_OFFSET),
526     DECL(AL_BYTE_OFFSET),
527     DECL(AL_SOURCE_TYPE),
528     DECL(AL_STATIC),
529     DECL(AL_STREAMING),
530     DECL(AL_UNDETERMINED),
531     DECL(AL_METERS_PER_UNIT),
532     DECL(AL_LOOP_POINTS_SOFT),
533     DECL(AL_DIRECT_CHANNELS_SOFT),
534 
535     DECL(AL_DIRECT_FILTER),
536     DECL(AL_AUXILIARY_SEND_FILTER),
537     DECL(AL_AIR_ABSORPTION_FACTOR),
538     DECL(AL_ROOM_ROLLOFF_FACTOR),
539     DECL(AL_CONE_OUTER_GAINHF),
540     DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
541     DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
542     DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
543 
544     DECL(AL_SOURCE_STATE),
545     DECL(AL_INITIAL),
546     DECL(AL_PLAYING),
547     DECL(AL_PAUSED),
548     DECL(AL_STOPPED),
549 
550     DECL(AL_BUFFERS_QUEUED),
551     DECL(AL_BUFFERS_PROCESSED),
552 
553     DECL(AL_FORMAT_MONO8),
554     DECL(AL_FORMAT_MONO16),
555     DECL(AL_FORMAT_MONO_FLOAT32),
556     DECL(AL_FORMAT_MONO_DOUBLE_EXT),
557     DECL(AL_FORMAT_STEREO8),
558     DECL(AL_FORMAT_STEREO16),
559     DECL(AL_FORMAT_STEREO_FLOAT32),
560     DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
561     DECL(AL_FORMAT_MONO_IMA4),
562     DECL(AL_FORMAT_STEREO_IMA4),
563     DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
564     DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
565     DECL(AL_FORMAT_QUAD8_LOKI),
566     DECL(AL_FORMAT_QUAD16_LOKI),
567     DECL(AL_FORMAT_QUAD8),
568     DECL(AL_FORMAT_QUAD16),
569     DECL(AL_FORMAT_QUAD32),
570     DECL(AL_FORMAT_51CHN8),
571     DECL(AL_FORMAT_51CHN16),
572     DECL(AL_FORMAT_51CHN32),
573     DECL(AL_FORMAT_61CHN8),
574     DECL(AL_FORMAT_61CHN16),
575     DECL(AL_FORMAT_61CHN32),
576     DECL(AL_FORMAT_71CHN8),
577     DECL(AL_FORMAT_71CHN16),
578     DECL(AL_FORMAT_71CHN32),
579     DECL(AL_FORMAT_REAR8),
580     DECL(AL_FORMAT_REAR16),
581     DECL(AL_FORMAT_REAR32),
582     DECL(AL_FORMAT_MONO_MULAW),
583     DECL(AL_FORMAT_MONO_MULAW_EXT),
584     DECL(AL_FORMAT_STEREO_MULAW),
585     DECL(AL_FORMAT_STEREO_MULAW_EXT),
586     DECL(AL_FORMAT_QUAD_MULAW),
587     DECL(AL_FORMAT_51CHN_MULAW),
588     DECL(AL_FORMAT_61CHN_MULAW),
589     DECL(AL_FORMAT_71CHN_MULAW),
590     DECL(AL_FORMAT_REAR_MULAW),
591     DECL(AL_FORMAT_MONO_ALAW_EXT),
592     DECL(AL_FORMAT_STEREO_ALAW_EXT),
593 
594     DECL(AL_FORMAT_BFORMAT2D_8),
595     DECL(AL_FORMAT_BFORMAT2D_16),
596     DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
597     DECL(AL_FORMAT_BFORMAT2D_MULAW),
598     DECL(AL_FORMAT_BFORMAT3D_8),
599     DECL(AL_FORMAT_BFORMAT3D_16),
600     DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
601     DECL(AL_FORMAT_BFORMAT3D_MULAW),
602 
603     DECL(AL_FREQUENCY),
604     DECL(AL_BITS),
605     DECL(AL_CHANNELS),
606     DECL(AL_SIZE),
607     DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
608     DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
609 
610     DECL(AL_SOURCE_RADIUS),
611 
612     DECL(AL_STEREO_ANGLES),
613 
614     DECL(AL_UNUSED),
615     DECL(AL_PENDING),
616     DECL(AL_PROCESSED),
617 
618     DECL(AL_NO_ERROR),
619     DECL(AL_INVALID_NAME),
620     DECL(AL_INVALID_ENUM),
621     DECL(AL_INVALID_VALUE),
622     DECL(AL_INVALID_OPERATION),
623     DECL(AL_OUT_OF_MEMORY),
624 
625     DECL(AL_VENDOR),
626     DECL(AL_VERSION),
627     DECL(AL_RENDERER),
628     DECL(AL_EXTENSIONS),
629 
630     DECL(AL_DOPPLER_FACTOR),
631     DECL(AL_DOPPLER_VELOCITY),
632     DECL(AL_DISTANCE_MODEL),
633     DECL(AL_SPEED_OF_SOUND),
634     DECL(AL_SOURCE_DISTANCE_MODEL),
635     DECL(AL_DEFERRED_UPDATES_SOFT),
636     DECL(AL_GAIN_LIMIT_SOFT),
637 
638     DECL(AL_INVERSE_DISTANCE),
639     DECL(AL_INVERSE_DISTANCE_CLAMPED),
640     DECL(AL_LINEAR_DISTANCE),
641     DECL(AL_LINEAR_DISTANCE_CLAMPED),
642     DECL(AL_EXPONENT_DISTANCE),
643     DECL(AL_EXPONENT_DISTANCE_CLAMPED),
644 
645     DECL(AL_FILTER_TYPE),
646     DECL(AL_FILTER_NULL),
647     DECL(AL_FILTER_LOWPASS),
648     DECL(AL_FILTER_HIGHPASS),
649     DECL(AL_FILTER_BANDPASS),
650 
651     DECL(AL_LOWPASS_GAIN),
652     DECL(AL_LOWPASS_GAINHF),
653 
654     DECL(AL_HIGHPASS_GAIN),
655     DECL(AL_HIGHPASS_GAINLF),
656 
657     DECL(AL_BANDPASS_GAIN),
658     DECL(AL_BANDPASS_GAINHF),
659     DECL(AL_BANDPASS_GAINLF),
660 
661     DECL(AL_EFFECT_TYPE),
662     DECL(AL_EFFECT_NULL),
663     DECL(AL_EFFECT_REVERB),
664     DECL(AL_EFFECT_EAXREVERB),
665     DECL(AL_EFFECT_CHORUS),
666     DECL(AL_EFFECT_DISTORTION),
667     DECL(AL_EFFECT_ECHO),
668     DECL(AL_EFFECT_FLANGER),
669     DECL(AL_EFFECT_PITCH_SHIFTER),
670     DECL(AL_EFFECT_FREQUENCY_SHIFTER),
671     DECL(AL_EFFECT_VOCAL_MORPHER),
672     DECL(AL_EFFECT_RING_MODULATOR),
673     DECL(AL_EFFECT_AUTOWAH),
674     DECL(AL_EFFECT_COMPRESSOR),
675     DECL(AL_EFFECT_EQUALIZER),
676     DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
677     DECL(AL_EFFECT_DEDICATED_DIALOGUE),
678 
679     DECL(AL_EFFECTSLOT_EFFECT),
680     DECL(AL_EFFECTSLOT_GAIN),
681     DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
682     DECL(AL_EFFECTSLOT_NULL),
683 
684     DECL(AL_EAXREVERB_DENSITY),
685     DECL(AL_EAXREVERB_DIFFUSION),
686     DECL(AL_EAXREVERB_GAIN),
687     DECL(AL_EAXREVERB_GAINHF),
688     DECL(AL_EAXREVERB_GAINLF),
689     DECL(AL_EAXREVERB_DECAY_TIME),
690     DECL(AL_EAXREVERB_DECAY_HFRATIO),
691     DECL(AL_EAXREVERB_DECAY_LFRATIO),
692     DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
693     DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
694     DECL(AL_EAXREVERB_REFLECTIONS_PAN),
695     DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
696     DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
697     DECL(AL_EAXREVERB_LATE_REVERB_PAN),
698     DECL(AL_EAXREVERB_ECHO_TIME),
699     DECL(AL_EAXREVERB_ECHO_DEPTH),
700     DECL(AL_EAXREVERB_MODULATION_TIME),
701     DECL(AL_EAXREVERB_MODULATION_DEPTH),
702     DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
703     DECL(AL_EAXREVERB_HFREFERENCE),
704     DECL(AL_EAXREVERB_LFREFERENCE),
705     DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
706     DECL(AL_EAXREVERB_DECAY_HFLIMIT),
707 
708     DECL(AL_REVERB_DENSITY),
709     DECL(AL_REVERB_DIFFUSION),
710     DECL(AL_REVERB_GAIN),
711     DECL(AL_REVERB_GAINHF),
712     DECL(AL_REVERB_DECAY_TIME),
713     DECL(AL_REVERB_DECAY_HFRATIO),
714     DECL(AL_REVERB_REFLECTIONS_GAIN),
715     DECL(AL_REVERB_REFLECTIONS_DELAY),
716     DECL(AL_REVERB_LATE_REVERB_GAIN),
717     DECL(AL_REVERB_LATE_REVERB_DELAY),
718     DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
719     DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
720     DECL(AL_REVERB_DECAY_HFLIMIT),
721 
722     DECL(AL_CHORUS_WAVEFORM),
723     DECL(AL_CHORUS_PHASE),
724     DECL(AL_CHORUS_RATE),
725     DECL(AL_CHORUS_DEPTH),
726     DECL(AL_CHORUS_FEEDBACK),
727     DECL(AL_CHORUS_DELAY),
728 
729     DECL(AL_DISTORTION_EDGE),
730     DECL(AL_DISTORTION_GAIN),
731     DECL(AL_DISTORTION_LOWPASS_CUTOFF),
732     DECL(AL_DISTORTION_EQCENTER),
733     DECL(AL_DISTORTION_EQBANDWIDTH),
734 
735     DECL(AL_ECHO_DELAY),
736     DECL(AL_ECHO_LRDELAY),
737     DECL(AL_ECHO_DAMPING),
738     DECL(AL_ECHO_FEEDBACK),
739     DECL(AL_ECHO_SPREAD),
740 
741     DECL(AL_FLANGER_WAVEFORM),
742     DECL(AL_FLANGER_PHASE),
743     DECL(AL_FLANGER_RATE),
744     DECL(AL_FLANGER_DEPTH),
745     DECL(AL_FLANGER_FEEDBACK),
746     DECL(AL_FLANGER_DELAY),
747 
748     DECL(AL_FREQUENCY_SHIFTER_FREQUENCY),
749     DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION),
750     DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION),
751 
752     DECL(AL_RING_MODULATOR_FREQUENCY),
753     DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
754     DECL(AL_RING_MODULATOR_WAVEFORM),
755 
756     DECL(AL_PITCH_SHIFTER_COARSE_TUNE),
757     DECL(AL_PITCH_SHIFTER_FINE_TUNE),
758 
759     DECL(AL_COMPRESSOR_ONOFF),
760 
761     DECL(AL_EQUALIZER_LOW_GAIN),
762     DECL(AL_EQUALIZER_LOW_CUTOFF),
763     DECL(AL_EQUALIZER_MID1_GAIN),
764     DECL(AL_EQUALIZER_MID1_CENTER),
765     DECL(AL_EQUALIZER_MID1_WIDTH),
766     DECL(AL_EQUALIZER_MID2_GAIN),
767     DECL(AL_EQUALIZER_MID2_CENTER),
768     DECL(AL_EQUALIZER_MID2_WIDTH),
769     DECL(AL_EQUALIZER_HIGH_GAIN),
770     DECL(AL_EQUALIZER_HIGH_CUTOFF),
771 
772     DECL(AL_DEDICATED_GAIN),
773 
774     DECL(AL_AUTOWAH_ATTACK_TIME),
775     DECL(AL_AUTOWAH_RELEASE_TIME),
776     DECL(AL_AUTOWAH_RESONANCE),
777     DECL(AL_AUTOWAH_PEAK_GAIN),
778 
779     DECL(AL_VOCAL_MORPHER_PHONEMEA),
780     DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING),
781     DECL(AL_VOCAL_MORPHER_PHONEMEB),
782     DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING),
783     DECL(AL_VOCAL_MORPHER_WAVEFORM),
784     DECL(AL_VOCAL_MORPHER_RATE),
785 
786     DECL(AL_EFFECTSLOT_TARGET_SOFT),
787 
788     DECL(AL_NUM_RESAMPLERS_SOFT),
789     DECL(AL_DEFAULT_RESAMPLER_SOFT),
790     DECL(AL_SOURCE_RESAMPLER_SOFT),
791     DECL(AL_RESAMPLER_NAME_SOFT),
792 
793     DECL(AL_SOURCE_SPATIALIZE_SOFT),
794     DECL(AL_AUTO_SOFT),
795 
796     DECL(AL_MAP_READ_BIT_SOFT),
797     DECL(AL_MAP_WRITE_BIT_SOFT),
798     DECL(AL_MAP_PERSISTENT_BIT_SOFT),
799     DECL(AL_PRESERVE_DATA_BIT_SOFT),
800 
801     DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT),
802     DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT),
803     DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT),
804     DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT),
805     DECL(AL_EVENT_TYPE_DISCONNECTED_SOFT),
806 
807     DECL(AL_DROP_UNMATCHED_SOFT),
808     DECL(AL_REMIX_UNMATCHED_SOFT),
809 
810     DECL(AL_AMBISONIC_LAYOUT_SOFT),
811     DECL(AL_AMBISONIC_SCALING_SOFT),
812     DECL(AL_FUMA_SOFT),
813     DECL(AL_ACN_SOFT),
814     DECL(AL_SN3D_SOFT),
815     DECL(AL_N3D_SOFT),
816 
817     DECL(AL_BUFFER_CALLBACK_FUNCTION_SOFT),
818     DECL(AL_BUFFER_CALLBACK_USER_PARAM_SOFT),
819 
820     DECL(AL_UNPACK_AMBISONIC_ORDER_SOFT),
821 
822     DECL(AL_EFFECT_CONVOLUTION_REVERB_SOFT),
823     DECL(AL_EFFECTSLOT_STATE_SOFT),
824 };
825 #undef DECL
826 
827 constexpr ALCchar alcNoError[] = "No Error";
828 constexpr ALCchar alcErrInvalidDevice[] = "Invalid Device";
829 constexpr ALCchar alcErrInvalidContext[] = "Invalid Context";
830 constexpr ALCchar alcErrInvalidEnum[] = "Invalid Enum";
831 constexpr ALCchar alcErrInvalidValue[] = "Invalid Value";
832 constexpr ALCchar alcErrOutOfMemory[] = "Out of Memory";
833 
834 
835 /************************************************
836  * Global variables
837  ************************************************/
838 
839 /* Enumerated device names */
840 constexpr ALCchar alcDefaultName[] = "OpenAL Soft\0";
841 
842 std::string alcAllDevicesList;
843 std::string alcCaptureDeviceList;
844 
845 /* Default is always the first in the list */
846 al::string alcDefaultAllDevicesSpecifier;
847 al::string alcCaptureDefaultDeviceSpecifier;
848 
849 /* Default context extensions */
850 constexpr ALchar alExtList[] =
851     "AL_EXT_ALAW "
852     "AL_EXT_BFORMAT "
853     "AL_EXT_DOUBLE "
854     "AL_EXT_EXPONENT_DISTANCE "
855     "AL_EXT_FLOAT32 "
856     "AL_EXT_IMA4 "
857     "AL_EXT_LINEAR_DISTANCE "
858     "AL_EXT_MCFORMATS "
859     "AL_EXT_MULAW "
860     "AL_EXT_MULAW_BFORMAT "
861     "AL_EXT_MULAW_MCFORMATS "
862     "AL_EXT_OFFSET "
863     "AL_EXT_source_distance_model "
864     "AL_EXT_SOURCE_RADIUS "
865     "AL_EXT_STEREO_ANGLES "
866     "AL_LOKI_quadriphonic "
867     "AL_SOFT_bformat_ex "
868     "AL_SOFTX_bformat_hoa "
869     "AL_SOFT_block_alignment "
870     "AL_SOFTX_callback_buffer "
871     "AL_SOFTX_convolution_reverb "
872     "AL_SOFT_deferred_updates "
873     "AL_SOFT_direct_channels "
874     "AL_SOFT_direct_channels_remix "
875     "AL_SOFT_effect_target "
876     "AL_SOFT_events "
877     "AL_SOFTX_filter_gain_ex "
878     "AL_SOFT_gain_clamp_ex "
879     "AL_SOFT_loop_points "
880     "AL_SOFTX_map_buffer "
881     "AL_SOFT_MSADPCM "
882     "AL_SOFT_source_latency "
883     "AL_SOFT_source_length "
884     "AL_SOFT_source_resampler "
885     "AL_SOFT_source_spatialize";
886 
887 std::atomic<ALCenum> LastNullDeviceError{ALC_NO_ERROR};
888 
889 /* Thread-local current context. The handling may look a little obtuse, but
890  * it's designed this way to avoid a bug with 32-bit GCC/MinGW, which causes
891  * thread-local object destructors to get a junk 'this' pointer. This method
892  * has the benefit of making LocalContext access more efficient since it's a
893  * a plain pointer, with the ThreadContext object used to check it at thread
894  * exit (and given no data fields, 'this' being junk is inconsequential since
895  * it's never accessed).
896  */
897 thread_local ALCcontext *LocalContext{nullptr};
898 class ThreadCtx {
899 public:
~ThreadCtx()900     ~ThreadCtx()
901     {
902         if(ALCcontext *ctx{LocalContext})
903         {
904             const bool result{ctx->releaseIfNoDelete()};
905             ERR("Context %p current for thread being destroyed%s!\n", voidp{ctx},
906                 result ? "" : ", leak detected");
907         }
908     }
909 
set(ALCcontext * ctx) const910     void set(ALCcontext *ctx) const noexcept { LocalContext = ctx; }
911 };
912 thread_local ThreadCtx ThreadContext;
913 
914 /* Process-wide current context */
915 std::atomic<ALCcontext*> GlobalContext{nullptr};
916 
917 /* Flag to trap ALC device errors */
918 bool TrapALCError{false};
919 
920 /* One-time configuration init control */
921 std::once_flag alc_config_once{};
922 
923 /* Default effect that applies to sources that don't have an effect on send 0 */
924 ALeffect DefaultEffect;
925 
926 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
927  * updates.
928  */
929 bool SuspendDefers{true};
930 
931 /* Initial seed for dithering. */
932 constexpr uint DitherRNGSeed{22222u};
933 
934 
935 /************************************************
936  * ALC information
937  ************************************************/
938 constexpr ALCchar alcNoDeviceExtList[] =
939     "ALC_ENUMERATE_ALL_EXT "
940     "ALC_ENUMERATION_EXT "
941     "ALC_EXT_CAPTURE "
942     "ALC_EXT_EFX "
943     "ALC_EXT_thread_local_context "
944     "ALC_SOFT_loopback "
945     "ALC_SOFT_loopback_bformat";
946 constexpr ALCchar alcExtensionList[] =
947     "ALC_ENUMERATE_ALL_EXT "
948     "ALC_ENUMERATION_EXT "
949     "ALC_EXT_CAPTURE "
950     "ALC_EXT_DEDICATED "
951     "ALC_EXT_disconnect "
952     "ALC_EXT_EFX "
953     "ALC_EXT_thread_local_context "
954     "ALC_SOFT_device_clock "
955     "ALC_SOFT_HRTF "
956     "ALC_SOFT_loopback "
957     "ALC_SOFT_loopback_bformat "
958     "ALC_SOFT_output_limiter "
959     "ALC_SOFT_pause_device";
960 constexpr int alcMajorVersion{1};
961 constexpr int alcMinorVersion{1};
962 
963 constexpr int alcEFXMajorVersion{1};
964 constexpr int alcEFXMinorVersion{0};
965 
966 
967 /* To avoid extraneous allocations, a 0-sized FlexArray<ALCcontext*> is defined
968  * globally as a sharable object.
969  */
970 al::FlexArray<ALCcontext*> EmptyContextArray{0u};
971 
972 
973 using DeviceRef = al::intrusive_ptr<ALCdevice>;
974 
975 
976 /************************************************
977  * Device lists
978  ************************************************/
979 al::vector<ALCdevice*> DeviceList;
980 al::vector<ALCcontext*> ContextList;
981 
982 std::recursive_mutex ListLock;
983 
984 
alc_initconfig(void)985 void alc_initconfig(void)
986 {
987     if(auto loglevel = al::getenv("ALSOFT_LOGLEVEL"))
988     {
989         long lvl = strtol(loglevel->c_str(), nullptr, 0);
990         if(lvl >= static_cast<long>(LogLevel::Trace))
991             gLogLevel = LogLevel::Trace;
992         else if(lvl <= static_cast<long>(LogLevel::Disable))
993             gLogLevel = LogLevel::Disable;
994         else
995             gLogLevel = static_cast<LogLevel>(lvl);
996     }
997 
998 #ifdef _WIN32
999     if(const auto logfile = al::getenv(L"ALSOFT_LOGFILE"))
1000     {
1001         FILE *logf{_wfopen(logfile->c_str(), L"wt")};
1002         if(logf) gLogFile = logf;
1003         else
1004         {
1005             auto u8name = wstr_to_utf8(logfile->c_str());
1006             ERR("Failed to open log file '%s'\n", u8name.c_str());
1007         }
1008     }
1009 #else
1010     if(const auto logfile = al::getenv("ALSOFT_LOGFILE"))
1011     {
1012         FILE *logf{fopen(logfile->c_str(), "wt")};
1013         if(logf) gLogFile = logf;
1014         else ERR("Failed to open log file '%s'\n", logfile->c_str());
1015     }
1016 #endif
1017 
1018     TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION, ALSOFT_GIT_COMMIT_HASH,
1019         ALSOFT_GIT_BRANCH);
1020     {
1021         al::string names;
1022         if(al::size(BackendList) < 1)
1023             names = "(none)";
1024         else
1025         {
1026             const al::span<const BackendInfo> infos{BackendList};
1027             names = infos[0].name;
1028             for(const auto &backend : infos.subspan<1>())
1029             {
1030                 names += ", ";
1031                 names += backend.name;
1032             }
1033         }
1034         TRACE("Supported backends: %s\n", names.c_str());
1035     }
1036     ReadALConfig();
1037 
1038     if(auto suspendmode = al::getenv("__ALSOFT_SUSPEND_CONTEXT"))
1039     {
1040         if(al::strcasecmp(suspendmode->c_str(), "ignore") == 0)
1041         {
1042             SuspendDefers = false;
1043             TRACE("Selected context suspend behavior, \"ignore\"\n");
1044         }
1045         else
1046             ERR("Unhandled context suspend behavior setting: \"%s\"\n", suspendmode->c_str());
1047     }
1048 
1049     int capfilter{0};
1050 #if defined(HAVE_SSE4_1)
1051     capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
1052 #elif defined(HAVE_SSE3)
1053     capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
1054 #elif defined(HAVE_SSE2)
1055     capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
1056 #elif defined(HAVE_SSE)
1057     capfilter |= CPU_CAP_SSE;
1058 #endif
1059 #ifdef HAVE_NEON
1060     capfilter |= CPU_CAP_NEON;
1061 #endif
1062     if(auto cpuopt = ConfigValueStr(nullptr, nullptr, "disable-cpu-exts"))
1063     {
1064         const char *str{cpuopt->c_str()};
1065         if(al::strcasecmp(str, "all") == 0)
1066             capfilter = 0;
1067         else
1068         {
1069             const char *next = str;
1070             do {
1071                 str = next;
1072                 while(isspace(str[0]))
1073                     str++;
1074                 next = strchr(str, ',');
1075 
1076                 if(!str[0] || str[0] == ',')
1077                     continue;
1078 
1079                 size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1080                 while(len > 0 && isspace(str[len-1]))
1081                     len--;
1082                 if(len == 3 && al::strncasecmp(str, "sse", len) == 0)
1083                     capfilter &= ~CPU_CAP_SSE;
1084                 else if(len == 4 && al::strncasecmp(str, "sse2", len) == 0)
1085                     capfilter &= ~CPU_CAP_SSE2;
1086                 else if(len == 4 && al::strncasecmp(str, "sse3", len) == 0)
1087                     capfilter &= ~CPU_CAP_SSE3;
1088                 else if(len == 6 && al::strncasecmp(str, "sse4.1", len) == 0)
1089                     capfilter &= ~CPU_CAP_SSE4_1;
1090                 else if(len == 4 && al::strncasecmp(str, "neon", len) == 0)
1091                     capfilter &= ~CPU_CAP_NEON;
1092                 else
1093                     WARN("Invalid CPU extension \"%s\"\n", str);
1094             } while(next++);
1095         }
1096     }
1097     if(auto cpuopt = GetCPUInfo())
1098     {
1099         if(!cpuopt->mVendor.empty() || !cpuopt->mName.empty())
1100         {
1101             TRACE("Vendor ID: \"%s\"\n", cpuopt->mVendor.c_str());
1102             TRACE("Name: \"%s\"\n", cpuopt->mName.c_str());
1103         }
1104         const int caps{cpuopt->mCaps};
1105         TRACE("Extensions:%s%s%s%s%s%s\n",
1106             ((capfilter&CPU_CAP_SSE)    ? ((caps&CPU_CAP_SSE)    ? " +SSE"    : " -SSE")    : ""),
1107             ((capfilter&CPU_CAP_SSE2)   ? ((caps&CPU_CAP_SSE2)   ? " +SSE2"   : " -SSE2")   : ""),
1108             ((capfilter&CPU_CAP_SSE3)   ? ((caps&CPU_CAP_SSE3)   ? " +SSE3"   : " -SSE3")   : ""),
1109             ((capfilter&CPU_CAP_SSE4_1) ? ((caps&CPU_CAP_SSE4_1) ? " +SSE4.1" : " -SSE4.1") : ""),
1110             ((capfilter&CPU_CAP_NEON)   ? ((caps&CPU_CAP_NEON)   ? " +NEON"   : " -NEON")   : ""),
1111             ((!capfilter) ? " -none-" : ""));
1112         CPUCapFlags = caps & capfilter;
1113     }
1114 
1115     if(auto priopt = ConfigValueInt(nullptr, nullptr, "rt-prio"))
1116         RTPrioLevel = *priopt;
1117 
1118     aluInit();
1119     aluInitMixer();
1120 
1121     auto traperr = al::getenv("ALSOFT_TRAP_ERROR");
1122     if(traperr && (al::strcasecmp(traperr->c_str(), "true") == 0
1123             || std::strtol(traperr->c_str(), nullptr, 0) == 1))
1124     {
1125         TrapALError  = true;
1126         TrapALCError = true;
1127     }
1128     else
1129     {
1130         traperr = al::getenv("ALSOFT_TRAP_AL_ERROR");
1131         if(traperr)
1132             TrapALError = al::strcasecmp(traperr->c_str(), "true") == 0
1133                 || strtol(traperr->c_str(), nullptr, 0) == 1;
1134         else
1135             TrapALError = !!GetConfigValueBool(nullptr, nullptr, "trap-al-error", false);
1136 
1137         traperr = al::getenv("ALSOFT_TRAP_ALC_ERROR");
1138         if(traperr)
1139             TrapALCError = al::strcasecmp(traperr->c_str(), "true") == 0
1140                 || strtol(traperr->c_str(), nullptr, 0) == 1;
1141         else
1142             TrapALCError = !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", false);
1143     }
1144 
1145     if(auto boostopt = ConfigValueFloat(nullptr, "reverb", "boost"))
1146     {
1147         const float valf{std::isfinite(*boostopt) ? clampf(*boostopt, -24.0f, 24.0f) : 0.0f};
1148         ReverbBoost *= std::pow(10.0f, valf / 20.0f);
1149     }
1150 
1151     auto BackendListEnd = std::end(BackendList);
1152     auto devopt = al::getenv("ALSOFT_DRIVERS");
1153     if(devopt || (devopt=ConfigValueStr(nullptr, nullptr, "drivers")))
1154     {
1155         auto backendlist_cur = std::begin(BackendList);
1156 
1157         bool endlist{true};
1158         const char *next{devopt->c_str()};
1159         do {
1160             const char *devs{next};
1161             while(isspace(devs[0]))
1162                 devs++;
1163             next = strchr(devs, ',');
1164 
1165             const bool delitem{devs[0] == '-'};
1166             if(devs[0] == '-') devs++;
1167 
1168             if(!devs[0] || devs[0] == ',')
1169             {
1170                 endlist = false;
1171                 continue;
1172             }
1173             endlist = true;
1174 
1175             size_t len{next ? (static_cast<size_t>(next-devs)) : strlen(devs)};
1176             while(len > 0 && isspace(devs[len-1])) --len;
1177 #ifdef HAVE_WASAPI
1178             /* HACK: For backwards compatibility, convert backend references of
1179              * mmdevapi to wasapi. This should eventually be removed.
1180              */
1181             if(len == 8 && strncmp(devs, "mmdevapi", len) == 0)
1182             {
1183                 devs = "wasapi";
1184                 len = 6;
1185             }
1186 #endif
1187 
1188             auto find_backend = [devs,len](const BackendInfo &backend) -> bool
1189             { return len == strlen(backend.name) && strncmp(backend.name, devs, len) == 0; };
1190             auto this_backend = std::find_if(std::begin(BackendList), BackendListEnd,
1191                 find_backend);
1192 
1193             if(this_backend == BackendListEnd)
1194                 continue;
1195 
1196             if(delitem)
1197                 BackendListEnd = std::move(this_backend+1, BackendListEnd, this_backend);
1198             else
1199                 backendlist_cur = std::rotate(backendlist_cur, this_backend, this_backend+1);
1200         } while(next++);
1201 
1202         if(endlist)
1203             BackendListEnd = backendlist_cur;
1204     }
1205 
1206     auto init_backend = [](BackendInfo &backend) -> void
1207     {
1208         if(PlaybackFactory && CaptureFactory)
1209             return;
1210 
1211         BackendFactory &factory = backend.getFactory();
1212         if(!factory.init())
1213         {
1214             WARN("Failed to initialize backend \"%s\"\n", backend.name);
1215             return;
1216         }
1217 
1218         TRACE("Initialized backend \"%s\"\n", backend.name);
1219         if(!PlaybackFactory && factory.querySupport(BackendType::Playback))
1220         {
1221             PlaybackFactory = &factory;
1222             TRACE("Added \"%s\" for playback\n", backend.name);
1223         }
1224         if(!CaptureFactory && factory.querySupport(BackendType::Capture))
1225         {
1226             CaptureFactory = &factory;
1227             TRACE("Added \"%s\" for capture\n", backend.name);
1228         }
1229     };
1230     std::for_each(std::begin(BackendList), BackendListEnd, init_backend);
1231 
1232     LoopbackBackendFactory::getFactory().init();
1233 
1234     if(!PlaybackFactory)
1235         WARN("No playback backend available!\n");
1236     if(!CaptureFactory)
1237         WARN("No capture backend available!\n");
1238 
1239     if(auto exclopt = ConfigValueStr(nullptr, nullptr, "excludefx"))
1240     {
1241         const char *next{exclopt->c_str()};
1242         do {
1243             const char *str{next};
1244             next = strchr(str, ',');
1245 
1246             if(!str[0] || next == str)
1247                 continue;
1248 
1249             size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1250             for(const EffectList &effectitem : gEffectList)
1251             {
1252                 if(len == strlen(effectitem.name) &&
1253                    strncmp(effectitem.name, str, len) == 0)
1254                     DisabledEffects[effectitem.type] = true;
1255             }
1256         } while(next++);
1257     }
1258 
1259     InitEffect(&DefaultEffect);
1260     auto defrevopt = al::getenv("ALSOFT_DEFAULT_REVERB");
1261     if(defrevopt || (defrevopt=ConfigValueStr(nullptr, nullptr, "default-reverb")))
1262         LoadReverbPreset(defrevopt->c_str(), &DefaultEffect);
1263 }
1264 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1265 
1266 
1267 /************************************************
1268  * Device enumeration
1269  ************************************************/
ProbeAllDevicesList()1270 void ProbeAllDevicesList()
1271 {
1272     DO_INITCONFIG();
1273 
1274     std::lock_guard<std::recursive_mutex> _{ListLock};
1275     if(!PlaybackFactory)
1276         decltype(alcAllDevicesList){}.swap(alcAllDevicesList);
1277     else
1278     {
1279         std::string names{PlaybackFactory->probe(BackendType::Playback)};
1280         if(names.empty()) names += '\0';
1281         names.swap(alcAllDevicesList);
1282     }
1283 }
ProbeCaptureDeviceList()1284 void ProbeCaptureDeviceList()
1285 {
1286     DO_INITCONFIG();
1287 
1288     std::lock_guard<std::recursive_mutex> _{ListLock};
1289     if(!CaptureFactory)
1290         decltype(alcCaptureDeviceList){}.swap(alcCaptureDeviceList);
1291     else
1292     {
1293         std::string names{CaptureFactory->probe(BackendType::Capture)};
1294         if(names.empty()) names += '\0';
1295         names.swap(alcCaptureDeviceList);
1296     }
1297 }
1298 
1299 } // namespace
1300 
1301 /* Mixing thread piority level */
1302 int RTPrioLevel{1};
1303 
1304 FILE *gLogFile{stderr};
1305 #ifdef _DEBUG
1306 LogLevel gLogLevel{LogLevel::Warning};
1307 #else
1308 LogLevel gLogLevel{LogLevel::Error};
1309 #endif
1310 
1311 /************************************************
1312  * Library initialization
1313  ************************************************/
1314 #if defined(_WIN32) && !defined(AL_LIBTYPE_STATIC)
DllMain(HINSTANCE module,DWORD reason,LPVOID)1315 BOOL APIENTRY DllMain(HINSTANCE module, DWORD reason, LPVOID /*reserved*/)
1316 {
1317     switch(reason)
1318     {
1319     case DLL_PROCESS_ATTACH:
1320         /* Pin the DLL so we won't get unloaded until the process terminates */
1321         GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
1322             reinterpret_cast<WCHAR*>(module), &module);
1323         break;
1324     }
1325     return TRUE;
1326 }
1327 #endif
1328 
1329 /************************************************
1330  * Device format information
1331  ************************************************/
1332 namespace {
1333 
1334 struct DevFmtPair { DevFmtChannels chans; DevFmtType type; };
DecomposeDevFormat(ALenum format)1335 al::optional<DevFmtPair> DecomposeDevFormat(ALenum format)
1336 {
1337     static const struct {
1338         ALenum format;
1339         DevFmtChannels channels;
1340         DevFmtType type;
1341     } list[] = {
1342         { AL_FORMAT_MONO8,        DevFmtMono, DevFmtUByte },
1343         { AL_FORMAT_MONO16,       DevFmtMono, DevFmtShort },
1344         { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1345 
1346         { AL_FORMAT_STEREO8,        DevFmtStereo, DevFmtUByte },
1347         { AL_FORMAT_STEREO16,       DevFmtStereo, DevFmtShort },
1348         { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1349 
1350         { AL_FORMAT_QUAD8,  DevFmtQuad, DevFmtUByte },
1351         { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1352         { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1353 
1354         { AL_FORMAT_51CHN8,  DevFmtX51, DevFmtUByte },
1355         { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1356         { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1357 
1358         { AL_FORMAT_61CHN8,  DevFmtX61, DevFmtUByte },
1359         { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1360         { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1361 
1362         { AL_FORMAT_71CHN8,  DevFmtX71, DevFmtUByte },
1363         { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1364         { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1365     };
1366 
1367     for(const auto &item : list)
1368     {
1369         if(item.format == format)
1370             return al::make_optional(DevFmtPair{item.channels, item.type});
1371     }
1372 
1373     return al::nullopt;
1374 }
1375 
DevFmtTypeFromEnum(ALCenum type)1376 al::optional<DevFmtType> DevFmtTypeFromEnum(ALCenum type)
1377 {
1378     switch(type)
1379     {
1380     case ALC_BYTE_SOFT: return al::make_optional(DevFmtByte);
1381     case ALC_UNSIGNED_BYTE_SOFT: return al::make_optional(DevFmtUByte);
1382     case ALC_SHORT_SOFT: return al::make_optional(DevFmtShort);
1383     case ALC_UNSIGNED_SHORT_SOFT: return al::make_optional(DevFmtUShort);
1384     case ALC_INT_SOFT: return al::make_optional(DevFmtInt);
1385     case ALC_UNSIGNED_INT_SOFT: return al::make_optional(DevFmtUInt);
1386     case ALC_FLOAT_SOFT: return al::make_optional(DevFmtFloat);
1387     }
1388     WARN("Unsupported format type: 0x%04x\n", type);
1389     return al::nullopt;
1390 }
EnumFromDevFmt(DevFmtType type)1391 ALCenum EnumFromDevFmt(DevFmtType type)
1392 {
1393     switch(type)
1394     {
1395     case DevFmtByte: return ALC_BYTE_SOFT;
1396     case DevFmtUByte: return ALC_UNSIGNED_BYTE_SOFT;
1397     case DevFmtShort: return ALC_SHORT_SOFT;
1398     case DevFmtUShort: return ALC_UNSIGNED_SHORT_SOFT;
1399     case DevFmtInt: return ALC_INT_SOFT;
1400     case DevFmtUInt: return ALC_UNSIGNED_INT_SOFT;
1401     case DevFmtFloat: return ALC_FLOAT_SOFT;
1402     }
1403     throw std::runtime_error{"Invalid DevFmtType: "+std::to_string(int(type))};
1404 }
1405 
DevFmtChannelsFromEnum(ALCenum channels)1406 al::optional<DevFmtChannels> DevFmtChannelsFromEnum(ALCenum channels)
1407 {
1408     switch(channels)
1409     {
1410     case ALC_MONO_SOFT: return al::make_optional(DevFmtMono);
1411     case ALC_STEREO_SOFT: return al::make_optional(DevFmtStereo);
1412     case ALC_QUAD_SOFT: return al::make_optional(DevFmtQuad);
1413     case ALC_5POINT1_SOFT: return al::make_optional(DevFmtX51);
1414     case ALC_6POINT1_SOFT: return al::make_optional(DevFmtX61);
1415     case ALC_7POINT1_SOFT: return al::make_optional(DevFmtX71);
1416     case ALC_BFORMAT3D_SOFT: return al::make_optional(DevFmtAmbi3D);
1417     }
1418     WARN("Unsupported format channels: 0x%04x\n", channels);
1419     return al::nullopt;
1420 }
EnumFromDevFmt(DevFmtChannels channels)1421 ALCenum EnumFromDevFmt(DevFmtChannels channels)
1422 {
1423     switch(channels)
1424     {
1425     case DevFmtMono: return ALC_MONO_SOFT;
1426     case DevFmtStereo: return ALC_STEREO_SOFT;
1427     case DevFmtQuad: return ALC_QUAD_SOFT;
1428     case DevFmtX51: /* fall-through */
1429     case DevFmtX51Rear: return ALC_5POINT1_SOFT;
1430     case DevFmtX61: return ALC_6POINT1_SOFT;
1431     case DevFmtX71: return ALC_7POINT1_SOFT;
1432     case DevFmtAmbi3D: return ALC_BFORMAT3D_SOFT;
1433     }
1434     throw std::runtime_error{"Invalid DevFmtChannels: "+std::to_string(int(channels))};
1435 }
1436 
DevAmbiLayoutFromEnum(ALCenum layout)1437 al::optional<DevAmbiLayout> DevAmbiLayoutFromEnum(ALCenum layout)
1438 {
1439     switch(layout)
1440     {
1441     case ALC_FUMA_SOFT: return al::make_optional(DevAmbiLayout::FuMa);
1442     case ALC_ACN_SOFT: return al::make_optional(DevAmbiLayout::ACN);
1443     }
1444     WARN("Unsupported ambisonic layout: 0x%04x\n", layout);
1445     return al::nullopt;
1446 }
EnumFromDevAmbi(DevAmbiLayout layout)1447 ALCenum EnumFromDevAmbi(DevAmbiLayout layout)
1448 {
1449     switch(layout)
1450     {
1451     case DevAmbiLayout::FuMa: return ALC_FUMA_SOFT;
1452     case DevAmbiLayout::ACN: return ALC_ACN_SOFT;
1453     }
1454     throw std::runtime_error{"Invalid DevAmbiLayout: "+std::to_string(int(layout))};
1455 }
1456 
DevAmbiScalingFromEnum(ALCenum scaling)1457 al::optional<DevAmbiScaling> DevAmbiScalingFromEnum(ALCenum scaling)
1458 {
1459     switch(scaling)
1460     {
1461     case ALC_FUMA_SOFT: return al::make_optional(DevAmbiScaling::FuMa);
1462     case ALC_SN3D_SOFT: return al::make_optional(DevAmbiScaling::SN3D);
1463     case ALC_N3D_SOFT: return al::make_optional(DevAmbiScaling::N3D);
1464     }
1465     WARN("Unsupported ambisonic scaling: 0x%04x\n", scaling);
1466     return al::nullopt;
1467 }
EnumFromDevAmbi(DevAmbiScaling scaling)1468 ALCenum EnumFromDevAmbi(DevAmbiScaling scaling)
1469 {
1470     switch(scaling)
1471     {
1472     case DevAmbiScaling::FuMa: return ALC_FUMA_SOFT;
1473     case DevAmbiScaling::SN3D: return ALC_SN3D_SOFT;
1474     case DevAmbiScaling::N3D: return ALC_N3D_SOFT;
1475     }
1476     throw std::runtime_error{"Invalid DevAmbiScaling: "+std::to_string(int(scaling))};
1477 }
1478 
1479 
1480 /* Downmixing channel arrays, to map the given format's missing channels to
1481  * existing ones. Based on Wine's DSound downmix values, which are based on
1482  * PulseAudio's.
1483  */
1484 const std::array<InputRemixMap,7> MonoDownmix{{
1485     { FrontLeft,   {{{FrontCenter, 0.5f},      {LFE, 0.0f}}} },
1486     { FrontRight,  {{{FrontCenter, 0.5f},      {LFE, 0.0f}}} },
1487     { SideLeft,    {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1488     { SideRight,   {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1489     { BackLeft,    {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1490     { BackRight,   {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1491     { BackCenter,  {{{FrontCenter, 1.0f/9.0f}, {LFE, 0.0f}}} },
1492 }};
1493 const std::array<InputRemixMap,6> StereoDownmix{{
1494     { FrontCenter, {{{FrontLeft, 0.5f},      {FrontRight, 0.5f}}} },
1495     { SideLeft,    {{{FrontLeft, 1.0f/9.0f}, {FrontRight, 0.0f}}} },
1496     { SideRight,   {{{FrontLeft, 0.0f},      {FrontRight, 1.0f/9.0f}}} },
1497     { BackLeft,    {{{FrontLeft, 1.0f/9.0f}, {FrontRight, 0.0f}}} },
1498     { BackRight,   {{{FrontLeft, 0.0f},      {FrontRight, 1.0f/9.0f}}} },
1499     { BackCenter,  {{{FrontLeft, 0.5f/9.0f}, {FrontRight, 0.5f/9.0f}}} },
1500 }};
1501 const std::array<InputRemixMap,4> QuadDownmix{{
1502     { FrontCenter, {{{FrontLeft,  0.5f}, {FrontRight, 0.5f}}} },
1503     { SideLeft,    {{{FrontLeft,  0.5f}, {BackLeft,   0.5f}}} },
1504     { SideRight,   {{{FrontRight, 0.5f}, {BackRight,  0.5f}}} },
1505     { BackCenter,  {{{BackLeft,   0.5f}, {BackRight,  0.5f}}} },
1506 }};
1507 const std::array<InputRemixMap,3> X51Downmix{{
1508     { BackLeft,   {{{SideLeft, 1.0f}, {SideRight, 0.0f}}} },
1509     { BackRight,  {{{SideLeft, 0.0f}, {SideRight, 1.0f}}} },
1510     { BackCenter, {{{SideLeft, 0.5f}, {SideRight, 0.5f}}} },
1511 }};
1512 const std::array<InputRemixMap,3> X51RearDownmix{{
1513     { SideLeft,   {{{BackLeft, 1.0f}, {BackRight, 0.0f}}} },
1514     { SideRight,  {{{BackLeft, 0.0f}, {BackRight, 1.0f}}} },
1515     { BackCenter, {{{BackLeft, 0.5f}, {BackRight, 0.5f}}} },
1516 }};
1517 const std::array<InputRemixMap,2> X61Downmix{{
1518     { BackLeft,  {{{BackCenter, 0.5f}, {SideLeft,  0.5f}}} },
1519     { BackRight, {{{BackCenter, 0.5f}, {SideRight, 0.5f}}} },
1520 }};
1521 const std::array<InputRemixMap,1> X71Downmix{{
1522     { BackCenter, {{{BackLeft, 0.5f}, {BackRight, 0.5f}}} },
1523 }};
1524 
1525 } // namespace
1526 
1527 /************************************************
1528  * Miscellaneous ALC helpers
1529  ************************************************/
1530 
processUpdates()1531 void ALCcontext::processUpdates()
1532 {
1533     std::lock_guard<std::mutex> _{mPropLock};
1534     if(mDeferUpdates.exchange(false, std::memory_order_acq_rel))
1535     {
1536         /* Tell the mixer to stop applying updates, then wait for any active
1537          * updating to finish, before providing updates.
1538          */
1539         mHoldUpdates.store(true, std::memory_order_release);
1540         while((mUpdateCount.load(std::memory_order_acquire)&1) != 0) {
1541             /* busy-wait */
1542         }
1543 
1544         if(!mPropsClean.test_and_set(std::memory_order_acq_rel))
1545             UpdateContextProps(this);
1546         if(!mListener.PropsClean.test_and_set(std::memory_order_acq_rel))
1547             UpdateListenerProps(this);
1548         UpdateAllEffectSlotProps(this);
1549         UpdateAllSourceProps(this);
1550 
1551         /* Now with all updates declared, let the mixer continue applying them
1552          * so they all happen at once.
1553          */
1554         mHoldUpdates.store(false, std::memory_order_release);
1555     }
1556 }
1557 
1558 
allocVoiceChanges(size_t addcount)1559 void ALCcontext::allocVoiceChanges(size_t addcount)
1560 {
1561     constexpr size_t clustersize{128};
1562     /* Convert element count to cluster count. */
1563     addcount = (addcount+(clustersize-1)) / clustersize;
1564     while(addcount)
1565     {
1566         VoiceChangeCluster cluster{std::make_unique<VoiceChange[]>(clustersize)};
1567         for(size_t i{1};i < clustersize;++i)
1568             cluster[i-1].mNext.store(std::addressof(cluster[i]), std::memory_order_relaxed);
1569         cluster[clustersize-1].mNext.store(mVoiceChangeTail, std::memory_order_relaxed);
1570         mVoiceChangeClusters.emplace_back(std::move(cluster));
1571         mVoiceChangeTail = mVoiceChangeClusters.back().get();
1572         --addcount;
1573     }
1574 }
1575 
allocVoices(size_t addcount)1576 void ALCcontext::allocVoices(size_t addcount)
1577 {
1578     constexpr size_t clustersize{32};
1579     /* Convert element count to cluster count. */
1580     addcount = (addcount+(clustersize-1)) / clustersize;
1581 
1582     if(addcount >= std::numeric_limits<int>::max()/clustersize - mVoiceClusters.size())
1583         throw std::runtime_error{"Allocating too many voices"};
1584     const size_t totalcount{(mVoiceClusters.size()+addcount) * clustersize};
1585     TRACE("Increasing allocated voices to %zu\n", totalcount);
1586 
1587     auto newarray = VoiceArray::Create(totalcount);
1588     while(addcount)
1589     {
1590         mVoiceClusters.emplace_back(std::make_unique<Voice[]>(clustersize));
1591         --addcount;
1592     }
1593 
1594     auto voice_iter = newarray->begin();
1595     for(VoiceCluster &cluster : mVoiceClusters)
1596     {
1597         for(size_t i{0};i < clustersize;++i)
1598             *(voice_iter++) = &cluster[i];
1599     }
1600 
1601     if(auto *oldvoices = mVoices.exchange(newarray.release(), std::memory_order_acq_rel))
1602     {
1603         mDevice->waitForMix();
1604         delete oldvoices;
1605     }
1606 }
1607 
1608 
1609 /** Stores the latest ALC device error. */
alcSetError(ALCdevice * device,ALCenum errorCode)1610 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1611 {
1612     WARN("Error generated on device %p, code 0x%04x\n", voidp{device}, errorCode);
1613     if(TrapALCError)
1614     {
1615 #ifdef _WIN32
1616         /* DebugBreak() will cause an exception if there is no debugger */
1617         if(IsDebuggerPresent())
1618             DebugBreak();
1619 #elif defined(SIGTRAP)
1620         raise(SIGTRAP);
1621 #endif
1622     }
1623 
1624     if(device)
1625         device->LastError.store(errorCode);
1626     else
1627         LastNullDeviceError.store(errorCode);
1628 }
1629 
1630 
CreateDeviceLimiter(const ALCdevice * device,const float threshold)1631 static std::unique_ptr<Compressor> CreateDeviceLimiter(const ALCdevice *device, const float threshold)
1632 {
1633     constexpr bool AutoKnee{true};
1634     constexpr bool AutoAttack{true};
1635     constexpr bool AutoRelease{true};
1636     constexpr bool AutoPostGain{true};
1637     constexpr bool AutoDeclip{true};
1638     constexpr float LookAheadTime{0.001f};
1639     constexpr float HoldTime{0.002f};
1640     constexpr float PreGainDb{0.0f};
1641     constexpr float PostGainDb{0.0f};
1642     constexpr float Ratio{std::numeric_limits<float>::infinity()};
1643     constexpr float KneeDb{0.0f};
1644     constexpr float AttackTime{0.02f};
1645     constexpr float ReleaseTime{0.2f};
1646 
1647     return Compressor::Create(device->RealOut.Buffer.size(), static_cast<float>(device->Frequency),
1648         AutoKnee, AutoAttack, AutoRelease, AutoPostGain, AutoDeclip, LookAheadTime, HoldTime,
1649         PreGainDb, PostGainDb, threshold, Ratio, KneeDb, AttackTime, ReleaseTime);
1650 }
1651 
1652 /**
1653  * Updates the device's base clock time with however many samples have been
1654  * done. This is used so frequency changes on the device don't cause the time
1655  * to jump forward or back. Must not be called while the device is running/
1656  * mixing.
1657  */
UpdateClockBase(ALCdevice * device)1658 static inline void UpdateClockBase(ALCdevice *device)
1659 {
1660     IncrementRef(device->MixCount);
1661     device->ClockBase += nanoseconds{seconds{device->SamplesDone}} / device->Frequency;
1662     device->SamplesDone = 0;
1663     IncrementRef(device->MixCount);
1664 }
1665 
1666 /**
1667  * Updates device parameters according to the attribute list (caller is
1668  * responsible for holding the list lock).
1669  */
UpdateDeviceParams(ALCdevice * device,const int * attrList)1670 static ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
1671 {
1672     HrtfRequestMode hrtf_userreq{Hrtf_Default};
1673     HrtfRequestMode hrtf_appreq{Hrtf_Default};
1674     ALCenum gainLimiter{device->LimiterState};
1675     uint new_sends{device->NumAuxSends};
1676     DevFmtChannels oldChans;
1677     DevFmtType oldType;
1678     int hrtf_id{-1};
1679     uint oldFreq;
1680 
1681     if((!attrList || !attrList[0]) && device->Type == DeviceType::Loopback)
1682     {
1683         WARN("Missing attributes for loopback device\n");
1684         return ALC_INVALID_VALUE;
1685     }
1686 
1687     // Check for attributes
1688     if(attrList && attrList[0])
1689     {
1690         uint numMono{device->NumMonoSources};
1691         uint numStereo{device->NumStereoSources};
1692         uint numSends{device->NumAuxSends};
1693 
1694         al::optional<DevFmtChannels> optchans;
1695         al::optional<DevFmtType> opttype;
1696         al::optional<DevAmbiLayout> optlayout;
1697         al::optional<DevAmbiScaling> optscale;
1698 
1699         uint aorder{0u};
1700         uint freq{0u};
1701 
1702 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1703         size_t attrIdx{0};
1704         while(attrList[attrIdx])
1705         {
1706             switch(attrList[attrIdx])
1707             {
1708             case ALC_FORMAT_CHANNELS_SOFT:
1709                 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, attrList[attrIdx + 1]);
1710                 optchans = DevFmtChannelsFromEnum(attrList[attrIdx + 1]);
1711                 break;
1712 
1713             case ALC_FORMAT_TYPE_SOFT:
1714                 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, attrList[attrIdx + 1]);
1715                 opttype = DevFmtTypeFromEnum(attrList[attrIdx + 1]);
1716                 break;
1717 
1718             case ALC_FREQUENCY:
1719                 freq = static_cast<uint>(attrList[attrIdx + 1]);
1720                 TRACE_ATTR(ALC_FREQUENCY, freq);
1721                 break;
1722 
1723             case ALC_AMBISONIC_LAYOUT_SOFT:
1724                 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, attrList[attrIdx + 1]);
1725                 optlayout = DevAmbiLayoutFromEnum(attrList[attrIdx + 1]);
1726                 break;
1727 
1728             case ALC_AMBISONIC_SCALING_SOFT:
1729                 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, attrList[attrIdx + 1]);
1730                 optscale = DevAmbiScalingFromEnum(attrList[attrIdx + 1]);
1731                 break;
1732 
1733             case ALC_AMBISONIC_ORDER_SOFT:
1734                 aorder = static_cast<uint>(attrList[attrIdx + 1]);
1735                 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1736                 break;
1737 
1738             case ALC_MONO_SOURCES:
1739                 numMono = static_cast<uint>(attrList[attrIdx + 1]);
1740                 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1741                 if(numMono > INT_MAX) numMono = 0;
1742                 break;
1743 
1744             case ALC_STEREO_SOURCES:
1745                 numStereo = static_cast<uint>(attrList[attrIdx + 1]);
1746                 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1747                 if(numStereo > INT_MAX) numStereo = 0;
1748                 break;
1749 
1750             case ALC_MAX_AUXILIARY_SENDS:
1751                 numSends = static_cast<uint>(attrList[attrIdx + 1]);
1752                 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1753                 if(numSends > INT_MAX) numSends = 0;
1754                 else numSends = minu(numSends, MAX_SENDS);
1755                 break;
1756 
1757             case ALC_HRTF_SOFT:
1758                 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1759                 if(attrList[attrIdx + 1] == ALC_FALSE)
1760                     hrtf_appreq = Hrtf_Disable;
1761                 else if(attrList[attrIdx + 1] == ALC_TRUE)
1762                     hrtf_appreq = Hrtf_Enable;
1763                 else
1764                     hrtf_appreq = Hrtf_Default;
1765                 break;
1766 
1767             case ALC_HRTF_ID_SOFT:
1768                 hrtf_id = attrList[attrIdx + 1];
1769                 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1770                 break;
1771 
1772             case ALC_OUTPUT_LIMITER_SOFT:
1773                 gainLimiter = attrList[attrIdx + 1];
1774                 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1775                 break;
1776 
1777             default:
1778                 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1779                     attrList[attrIdx + 1], attrList[attrIdx + 1]);
1780                 break;
1781             }
1782 
1783             attrIdx += 2;
1784         }
1785 #undef TRACE_ATTR
1786 
1787         const bool loopback{device->Type == DeviceType::Loopback};
1788         if(loopback)
1789         {
1790             if(!optchans || !opttype)
1791                 return ALC_INVALID_VALUE;
1792             if(freq < MIN_OUTPUT_RATE || freq > MAX_OUTPUT_RATE)
1793                 return ALC_INVALID_VALUE;
1794             if(*optchans == DevFmtAmbi3D)
1795             {
1796                 if(!optlayout || !optscale)
1797                     return ALC_INVALID_VALUE;
1798                 if(aorder < 1 || aorder > MaxAmbiOrder)
1799                     return ALC_INVALID_VALUE;
1800                 if((*optlayout == DevAmbiLayout::FuMa || *optscale == DevAmbiScaling::FuMa)
1801                     && aorder > 3)
1802                     return ALC_INVALID_VALUE;
1803             }
1804         }
1805 
1806         /* If a context is already running on the device, stop playback so the
1807          * device attributes can be updated.
1808          */
1809         if(device->Flags.test(DeviceRunning))
1810             device->Backend->stop();
1811         device->Flags.reset(DeviceRunning);
1812 
1813         UpdateClockBase(device);
1814 
1815         const char *devname{nullptr};
1816         if(loopback)
1817         {
1818             device->Frequency = freq;
1819             device->FmtChans = *optchans;
1820             device->FmtType = *opttype;
1821             if(device->FmtChans == DevFmtAmbi3D)
1822             {
1823                 device->mAmbiOrder = aorder;
1824                 device->mAmbiLayout = *optlayout;
1825                 device->mAmbiScale = *optscale;
1826             }
1827         }
1828         else
1829         {
1830             devname = device->DeviceName.c_str();
1831 
1832             device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
1833             device->UpdateSize = DEFAULT_UPDATE_SIZE;
1834             device->Frequency = DEFAULT_OUTPUT_RATE;
1835 
1836             freq = ConfigValueUInt(devname, nullptr, "frequency").value_or(freq);
1837             if(freq < 1)
1838                 device->Flags.reset(FrequencyRequest);
1839             else
1840             {
1841                 freq = clampu(freq, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE);
1842 
1843                 const double scale{static_cast<double>(freq) / device->Frequency};
1844                 device->UpdateSize = static_cast<uint>(device->UpdateSize*scale + 0.5);
1845                 device->BufferSize = static_cast<uint>(device->BufferSize*scale + 0.5);
1846 
1847                 device->Frequency = freq;
1848                 device->Flags.set(FrequencyRequest);
1849             }
1850 
1851             if(auto persizeopt = ConfigValueUInt(devname, nullptr, "period_size"))
1852                 device->UpdateSize = clampu(*persizeopt, 64, 8192);
1853 
1854             if(auto peropt = ConfigValueUInt(devname, nullptr, "periods"))
1855                 device->BufferSize = device->UpdateSize * clampu(*peropt, 2, 16);
1856             else
1857                 device->BufferSize = maxu(device->BufferSize, device->UpdateSize*2);
1858         }
1859 
1860         if(numMono > INT_MAX-numStereo)
1861             numMono = INT_MAX-numStereo;
1862         numMono += numStereo;
1863         if(auto srcsopt = ConfigValueUInt(devname, nullptr, "sources"))
1864         {
1865             if(*srcsopt <= 0) numMono = 256;
1866             else numMono = *srcsopt;
1867         }
1868         else
1869             numMono = maxu(numMono, 256);
1870         numStereo = minu(numStereo, numMono);
1871         numMono -= numStereo;
1872         device->SourcesMax = numMono + numStereo;
1873 
1874         device->NumMonoSources = numMono;
1875         device->NumStereoSources = numStereo;
1876 
1877         if(auto sendsopt = ConfigValueInt(devname, nullptr, "sends"))
1878             new_sends = minu(numSends, static_cast<uint>(clampi(*sendsopt, 0, MAX_SENDS)));
1879         else
1880             new_sends = numSends;
1881     }
1882 
1883     if(device->Flags.test(DeviceRunning))
1884         return ALC_NO_ERROR;
1885 
1886     device->AvgSpeakerDist = 0.0f;
1887     device->Uhj_Encoder = nullptr;
1888     device->AmbiDecoder = nullptr;
1889     device->Bs2b = nullptr;
1890     device->PostProcess = nullptr;
1891 
1892     device->Limiter = nullptr;
1893     device->ChannelDelays = nullptr;
1894 
1895     std::fill(std::begin(device->HrtfAccumData), std::end(device->HrtfAccumData), float2{});
1896 
1897     device->Dry.AmbiMap.fill(BFChannelConfig{});
1898     device->Dry.Buffer = {};
1899     std::fill(std::begin(device->NumChannelsPerOrder), std::end(device->NumChannelsPerOrder), 0u);
1900     device->RealOut.RemixMap = {};
1901     device->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
1902     device->RealOut.Buffer = {};
1903     device->MixBuffer.clear();
1904     device->MixBuffer.shrink_to_fit();
1905 
1906     UpdateClockBase(device);
1907     device->FixedLatency = nanoseconds::zero();
1908 
1909     device->DitherDepth = 0.0f;
1910     device->DitherSeed = DitherRNGSeed;
1911 
1912     /*************************************************************************
1913      * Update device format request if HRTF is requested
1914      */
1915     device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
1916     if(device->Type != DeviceType::Loopback)
1917     {
1918         if(auto hrtfopt = ConfigValueStr(device->DeviceName.c_str(), nullptr, "hrtf"))
1919         {
1920             const char *hrtf{hrtfopt->c_str()};
1921             if(al::strcasecmp(hrtf, "true") == 0)
1922                 hrtf_userreq = Hrtf_Enable;
1923             else if(al::strcasecmp(hrtf, "false") == 0)
1924                 hrtf_userreq = Hrtf_Disable;
1925             else if(al::strcasecmp(hrtf, "auto") != 0)
1926                 ERR("Unexpected hrtf value: %s\n", hrtf);
1927         }
1928 
1929         if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
1930         {
1931             device->FmtChans = DevFmtStereo;
1932             device->Flags.set(ChannelsRequest);
1933         }
1934     }
1935 
1936     oldFreq  = device->Frequency;
1937     oldChans = device->FmtChans;
1938     oldType  = device->FmtType;
1939 
1940     TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u / %u buffer\n",
1941         device->Flags.test(ChannelsRequest)?"*":"", DevFmtChannelsString(device->FmtChans),
1942         device->Flags.test(SampleTypeRequest)?"*":"", DevFmtTypeString(device->FmtType),
1943         device->Flags.test(FrequencyRequest)?"*":"", device->Frequency,
1944         device->UpdateSize, device->BufferSize);
1945 
1946     try {
1947         auto backend = device->Backend.get();
1948         if(!backend->reset())
1949             throw al::backend_exception{al::backend_error::DeviceError, "Device reset failure"};
1950     }
1951     catch(std::exception &e) {
1952         device->handleDisconnect("%s", e.what());
1953         return ALC_INVALID_DEVICE;
1954     }
1955 
1956     if(device->FmtChans != oldChans && device->Flags.test(ChannelsRequest))
1957     {
1958         ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1959             DevFmtChannelsString(device->FmtChans));
1960         device->Flags.reset(ChannelsRequest);
1961     }
1962     if(device->FmtType != oldType && device->Flags.test(SampleTypeRequest))
1963     {
1964         ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1965             DevFmtTypeString(device->FmtType));
1966         device->Flags.reset(SampleTypeRequest);
1967     }
1968     if(device->Frequency != oldFreq && device->Flags.test(FrequencyRequest))
1969     {
1970         WARN("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1971         device->Flags.reset(FrequencyRequest);
1972     }
1973 
1974     TRACE("Post-reset: %s, %s, %uhz, %u / %u buffer\n",
1975         DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
1976         device->Frequency, device->UpdateSize, device->BufferSize);
1977 
1978     switch(device->FmtChans)
1979     {
1980     case DevFmtMono: device->RealOut.RemixMap = MonoDownmix; break;
1981     case DevFmtStereo: device->RealOut.RemixMap = StereoDownmix; break;
1982     case DevFmtQuad: device->RealOut.RemixMap = QuadDownmix; break;
1983     case DevFmtX51: device->RealOut.RemixMap = X51Downmix; break;
1984     case DevFmtX51Rear: device->RealOut.RemixMap = X51RearDownmix; break;
1985     case DevFmtX61: device->RealOut.RemixMap = X61Downmix; break;
1986     case DevFmtX71: device->RealOut.RemixMap = X71Downmix; break;
1987     case DevFmtAmbi3D: break;
1988     }
1989 
1990     aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
1991 
1992     device->NumAuxSends = new_sends;
1993     TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
1994         device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
1995         device->AuxiliaryEffectSlotMax, device->NumAuxSends);
1996 
1997     nanoseconds::rep sample_delay{0};
1998     if(device->Uhj_Encoder)
1999         sample_delay += Uhj2Encoder::sFilterSize;
2000     if(device->mHrtfState)
2001         sample_delay += HrtfDirectDelay;
2002     if(auto *ambidec = device->AmbiDecoder.get())
2003     {
2004         if(ambidec->hasStablizer())
2005             sample_delay += FrontStablizer::DelayLength;
2006     }
2007 
2008     if(GetConfigValueBool(device->DeviceName.c_str(), nullptr, "dither", 1))
2009     {
2010         int depth{ConfigValueInt(device->DeviceName.c_str(), nullptr, "dither-depth").value_or(0)};
2011         if(depth <= 0)
2012         {
2013             switch(device->FmtType)
2014             {
2015             case DevFmtByte:
2016             case DevFmtUByte:
2017                 depth = 8;
2018                 break;
2019             case DevFmtShort:
2020             case DevFmtUShort:
2021                 depth = 16;
2022                 break;
2023             case DevFmtInt:
2024             case DevFmtUInt:
2025             case DevFmtFloat:
2026                 break;
2027             }
2028         }
2029 
2030         if(depth > 0)
2031         {
2032             depth = clampi(depth, 2, 24);
2033             device->DitherDepth = std::pow(2.0f, static_cast<float>(depth-1));
2034         }
2035     }
2036     if(!(device->DitherDepth > 0.0f))
2037         TRACE("Dithering disabled\n");
2038     else
2039         TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device->DitherDepth)+0.5f)+1,
2040               device->DitherDepth);
2041 
2042     device->LimiterState = gainLimiter;
2043     if(auto limopt = ConfigValueBool(device->DeviceName.c_str(), nullptr, "output-limiter"))
2044         gainLimiter = *limopt ? ALC_TRUE : ALC_FALSE;
2045 
2046     /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2047      * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2048      * output (where samples must be clamped), and don't for floating-point
2049      * (which can take unclamped samples).
2050      */
2051     if(gainLimiter == ALC_DONT_CARE_SOFT)
2052     {
2053         switch(device->FmtType)
2054         {
2055             case DevFmtByte:
2056             case DevFmtUByte:
2057             case DevFmtShort:
2058             case DevFmtUShort:
2059             case DevFmtInt:
2060             case DevFmtUInt:
2061                 gainLimiter = ALC_TRUE;
2062                 break;
2063             case DevFmtFloat:
2064                 gainLimiter = ALC_FALSE;
2065                 break;
2066         }
2067     }
2068     if(gainLimiter == ALC_FALSE)
2069         TRACE("Output limiter disabled\n");
2070     else
2071     {
2072         float thrshld{1.0f};
2073         switch(device->FmtType)
2074         {
2075             case DevFmtByte:
2076             case DevFmtUByte:
2077                 thrshld = 127.0f / 128.0f;
2078                 break;
2079             case DevFmtShort:
2080             case DevFmtUShort:
2081                 thrshld = 32767.0f / 32768.0f;
2082                 break;
2083             case DevFmtInt:
2084             case DevFmtUInt:
2085             case DevFmtFloat:
2086                 break;
2087         }
2088         if(device->DitherDepth > 0.0f)
2089             thrshld -= 1.0f / device->DitherDepth;
2090 
2091         const float thrshld_dB{std::log10(thrshld) * 20.0f};
2092         auto limiter = CreateDeviceLimiter(device, thrshld_dB);
2093 
2094         sample_delay += limiter->getLookAhead();
2095         device->Limiter = std::move(limiter);
2096         TRACE("Output limiter enabled, %.4fdB limit\n", thrshld_dB);
2097     }
2098 
2099     /* Convert the sample delay from samples to nanosamples to nanoseconds. */
2100     device->FixedLatency += nanoseconds{seconds{sample_delay}} / device->Frequency;
2101     TRACE("Fixed device latency: %" PRId64 "ns\n", int64_t{device->FixedLatency.count()});
2102 
2103     FPUCtl mixer_mode{};
2104     for(ALCcontext *context : *device->mContexts.load())
2105     {
2106         auto GetEffectBuffer = [](ALbuffer *buffer) noexcept -> EffectState::Buffer
2107         {
2108             if(!buffer) return EffectState::Buffer{};
2109             return EffectState::Buffer{buffer, buffer->mData};
2110         };
2111         std::unique_lock<std::mutex> proplock{context->mPropLock};
2112         std::unique_lock<std::mutex> slotlock{context->mEffectSlotLock};
2113 
2114         /* Clear out unused wet buffers. */
2115         auto buffer_not_in_use = [](WetBufferPtr &wetbuffer) noexcept -> bool
2116         { return !wetbuffer->mInUse; };
2117         auto wetbuffer_iter = std::remove_if(context->mWetBuffers.begin(),
2118             context->mWetBuffers.end(), buffer_not_in_use);
2119         context->mWetBuffers.erase(wetbuffer_iter, context->mWetBuffers.end());
2120 
2121         if(ALeffectslot *slot{context->mDefaultSlot.get()})
2122         {
2123             aluInitEffectPanning(&slot->mSlot, context);
2124 
2125             EffectState *state{slot->Effect.State.get()};
2126             state->mOutTarget = device->Dry.Buffer;
2127             state->deviceUpdate(device, GetEffectBuffer(slot->Buffer));
2128             slot->updateProps(context);
2129         }
2130 
2131         if(EffectSlotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_relaxed)})
2132             std::fill_n(curarray->end(), curarray->size(), nullptr);
2133         for(auto &sublist : context->mEffectSlotList)
2134         {
2135             uint64_t usemask{~sublist.FreeMask};
2136             while(usemask)
2137             {
2138                 const int idx{al::countr_zero(usemask)};
2139                 ALeffectslot *slot{sublist.EffectSlots + idx};
2140                 usemask &= ~(1_u64 << idx);
2141 
2142                 aluInitEffectPanning(&slot->mSlot, context);
2143 
2144                 EffectState *state{slot->Effect.State.get()};
2145                 state->mOutTarget = device->Dry.Buffer;
2146                 state->deviceUpdate(device, GetEffectBuffer(slot->Buffer));
2147                 slot->updateProps(context);
2148             }
2149         }
2150         slotlock.unlock();
2151 
2152         const uint num_sends{device->NumAuxSends};
2153         std::unique_lock<std::mutex> srclock{context->mSourceLock};
2154         for(auto &sublist : context->mSourceList)
2155         {
2156             uint64_t usemask{~sublist.FreeMask};
2157             while(usemask)
2158             {
2159                 const int idx{al::countr_zero(usemask)};
2160                 ALsource *source{sublist.Sources + idx};
2161                 usemask &= ~(1_u64 << idx);
2162 
2163                 auto clear_send = [](ALsource::SendData &send) -> void
2164                 {
2165                     if(send.Slot)
2166                         DecrementRef(send.Slot->ref);
2167                     send.Slot = nullptr;
2168                     send.Gain = 1.0f;
2169                     send.GainHF = 1.0f;
2170                     send.HFReference = LOWPASSFREQREF;
2171                     send.GainLF = 1.0f;
2172                     send.LFReference = HIGHPASSFREQREF;
2173                 };
2174                 auto send_begin = source->Send.begin() + static_cast<ptrdiff_t>(num_sends);
2175                 std::for_each(send_begin, source->Send.end(), clear_send);
2176 
2177                 source->PropsClean.clear(std::memory_order_release);
2178             }
2179         }
2180 
2181         /* Clear any pre-existing voice property structs, in case the number of
2182          * auxiliary sends is changing. Active sources will have updates
2183          * respecified in UpdateAllSourceProps.
2184          */
2185         VoicePropsItem *vprops{context->mFreeVoiceProps.exchange(nullptr, std::memory_order_acq_rel)};
2186         while(vprops)
2187         {
2188             VoicePropsItem *next = vprops->next.load(std::memory_order_relaxed);
2189             delete vprops;
2190             vprops = next;
2191         }
2192 
2193         auto voicelist = context->getVoicesSpan();
2194         for(Voice *voice : voicelist)
2195         {
2196             /* Clear extraneous property set sends. */
2197             std::fill(std::begin(voice->mProps.Send)+num_sends, std::end(voice->mProps.Send),
2198                 VoiceProps::SendData{});
2199 
2200             std::fill(voice->mSend.begin()+num_sends, voice->mSend.end(), Voice::TargetData{});
2201             for(auto &chandata : voice->mChans)
2202             {
2203                 std::fill(chandata.mWetParams.begin()+num_sends, chandata.mWetParams.end(),
2204                     SendParams{});
2205             }
2206 
2207             delete voice->mUpdate.exchange(nullptr, std::memory_order_acq_rel);
2208 
2209             /* Force the voice to stopped if it was stopping. */
2210             Voice::State vstate{Voice::Stopping};
2211             voice->mPlayState.compare_exchange_strong(vstate, Voice::Stopped,
2212                 std::memory_order_acquire, std::memory_order_acquire);
2213             if(voice->mSourceID.load(std::memory_order_relaxed) == 0u)
2214                 continue;
2215 
2216             voice->mStep = 0;
2217             voice->mFlags |= VoiceIsFading;
2218 
2219             if(voice->mAmbiOrder && device->mAmbiOrder > voice->mAmbiOrder)
2220             {
2221                 const uint8_t *OrderFromChan{(voice->mFmtChannels == FmtBFormat2D) ?
2222                     AmbiIndex::OrderFrom2DChannel().data() :
2223                     AmbiIndex::OrderFromChannel().data()};
2224 
2225                 const BandSplitter splitter{device->mXOverFreq /
2226                     static_cast<float>(device->Frequency)};
2227 
2228                 const auto scales = BFormatDec::GetHFOrderScales(voice->mAmbiOrder,
2229                     device->mAmbiOrder);
2230                 for(auto &chandata : voice->mChans)
2231                 {
2232                     chandata.mPrevSamples.fill(0.0f);
2233                     chandata.mAmbiScale = scales[*(OrderFromChan++)];
2234                     chandata.mAmbiSplitter = splitter;
2235                     chandata.mDryParams = DirectParams{};
2236                     std::fill_n(chandata.mWetParams.begin(), num_sends, SendParams{});
2237                 }
2238 
2239                 voice->mFlags |= VoiceIsAmbisonic;
2240             }
2241             else
2242             {
2243                 /* Clear previous samples. */
2244                 for(auto &chandata : voice->mChans)
2245                 {
2246                     chandata.mPrevSamples.fill(0.0f);
2247                     chandata.mDryParams = DirectParams{};
2248                     std::fill_n(chandata.mWetParams.begin(), num_sends, SendParams{});
2249                 }
2250 
2251                 voice->mFlags &= ~VoiceIsAmbisonic;
2252             }
2253 
2254             if(device->AvgSpeakerDist > 0.0f)
2255             {
2256                 /* Reinitialize the NFC filters for new parameters. */
2257                 const float w1{SpeedOfSoundMetersPerSec /
2258                     (device->AvgSpeakerDist * static_cast<float>(device->Frequency))};
2259                 for(auto &chandata : voice->mChans)
2260                     chandata.mDryParams.NFCtrlFilter.init(w1);
2261             }
2262         }
2263         srclock.unlock();
2264 
2265         context->mPropsClean.test_and_set(std::memory_order_release);
2266         UpdateContextProps(context);
2267         context->mListener.PropsClean.test_and_set(std::memory_order_release);
2268         UpdateListenerProps(context);
2269         UpdateAllSourceProps(context);
2270     }
2271     mixer_mode.leave();
2272 
2273     if(!device->Flags.test(DevicePaused))
2274     {
2275         try {
2276             auto backend = device->Backend.get();
2277             backend->start();
2278             device->Flags.set(DeviceRunning);
2279         }
2280         catch(al::backend_exception& e) {
2281             device->handleDisconnect("%s", e.what());
2282             return ALC_INVALID_DEVICE;
2283         }
2284     }
2285 
2286     return ALC_NO_ERROR;
2287 }
2288 
2289 
ALCdevice(DeviceType type)2290 ALCdevice::ALCdevice(DeviceType type) : Type{type}, mContexts{&EmptyContextArray}
2291 {
2292 }
2293 
~ALCdevice()2294 ALCdevice::~ALCdevice()
2295 {
2296     TRACE("Freeing device %p\n", voidp{this});
2297 
2298     Backend = nullptr;
2299 
2300     size_t count{std::accumulate(BufferList.cbegin(), BufferList.cend(), size_t{0u},
2301         [](size_t cur, const BufferSubList &sublist) noexcept -> size_t
2302         { return cur + static_cast<uint>(al::popcount(~sublist.FreeMask)); })};
2303     if(count > 0)
2304         WARN("%zu Buffer%s not deleted\n", count, (count==1)?"":"s");
2305 
2306     count = std::accumulate(EffectList.cbegin(), EffectList.cend(), size_t{0u},
2307         [](size_t cur, const EffectSubList &sublist) noexcept -> size_t
2308         { return cur + static_cast<uint>(al::popcount(~sublist.FreeMask)); });
2309     if(count > 0)
2310         WARN("%zu Effect%s not deleted\n", count, (count==1)?"":"s");
2311 
2312     count = std::accumulate(FilterList.cbegin(), FilterList.cend(), size_t{0u},
2313         [](size_t cur, const FilterSubList &sublist) noexcept -> size_t
2314         { return cur + static_cast<uint>(al::popcount(~sublist.FreeMask)); });
2315     if(count > 0)
2316         WARN("%zu Filter%s not deleted\n", count, (count==1)?"":"s");
2317 
2318     mHrtf = nullptr;
2319 
2320     auto *oldarray = mContexts.exchange(nullptr, std::memory_order_relaxed);
2321     if(oldarray != &EmptyContextArray) delete oldarray;
2322 }
2323 
2324 
2325 /** Checks if the device handle is valid, and returns a new reference if so. */
VerifyDevice(ALCdevice * device)2326 static DeviceRef VerifyDevice(ALCdevice *device)
2327 {
2328     std::lock_guard<std::recursive_mutex> _{ListLock};
2329     auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
2330     if(iter != DeviceList.end() && *iter == device)
2331     {
2332         (*iter)->add_ref();
2333         return DeviceRef{*iter};
2334     }
2335     return nullptr;
2336 }
2337 
2338 
ALCcontext(al::intrusive_ptr<ALCdevice> device)2339 ALCcontext::ALCcontext(al::intrusive_ptr<ALCdevice> device) : mDevice{std::move(device)}
2340 {
2341     mPropsClean.test_and_set(std::memory_order_relaxed);
2342 }
2343 
~ALCcontext()2344 ALCcontext::~ALCcontext()
2345 {
2346     TRACE("Freeing context %p\n", voidp{this});
2347 
2348     size_t count{0};
2349     ContextProps *cprops{mParams.ContextUpdate.exchange(nullptr, std::memory_order_relaxed)};
2350     if(cprops)
2351     {
2352         ++count;
2353         delete cprops;
2354     }
2355     cprops = mFreeContextProps.exchange(nullptr, std::memory_order_acquire);
2356     while(cprops)
2357     {
2358         std::unique_ptr<ContextProps> old{cprops};
2359         cprops = old->next.load(std::memory_order_relaxed);
2360         ++count;
2361     }
2362     TRACE("Freed %zu context property object%s\n", count, (count==1)?"":"s");
2363 
2364     count = std::accumulate(mSourceList.cbegin(), mSourceList.cend(), size_t{0u},
2365         [](size_t cur, const SourceSubList &sublist) noexcept -> size_t
2366         { return cur + static_cast<uint>(al::popcount(~sublist.FreeMask)); });
2367     if(count > 0)
2368         WARN("%zu Source%s not deleted\n", count, (count==1)?"":"s");
2369     mSourceList.clear();
2370     mNumSources = 0;
2371 
2372     count = 0;
2373     EffectSlotProps *eprops{mFreeEffectslotProps.exchange(nullptr, std::memory_order_acquire)};
2374     while(eprops)
2375     {
2376         std::unique_ptr<EffectSlotProps> old{eprops};
2377         eprops = old->next.load(std::memory_order_relaxed);
2378         ++count;
2379     }
2380     TRACE("Freed %zu AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2381 
2382     if(EffectSlotArray *curarray{mActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed)})
2383     {
2384         al::destroy_n(curarray->end(), curarray->size());
2385         delete curarray;
2386     }
2387     mDefaultSlot = nullptr;
2388 
2389     count = std::accumulate(mEffectSlotList.cbegin(), mEffectSlotList.cend(), size_t{0u},
2390         [](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t
2391         { return cur + static_cast<uint>(al::popcount(~sublist.FreeMask)); });
2392     if(count > 0)
2393         WARN("%zu AuxiliaryEffectSlot%s not deleted\n", count, (count==1)?"":"s");
2394     mEffectSlotList.clear();
2395     mNumEffectSlots = 0;
2396 
2397     count = 0;
2398     VoicePropsItem *vprops{mFreeVoiceProps.exchange(nullptr, std::memory_order_acquire)};
2399     while(vprops)
2400     {
2401         std::unique_ptr<VoicePropsItem> old{vprops};
2402         vprops = old->next.load(std::memory_order_relaxed);
2403         ++count;
2404     }
2405     TRACE("Freed %zu voice property object%s\n", count, (count==1)?"":"s");
2406 
2407     delete mVoices.exchange(nullptr, std::memory_order_relaxed);
2408 
2409     count = 0;
2410     ListenerProps *lprops{mParams.ListenerUpdate.exchange(nullptr, std::memory_order_relaxed)};
2411     if(lprops)
2412     {
2413         ++count;
2414         delete lprops;
2415     }
2416     lprops = mFreeListenerProps.exchange(nullptr, std::memory_order_acquire);
2417     while(lprops)
2418     {
2419         std::unique_ptr<ListenerProps> old{lprops};
2420         lprops = old->next.load(std::memory_order_relaxed);
2421         ++count;
2422     }
2423     TRACE("Freed %zu listener property object%s\n", count, (count==1)?"":"s");
2424 
2425     if(mAsyncEvents)
2426     {
2427         count = 0;
2428         auto evt_vec = mAsyncEvents->getReadVector();
2429         if(evt_vec.first.len > 0)
2430         {
2431             al::destroy_n(reinterpret_cast<AsyncEvent*>(evt_vec.first.buf), evt_vec.first.len);
2432             count += evt_vec.first.len;
2433         }
2434         if(evt_vec.second.len > 0)
2435         {
2436             al::destroy_n(reinterpret_cast<AsyncEvent*>(evt_vec.second.buf), evt_vec.second.len);
2437             count += evt_vec.second.len;
2438         }
2439         if(count > 0)
2440             TRACE("Destructed %zu orphaned event%s\n", count, (count==1)?"":"s");
2441         mAsyncEvents->readAdvance(count);
2442     }
2443 }
2444 
init()2445 void ALCcontext::init()
2446 {
2447     if(DefaultEffect.type != AL_EFFECT_NULL && mDevice->Type == DeviceType::Playback)
2448     {
2449         mDefaultSlot = std::make_unique<ALeffectslot>();
2450         aluInitEffectPanning(&mDefaultSlot->mSlot, this);
2451     }
2452 
2453     EffectSlotArray *auxslots;
2454     if(!mDefaultSlot)
2455         auxslots = EffectSlot::CreatePtrArray(0);
2456     else
2457     {
2458         auxslots = EffectSlot::CreatePtrArray(1);
2459         (*auxslots)[0] = &mDefaultSlot->mSlot;
2460         mDefaultSlot->mState = SlotState::Playing;
2461     }
2462     mActiveAuxSlots.store(auxslots, std::memory_order_relaxed);
2463 
2464     allocVoiceChanges(1);
2465     {
2466         VoiceChange *cur{mVoiceChangeTail};
2467         while(VoiceChange *next{cur->mNext.load(std::memory_order_relaxed)})
2468             cur = next;
2469         mCurrentVoiceChange.store(cur, std::memory_order_relaxed);
2470     }
2471 
2472     mExtensionList = alExtList;
2473 
2474 
2475     mParams.Matrix = alu::Matrix::Identity();
2476     mParams.Velocity = alu::Vector{};
2477     mParams.Gain = mListener.Gain;
2478     mParams.MetersPerUnit = mListener.mMetersPerUnit;
2479     mParams.DopplerFactor = mDopplerFactor;
2480     mParams.SpeedOfSound = mSpeedOfSound * mDopplerVelocity;
2481     mParams.SourceDistanceModel = mSourceDistanceModel;
2482     mParams.mDistanceModel = mDistanceModel;
2483 
2484 
2485     mAsyncEvents = RingBuffer::Create(511, sizeof(AsyncEvent), false);
2486     StartEventThrd(this);
2487 
2488 
2489     allocVoices(256);
2490     mActiveVoiceCount.store(64, std::memory_order_relaxed);
2491 }
2492 
deinit()2493 bool ALCcontext::deinit()
2494 {
2495     if(LocalContext == this)
2496     {
2497         WARN("%p released while current on thread\n", voidp{this});
2498         ThreadContext.set(nullptr);
2499         release();
2500     }
2501 
2502     ALCcontext *origctx{this};
2503     if(GlobalContext.compare_exchange_strong(origctx, nullptr))
2504         release();
2505 
2506     bool ret{};
2507     /* First make sure this context exists in the device's list. */
2508     auto *oldarray = mDevice->mContexts.load(std::memory_order_acquire);
2509     if(auto toremove = static_cast<size_t>(std::count(oldarray->begin(), oldarray->end(), this)))
2510     {
2511         using ContextArray = al::FlexArray<ALCcontext*>;
2512         auto alloc_ctx_array = [](const size_t count) -> ContextArray*
2513         {
2514             if(count == 0) return &EmptyContextArray;
2515             return ContextArray::Create(count).release();
2516         };
2517         auto *newarray = alloc_ctx_array(oldarray->size() - toremove);
2518 
2519         /* Copy the current/old context handles to the new array, excluding the
2520          * given context.
2521          */
2522         std::copy_if(oldarray->begin(), oldarray->end(), newarray->begin(),
2523             std::bind(std::not_equal_to<ALCcontext*>{}, _1, this));
2524 
2525         /* Store the new context array in the device. Wait for any current mix
2526          * to finish before deleting the old array.
2527          */
2528         mDevice->mContexts.store(newarray);
2529         if(oldarray != &EmptyContextArray)
2530         {
2531             mDevice->waitForMix();
2532             delete oldarray;
2533         }
2534 
2535         ret = !newarray->empty();
2536     }
2537     else
2538         ret = !oldarray->empty();
2539 
2540     StopEventThrd(this);
2541 
2542     return ret;
2543 }
2544 
2545 
2546 /**
2547  * Checks if the given context is valid, returning a new reference to it if so.
2548  */
VerifyContext(ALCcontext * context)2549 static ContextRef VerifyContext(ALCcontext *context)
2550 {
2551     std::lock_guard<std::recursive_mutex> _{ListLock};
2552     auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
2553     if(iter != ContextList.end() && *iter == context)
2554     {
2555         (*iter)->add_ref();
2556         return ContextRef{*iter};
2557     }
2558     return nullptr;
2559 }
2560 
2561 /** Returns a new reference to the currently active context for this thread. */
GetContextRef(void)2562 ContextRef GetContextRef(void)
2563 {
2564     ALCcontext *context{LocalContext};
2565     if(context)
2566         context->add_ref();
2567     else
2568     {
2569         std::lock_guard<std::recursive_mutex> _{ListLock};
2570         context = GlobalContext.load(std::memory_order_acquire);
2571         if(context) context->add_ref();
2572     }
2573     return ContextRef{context};
2574 }
2575 
2576 
2577 /************************************************
2578  * Standard ALC functions
2579  ************************************************/
2580 
alcGetError(ALCdevice * device)2581 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2582 START_API_FUNC
2583 {
2584     DeviceRef dev{VerifyDevice(device)};
2585     if(dev) return dev->LastError.exchange(ALC_NO_ERROR);
2586     return LastNullDeviceError.exchange(ALC_NO_ERROR);
2587 }
2588 END_API_FUNC
2589 
2590 
alcSuspendContext(ALCcontext * context)2591 ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2592 START_API_FUNC
2593 {
2594     if(!SuspendDefers)
2595         return;
2596 
2597     ContextRef ctx{VerifyContext(context)};
2598     if(!ctx)
2599         alcSetError(nullptr, ALC_INVALID_CONTEXT);
2600     else
2601         ctx->deferUpdates();
2602 }
2603 END_API_FUNC
2604 
alcProcessContext(ALCcontext * context)2605 ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context)
2606 START_API_FUNC
2607 {
2608     if(!SuspendDefers)
2609         return;
2610 
2611     ContextRef ctx{VerifyContext(context)};
2612     if(!ctx)
2613         alcSetError(nullptr, ALC_INVALID_CONTEXT);
2614     else
2615         ctx->processUpdates();
2616 }
2617 END_API_FUNC
2618 
2619 
alcGetString(ALCdevice * Device,ALCenum param)2620 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2621 START_API_FUNC
2622 {
2623     const ALCchar *value{nullptr};
2624 
2625     switch(param)
2626     {
2627     case ALC_NO_ERROR:
2628         value = alcNoError;
2629         break;
2630 
2631     case ALC_INVALID_ENUM:
2632         value = alcErrInvalidEnum;
2633         break;
2634 
2635     case ALC_INVALID_VALUE:
2636         value = alcErrInvalidValue;
2637         break;
2638 
2639     case ALC_INVALID_DEVICE:
2640         value = alcErrInvalidDevice;
2641         break;
2642 
2643     case ALC_INVALID_CONTEXT:
2644         value = alcErrInvalidContext;
2645         break;
2646 
2647     case ALC_OUT_OF_MEMORY:
2648         value = alcErrOutOfMemory;
2649         break;
2650 
2651     case ALC_DEVICE_SPECIFIER:
2652         value = alcDefaultName;
2653         break;
2654 
2655     case ALC_ALL_DEVICES_SPECIFIER:
2656         if(DeviceRef dev{VerifyDevice(Device)})
2657             value = dev->DeviceName.c_str();
2658         else
2659         {
2660             ProbeAllDevicesList();
2661             value = alcAllDevicesList.c_str();
2662         }
2663         break;
2664 
2665     case ALC_CAPTURE_DEVICE_SPECIFIER:
2666         if(DeviceRef dev{VerifyDevice(Device)})
2667             value = dev->DeviceName.c_str();
2668         else
2669         {
2670             ProbeCaptureDeviceList();
2671             value = alcCaptureDeviceList.c_str();
2672         }
2673         break;
2674 
2675     /* Default devices are always first in the list */
2676     case ALC_DEFAULT_DEVICE_SPECIFIER:
2677         value = alcDefaultName;
2678         break;
2679 
2680     case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2681         if(alcAllDevicesList.empty())
2682             ProbeAllDevicesList();
2683 
2684         /* Copy first entry as default. */
2685         alcDefaultAllDevicesSpecifier = alcAllDevicesList.c_str();
2686         value = alcDefaultAllDevicesSpecifier.c_str();
2687         break;
2688 
2689     case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2690         if(alcCaptureDeviceList.empty())
2691             ProbeCaptureDeviceList();
2692 
2693         /* Copy first entry as default. */
2694         alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList.c_str();
2695         value = alcCaptureDefaultDeviceSpecifier.c_str();
2696         break;
2697 
2698     case ALC_EXTENSIONS:
2699         if(VerifyDevice(Device))
2700             value = alcExtensionList;
2701         else
2702             value = alcNoDeviceExtList;
2703         break;
2704 
2705     case ALC_HRTF_SPECIFIER_SOFT:
2706         if(DeviceRef dev{VerifyDevice(Device)})
2707         {
2708             std::lock_guard<std::mutex> _{dev->StateLock};
2709             value = (dev->mHrtf ? dev->HrtfName.c_str() : "");
2710         }
2711         else
2712             alcSetError(nullptr, ALC_INVALID_DEVICE);
2713         break;
2714 
2715     default:
2716         alcSetError(VerifyDevice(Device).get(), ALC_INVALID_ENUM);
2717         break;
2718     }
2719 
2720     return value;
2721 }
2722 END_API_FUNC
2723 
2724 
NumAttrsForDevice(ALCdevice * device)2725 static inline int NumAttrsForDevice(ALCdevice *device)
2726 {
2727     if(device->Type == DeviceType::Capture) return 9;
2728     if(device->Type != DeviceType::Loopback) return 29;
2729     if(device->FmtChans == DevFmtAmbi3D)
2730         return 35;
2731     return 29;
2732 }
2733 
GetIntegerv(ALCdevice * device,ALCenum param,const al::span<int> values)2734 static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span<int> values)
2735 {
2736     size_t i;
2737 
2738     if(values.empty())
2739     {
2740         alcSetError(device, ALC_INVALID_VALUE);
2741         return 0;
2742     }
2743 
2744     if(!device)
2745     {
2746         switch(param)
2747         {
2748         case ALC_MAJOR_VERSION:
2749             values[0] = alcMajorVersion;
2750             return 1;
2751         case ALC_MINOR_VERSION:
2752             values[0] = alcMinorVersion;
2753             return 1;
2754 
2755         case ALC_EFX_MAJOR_VERSION:
2756             values[0] = alcEFXMajorVersion;
2757             return 1;
2758         case ALC_EFX_MINOR_VERSION:
2759             values[0] = alcEFXMinorVersion;
2760             return 1;
2761         case ALC_MAX_AUXILIARY_SENDS:
2762             values[0] = MAX_SENDS;
2763             return 1;
2764 
2765         case ALC_ATTRIBUTES_SIZE:
2766         case ALC_ALL_ATTRIBUTES:
2767         case ALC_FREQUENCY:
2768         case ALC_REFRESH:
2769         case ALC_SYNC:
2770         case ALC_MONO_SOURCES:
2771         case ALC_STEREO_SOURCES:
2772         case ALC_CAPTURE_SAMPLES:
2773         case ALC_FORMAT_CHANNELS_SOFT:
2774         case ALC_FORMAT_TYPE_SOFT:
2775         case ALC_AMBISONIC_LAYOUT_SOFT:
2776         case ALC_AMBISONIC_SCALING_SOFT:
2777         case ALC_AMBISONIC_ORDER_SOFT:
2778         case ALC_MAX_AMBISONIC_ORDER_SOFT:
2779             alcSetError(nullptr, ALC_INVALID_DEVICE);
2780             return 0;
2781 
2782         default:
2783             alcSetError(nullptr, ALC_INVALID_ENUM);
2784         }
2785         return 0;
2786     }
2787 
2788     if(device->Type == DeviceType::Capture)
2789     {
2790         switch(param)
2791         {
2792         case ALC_ATTRIBUTES_SIZE:
2793             values[0] = NumAttrsForDevice(device);
2794             return 1;
2795 
2796         case ALC_ALL_ATTRIBUTES:
2797             i = 0;
2798             if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2799                 alcSetError(device, ALC_INVALID_VALUE);
2800             else
2801             {
2802                 std::lock_guard<std::mutex> _{device->StateLock};
2803                 values[i++] = ALC_MAJOR_VERSION;
2804                 values[i++] = alcMajorVersion;
2805                 values[i++] = ALC_MINOR_VERSION;
2806                 values[i++] = alcMinorVersion;
2807                 values[i++] = ALC_CAPTURE_SAMPLES;
2808                 values[i++] = static_cast<int>(device->Backend->availableSamples());
2809                 values[i++] = ALC_CONNECTED;
2810                 values[i++] = device->Connected.load(std::memory_order_relaxed);
2811                 values[i++] = 0;
2812             }
2813             return i;
2814 
2815         case ALC_MAJOR_VERSION:
2816             values[0] = alcMajorVersion;
2817             return 1;
2818         case ALC_MINOR_VERSION:
2819             values[0] = alcMinorVersion;
2820             return 1;
2821 
2822         case ALC_CAPTURE_SAMPLES:
2823             {
2824                 std::lock_guard<std::mutex> _{device->StateLock};
2825                 values[0] = static_cast<int>(device->Backend->availableSamples());
2826             }
2827             return 1;
2828 
2829         case ALC_CONNECTED:
2830             {
2831                 std::lock_guard<std::mutex> _{device->StateLock};
2832                 values[0] = device->Connected.load(std::memory_order_acquire);
2833             }
2834             return 1;
2835 
2836         default:
2837             alcSetError(device, ALC_INVALID_ENUM);
2838         }
2839         return 0;
2840     }
2841 
2842     /* render device */
2843     switch(param)
2844     {
2845     case ALC_ATTRIBUTES_SIZE:
2846         values[0] = NumAttrsForDevice(device);
2847         return 1;
2848 
2849     case ALC_ALL_ATTRIBUTES:
2850         i = 0;
2851         if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2852             alcSetError(device, ALC_INVALID_VALUE);
2853         else
2854         {
2855             std::lock_guard<std::mutex> _{device->StateLock};
2856             values[i++] = ALC_MAJOR_VERSION;
2857             values[i++] = alcMajorVersion;
2858             values[i++] = ALC_MINOR_VERSION;
2859             values[i++] = alcMinorVersion;
2860             values[i++] = ALC_EFX_MAJOR_VERSION;
2861             values[i++] = alcEFXMajorVersion;
2862             values[i++] = ALC_EFX_MINOR_VERSION;
2863             values[i++] = alcEFXMinorVersion;
2864 
2865             values[i++] = ALC_FREQUENCY;
2866             values[i++] = static_cast<int>(device->Frequency);
2867             if(device->Type != DeviceType::Loopback)
2868             {
2869                 values[i++] = ALC_REFRESH;
2870                 values[i++] = static_cast<int>(device->Frequency / device->UpdateSize);
2871 
2872                 values[i++] = ALC_SYNC;
2873                 values[i++] = ALC_FALSE;
2874             }
2875             else
2876             {
2877                 if(device->FmtChans == DevFmtAmbi3D)
2878                 {
2879                     values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
2880                     values[i++] = EnumFromDevAmbi(device->mAmbiLayout);
2881 
2882                     values[i++] = ALC_AMBISONIC_SCALING_SOFT;
2883                     values[i++] = EnumFromDevAmbi(device->mAmbiScale);
2884 
2885                     values[i++] = ALC_AMBISONIC_ORDER_SOFT;
2886                     values[i++] = static_cast<int>(device->mAmbiOrder);
2887                 }
2888 
2889                 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2890                 values[i++] = EnumFromDevFmt(device->FmtChans);
2891 
2892                 values[i++] = ALC_FORMAT_TYPE_SOFT;
2893                 values[i++] = EnumFromDevFmt(device->FmtType);
2894             }
2895 
2896             values[i++] = ALC_MONO_SOURCES;
2897             values[i++] = static_cast<int>(device->NumMonoSources);
2898 
2899             values[i++] = ALC_STEREO_SOURCES;
2900             values[i++] = static_cast<int>(device->NumStereoSources);
2901 
2902             values[i++] = ALC_MAX_AUXILIARY_SENDS;
2903             values[i++] = static_cast<int>(device->NumAuxSends);
2904 
2905             values[i++] = ALC_HRTF_SOFT;
2906             values[i++] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
2907 
2908             values[i++] = ALC_HRTF_STATUS_SOFT;
2909             values[i++] = device->HrtfStatus;
2910 
2911             values[i++] = ALC_OUTPUT_LIMITER_SOFT;
2912             values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
2913 
2914             values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
2915             values[i++] = MaxAmbiOrder;
2916 
2917             values[i++] = 0;
2918         }
2919         return i;
2920 
2921     case ALC_MAJOR_VERSION:
2922         values[0] = alcMajorVersion;
2923         return 1;
2924 
2925     case ALC_MINOR_VERSION:
2926         values[0] = alcMinorVersion;
2927         return 1;
2928 
2929     case ALC_EFX_MAJOR_VERSION:
2930         values[0] = alcEFXMajorVersion;
2931         return 1;
2932 
2933     case ALC_EFX_MINOR_VERSION:
2934         values[0] = alcEFXMinorVersion;
2935         return 1;
2936 
2937     case ALC_FREQUENCY:
2938         values[0] = static_cast<int>(device->Frequency);
2939         return 1;
2940 
2941     case ALC_REFRESH:
2942         if(device->Type == DeviceType::Loopback)
2943         {
2944             alcSetError(device, ALC_INVALID_DEVICE);
2945             return 0;
2946         }
2947         {
2948             std::lock_guard<std::mutex> _{device->StateLock};
2949             values[0] = static_cast<int>(device->Frequency / device->UpdateSize);
2950         }
2951         return 1;
2952 
2953     case ALC_SYNC:
2954         if(device->Type == DeviceType::Loopback)
2955         {
2956             alcSetError(device, ALC_INVALID_DEVICE);
2957             return 0;
2958         }
2959         values[0] = ALC_FALSE;
2960         return 1;
2961 
2962     case ALC_FORMAT_CHANNELS_SOFT:
2963         if(device->Type != DeviceType::Loopback)
2964         {
2965             alcSetError(device, ALC_INVALID_DEVICE);
2966             return 0;
2967         }
2968         values[0] = EnumFromDevFmt(device->FmtChans);
2969         return 1;
2970 
2971     case ALC_FORMAT_TYPE_SOFT:
2972         if(device->Type != DeviceType::Loopback)
2973         {
2974             alcSetError(device, ALC_INVALID_DEVICE);
2975             return 0;
2976         }
2977         values[0] = EnumFromDevFmt(device->FmtType);
2978         return 1;
2979 
2980     case ALC_AMBISONIC_LAYOUT_SOFT:
2981         if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2982         {
2983             alcSetError(device, ALC_INVALID_DEVICE);
2984             return 0;
2985         }
2986         values[0] = EnumFromDevAmbi(device->mAmbiLayout);
2987         return 1;
2988 
2989     case ALC_AMBISONIC_SCALING_SOFT:
2990         if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2991         {
2992             alcSetError(device, ALC_INVALID_DEVICE);
2993             return 0;
2994         }
2995         values[0] = EnumFromDevAmbi(device->mAmbiScale);
2996         return 1;
2997 
2998     case ALC_AMBISONIC_ORDER_SOFT:
2999         if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
3000         {
3001             alcSetError(device, ALC_INVALID_DEVICE);
3002             return 0;
3003         }
3004         values[0] = static_cast<int>(device->mAmbiOrder);
3005         return 1;
3006 
3007     case ALC_MONO_SOURCES:
3008         values[0] = static_cast<int>(device->NumMonoSources);
3009         return 1;
3010 
3011     case ALC_STEREO_SOURCES:
3012         values[0] = static_cast<int>(device->NumStereoSources);
3013         return 1;
3014 
3015     case ALC_MAX_AUXILIARY_SENDS:
3016         values[0] = static_cast<int>(device->NumAuxSends);
3017         return 1;
3018 
3019     case ALC_CONNECTED:
3020         {
3021             std::lock_guard<std::mutex> _{device->StateLock};
3022             values[0] = device->Connected.load(std::memory_order_acquire);
3023         }
3024         return 1;
3025 
3026     case ALC_HRTF_SOFT:
3027         values[0] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
3028         return 1;
3029 
3030     case ALC_HRTF_STATUS_SOFT:
3031         values[0] = device->HrtfStatus;
3032         return 1;
3033 
3034     case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3035         {
3036             std::lock_guard<std::mutex> _{device->StateLock};
3037             device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
3038             values[0] = static_cast<int>(minz(device->HrtfList.size(),
3039                 std::numeric_limits<int>::max()));
3040         }
3041         return 1;
3042 
3043     case ALC_OUTPUT_LIMITER_SOFT:
3044         values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3045         return 1;
3046 
3047     case ALC_MAX_AMBISONIC_ORDER_SOFT:
3048         values[0] = MaxAmbiOrder;
3049         return 1;
3050 
3051     default:
3052         alcSetError(device, ALC_INVALID_ENUM);
3053     }
3054     return 0;
3055 }
3056 
alcGetIntegerv(ALCdevice * device,ALCenum param,ALCsizei size,ALCint * values)3057 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3058 START_API_FUNC
3059 {
3060     DeviceRef dev{VerifyDevice(device)};
3061     if(size <= 0 || values == nullptr)
3062         alcSetError(dev.get(), ALC_INVALID_VALUE);
3063     else
3064         GetIntegerv(dev.get(), param, {values, static_cast<uint>(size)});
3065 }
3066 END_API_FUNC
3067 
alcGetInteger64vSOFT(ALCdevice * device,ALCenum pname,ALCsizei size,ALCint64SOFT * values)3068 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3069 START_API_FUNC
3070 {
3071     DeviceRef dev{VerifyDevice(device)};
3072     if(size <= 0 || values == nullptr)
3073     {
3074         alcSetError(dev.get(), ALC_INVALID_VALUE);
3075         return;
3076     }
3077     if(!dev || dev->Type == DeviceType::Capture)
3078     {
3079         auto ivals = al::vector<int>(static_cast<uint>(size));
3080         size_t got{GetIntegerv(dev.get(), pname, ivals)};
3081         std::copy_n(ivals.begin(), got, values);
3082         return;
3083     }
3084     /* render device */
3085     switch(pname)
3086     {
3087     case ALC_ATTRIBUTES_SIZE:
3088         *values = NumAttrsForDevice(dev.get())+4;
3089         break;
3090 
3091     case ALC_ALL_ATTRIBUTES:
3092         if(size < NumAttrsForDevice(dev.get())+4)
3093             alcSetError(dev.get(), ALC_INVALID_VALUE);
3094         else
3095         {
3096             size_t i{0};
3097             std::lock_guard<std::mutex> _{dev->StateLock};
3098             values[i++] = ALC_FREQUENCY;
3099             values[i++] = dev->Frequency;
3100 
3101             if(dev->Type != DeviceType::Loopback)
3102             {
3103                 values[i++] = ALC_REFRESH;
3104                 values[i++] = dev->Frequency / dev->UpdateSize;
3105 
3106                 values[i++] = ALC_SYNC;
3107                 values[i++] = ALC_FALSE;
3108             }
3109             else
3110             {
3111                 if(dev->FmtChans == DevFmtAmbi3D)
3112                 {
3113                     values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3114                     values[i++] = EnumFromDevAmbi(dev->mAmbiLayout);
3115 
3116                     values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3117                     values[i++] = EnumFromDevAmbi(dev->mAmbiScale);
3118 
3119                     values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3120                     values[i++] = dev->mAmbiOrder;
3121                 }
3122 
3123                 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3124                 values[i++] = EnumFromDevFmt(dev->FmtChans);
3125 
3126                 values[i++] = ALC_FORMAT_TYPE_SOFT;
3127                 values[i++] = EnumFromDevFmt(dev->FmtType);
3128             }
3129 
3130             values[i++] = ALC_MONO_SOURCES;
3131             values[i++] = dev->NumMonoSources;
3132 
3133             values[i++] = ALC_STEREO_SOURCES;
3134             values[i++] = dev->NumStereoSources;
3135 
3136             values[i++] = ALC_MAX_AUXILIARY_SENDS;
3137             values[i++] = dev->NumAuxSends;
3138 
3139             values[i++] = ALC_HRTF_SOFT;
3140             values[i++] = (dev->mHrtf ? ALC_TRUE : ALC_FALSE);
3141 
3142             values[i++] = ALC_HRTF_STATUS_SOFT;
3143             values[i++] = dev->HrtfStatus;
3144 
3145             values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3146             values[i++] = dev->Limiter ? ALC_TRUE : ALC_FALSE;
3147 
3148             ClockLatency clock{GetClockLatency(dev.get())};
3149             values[i++] = ALC_DEVICE_CLOCK_SOFT;
3150             values[i++] = clock.ClockTime.count();
3151 
3152             values[i++] = ALC_DEVICE_LATENCY_SOFT;
3153             values[i++] = clock.Latency.count();
3154 
3155             values[i++] = 0;
3156         }
3157         break;
3158 
3159     case ALC_DEVICE_CLOCK_SOFT:
3160         {
3161             std::lock_guard<std::mutex> _{dev->StateLock};
3162             uint samplecount, refcount;
3163             nanoseconds basecount;
3164             do {
3165                 refcount = dev->waitForMix();
3166                 basecount = dev->ClockBase;
3167                 samplecount = dev->SamplesDone;
3168             } while(refcount != ReadRef(dev->MixCount));
3169             basecount += nanoseconds{seconds{samplecount}} / dev->Frequency;
3170             *values = basecount.count();
3171         }
3172         break;
3173 
3174     case ALC_DEVICE_LATENCY_SOFT:
3175         {
3176             std::lock_guard<std::mutex> _{dev->StateLock};
3177             ClockLatency clock{GetClockLatency(dev.get())};
3178             *values = clock.Latency.count();
3179         }
3180         break;
3181 
3182     case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3183         if(size < 2)
3184             alcSetError(dev.get(), ALC_INVALID_VALUE);
3185         else
3186         {
3187             std::lock_guard<std::mutex> _{dev->StateLock};
3188             ClockLatency clock{GetClockLatency(dev.get())};
3189             values[0] = clock.ClockTime.count();
3190             values[1] = clock.Latency.count();
3191         }
3192         break;
3193 
3194     default:
3195         auto ivals = al::vector<int>(static_cast<uint>(size));
3196         size_t got{GetIntegerv(dev.get(), pname, ivals)};
3197         std::copy_n(ivals.begin(), got, values);
3198         break;
3199     }
3200 }
3201 END_API_FUNC
3202 
3203 
alcIsExtensionPresent(ALCdevice * device,const ALCchar * extName)3204 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3205 START_API_FUNC
3206 {
3207     DeviceRef dev{VerifyDevice(device)};
3208     if(!extName)
3209         alcSetError(dev.get(), ALC_INVALID_VALUE);
3210     else
3211     {
3212         size_t len = strlen(extName);
3213         const char *ptr = (dev ? alcExtensionList : alcNoDeviceExtList);
3214         while(ptr && *ptr)
3215         {
3216             if(al::strncasecmp(ptr, extName, len) == 0 && (ptr[len] == '\0' || isspace(ptr[len])))
3217                 return ALC_TRUE;
3218 
3219             if((ptr=strchr(ptr, ' ')) != nullptr)
3220             {
3221                 do {
3222                     ++ptr;
3223                 } while(isspace(*ptr));
3224             }
3225         }
3226     }
3227     return ALC_FALSE;
3228 }
3229 END_API_FUNC
3230 
3231 
alcGetProcAddress(ALCdevice * device,const ALCchar * funcName)3232 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3233 START_API_FUNC
3234 {
3235     if(!funcName)
3236     {
3237         DeviceRef dev{VerifyDevice(device)};
3238         alcSetError(dev.get(), ALC_INVALID_VALUE);
3239     }
3240     else
3241     {
3242         for(const auto &func : alcFunctions)
3243         {
3244             if(strcmp(func.funcName, funcName) == 0)
3245                 return func.address;
3246         }
3247     }
3248     return nullptr;
3249 }
3250 END_API_FUNC
3251 
3252 
alcGetEnumValue(ALCdevice * device,const ALCchar * enumName)3253 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3254 START_API_FUNC
3255 {
3256     if(!enumName)
3257     {
3258         DeviceRef dev{VerifyDevice(device)};
3259         alcSetError(dev.get(), ALC_INVALID_VALUE);
3260     }
3261     else
3262     {
3263         for(const auto &enm : alcEnumerations)
3264         {
3265             if(strcmp(enm.enumName, enumName) == 0)
3266                 return enm.value;
3267         }
3268     }
3269     return 0;
3270 }
3271 END_API_FUNC
3272 
3273 
alcCreateContext(ALCdevice * device,const ALCint * attrList)3274 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3275 START_API_FUNC
3276 {
3277     /* Explicitly hold the list lock while taking the StateLock in case the
3278      * device is asynchronously destroyed, to ensure this new context is
3279      * properly cleaned up after being made.
3280      */
3281     std::unique_lock<std::recursive_mutex> listlock{ListLock};
3282     DeviceRef dev{VerifyDevice(device)};
3283     if(!dev || dev->Type == DeviceType::Capture || !dev->Connected.load(std::memory_order_relaxed))
3284     {
3285         listlock.unlock();
3286         alcSetError(dev.get(), ALC_INVALID_DEVICE);
3287         return nullptr;
3288     }
3289     std::unique_lock<std::mutex> statelock{dev->StateLock};
3290     listlock.unlock();
3291 
3292     dev->LastError.store(ALC_NO_ERROR);
3293 
3294     ALCenum err{UpdateDeviceParams(dev.get(), attrList)};
3295     if(err != ALC_NO_ERROR)
3296     {
3297         alcSetError(dev.get(), err);
3298         return nullptr;
3299     }
3300 
3301     ContextRef context{new ALCcontext{dev}};
3302     context->init();
3303 
3304     if(auto volopt = ConfigValueFloat(dev->DeviceName.c_str(), nullptr, "volume-adjust"))
3305     {
3306         const float valf{*volopt};
3307         if(!std::isfinite(valf))
3308             ERR("volume-adjust must be finite: %f\n", valf);
3309         else
3310         {
3311             const float db{clampf(valf, -24.0f, 24.0f)};
3312             if(db != valf)
3313                 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3314             context->mGainBoost = std::pow(10.0f, db/20.0f);
3315             TRACE("volume-adjust gain: %f\n", context->mGainBoost);
3316         }
3317     }
3318     UpdateListenerProps(context.get());
3319 
3320     {
3321         using ContextArray = al::FlexArray<ALCcontext*>;
3322 
3323         /* Allocate a new context array, which holds 1 more than the current/
3324          * old array.
3325          */
3326         auto *oldarray = device->mContexts.load();
3327         const size_t newcount{oldarray->size()+1};
3328         std::unique_ptr<ContextArray> newarray{ContextArray::Create(newcount)};
3329 
3330         /* Copy the current/old context handles to the new array, appending the
3331          * new context.
3332          */
3333         auto iter = std::copy(oldarray->begin(), oldarray->end(), newarray->begin());
3334         *iter = context.get();
3335 
3336         /* Store the new context array in the device. Wait for any current mix
3337          * to finish before deleting the old array.
3338          */
3339         dev->mContexts.store(newarray.release());
3340         if(oldarray != &EmptyContextArray)
3341         {
3342             dev->waitForMix();
3343             delete oldarray;
3344         }
3345     }
3346     statelock.unlock();
3347 
3348     {
3349         std::lock_guard<std::recursive_mutex> _{ListLock};
3350         auto iter = std::lower_bound(ContextList.cbegin(), ContextList.cend(), context.get());
3351         ContextList.emplace(iter, context.get());
3352     }
3353 
3354     if(ALeffectslot *slot{context->mDefaultSlot.get()})
3355     {
3356         if(slot->initEffect(&DefaultEffect, context.get()) == AL_NO_ERROR)
3357             slot->updateProps(context.get());
3358         else
3359             ERR("Failed to initialize the default effect\n");
3360     }
3361 
3362     TRACE("Created context %p\n", voidp{context.get()});
3363     return context.release();
3364 }
3365 END_API_FUNC
3366 
alcDestroyContext(ALCcontext * context)3367 ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3368 START_API_FUNC
3369 {
3370     std::unique_lock<std::recursive_mutex> listlock{ListLock};
3371     auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
3372     if(iter == ContextList.end() || *iter != context)
3373     {
3374         listlock.unlock();
3375         alcSetError(nullptr, ALC_INVALID_CONTEXT);
3376         return;
3377     }
3378     /* Hold a reference to this context so it remains valid until the ListLock
3379      * is released.
3380      */
3381     ContextRef ctx{*iter};
3382     ContextList.erase(iter);
3383 
3384     ALCdevice *Device{ctx->mDevice.get()};
3385 
3386     std::lock_guard<std::mutex> _{Device->StateLock};
3387     if(!ctx->deinit() && Device->Flags.test(DeviceRunning))
3388     {
3389         Device->Backend->stop();
3390         Device->Flags.reset(DeviceRunning);
3391     }
3392 }
3393 END_API_FUNC
3394 
3395 
alcGetCurrentContext(void)3396 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3397 START_API_FUNC
3398 {
3399     ALCcontext *Context{LocalContext};
3400     if(!Context) Context = GlobalContext.load();
3401     return Context;
3402 }
3403 END_API_FUNC
3404 
3405 /** Returns the currently active thread-local context. */
alcGetThreadContext(void)3406 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3407 START_API_FUNC
3408 { return LocalContext; }
3409 END_API_FUNC
3410 
alcMakeContextCurrent(ALCcontext * context)3411 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3412 START_API_FUNC
3413 {
3414     /* context must be valid or nullptr */
3415     ContextRef ctx;
3416     if(context)
3417     {
3418         ctx = VerifyContext(context);
3419         if(!ctx)
3420         {
3421             alcSetError(nullptr, ALC_INVALID_CONTEXT);
3422             return ALC_FALSE;
3423         }
3424     }
3425     /* Release this reference (if any) to store it in the GlobalContext
3426      * pointer. Take ownership of the reference (if any) that was previously
3427      * stored there.
3428      */
3429     ctx = ContextRef{GlobalContext.exchange(ctx.release())};
3430 
3431     /* Reset (decrement) the previous global reference by replacing it with the
3432      * thread-local context. Take ownership of the thread-local context
3433      * reference (if any), clearing the storage to null.
3434      */
3435     ctx = ContextRef{LocalContext};
3436     if(ctx) ThreadContext.set(nullptr);
3437     /* Reset (decrement) the previous thread-local reference. */
3438 
3439     return ALC_TRUE;
3440 }
3441 END_API_FUNC
3442 
3443 /** Makes the given context the active context for the current thread. */
alcSetThreadContext(ALCcontext * context)3444 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3445 START_API_FUNC
3446 {
3447     /* context must be valid or nullptr */
3448     ContextRef ctx;
3449     if(context)
3450     {
3451         ctx = VerifyContext(context);
3452         if(!ctx)
3453         {
3454             alcSetError(nullptr, ALC_INVALID_CONTEXT);
3455             return ALC_FALSE;
3456         }
3457     }
3458     /* context's reference count is already incremented */
3459     ContextRef old{LocalContext};
3460     ThreadContext.set(ctx.release());
3461 
3462     return ALC_TRUE;
3463 }
3464 END_API_FUNC
3465 
3466 
alcGetContextsDevice(ALCcontext * Context)3467 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3468 START_API_FUNC
3469 {
3470     ContextRef ctx{VerifyContext(Context)};
3471     if(!ctx)
3472     {
3473         alcSetError(nullptr, ALC_INVALID_CONTEXT);
3474         return nullptr;
3475     }
3476     return ctx->mDevice.get();
3477 }
3478 END_API_FUNC
3479 
3480 
alcOpenDevice(const ALCchar * deviceName)3481 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3482 START_API_FUNC
3483 {
3484     DO_INITCONFIG();
3485 
3486     if(!PlaybackFactory)
3487     {
3488         alcSetError(nullptr, ALC_INVALID_VALUE);
3489         return nullptr;
3490     }
3491 
3492     if(deviceName)
3493     {
3494         if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3495 #ifdef _WIN32
3496             /* Some old Windows apps hardcode these expecting OpenAL to use a
3497              * specific audio API, even when they're not enumerated. Creative's
3498              * router effectively ignores them too.
3499              */
3500             || al::strcasecmp(deviceName, "DirectSound3D") == 0
3501             || al::strcasecmp(deviceName, "DirectSound") == 0
3502             || al::strcasecmp(deviceName, "MMSYSTEM") == 0
3503 #endif
3504             /* Some old Linux apps hardcode configuration strings that were
3505              * supported by the OpenAL SI. We can't really do anything useful
3506              * with them, so just ignore.
3507              */
3508             || (deviceName[0] == '\'' && deviceName[1] == '(')
3509             || al::strcasecmp(deviceName, "openal-soft") == 0)
3510             deviceName = nullptr;
3511     }
3512 
3513     DeviceRef device{new ALCdevice{DeviceType::Playback}};
3514 
3515     /* Set output format */
3516     device->FmtChans = DevFmtChannelsDefault;
3517     device->FmtType = DevFmtTypeDefault;
3518     device->Frequency = DEFAULT_OUTPUT_RATE;
3519     device->UpdateSize = DEFAULT_UPDATE_SIZE;
3520     device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
3521 
3522     device->SourcesMax = 256;
3523     device->AuxiliaryEffectSlotMax = 64;
3524     device->NumAuxSends = DEFAULT_SENDS;
3525 
3526     try {
3527         auto backend = PlaybackFactory->createBackend(device.get(), BackendType::Playback);
3528         std::lock_guard<std::recursive_mutex> _{ListLock};
3529         backend->open(deviceName);
3530         device->Backend = std::move(backend);
3531     }
3532     catch(al::backend_exception &e) {
3533         WARN("Failed to open playback device: %s\n", e.what());
3534         alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory)
3535             ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
3536         return nullptr;
3537     }
3538 
3539     deviceName = device->DeviceName.c_str();
3540     if(auto chanopt = ConfigValueStr(deviceName, nullptr, "channels"))
3541     {
3542         static const struct ChannelMap {
3543             const char name[16];
3544             DevFmtChannels chans;
3545             uint order;
3546         } chanlist[] = {
3547             { "mono",       DevFmtMono,   0 },
3548             { "stereo",     DevFmtStereo, 0 },
3549             { "quad",       DevFmtQuad,   0 },
3550             { "surround51", DevFmtX51,    0 },
3551             { "surround61", DevFmtX61,    0 },
3552             { "surround71", DevFmtX71,    0 },
3553             { "surround51rear", DevFmtX51Rear, 0 },
3554             { "ambi1", DevFmtAmbi3D, 1 },
3555             { "ambi2", DevFmtAmbi3D, 2 },
3556             { "ambi3", DevFmtAmbi3D, 3 },
3557         };
3558 
3559         const ALCchar *fmt{chanopt->c_str()};
3560         auto iter = std::find_if(std::begin(chanlist), std::end(chanlist),
3561             [fmt](const ChannelMap &entry) -> bool
3562             { return al::strcasecmp(entry.name, fmt) == 0; }
3563         );
3564         if(iter == std::end(chanlist))
3565             ERR("Unsupported channels: %s\n", fmt);
3566         else
3567         {
3568             device->FmtChans = iter->chans;
3569             device->mAmbiOrder = iter->order;
3570             device->Flags.set(ChannelsRequest);
3571         }
3572     }
3573     if(auto typeopt = ConfigValueStr(deviceName, nullptr, "sample-type"))
3574     {
3575         static const struct TypeMap {
3576             const char name[16];
3577             DevFmtType type;
3578         } typelist[] = {
3579             { "int8",    DevFmtByte   },
3580             { "uint8",   DevFmtUByte  },
3581             { "int16",   DevFmtShort  },
3582             { "uint16",  DevFmtUShort },
3583             { "int32",   DevFmtInt    },
3584             { "uint32",  DevFmtUInt   },
3585             { "float32", DevFmtFloat  },
3586         };
3587 
3588         const ALCchar *fmt{typeopt->c_str()};
3589         auto iter = std::find_if(std::begin(typelist), std::end(typelist),
3590             [fmt](const TypeMap &entry) -> bool
3591             { return al::strcasecmp(entry.name, fmt) == 0; }
3592         );
3593         if(iter == std::end(typelist))
3594             ERR("Unsupported sample-type: %s\n", fmt);
3595         else
3596         {
3597             device->FmtType = iter->type;
3598             device->Flags.set(SampleTypeRequest);
3599         }
3600     }
3601 
3602     if(uint freq{ConfigValueUInt(deviceName, nullptr, "frequency").value_or(0u)})
3603     {
3604         if(freq < MIN_OUTPUT_RATE || freq > MAX_OUTPUT_RATE)
3605         {
3606             const uint newfreq{clampu(freq, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE)};
3607             ERR("%uhz request clamped to %uhz\n", freq, newfreq);
3608             freq = newfreq;
3609         }
3610         const double scale{static_cast<double>(freq) / device->Frequency};
3611         device->UpdateSize = static_cast<uint>(device->UpdateSize*scale + 0.5);
3612         device->BufferSize = static_cast<uint>(device->BufferSize*scale + 0.5);
3613         device->Frequency = freq;
3614         device->Flags.set(FrequencyRequest);
3615     }
3616 
3617     if(auto persizeopt = ConfigValueUInt(deviceName, nullptr, "period_size"))
3618         device->UpdateSize = clampu(*persizeopt, 64, 8192);
3619 
3620     if(auto peropt = ConfigValueUInt(deviceName, nullptr, "periods"))
3621         device->BufferSize = device->UpdateSize * clampu(*peropt, 2, 16);
3622     else
3623         device->BufferSize = maxu(device->BufferSize, device->UpdateSize*2);
3624 
3625     if(auto srcsmax = ConfigValueUInt(deviceName, nullptr, "sources").value_or(0))
3626         device->SourcesMax = srcsmax;
3627 
3628     if(auto slotsmax = ConfigValueUInt(deviceName, nullptr, "slots").value_or(0))
3629         device->AuxiliaryEffectSlotMax = minu(slotsmax, INT_MAX);
3630 
3631     if(auto sendsopt = ConfigValueInt(deviceName, nullptr, "sends"))
3632         device->NumAuxSends = minu(DEFAULT_SENDS,
3633             static_cast<uint>(clampi(*sendsopt, 0, MAX_SENDS)));
3634 
3635     device->NumStereoSources = 1;
3636     device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3637 
3638     if(auto ambiopt = ConfigValueStr(deviceName, nullptr, "ambi-format"))
3639     {
3640         const ALCchar *fmt{ambiopt->c_str()};
3641         if(al::strcasecmp(fmt, "fuma") == 0)
3642         {
3643             if(device->mAmbiOrder > 3)
3644                 ERR("FuMa is incompatible with %d%s order ambisonics (up to third-order only)\n",
3645                     device->mAmbiOrder,
3646                     (((device->mAmbiOrder%100)/10) == 1) ? "th" :
3647                     ((device->mAmbiOrder%10) == 1) ? "st" :
3648                     ((device->mAmbiOrder%10) == 2) ? "nd" :
3649                     ((device->mAmbiOrder%10) == 3) ? "rd" : "th");
3650             else
3651             {
3652                 device->mAmbiLayout = DevAmbiLayout::FuMa;
3653                 device->mAmbiScale = DevAmbiScaling::FuMa;
3654             }
3655         }
3656         else if(al::strcasecmp(fmt, "ambix") == 0 || al::strcasecmp(fmt, "acn+sn3d") == 0)
3657         {
3658             device->mAmbiLayout = DevAmbiLayout::ACN;
3659             device->mAmbiScale = DevAmbiScaling::SN3D;
3660         }
3661         else if(al::strcasecmp(fmt, "acn+n3d") == 0)
3662         {
3663             device->mAmbiLayout = DevAmbiLayout::ACN;
3664             device->mAmbiScale = DevAmbiScaling::N3D;
3665         }
3666         else
3667             ERR("Unsupported ambi-format: %s\n", fmt);
3668     }
3669 
3670     {
3671         std::lock_guard<std::recursive_mutex> _{ListLock};
3672         auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3673         DeviceList.emplace(iter, device.get());
3674     }
3675 
3676     TRACE("Created device %p, \"%s\"\n", voidp{device.get()}, device->DeviceName.c_str());
3677     return device.release();
3678 }
3679 END_API_FUNC
3680 
alcCloseDevice(ALCdevice * device)3681 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3682 START_API_FUNC
3683 {
3684     std::unique_lock<std::recursive_mutex> listlock{ListLock};
3685     auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3686     if(iter == DeviceList.end() || *iter != device)
3687     {
3688         alcSetError(nullptr, ALC_INVALID_DEVICE);
3689         return ALC_FALSE;
3690     }
3691     if((*iter)->Type == DeviceType::Capture)
3692     {
3693         alcSetError(*iter, ALC_INVALID_DEVICE);
3694         return ALC_FALSE;
3695     }
3696 
3697     /* Erase the device, and any remaining contexts left on it, from their
3698      * respective lists.
3699      */
3700     DeviceRef dev{*iter};
3701     DeviceList.erase(iter);
3702 
3703     std::unique_lock<std::mutex> statelock{dev->StateLock};
3704     al::vector<ContextRef> orphanctxs;
3705     for(ALCcontext *ctx : *dev->mContexts.load())
3706     {
3707         auto ctxiter = std::lower_bound(ContextList.begin(), ContextList.end(), ctx);
3708         if(ctxiter != ContextList.end() && *ctxiter == ctx)
3709         {
3710             orphanctxs.emplace_back(ContextRef{*ctxiter});
3711             ContextList.erase(ctxiter);
3712         }
3713     }
3714     listlock.unlock();
3715 
3716     for(ContextRef &context : orphanctxs)
3717     {
3718         WARN("Releasing orphaned context %p\n", voidp{context.get()});
3719         context->deinit();
3720     }
3721     orphanctxs.clear();
3722 
3723     if(dev->Flags.test(DeviceRunning))
3724         dev->Backend->stop();
3725     dev->Flags.reset(DeviceRunning);
3726 
3727     return ALC_TRUE;
3728 }
3729 END_API_FUNC
3730 
3731 
3732 /************************************************
3733  * ALC capture functions
3734  ************************************************/
alcCaptureOpenDevice(const ALCchar * deviceName,ALCuint frequency,ALCenum format,ALCsizei samples)3735 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3736 START_API_FUNC
3737 {
3738     DO_INITCONFIG();
3739 
3740     if(!CaptureFactory)
3741     {
3742         alcSetError(nullptr, ALC_INVALID_VALUE);
3743         return nullptr;
3744     }
3745 
3746     if(samples <= 0)
3747     {
3748         alcSetError(nullptr, ALC_INVALID_VALUE);
3749         return nullptr;
3750     }
3751 
3752     if(deviceName)
3753     {
3754         if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3755             || al::strcasecmp(deviceName, "openal-soft") == 0)
3756             deviceName = nullptr;
3757     }
3758 
3759     DeviceRef device{new ALCdevice{DeviceType::Capture}};
3760 
3761     auto decompfmt = DecomposeDevFormat(format);
3762     if(!decompfmt)
3763     {
3764         alcSetError(nullptr, ALC_INVALID_ENUM);
3765         return nullptr;
3766     }
3767 
3768     device->Frequency = frequency;
3769     device->FmtChans = decompfmt->chans;
3770     device->FmtType = decompfmt->type;
3771     device->Flags.set(FrequencyRequest);
3772     device->Flags.set(ChannelsRequest);
3773     device->Flags.set(SampleTypeRequest);
3774 
3775     device->UpdateSize = static_cast<uint>(samples);
3776     device->BufferSize = static_cast<uint>(samples);
3777 
3778     try {
3779         TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n",
3780             DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
3781             device->Frequency, device->UpdateSize, device->BufferSize);
3782 
3783         auto backend = CaptureFactory->createBackend(device.get(), BackendType::Capture);
3784         std::lock_guard<std::recursive_mutex> _{ListLock};
3785         backend->open(deviceName);
3786         device->Backend = std::move(backend);
3787     }
3788     catch(al::backend_exception &e) {
3789         WARN("Failed to open capture device: %s\n", e.what());
3790         alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory)
3791             ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
3792         return nullptr;
3793     }
3794 
3795     {
3796         std::lock_guard<std::recursive_mutex> _{ListLock};
3797         auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3798         DeviceList.emplace(iter, device.get());
3799     }
3800 
3801     TRACE("Created capture device %p, \"%s\"\n", voidp{device.get()}, device->DeviceName.c_str());
3802     return device.release();
3803 }
3804 END_API_FUNC
3805 
alcCaptureCloseDevice(ALCdevice * device)3806 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3807 START_API_FUNC
3808 {
3809     std::unique_lock<std::recursive_mutex> listlock{ListLock};
3810     auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3811     if(iter == DeviceList.end() || *iter != device)
3812     {
3813         alcSetError(nullptr, ALC_INVALID_DEVICE);
3814         return ALC_FALSE;
3815     }
3816     if((*iter)->Type != DeviceType::Capture)
3817     {
3818         alcSetError(*iter, ALC_INVALID_DEVICE);
3819         return ALC_FALSE;
3820     }
3821 
3822     DeviceRef dev{*iter};
3823     DeviceList.erase(iter);
3824     listlock.unlock();
3825 
3826     std::lock_guard<std::mutex> _{dev->StateLock};
3827     if(dev->Flags.test(DeviceRunning))
3828         dev->Backend->stop();
3829     dev->Flags.reset(DeviceRunning);
3830 
3831     return ALC_TRUE;
3832 }
3833 END_API_FUNC
3834 
alcCaptureStart(ALCdevice * device)3835 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3836 START_API_FUNC
3837 {
3838     DeviceRef dev{VerifyDevice(device)};
3839     if(!dev || dev->Type != DeviceType::Capture)
3840     {
3841         alcSetError(dev.get(), ALC_INVALID_DEVICE);
3842         return;
3843     }
3844 
3845     std::lock_guard<std::mutex> _{dev->StateLock};
3846     if(!dev->Connected.load(std::memory_order_acquire))
3847         alcSetError(dev.get(), ALC_INVALID_DEVICE);
3848     else if(!dev->Flags.test(DeviceRunning))
3849     {
3850         try {
3851             auto backend = dev->Backend.get();
3852             backend->start();
3853             dev->Flags.set(DeviceRunning);
3854         }
3855         catch(al::backend_exception& e) {
3856             dev->handleDisconnect("%s", e.what());
3857             alcSetError(dev.get(), ALC_INVALID_DEVICE);
3858         }
3859     }
3860 }
3861 END_API_FUNC
3862 
alcCaptureStop(ALCdevice * device)3863 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3864 START_API_FUNC
3865 {
3866     DeviceRef dev{VerifyDevice(device)};
3867     if(!dev || dev->Type != DeviceType::Capture)
3868         alcSetError(dev.get(), ALC_INVALID_DEVICE);
3869     else
3870     {
3871         std::lock_guard<std::mutex> _{dev->StateLock};
3872         if(dev->Flags.test(DeviceRunning))
3873             dev->Backend->stop();
3874         dev->Flags.reset(DeviceRunning);
3875     }
3876 }
3877 END_API_FUNC
3878 
alcCaptureSamples(ALCdevice * device,ALCvoid * buffer,ALCsizei samples)3879 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3880 START_API_FUNC
3881 {
3882     DeviceRef dev{VerifyDevice(device)};
3883     if(!dev || dev->Type != DeviceType::Capture)
3884     {
3885         alcSetError(dev.get(), ALC_INVALID_DEVICE);
3886         return;
3887     }
3888 
3889     if(samples < 0 || (samples > 0 && buffer == nullptr))
3890     {
3891         alcSetError(dev.get(), ALC_INVALID_VALUE);
3892         return;
3893     }
3894     if(samples < 1)
3895         return;
3896 
3897     std::lock_guard<std::mutex> _{dev->StateLock};
3898     BackendBase *backend{dev->Backend.get()};
3899 
3900     const auto usamples = static_cast<uint>(samples);
3901     if(usamples > backend->availableSamples())
3902     {
3903         alcSetError(dev.get(), ALC_INVALID_VALUE);
3904         return;
3905     }
3906 
3907     backend->captureSamples(static_cast<al::byte*>(buffer), usamples);
3908 }
3909 END_API_FUNC
3910 
3911 
3912 /************************************************
3913  * ALC loopback functions
3914  ************************************************/
3915 
3916 /** Open a loopback device, for manual rendering. */
alcLoopbackOpenDeviceSOFT(const ALCchar * deviceName)3917 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3918 START_API_FUNC
3919 {
3920     DO_INITCONFIG();
3921 
3922     /* Make sure the device name, if specified, is us. */
3923     if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3924     {
3925         alcSetError(nullptr, ALC_INVALID_VALUE);
3926         return nullptr;
3927     }
3928 
3929     DeviceRef device{new ALCdevice{DeviceType::Loopback}};
3930 
3931     device->SourcesMax = 256;
3932     device->AuxiliaryEffectSlotMax = 64;
3933     device->NumAuxSends = DEFAULT_SENDS;
3934 
3935     //Set output format
3936     device->BufferSize = 0;
3937     device->UpdateSize = 0;
3938 
3939     device->Frequency = DEFAULT_OUTPUT_RATE;
3940     device->FmtChans = DevFmtChannelsDefault;
3941     device->FmtType = DevFmtTypeDefault;
3942 
3943     if(auto srcsmax = ConfigValueUInt(nullptr, nullptr, "sources").value_or(0))
3944         device->SourcesMax = srcsmax;
3945 
3946     if(auto slotsmax = ConfigValueUInt(nullptr, nullptr, "slots").value_or(0))
3947         device->AuxiliaryEffectSlotMax = minu(slotsmax, INT_MAX);
3948 
3949     if(auto sendsopt = ConfigValueInt(nullptr, nullptr, "sends"))
3950         device->NumAuxSends = minu(DEFAULT_SENDS,
3951             static_cast<uint>(clampi(*sendsopt, 0, MAX_SENDS)));
3952 
3953     device->NumStereoSources = 1;
3954     device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3955 
3956     try {
3957         auto backend = LoopbackBackendFactory::getFactory().createBackend(device.get(),
3958             BackendType::Playback);
3959         backend->open("Loopback");
3960         device->Backend = std::move(backend);
3961     }
3962     catch(al::backend_exception &e) {
3963         WARN("Failed to open loopback device: %s\n", e.what());
3964         alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory)
3965             ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
3966         return nullptr;
3967     }
3968 
3969     {
3970         std::lock_guard<std::recursive_mutex> _{ListLock};
3971         auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3972         DeviceList.emplace(iter, device.get());
3973     }
3974 
3975     TRACE("Created loopback device %p\n", voidp{device.get()});
3976     return device.release();
3977 }
3978 END_API_FUNC
3979 
3980 /**
3981  * Determines if the loopback device supports the given format for rendering.
3982  */
alcIsRenderFormatSupportedSOFT(ALCdevice * device,ALCsizei freq,ALCenum channels,ALCenum type)3983 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3984 START_API_FUNC
3985 {
3986     DeviceRef dev{VerifyDevice(device)};
3987     if(!dev || dev->Type != DeviceType::Loopback)
3988         alcSetError(dev.get(), ALC_INVALID_DEVICE);
3989     else if(freq <= 0)
3990         alcSetError(dev.get(), ALC_INVALID_VALUE);
3991     else
3992     {
3993         if(DevFmtTypeFromEnum(type).has_value() && DevFmtChannelsFromEnum(channels).has_value()
3994             && freq >= MIN_OUTPUT_RATE && freq <= MAX_OUTPUT_RATE)
3995             return ALC_TRUE;
3996     }
3997 
3998     return ALC_FALSE;
3999 }
4000 END_API_FUNC
4001 
4002 /**
4003  * Renders some samples into a buffer, using the format last set by the
4004  * attributes given to alcCreateContext.
4005  */
alcRenderSamplesSOFT(ALCdevice * device,ALCvoid * buffer,ALCsizei samples)4006 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4007 START_API_FUNC
4008 {
4009     DeviceRef dev{VerifyDevice(device)};
4010     if(!dev || dev->Type != DeviceType::Loopback)
4011         alcSetError(dev.get(), ALC_INVALID_DEVICE);
4012     else if(samples < 0 || (samples > 0 && buffer == nullptr))
4013         alcSetError(dev.get(), ALC_INVALID_VALUE);
4014     else
4015         dev->renderSamples(buffer, static_cast<uint>(samples), dev->channelsFromFmt());
4016 }
4017 END_API_FUNC
4018 
4019 
4020 /************************************************
4021  * ALC DSP pause/resume functions
4022  ************************************************/
4023 
4024 /** Pause the DSP to stop audio processing. */
alcDevicePauseSOFT(ALCdevice * device)4025 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4026 START_API_FUNC
4027 {
4028     DeviceRef dev{VerifyDevice(device)};
4029     if(!dev || dev->Type != DeviceType::Playback)
4030         alcSetError(dev.get(), ALC_INVALID_DEVICE);
4031     else
4032     {
4033         std::lock_guard<std::mutex> _{dev->StateLock};
4034         if(dev->Flags.test(DeviceRunning))
4035             dev->Backend->stop();
4036         dev->Flags.reset(DeviceRunning);
4037         dev->Flags.set(DevicePaused);
4038     }
4039 }
4040 END_API_FUNC
4041 
4042 /** Resume the DSP to restart audio processing. */
alcDeviceResumeSOFT(ALCdevice * device)4043 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4044 START_API_FUNC
4045 {
4046     DeviceRef dev{VerifyDevice(device)};
4047     if(!dev || dev->Type != DeviceType::Playback)
4048     {
4049         alcSetError(dev.get(), ALC_INVALID_DEVICE);
4050         return;
4051     }
4052 
4053     std::lock_guard<std::mutex> _{dev->StateLock};
4054     if(!dev->Flags.test(DevicePaused))
4055         return;
4056     dev->Flags.reset(DevicePaused);
4057     if(dev->mContexts.load()->empty())
4058         return;
4059 
4060     try {
4061         auto backend = dev->Backend.get();
4062         backend->start();
4063         dev->Flags.set(DeviceRunning);
4064     }
4065     catch(al::backend_exception& e) {
4066         dev->handleDisconnect("%s", e.what());
4067         alcSetError(dev.get(), ALC_INVALID_DEVICE);
4068     }
4069 }
4070 END_API_FUNC
4071 
4072 
4073 /************************************************
4074  * ALC HRTF functions
4075  ************************************************/
4076 
4077 /** Gets a string parameter at the given index. */
alcGetStringiSOFT(ALCdevice * device,ALCenum paramName,ALCsizei index)4078 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4079 START_API_FUNC
4080 {
4081     DeviceRef dev{VerifyDevice(device)};
4082     if(!dev || dev->Type == DeviceType::Capture)
4083         alcSetError(dev.get(), ALC_INVALID_DEVICE);
4084     else switch(paramName)
4085     {
4086         case ALC_HRTF_SPECIFIER_SOFT:
4087             if(index >= 0 && static_cast<uint>(index) < dev->HrtfList.size())
4088                 return dev->HrtfList[static_cast<uint>(index)].c_str();
4089             alcSetError(dev.get(), ALC_INVALID_VALUE);
4090             break;
4091 
4092         default:
4093             alcSetError(dev.get(), ALC_INVALID_ENUM);
4094             break;
4095     }
4096 
4097     return nullptr;
4098 }
4099 END_API_FUNC
4100 
4101 /** Resets the given device output, using the specified attribute list. */
alcResetDeviceSOFT(ALCdevice * device,const ALCint * attribs)4102 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4103 START_API_FUNC
4104 {
4105     std::unique_lock<std::recursive_mutex> listlock{ListLock};
4106     DeviceRef dev{VerifyDevice(device)};
4107     if(!dev || dev->Type == DeviceType::Capture)
4108     {
4109         listlock.unlock();
4110         alcSetError(dev.get(), ALC_INVALID_DEVICE);
4111         return ALC_FALSE;
4112     }
4113     std::lock_guard<std::mutex> _{dev->StateLock};
4114     listlock.unlock();
4115 
4116     /* Force the backend to stop mixing first since we're resetting. Also reset
4117      * the connected state so lost devices can attempt recover.
4118      */
4119     if(dev->Flags.test(DeviceRunning))
4120         dev->Backend->stop();
4121     dev->Flags.reset(DeviceRunning);
4122     if(!dev->Connected.load(std::memory_order_relaxed))
4123     {
4124         /* Make sure disconnection is finished before continuing on. */
4125         dev->waitForMix();
4126 
4127         for(ALCcontext *ctx : *dev->mContexts.load(std::memory_order_acquire))
4128         {
4129             /* Clear any pending voice changes and reallocate voices to get a
4130              * clean restart.
4131              */
4132             std::lock_guard<std::mutex> __{ctx->mSourceLock};
4133             auto *vchg = ctx->mCurrentVoiceChange.load(std::memory_order_acquire);
4134             while(auto *next = vchg->mNext.load(std::memory_order_acquire))
4135                 vchg = next;
4136             ctx->mCurrentVoiceChange.store(vchg, std::memory_order_release);
4137 
4138             ctx->mVoiceClusters.clear();
4139             ctx->allocVoices(std::max<size_t>(256,
4140                 ctx->mActiveVoiceCount.load(std::memory_order_relaxed)));
4141         }
4142 
4143         dev->Connected.store(true);
4144     }
4145 
4146     ALCenum err{UpdateDeviceParams(dev.get(), attribs)};
4147     if LIKELY(err == ALC_NO_ERROR) return ALC_TRUE;
4148 
4149     alcSetError(dev.get(), err);
4150     return ALC_FALSE;
4151 }
4152 END_API_FUNC
4153