Use one PulseAudio mainloop per device
[openal-soft.git] / alc / alc.cpp
blob7702a147333fdb0a5471e80698c3680f16a2be24
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.
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.
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
21 #include "config.h"
23 #include "version.h"
25 #include <exception>
26 #include <algorithm>
27 #include <array>
28 #include <atomic>
29 #include <cctype>
30 #include <chrono>
31 #include <cinttypes>
32 #include <climits>
33 #include <cmath>
34 #include <csignal>
35 #include <cstdint>
36 #include <cstdio>
37 #include <cstdlib>
38 #include <cstring>
39 #include <functional>
40 #include <iterator>
41 #include <limits>
42 #include <memory>
43 #include <mutex>
44 #include <new>
45 #include <numeric>
46 #include <string>
47 #include <thread>
48 #include <utility>
50 #include "AL/al.h"
51 #include "AL/alc.h"
52 #include "AL/alext.h"
53 #include "AL/efx.h"
55 #include "al/auxeffectslot.h"
56 #include "al/effect.h"
57 #include "al/event.h"
58 #include "al/filter.h"
59 #include "al/listener.h"
60 #include "al/source.h"
61 #include "alcmain.h"
62 #include "albyte.h"
63 #include "alconfig.h"
64 #include "alcontext.h"
65 #include "alexcpt.h"
66 #include "almalloc.h"
67 #include "alnumeric.h"
68 #include "aloptional.h"
69 #include "alspan.h"
70 #include "alstring.h"
71 #include "alu.h"
72 #include "ambidefs.h"
73 #include "atomic.h"
74 #include "bformatdec.h"
75 #include "bs2b.h"
76 #include "compat.h"
77 #include "cpu_caps.h"
78 #include "devformat.h"
79 #include "effects/base.h"
80 #include "filters/nfc.h"
81 #include "filters/splitter.h"
82 #include "fpu_modes.h"
83 #include "hrtf.h"
84 #include "inprogext.h"
85 #include "intrusive_ptr.h"
86 #include "logging.h"
87 #include "mastering.h"
88 #include "opthelpers.h"
89 #include "pragmadefs.h"
90 #include "ringbuffer.h"
91 #include "strutils.h"
92 #include "threads.h"
93 #include "uhjfilter.h"
94 #include "vecmat.h"
95 #include "vector.h"
97 #include "backends/base.h"
98 #include "backends/null.h"
99 #include "backends/loopback.h"
100 #ifdef HAVE_JACK
101 #include "backends/jack.h"
102 #endif
103 #ifdef HAVE_PULSEAUDIO
104 #include "backends/pulseaudio.h"
105 #endif
106 #ifdef HAVE_ALSA
107 #include "backends/alsa.h"
108 #endif
109 #ifdef HAVE_WASAPI
110 #include "backends/wasapi.h"
111 #endif
112 #ifdef HAVE_COREAUDIO
113 #include "backends/coreaudio.h"
114 #endif
115 #ifdef HAVE_OPENSL
116 #include "backends/opensl.h"
117 #endif
118 #ifdef HAVE_SOLARIS
119 #include "backends/solaris.h"
120 #endif
121 #ifdef HAVE_SNDIO
122 #include "backends/sndio.h"
123 #endif
124 #ifdef HAVE_OSS
125 #include "backends/oss.h"
126 #endif
127 #ifdef HAVE_QSA
128 #include "backends/qsa.h"
129 #endif
130 #ifdef HAVE_DSOUND
131 #include "backends/dsound.h"
132 #endif
133 #ifdef HAVE_WINMM
134 #include "backends/winmm.h"
135 #endif
136 #ifdef HAVE_PORTAUDIO
137 #include "backends/portaudio.h"
138 #endif
139 #ifdef HAVE_SDL2
140 #include "backends/sdl2.h"
141 #endif
142 #ifdef HAVE_WAVE
143 #include "backends/wave.h"
144 #endif
147 namespace {
149 using namespace std::placeholders;
150 using std::chrono::seconds;
151 using std::chrono::nanoseconds;
154 /************************************************
155 * Backends
156 ************************************************/
157 struct BackendInfo {
158 const char *name;
159 BackendFactory& (*getFactory)(void);
162 BackendInfo BackendList[] = {
163 #ifdef HAVE_JACK
164 { "jack", JackBackendFactory::getFactory },
165 #endif
166 #ifdef HAVE_PULSEAUDIO
167 { "pulse", PulseBackendFactory::getFactory },
168 #endif
169 #ifdef HAVE_ALSA
170 { "alsa", AlsaBackendFactory::getFactory },
171 #endif
172 #ifdef HAVE_WASAPI
173 { "wasapi", WasapiBackendFactory::getFactory },
174 #endif
175 #ifdef HAVE_COREAUDIO
176 { "core", CoreAudioBackendFactory::getFactory },
177 #endif
178 #ifdef HAVE_OPENSL
179 { "opensl", OSLBackendFactory::getFactory },
180 #endif
181 #ifdef HAVE_SOLARIS
182 { "solaris", SolarisBackendFactory::getFactory },
183 #endif
184 #ifdef HAVE_SNDIO
185 { "sndio", SndIOBackendFactory::getFactory },
186 #endif
187 #ifdef HAVE_OSS
188 { "oss", OSSBackendFactory::getFactory },
189 #endif
190 #ifdef HAVE_QSA
191 { "qsa", QSABackendFactory::getFactory },
192 #endif
193 #ifdef HAVE_DSOUND
194 { "dsound", DSoundBackendFactory::getFactory },
195 #endif
196 #ifdef HAVE_WINMM
197 { "winmm", WinMMBackendFactory::getFactory },
198 #endif
199 #ifdef HAVE_PORTAUDIO
200 { "port", PortBackendFactory::getFactory },
201 #endif
202 #ifdef HAVE_SDL2
203 { "sdl2", SDL2BackendFactory::getFactory },
204 #endif
206 { "null", NullBackendFactory::getFactory },
207 #ifdef HAVE_WAVE
208 { "wave", WaveBackendFactory::getFactory },
209 #endif
211 auto BackendListEnd = std::end(BackendList);
213 BackendFactory *PlaybackFactory{};
214 BackendFactory *CaptureFactory{};
217 /************************************************
218 * Functions, enums, and errors
219 ************************************************/
220 #define DECL(x) { #x, reinterpret_cast<void*>(x) }
221 const struct {
222 const ALCchar *funcName;
223 ALCvoid *address;
224 } alcFunctions[] = {
225 DECL(alcCreateContext),
226 DECL(alcMakeContextCurrent),
227 DECL(alcProcessContext),
228 DECL(alcSuspendContext),
229 DECL(alcDestroyContext),
230 DECL(alcGetCurrentContext),
231 DECL(alcGetContextsDevice),
232 DECL(alcOpenDevice),
233 DECL(alcCloseDevice),
234 DECL(alcGetError),
235 DECL(alcIsExtensionPresent),
236 DECL(alcGetProcAddress),
237 DECL(alcGetEnumValue),
238 DECL(alcGetString),
239 DECL(alcGetIntegerv),
240 DECL(alcCaptureOpenDevice),
241 DECL(alcCaptureCloseDevice),
242 DECL(alcCaptureStart),
243 DECL(alcCaptureStop),
244 DECL(alcCaptureSamples),
246 DECL(alcSetThreadContext),
247 DECL(alcGetThreadContext),
249 DECL(alcLoopbackOpenDeviceSOFT),
250 DECL(alcIsRenderFormatSupportedSOFT),
251 DECL(alcRenderSamplesSOFT),
253 DECL(alcDevicePauseSOFT),
254 DECL(alcDeviceResumeSOFT),
256 DECL(alcGetStringiSOFT),
257 DECL(alcResetDeviceSOFT),
259 DECL(alcGetInteger64vSOFT),
261 DECL(alEnable),
262 DECL(alDisable),
263 DECL(alIsEnabled),
264 DECL(alGetString),
265 DECL(alGetBooleanv),
266 DECL(alGetIntegerv),
267 DECL(alGetFloatv),
268 DECL(alGetDoublev),
269 DECL(alGetBoolean),
270 DECL(alGetInteger),
271 DECL(alGetFloat),
272 DECL(alGetDouble),
273 DECL(alGetError),
274 DECL(alIsExtensionPresent),
275 DECL(alGetProcAddress),
276 DECL(alGetEnumValue),
277 DECL(alListenerf),
278 DECL(alListener3f),
279 DECL(alListenerfv),
280 DECL(alListeneri),
281 DECL(alListener3i),
282 DECL(alListeneriv),
283 DECL(alGetListenerf),
284 DECL(alGetListener3f),
285 DECL(alGetListenerfv),
286 DECL(alGetListeneri),
287 DECL(alGetListener3i),
288 DECL(alGetListeneriv),
289 DECL(alGenSources),
290 DECL(alDeleteSources),
291 DECL(alIsSource),
292 DECL(alSourcef),
293 DECL(alSource3f),
294 DECL(alSourcefv),
295 DECL(alSourcei),
296 DECL(alSource3i),
297 DECL(alSourceiv),
298 DECL(alGetSourcef),
299 DECL(alGetSource3f),
300 DECL(alGetSourcefv),
301 DECL(alGetSourcei),
302 DECL(alGetSource3i),
303 DECL(alGetSourceiv),
304 DECL(alSourcePlayv),
305 DECL(alSourceStopv),
306 DECL(alSourceRewindv),
307 DECL(alSourcePausev),
308 DECL(alSourcePlay),
309 DECL(alSourceStop),
310 DECL(alSourceRewind),
311 DECL(alSourcePause),
312 DECL(alSourceQueueBuffers),
313 DECL(alSourceUnqueueBuffers),
314 DECL(alGenBuffers),
315 DECL(alDeleteBuffers),
316 DECL(alIsBuffer),
317 DECL(alBufferData),
318 DECL(alBufferf),
319 DECL(alBuffer3f),
320 DECL(alBufferfv),
321 DECL(alBufferi),
322 DECL(alBuffer3i),
323 DECL(alBufferiv),
324 DECL(alGetBufferf),
325 DECL(alGetBuffer3f),
326 DECL(alGetBufferfv),
327 DECL(alGetBufferi),
328 DECL(alGetBuffer3i),
329 DECL(alGetBufferiv),
330 DECL(alDopplerFactor),
331 DECL(alDopplerVelocity),
332 DECL(alSpeedOfSound),
333 DECL(alDistanceModel),
335 DECL(alGenFilters),
336 DECL(alDeleteFilters),
337 DECL(alIsFilter),
338 DECL(alFilteri),
339 DECL(alFilteriv),
340 DECL(alFilterf),
341 DECL(alFilterfv),
342 DECL(alGetFilteri),
343 DECL(alGetFilteriv),
344 DECL(alGetFilterf),
345 DECL(alGetFilterfv),
346 DECL(alGenEffects),
347 DECL(alDeleteEffects),
348 DECL(alIsEffect),
349 DECL(alEffecti),
350 DECL(alEffectiv),
351 DECL(alEffectf),
352 DECL(alEffectfv),
353 DECL(alGetEffecti),
354 DECL(alGetEffectiv),
355 DECL(alGetEffectf),
356 DECL(alGetEffectfv),
357 DECL(alGenAuxiliaryEffectSlots),
358 DECL(alDeleteAuxiliaryEffectSlots),
359 DECL(alIsAuxiliaryEffectSlot),
360 DECL(alAuxiliaryEffectSloti),
361 DECL(alAuxiliaryEffectSlotiv),
362 DECL(alAuxiliaryEffectSlotf),
363 DECL(alAuxiliaryEffectSlotfv),
364 DECL(alGetAuxiliaryEffectSloti),
365 DECL(alGetAuxiliaryEffectSlotiv),
366 DECL(alGetAuxiliaryEffectSlotf),
367 DECL(alGetAuxiliaryEffectSlotfv),
369 DECL(alDeferUpdatesSOFT),
370 DECL(alProcessUpdatesSOFT),
372 DECL(alSourcedSOFT),
373 DECL(alSource3dSOFT),
374 DECL(alSourcedvSOFT),
375 DECL(alGetSourcedSOFT),
376 DECL(alGetSource3dSOFT),
377 DECL(alGetSourcedvSOFT),
378 DECL(alSourcei64SOFT),
379 DECL(alSource3i64SOFT),
380 DECL(alSourcei64vSOFT),
381 DECL(alGetSourcei64SOFT),
382 DECL(alGetSource3i64SOFT),
383 DECL(alGetSourcei64vSOFT),
385 DECL(alGetStringiSOFT),
387 DECL(alBufferStorageSOFT),
388 DECL(alMapBufferSOFT),
389 DECL(alUnmapBufferSOFT),
390 DECL(alFlushMappedBufferSOFT),
392 DECL(alEventControlSOFT),
393 DECL(alEventCallbackSOFT),
394 DECL(alGetPointerSOFT),
395 DECL(alGetPointervSOFT),
397 #undef DECL
399 #define DECL(x) { #x, (x) }
400 constexpr struct {
401 const ALCchar *enumName;
402 ALCenum value;
403 } alcEnumerations[] = {
404 DECL(ALC_INVALID),
405 DECL(ALC_FALSE),
406 DECL(ALC_TRUE),
408 DECL(ALC_MAJOR_VERSION),
409 DECL(ALC_MINOR_VERSION),
410 DECL(ALC_ATTRIBUTES_SIZE),
411 DECL(ALC_ALL_ATTRIBUTES),
412 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
413 DECL(ALC_DEVICE_SPECIFIER),
414 DECL(ALC_ALL_DEVICES_SPECIFIER),
415 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
416 DECL(ALC_EXTENSIONS),
417 DECL(ALC_FREQUENCY),
418 DECL(ALC_REFRESH),
419 DECL(ALC_SYNC),
420 DECL(ALC_MONO_SOURCES),
421 DECL(ALC_STEREO_SOURCES),
422 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
423 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
424 DECL(ALC_CAPTURE_SAMPLES),
425 DECL(ALC_CONNECTED),
427 DECL(ALC_EFX_MAJOR_VERSION),
428 DECL(ALC_EFX_MINOR_VERSION),
429 DECL(ALC_MAX_AUXILIARY_SENDS),
431 DECL(ALC_FORMAT_CHANNELS_SOFT),
432 DECL(ALC_FORMAT_TYPE_SOFT),
434 DECL(ALC_MONO_SOFT),
435 DECL(ALC_STEREO_SOFT),
436 DECL(ALC_QUAD_SOFT),
437 DECL(ALC_5POINT1_SOFT),
438 DECL(ALC_6POINT1_SOFT),
439 DECL(ALC_7POINT1_SOFT),
440 DECL(ALC_BFORMAT3D_SOFT),
442 DECL(ALC_BYTE_SOFT),
443 DECL(ALC_UNSIGNED_BYTE_SOFT),
444 DECL(ALC_SHORT_SOFT),
445 DECL(ALC_UNSIGNED_SHORT_SOFT),
446 DECL(ALC_INT_SOFT),
447 DECL(ALC_UNSIGNED_INT_SOFT),
448 DECL(ALC_FLOAT_SOFT),
450 DECL(ALC_HRTF_SOFT),
451 DECL(ALC_DONT_CARE_SOFT),
452 DECL(ALC_HRTF_STATUS_SOFT),
453 DECL(ALC_HRTF_DISABLED_SOFT),
454 DECL(ALC_HRTF_ENABLED_SOFT),
455 DECL(ALC_HRTF_DENIED_SOFT),
456 DECL(ALC_HRTF_REQUIRED_SOFT),
457 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
458 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
459 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
460 DECL(ALC_HRTF_SPECIFIER_SOFT),
461 DECL(ALC_HRTF_ID_SOFT),
463 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
464 DECL(ALC_AMBISONIC_SCALING_SOFT),
465 DECL(ALC_AMBISONIC_ORDER_SOFT),
466 DECL(ALC_ACN_SOFT),
467 DECL(ALC_FUMA_SOFT),
468 DECL(ALC_N3D_SOFT),
469 DECL(ALC_SN3D_SOFT),
471 DECL(ALC_OUTPUT_LIMITER_SOFT),
473 DECL(ALC_NO_ERROR),
474 DECL(ALC_INVALID_DEVICE),
475 DECL(ALC_INVALID_CONTEXT),
476 DECL(ALC_INVALID_ENUM),
477 DECL(ALC_INVALID_VALUE),
478 DECL(ALC_OUT_OF_MEMORY),
481 DECL(AL_INVALID),
482 DECL(AL_NONE),
483 DECL(AL_FALSE),
484 DECL(AL_TRUE),
486 DECL(AL_SOURCE_RELATIVE),
487 DECL(AL_CONE_INNER_ANGLE),
488 DECL(AL_CONE_OUTER_ANGLE),
489 DECL(AL_PITCH),
490 DECL(AL_POSITION),
491 DECL(AL_DIRECTION),
492 DECL(AL_VELOCITY),
493 DECL(AL_LOOPING),
494 DECL(AL_BUFFER),
495 DECL(AL_GAIN),
496 DECL(AL_MIN_GAIN),
497 DECL(AL_MAX_GAIN),
498 DECL(AL_ORIENTATION),
499 DECL(AL_REFERENCE_DISTANCE),
500 DECL(AL_ROLLOFF_FACTOR),
501 DECL(AL_CONE_OUTER_GAIN),
502 DECL(AL_MAX_DISTANCE),
503 DECL(AL_SEC_OFFSET),
504 DECL(AL_SAMPLE_OFFSET),
505 DECL(AL_BYTE_OFFSET),
506 DECL(AL_SOURCE_TYPE),
507 DECL(AL_STATIC),
508 DECL(AL_STREAMING),
509 DECL(AL_UNDETERMINED),
510 DECL(AL_METERS_PER_UNIT),
511 DECL(AL_LOOP_POINTS_SOFT),
512 DECL(AL_DIRECT_CHANNELS_SOFT),
514 DECL(AL_DIRECT_FILTER),
515 DECL(AL_AUXILIARY_SEND_FILTER),
516 DECL(AL_AIR_ABSORPTION_FACTOR),
517 DECL(AL_ROOM_ROLLOFF_FACTOR),
518 DECL(AL_CONE_OUTER_GAINHF),
519 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
520 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
521 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
523 DECL(AL_SOURCE_STATE),
524 DECL(AL_INITIAL),
525 DECL(AL_PLAYING),
526 DECL(AL_PAUSED),
527 DECL(AL_STOPPED),
529 DECL(AL_BUFFERS_QUEUED),
530 DECL(AL_BUFFERS_PROCESSED),
532 DECL(AL_FORMAT_MONO8),
533 DECL(AL_FORMAT_MONO16),
534 DECL(AL_FORMAT_MONO_FLOAT32),
535 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
536 DECL(AL_FORMAT_STEREO8),
537 DECL(AL_FORMAT_STEREO16),
538 DECL(AL_FORMAT_STEREO_FLOAT32),
539 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
540 DECL(AL_FORMAT_MONO_IMA4),
541 DECL(AL_FORMAT_STEREO_IMA4),
542 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
543 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
544 DECL(AL_FORMAT_QUAD8_LOKI),
545 DECL(AL_FORMAT_QUAD16_LOKI),
546 DECL(AL_FORMAT_QUAD8),
547 DECL(AL_FORMAT_QUAD16),
548 DECL(AL_FORMAT_QUAD32),
549 DECL(AL_FORMAT_51CHN8),
550 DECL(AL_FORMAT_51CHN16),
551 DECL(AL_FORMAT_51CHN32),
552 DECL(AL_FORMAT_61CHN8),
553 DECL(AL_FORMAT_61CHN16),
554 DECL(AL_FORMAT_61CHN32),
555 DECL(AL_FORMAT_71CHN8),
556 DECL(AL_FORMAT_71CHN16),
557 DECL(AL_FORMAT_71CHN32),
558 DECL(AL_FORMAT_REAR8),
559 DECL(AL_FORMAT_REAR16),
560 DECL(AL_FORMAT_REAR32),
561 DECL(AL_FORMAT_MONO_MULAW),
562 DECL(AL_FORMAT_MONO_MULAW_EXT),
563 DECL(AL_FORMAT_STEREO_MULAW),
564 DECL(AL_FORMAT_STEREO_MULAW_EXT),
565 DECL(AL_FORMAT_QUAD_MULAW),
566 DECL(AL_FORMAT_51CHN_MULAW),
567 DECL(AL_FORMAT_61CHN_MULAW),
568 DECL(AL_FORMAT_71CHN_MULAW),
569 DECL(AL_FORMAT_REAR_MULAW),
570 DECL(AL_FORMAT_MONO_ALAW_EXT),
571 DECL(AL_FORMAT_STEREO_ALAW_EXT),
573 DECL(AL_FORMAT_BFORMAT2D_8),
574 DECL(AL_FORMAT_BFORMAT2D_16),
575 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
576 DECL(AL_FORMAT_BFORMAT2D_MULAW),
577 DECL(AL_FORMAT_BFORMAT3D_8),
578 DECL(AL_FORMAT_BFORMAT3D_16),
579 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
580 DECL(AL_FORMAT_BFORMAT3D_MULAW),
582 DECL(AL_FREQUENCY),
583 DECL(AL_BITS),
584 DECL(AL_CHANNELS),
585 DECL(AL_SIZE),
586 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
587 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
589 DECL(AL_SOURCE_RADIUS),
591 DECL(AL_STEREO_ANGLES),
593 DECL(AL_UNUSED),
594 DECL(AL_PENDING),
595 DECL(AL_PROCESSED),
597 DECL(AL_NO_ERROR),
598 DECL(AL_INVALID_NAME),
599 DECL(AL_INVALID_ENUM),
600 DECL(AL_INVALID_VALUE),
601 DECL(AL_INVALID_OPERATION),
602 DECL(AL_OUT_OF_MEMORY),
604 DECL(AL_VENDOR),
605 DECL(AL_VERSION),
606 DECL(AL_RENDERER),
607 DECL(AL_EXTENSIONS),
609 DECL(AL_DOPPLER_FACTOR),
610 DECL(AL_DOPPLER_VELOCITY),
611 DECL(AL_DISTANCE_MODEL),
612 DECL(AL_SPEED_OF_SOUND),
613 DECL(AL_SOURCE_DISTANCE_MODEL),
614 DECL(AL_DEFERRED_UPDATES_SOFT),
615 DECL(AL_GAIN_LIMIT_SOFT),
617 DECL(AL_INVERSE_DISTANCE),
618 DECL(AL_INVERSE_DISTANCE_CLAMPED),
619 DECL(AL_LINEAR_DISTANCE),
620 DECL(AL_LINEAR_DISTANCE_CLAMPED),
621 DECL(AL_EXPONENT_DISTANCE),
622 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
624 DECL(AL_FILTER_TYPE),
625 DECL(AL_FILTER_NULL),
626 DECL(AL_FILTER_LOWPASS),
627 DECL(AL_FILTER_HIGHPASS),
628 DECL(AL_FILTER_BANDPASS),
630 DECL(AL_LOWPASS_GAIN),
631 DECL(AL_LOWPASS_GAINHF),
633 DECL(AL_HIGHPASS_GAIN),
634 DECL(AL_HIGHPASS_GAINLF),
636 DECL(AL_BANDPASS_GAIN),
637 DECL(AL_BANDPASS_GAINHF),
638 DECL(AL_BANDPASS_GAINLF),
640 DECL(AL_EFFECT_TYPE),
641 DECL(AL_EFFECT_NULL),
642 DECL(AL_EFFECT_REVERB),
643 DECL(AL_EFFECT_EAXREVERB),
644 DECL(AL_EFFECT_CHORUS),
645 DECL(AL_EFFECT_DISTORTION),
646 DECL(AL_EFFECT_ECHO),
647 DECL(AL_EFFECT_FLANGER),
648 DECL(AL_EFFECT_PITCH_SHIFTER),
649 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
650 DECL(AL_EFFECT_VOCAL_MORPHER),
651 DECL(AL_EFFECT_RING_MODULATOR),
652 DECL(AL_EFFECT_AUTOWAH),
653 DECL(AL_EFFECT_COMPRESSOR),
654 DECL(AL_EFFECT_EQUALIZER),
655 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
656 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
658 DECL(AL_EFFECTSLOT_EFFECT),
659 DECL(AL_EFFECTSLOT_GAIN),
660 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
661 DECL(AL_EFFECTSLOT_NULL),
663 DECL(AL_EAXREVERB_DENSITY),
664 DECL(AL_EAXREVERB_DIFFUSION),
665 DECL(AL_EAXREVERB_GAIN),
666 DECL(AL_EAXREVERB_GAINHF),
667 DECL(AL_EAXREVERB_GAINLF),
668 DECL(AL_EAXREVERB_DECAY_TIME),
669 DECL(AL_EAXREVERB_DECAY_HFRATIO),
670 DECL(AL_EAXREVERB_DECAY_LFRATIO),
671 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
672 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
673 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
674 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
675 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
676 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
677 DECL(AL_EAXREVERB_ECHO_TIME),
678 DECL(AL_EAXREVERB_ECHO_DEPTH),
679 DECL(AL_EAXREVERB_MODULATION_TIME),
680 DECL(AL_EAXREVERB_MODULATION_DEPTH),
681 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
682 DECL(AL_EAXREVERB_HFREFERENCE),
683 DECL(AL_EAXREVERB_LFREFERENCE),
684 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
685 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
687 DECL(AL_REVERB_DENSITY),
688 DECL(AL_REVERB_DIFFUSION),
689 DECL(AL_REVERB_GAIN),
690 DECL(AL_REVERB_GAINHF),
691 DECL(AL_REVERB_DECAY_TIME),
692 DECL(AL_REVERB_DECAY_HFRATIO),
693 DECL(AL_REVERB_REFLECTIONS_GAIN),
694 DECL(AL_REVERB_REFLECTIONS_DELAY),
695 DECL(AL_REVERB_LATE_REVERB_GAIN),
696 DECL(AL_REVERB_LATE_REVERB_DELAY),
697 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
698 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
699 DECL(AL_REVERB_DECAY_HFLIMIT),
701 DECL(AL_CHORUS_WAVEFORM),
702 DECL(AL_CHORUS_PHASE),
703 DECL(AL_CHORUS_RATE),
704 DECL(AL_CHORUS_DEPTH),
705 DECL(AL_CHORUS_FEEDBACK),
706 DECL(AL_CHORUS_DELAY),
708 DECL(AL_DISTORTION_EDGE),
709 DECL(AL_DISTORTION_GAIN),
710 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
711 DECL(AL_DISTORTION_EQCENTER),
712 DECL(AL_DISTORTION_EQBANDWIDTH),
714 DECL(AL_ECHO_DELAY),
715 DECL(AL_ECHO_LRDELAY),
716 DECL(AL_ECHO_DAMPING),
717 DECL(AL_ECHO_FEEDBACK),
718 DECL(AL_ECHO_SPREAD),
720 DECL(AL_FLANGER_WAVEFORM),
721 DECL(AL_FLANGER_PHASE),
722 DECL(AL_FLANGER_RATE),
723 DECL(AL_FLANGER_DEPTH),
724 DECL(AL_FLANGER_FEEDBACK),
725 DECL(AL_FLANGER_DELAY),
727 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY),
728 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION),
729 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION),
731 DECL(AL_RING_MODULATOR_FREQUENCY),
732 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
733 DECL(AL_RING_MODULATOR_WAVEFORM),
735 DECL(AL_PITCH_SHIFTER_COARSE_TUNE),
736 DECL(AL_PITCH_SHIFTER_FINE_TUNE),
738 DECL(AL_COMPRESSOR_ONOFF),
740 DECL(AL_EQUALIZER_LOW_GAIN),
741 DECL(AL_EQUALIZER_LOW_CUTOFF),
742 DECL(AL_EQUALIZER_MID1_GAIN),
743 DECL(AL_EQUALIZER_MID1_CENTER),
744 DECL(AL_EQUALIZER_MID1_WIDTH),
745 DECL(AL_EQUALIZER_MID2_GAIN),
746 DECL(AL_EQUALIZER_MID2_CENTER),
747 DECL(AL_EQUALIZER_MID2_WIDTH),
748 DECL(AL_EQUALIZER_HIGH_GAIN),
749 DECL(AL_EQUALIZER_HIGH_CUTOFF),
751 DECL(AL_DEDICATED_GAIN),
753 DECL(AL_AUTOWAH_ATTACK_TIME),
754 DECL(AL_AUTOWAH_RELEASE_TIME),
755 DECL(AL_AUTOWAH_RESONANCE),
756 DECL(AL_AUTOWAH_PEAK_GAIN),
758 DECL(AL_VOCAL_MORPHER_PHONEMEA),
759 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING),
760 DECL(AL_VOCAL_MORPHER_PHONEMEB),
761 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING),
762 DECL(AL_VOCAL_MORPHER_WAVEFORM),
763 DECL(AL_VOCAL_MORPHER_RATE),
765 DECL(AL_NUM_RESAMPLERS_SOFT),
766 DECL(AL_DEFAULT_RESAMPLER_SOFT),
767 DECL(AL_SOURCE_RESAMPLER_SOFT),
768 DECL(AL_RESAMPLER_NAME_SOFT),
770 DECL(AL_SOURCE_SPATIALIZE_SOFT),
771 DECL(AL_AUTO_SOFT),
773 DECL(AL_MAP_READ_BIT_SOFT),
774 DECL(AL_MAP_WRITE_BIT_SOFT),
775 DECL(AL_MAP_PERSISTENT_BIT_SOFT),
776 DECL(AL_PRESERVE_DATA_BIT_SOFT),
778 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT),
779 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT),
780 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT),
781 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT),
782 DECL(AL_EVENT_TYPE_ERROR_SOFT),
783 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT),
784 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT),
786 #undef DECL
788 constexpr ALCchar alcNoError[] = "No Error";
789 constexpr ALCchar alcErrInvalidDevice[] = "Invalid Device";
790 constexpr ALCchar alcErrInvalidContext[] = "Invalid Context";
791 constexpr ALCchar alcErrInvalidEnum[] = "Invalid Enum";
792 constexpr ALCchar alcErrInvalidValue[] = "Invalid Value";
793 constexpr ALCchar alcErrOutOfMemory[] = "Out of Memory";
796 /************************************************
797 * Global variables
798 ************************************************/
800 /* Enumerated device names */
801 constexpr ALCchar alcDefaultName[] = "OpenAL Soft\0";
803 std::string alcAllDevicesList;
804 std::string alcCaptureDeviceList;
806 /* Default is always the first in the list */
807 al::string alcDefaultAllDevicesSpecifier;
808 al::string alcCaptureDefaultDeviceSpecifier;
810 /* Default context extensions */
811 constexpr ALchar alExtList[] =
812 "AL_EXT_ALAW "
813 "AL_EXT_BFORMAT "
814 "AL_EXT_DOUBLE "
815 "AL_EXT_EXPONENT_DISTANCE "
816 "AL_EXT_FLOAT32 "
817 "AL_EXT_IMA4 "
818 "AL_EXT_LINEAR_DISTANCE "
819 "AL_EXT_MCFORMATS "
820 "AL_EXT_MULAW "
821 "AL_EXT_MULAW_BFORMAT "
822 "AL_EXT_MULAW_MCFORMATS "
823 "AL_EXT_OFFSET "
824 "AL_EXT_source_distance_model "
825 "AL_EXT_SOURCE_RADIUS "
826 "AL_EXT_STEREO_ANGLES "
827 "AL_LOKI_quadriphonic "
828 "AL_SOFT_block_alignment "
829 "AL_SOFT_deferred_updates "
830 "AL_SOFT_direct_channels "
831 "AL_SOFTX_effect_chain "
832 "AL_SOFTX_events "
833 "AL_SOFTX_filter_gain_ex "
834 "AL_SOFT_gain_clamp_ex "
835 "AL_SOFT_loop_points "
836 "AL_SOFTX_map_buffer "
837 "AL_SOFT_MSADPCM "
838 "AL_SOFT_source_latency "
839 "AL_SOFT_source_length "
840 "AL_SOFT_source_resampler "
841 "AL_SOFT_source_spatialize";
843 std::atomic<ALCenum> LastNullDeviceError{ALC_NO_ERROR};
845 /* Thread-local current context */
846 class ThreadCtx {
847 ALCcontext *ctx{nullptr};
849 public:
850 ~ThreadCtx()
852 if(ctx)
854 const bool result{ctx->releaseIfNoDelete()};
855 ERR("Context %p current for thread being destroyed%s!\n",
856 decltype(std::declval<void*>()){ctx}, result ? "" : ", leak detected");
860 ALCcontext *get() const noexcept { return ctx; }
861 void set(ALCcontext *ctx_) noexcept { ctx = ctx_; }
863 thread_local ThreadCtx LocalContext;
864 /* Process-wide current context */
865 std::atomic<ALCcontext*> GlobalContext{nullptr};
867 /* Flag to trap ALC device errors */
868 bool TrapALCError{false};
870 /* One-time configuration init control */
871 std::once_flag alc_config_once{};
873 /* Default effect that applies to sources that don't have an effect on send 0 */
874 ALeffect DefaultEffect;
876 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
877 * updates.
879 bool SuspendDefers{true};
881 /* Initial seed for dithering. */
882 constexpr ALuint DitherRNGSeed{22222u};
885 /************************************************
886 * ALC information
887 ************************************************/
888 constexpr ALCchar alcNoDeviceExtList[] =
889 "ALC_ENUMERATE_ALL_EXT "
890 "ALC_ENUMERATION_EXT "
891 "ALC_EXT_CAPTURE "
892 "ALC_EXT_thread_local_context "
893 "ALC_SOFT_loopback";
894 constexpr ALCchar alcExtensionList[] =
895 "ALC_ENUMERATE_ALL_EXT "
896 "ALC_ENUMERATION_EXT "
897 "ALC_EXT_CAPTURE "
898 "ALC_EXT_DEDICATED "
899 "ALC_EXT_disconnect "
900 "ALC_EXT_EFX "
901 "ALC_EXT_thread_local_context "
902 "ALC_SOFT_device_clock "
903 "ALC_SOFT_HRTF "
904 "ALC_SOFT_loopback "
905 "ALC_SOFT_output_limiter "
906 "ALC_SOFT_pause_device";
907 constexpr ALCint alcMajorVersion = 1;
908 constexpr ALCint alcMinorVersion = 1;
910 constexpr ALCint alcEFXMajorVersion = 1;
911 constexpr ALCint alcEFXMinorVersion = 0;
914 /* To avoid extraneous allocations, a 0-sized FlexArray<ALCcontext*> is defined
915 * globally as a sharable object. MSVC warns that a zero-sized array will have
916 * zero objects here, so silence that.
918 DIAGNOSTIC_PUSH
919 msc_pragma(warning(disable : 4815))
920 al::FlexArray<ALCcontext*> EmptyContextArray{0u};
921 DIAGNOSTIC_POP
924 using DeviceRef = al::intrusive_ptr<ALCdevice>;
927 /************************************************
928 * Device lists
929 ************************************************/
930 al::vector<DeviceRef> DeviceList;
931 al::vector<ContextRef> ContextList;
933 std::recursive_mutex ListLock;
936 void alc_initconfig(void)
938 if(auto loglevel = al::getenv("ALSOFT_LOGLEVEL"))
940 long lvl = strtol(loglevel->c_str(), nullptr, 0);
941 if(lvl >= NoLog && lvl <= LogRef)
942 gLogLevel = static_cast<LogLevel>(lvl);
945 if(auto logfile = al::getenv("ALSOFT_LOGFILE"))
947 #ifdef _WIN32
948 std::wstring wname{utf8_to_wstr(logfile->c_str())};
949 FILE *logf{_wfopen(wname.c_str(), L"wt")};
950 #else
951 FILE *logf{fopen(logfile->c_str(), "wt")};
952 #endif
953 if(logf) gLogFile = logf;
954 else ERR("Failed to open log file '%s'\n", logfile->c_str());
957 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION, ALSOFT_GIT_COMMIT_HASH,
958 ALSOFT_GIT_BRANCH);
960 al::string names;
961 if(std::begin(BackendList) == BackendListEnd)
962 names += "(none)";
963 else
965 const al::span<const BackendInfo> infos{std::begin(BackendList), BackendListEnd};
966 names += infos[0].name;
967 for(const auto &backend : infos.subspan(1))
969 names += ", ";
970 names += backend.name;
973 TRACE("Supported backends: %s\n", names.c_str());
975 ReadALConfig();
977 if(auto suspendmode = al::getenv("__ALSOFT_SUSPEND_CONTEXT"))
979 if(al::strcasecmp(suspendmode->c_str(), "ignore") == 0)
981 SuspendDefers = false;
982 TRACE("Selected context suspend behavior, \"ignore\"\n");
984 else
985 ERR("Unhandled context suspend behavior setting: \"%s\"\n", suspendmode->c_str());
988 int capfilter{0};
989 #if defined(HAVE_SSE4_1)
990 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
991 #elif defined(HAVE_SSE3)
992 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
993 #elif defined(HAVE_SSE2)
994 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
995 #elif defined(HAVE_SSE)
996 capfilter |= CPU_CAP_SSE;
997 #endif
998 #ifdef HAVE_NEON
999 capfilter |= CPU_CAP_NEON;
1000 #endif
1001 if(auto cpuopt = ConfigValueStr(nullptr, nullptr, "disable-cpu-exts"))
1003 const char *str{cpuopt->c_str()};
1004 if(al::strcasecmp(str, "all") == 0)
1005 capfilter = 0;
1006 else
1008 const char *next = str;
1009 do {
1010 str = next;
1011 while(isspace(str[0]))
1012 str++;
1013 next = strchr(str, ',');
1015 if(!str[0] || str[0] == ',')
1016 continue;
1018 size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1019 while(len > 0 && isspace(str[len-1]))
1020 len--;
1021 if(len == 3 && al::strncasecmp(str, "sse", len) == 0)
1022 capfilter &= ~CPU_CAP_SSE;
1023 else if(len == 4 && al::strncasecmp(str, "sse2", len) == 0)
1024 capfilter &= ~CPU_CAP_SSE2;
1025 else if(len == 4 && al::strncasecmp(str, "sse3", len) == 0)
1026 capfilter &= ~CPU_CAP_SSE3;
1027 else if(len == 6 && al::strncasecmp(str, "sse4.1", len) == 0)
1028 capfilter &= ~CPU_CAP_SSE4_1;
1029 else if(len == 4 && al::strncasecmp(str, "neon", len) == 0)
1030 capfilter &= ~CPU_CAP_NEON;
1031 else
1032 WARN("Invalid CPU extension \"%s\"\n", str);
1033 } while(next++);
1036 FillCPUCaps(capfilter);
1038 #ifdef _WIN32
1039 #define DEF_MIXER_PRIO 1
1040 #else
1041 #define DEF_MIXER_PRIO 0
1042 #endif
1043 RTPrioLevel = ConfigValueInt(nullptr, nullptr, "rt-prio").value_or(DEF_MIXER_PRIO);
1044 #undef DEF_MIXER_PRIO
1046 aluInit();
1047 aluInitMixer();
1049 auto traperr = al::getenv("ALSOFT_TRAP_ERROR");
1050 if(traperr && (al::strcasecmp(traperr->c_str(), "true") == 0
1051 || std::strtol(traperr->c_str(), nullptr, 0) == 1))
1053 TrapALError = true;
1054 TrapALCError = true;
1056 else
1058 traperr = al::getenv("ALSOFT_TRAP_AL_ERROR");
1059 if(traperr)
1060 TrapALError = al::strcasecmp(traperr->c_str(), "true") == 0
1061 || strtol(traperr->c_str(), nullptr, 0) == 1;
1062 else
1063 TrapALError = !!GetConfigValueBool(nullptr, nullptr, "trap-al-error", false);
1065 traperr = al::getenv("ALSOFT_TRAP_ALC_ERROR");
1066 if(traperr)
1067 TrapALCError = al::strcasecmp(traperr->c_str(), "true") == 0
1068 || strtol(traperr->c_str(), nullptr, 0) == 1;
1069 else
1070 TrapALCError = !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", false);
1073 if(auto boostopt = ConfigValueFloat(nullptr, "reverb", "boost"))
1075 const float valf{std::isfinite(*boostopt) ? clampf(*boostopt, -24.0f, 24.0f) : 0.0f};
1076 ReverbBoost *= std::pow(10.0f, valf / 20.0f);
1079 auto devopt = al::getenv("ALSOFT_DRIVERS");
1080 if(devopt || (devopt=ConfigValueStr(nullptr, nullptr, "drivers")))
1082 auto backendlist_cur = std::begin(BackendList);
1084 bool endlist{true};
1085 const char *next{devopt->c_str()};
1086 do {
1087 const char *devs{next};
1088 while(isspace(devs[0]))
1089 devs++;
1090 next = strchr(devs, ',');
1092 const bool delitem{devs[0] == '-'};
1093 if(devs[0] == '-') devs++;
1095 if(!devs[0] || devs[0] == ',')
1097 endlist = false;
1098 continue;
1100 endlist = true;
1102 size_t len{next ? (static_cast<size_t>(next-devs)) : strlen(devs)};
1103 while(len > 0 && isspace(devs[len-1])) --len;
1104 #ifdef HAVE_WASAPI
1105 /* HACK: For backwards compatibility, convert backend references of
1106 * mmdevapi to wasapi. This should eventually be removed.
1108 if(len == 8 && strncmp(devs, "mmdevapi", len) == 0)
1110 devs = "wasapi";
1111 len = 6;
1113 #endif
1115 auto find_backend = [devs,len](const BackendInfo &backend) -> bool
1116 { return len == strlen(backend.name) && strncmp(backend.name, devs, len) == 0; };
1117 auto this_backend = std::find_if(std::begin(BackendList), BackendListEnd,
1118 find_backend);
1120 if(this_backend == BackendListEnd)
1121 continue;
1123 if(delitem)
1124 BackendListEnd = std::move(this_backend+1, BackendListEnd, this_backend);
1125 else
1126 backendlist_cur = std::rotate(backendlist_cur, this_backend, this_backend+1);
1127 } while(next++);
1129 if(endlist)
1130 BackendListEnd = backendlist_cur;
1133 auto init_backend = [](BackendInfo &backend) -> bool
1135 if(PlaybackFactory && CaptureFactory)
1136 return true;
1138 BackendFactory &factory = backend.getFactory();
1139 if(!factory.init())
1141 WARN("Failed to initialize backend \"%s\"\n", backend.name);
1142 return true;
1145 TRACE("Initialized backend \"%s\"\n", backend.name);
1146 if(!PlaybackFactory && factory.querySupport(BackendType::Playback))
1148 PlaybackFactory = &factory;
1149 TRACE("Added \"%s\" for playback\n", backend.name);
1151 if(!CaptureFactory && factory.querySupport(BackendType::Capture))
1153 CaptureFactory = &factory;
1154 TRACE("Added \"%s\" for capture\n", backend.name);
1156 return false;
1158 BackendListEnd = std::remove_if(std::begin(BackendList), BackendListEnd, init_backend);
1160 LoopbackBackendFactory::getFactory().init();
1162 if(!PlaybackFactory)
1163 WARN("No playback backend available!\n");
1164 if(!CaptureFactory)
1165 WARN("No capture backend available!\n");
1167 if(auto exclopt = ConfigValueStr(nullptr, nullptr, "excludefx"))
1169 const char *next{exclopt->c_str()};
1170 do {
1171 const char *str{next};
1172 next = strchr(str, ',');
1174 if(!str[0] || next == str)
1175 continue;
1177 size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1178 for(const EffectList &effectitem : gEffectList)
1180 if(len == strlen(effectitem.name) &&
1181 strncmp(effectitem.name, str, len) == 0)
1182 DisabledEffects[effectitem.type] = AL_TRUE;
1184 } while(next++);
1187 InitEffect(&DefaultEffect);
1188 auto defrevopt = al::getenv("ALSOFT_DEFAULT_REVERB");
1189 if(defrevopt || (defrevopt=ConfigValueStr(nullptr, nullptr, "default-reverb")))
1190 LoadReverbPreset(defrevopt->c_str(), &DefaultEffect);
1192 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1195 /************************************************
1196 * Device enumeration
1197 ************************************************/
1198 void ProbeAllDevicesList()
1200 DO_INITCONFIG();
1202 std::lock_guard<std::recursive_mutex> _{ListLock};
1203 alcAllDevicesList.clear();
1204 if(PlaybackFactory)
1205 PlaybackFactory->probe(DevProbe::Playback, &alcAllDevicesList);
1207 void ProbeCaptureDeviceList()
1209 DO_INITCONFIG();
1211 std::lock_guard<std::recursive_mutex> _{ListLock};
1212 alcCaptureDeviceList.clear();
1213 if(CaptureFactory)
1214 CaptureFactory->probe(DevProbe::Capture, &alcCaptureDeviceList);
1217 } // namespace
1219 /* Mixing thread piority level */
1220 ALint RTPrioLevel;
1222 FILE *gLogFile{stderr};
1223 #ifdef _DEBUG
1224 LogLevel gLogLevel{LogWarning};
1225 #else
1226 LogLevel gLogLevel{LogError};
1227 #endif
1229 /************************************************
1230 * Library initialization
1231 ************************************************/
1232 #if defined(_WIN32) && !defined(AL_LIBTYPE_STATIC)
1233 BOOL APIENTRY DllMain(HINSTANCE module, DWORD reason, LPVOID /*reserved*/)
1235 switch(reason)
1237 case DLL_PROCESS_ATTACH:
1238 /* Pin the DLL so we won't get unloaded until the process terminates */
1239 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
1240 reinterpret_cast<WCHAR*>(module), &module);
1241 break;
1243 return TRUE;
1245 #endif
1247 /************************************************
1248 * Device format information
1249 ************************************************/
1250 const ALCchar *DevFmtTypeString(DevFmtType type) noexcept
1252 switch(type)
1254 case DevFmtByte: return "Signed Byte";
1255 case DevFmtUByte: return "Unsigned Byte";
1256 case DevFmtShort: return "Signed Short";
1257 case DevFmtUShort: return "Unsigned Short";
1258 case DevFmtInt: return "Signed Int";
1259 case DevFmtUInt: return "Unsigned Int";
1260 case DevFmtFloat: return "Float";
1262 return "(unknown type)";
1264 const ALCchar *DevFmtChannelsString(DevFmtChannels chans) noexcept
1266 switch(chans)
1268 case DevFmtMono: return "Mono";
1269 case DevFmtStereo: return "Stereo";
1270 case DevFmtQuad: return "Quadraphonic";
1271 case DevFmtX51: return "5.1 Surround";
1272 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1273 case DevFmtX61: return "6.1 Surround";
1274 case DevFmtX71: return "7.1 Surround";
1275 case DevFmtAmbi3D: return "Ambisonic 3D";
1277 return "(unknown channels)";
1280 ALuint BytesFromDevFmt(DevFmtType type) noexcept
1282 switch(type)
1284 case DevFmtByte: return sizeof(ALbyte);
1285 case DevFmtUByte: return sizeof(ALubyte);
1286 case DevFmtShort: return sizeof(ALshort);
1287 case DevFmtUShort: return sizeof(ALushort);
1288 case DevFmtInt: return sizeof(ALint);
1289 case DevFmtUInt: return sizeof(ALuint);
1290 case DevFmtFloat: return sizeof(ALfloat);
1292 return 0;
1294 ALuint ChannelsFromDevFmt(DevFmtChannels chans, ALuint ambiorder) noexcept
1296 switch(chans)
1298 case DevFmtMono: return 1;
1299 case DevFmtStereo: return 2;
1300 case DevFmtQuad: return 4;
1301 case DevFmtX51: return 6;
1302 case DevFmtX51Rear: return 6;
1303 case DevFmtX61: return 7;
1304 case DevFmtX71: return 8;
1305 case DevFmtAmbi3D: return (ambiorder+1) * (ambiorder+1);
1307 return 0;
1310 struct DevFmtPair { DevFmtChannels chans; DevFmtType type; };
1311 static al::optional<DevFmtPair> DecomposeDevFormat(ALenum format)
1313 static const struct {
1314 ALenum format;
1315 DevFmtChannels channels;
1316 DevFmtType type;
1317 } list[] = {
1318 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1319 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1320 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1322 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1323 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1324 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1326 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1327 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1328 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1330 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1331 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1332 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1334 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1335 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1336 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1338 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1339 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1340 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1343 for(const auto &item : list)
1345 if(item.format == format)
1346 return al::make_optional(DevFmtPair{item.channels, item.type});
1349 return al::nullopt;
1352 static ALCboolean IsValidALCType(ALCenum type)
1354 switch(type)
1356 case ALC_BYTE_SOFT:
1357 case ALC_UNSIGNED_BYTE_SOFT:
1358 case ALC_SHORT_SOFT:
1359 case ALC_UNSIGNED_SHORT_SOFT:
1360 case ALC_INT_SOFT:
1361 case ALC_UNSIGNED_INT_SOFT:
1362 case ALC_FLOAT_SOFT:
1363 return ALC_TRUE;
1365 return ALC_FALSE;
1368 static ALCboolean IsValidALCChannels(ALCenum channels)
1370 switch(channels)
1372 case ALC_MONO_SOFT:
1373 case ALC_STEREO_SOFT:
1374 case ALC_QUAD_SOFT:
1375 case ALC_5POINT1_SOFT:
1376 case ALC_6POINT1_SOFT:
1377 case ALC_7POINT1_SOFT:
1378 case ALC_BFORMAT3D_SOFT:
1379 return ALC_TRUE;
1381 return ALC_FALSE;
1384 static ALCboolean IsValidAmbiLayout(ALCenum layout)
1386 switch(layout)
1388 case ALC_ACN_SOFT:
1389 case ALC_FUMA_SOFT:
1390 return ALC_TRUE;
1392 return ALC_FALSE;
1395 static ALCboolean IsValidAmbiScaling(ALCenum scaling)
1397 switch(scaling)
1399 case ALC_N3D_SOFT:
1400 case ALC_SN3D_SOFT:
1401 case ALC_FUMA_SOFT:
1402 return ALC_TRUE;
1404 return ALC_FALSE;
1407 /************************************************
1408 * Miscellaneous ALC helpers
1409 ************************************************/
1411 /* SetDefaultWFXChannelOrder
1413 * Sets the default channel order used by WaveFormatEx.
1415 void SetDefaultWFXChannelOrder(ALCdevice *device)
1417 device->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
1419 switch(device->FmtChans)
1421 case DevFmtMono:
1422 device->RealOut.ChannelIndex[FrontCenter] = 0;
1423 break;
1424 case DevFmtStereo:
1425 device->RealOut.ChannelIndex[FrontLeft] = 0;
1426 device->RealOut.ChannelIndex[FrontRight] = 1;
1427 break;
1428 case DevFmtQuad:
1429 device->RealOut.ChannelIndex[FrontLeft] = 0;
1430 device->RealOut.ChannelIndex[FrontRight] = 1;
1431 device->RealOut.ChannelIndex[BackLeft] = 2;
1432 device->RealOut.ChannelIndex[BackRight] = 3;
1433 break;
1434 case DevFmtX51:
1435 device->RealOut.ChannelIndex[FrontLeft] = 0;
1436 device->RealOut.ChannelIndex[FrontRight] = 1;
1437 device->RealOut.ChannelIndex[FrontCenter] = 2;
1438 device->RealOut.ChannelIndex[LFE] = 3;
1439 device->RealOut.ChannelIndex[SideLeft] = 4;
1440 device->RealOut.ChannelIndex[SideRight] = 5;
1441 break;
1442 case DevFmtX51Rear:
1443 device->RealOut.ChannelIndex[FrontLeft] = 0;
1444 device->RealOut.ChannelIndex[FrontRight] = 1;
1445 device->RealOut.ChannelIndex[FrontCenter] = 2;
1446 device->RealOut.ChannelIndex[LFE] = 3;
1447 device->RealOut.ChannelIndex[BackLeft] = 4;
1448 device->RealOut.ChannelIndex[BackRight] = 5;
1449 break;
1450 case DevFmtX61:
1451 device->RealOut.ChannelIndex[FrontLeft] = 0;
1452 device->RealOut.ChannelIndex[FrontRight] = 1;
1453 device->RealOut.ChannelIndex[FrontCenter] = 2;
1454 device->RealOut.ChannelIndex[LFE] = 3;
1455 device->RealOut.ChannelIndex[BackCenter] = 4;
1456 device->RealOut.ChannelIndex[SideLeft] = 5;
1457 device->RealOut.ChannelIndex[SideRight] = 6;
1458 break;
1459 case DevFmtX71:
1460 device->RealOut.ChannelIndex[FrontLeft] = 0;
1461 device->RealOut.ChannelIndex[FrontRight] = 1;
1462 device->RealOut.ChannelIndex[FrontCenter] = 2;
1463 device->RealOut.ChannelIndex[LFE] = 3;
1464 device->RealOut.ChannelIndex[BackLeft] = 4;
1465 device->RealOut.ChannelIndex[BackRight] = 5;
1466 device->RealOut.ChannelIndex[SideLeft] = 6;
1467 device->RealOut.ChannelIndex[SideRight] = 7;
1468 break;
1469 case DevFmtAmbi3D:
1470 device->RealOut.ChannelIndex[Aux0] = 0;
1471 if(device->mAmbiOrder > 0)
1473 device->RealOut.ChannelIndex[Aux1] = 1;
1474 device->RealOut.ChannelIndex[Aux2] = 2;
1475 device->RealOut.ChannelIndex[Aux3] = 3;
1477 if(device->mAmbiOrder > 1)
1479 device->RealOut.ChannelIndex[Aux4] = 4;
1480 device->RealOut.ChannelIndex[Aux5] = 5;
1481 device->RealOut.ChannelIndex[Aux6] = 6;
1482 device->RealOut.ChannelIndex[Aux7] = 7;
1483 device->RealOut.ChannelIndex[Aux8] = 8;
1485 if(device->mAmbiOrder > 2)
1487 device->RealOut.ChannelIndex[Aux9] = 9;
1488 device->RealOut.ChannelIndex[Aux10] = 10;
1489 device->RealOut.ChannelIndex[Aux11] = 11;
1490 device->RealOut.ChannelIndex[Aux12] = 12;
1491 device->RealOut.ChannelIndex[Aux13] = 13;
1492 device->RealOut.ChannelIndex[Aux14] = 14;
1493 device->RealOut.ChannelIndex[Aux15] = 15;
1495 break;
1499 /* SetDefaultChannelOrder
1501 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1503 void SetDefaultChannelOrder(ALCdevice *device)
1505 device->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
1507 switch(device->FmtChans)
1509 case DevFmtX51Rear:
1510 device->RealOut.ChannelIndex[FrontLeft] = 0;
1511 device->RealOut.ChannelIndex[FrontRight] = 1;
1512 device->RealOut.ChannelIndex[BackLeft] = 2;
1513 device->RealOut.ChannelIndex[BackRight] = 3;
1514 device->RealOut.ChannelIndex[FrontCenter] = 4;
1515 device->RealOut.ChannelIndex[LFE] = 5;
1516 return;
1517 case DevFmtX71:
1518 device->RealOut.ChannelIndex[FrontLeft] = 0;
1519 device->RealOut.ChannelIndex[FrontRight] = 1;
1520 device->RealOut.ChannelIndex[BackLeft] = 2;
1521 device->RealOut.ChannelIndex[BackRight] = 3;
1522 device->RealOut.ChannelIndex[FrontCenter] = 4;
1523 device->RealOut.ChannelIndex[LFE] = 5;
1524 device->RealOut.ChannelIndex[SideLeft] = 6;
1525 device->RealOut.ChannelIndex[SideRight] = 7;
1526 return;
1528 /* Same as WFX order */
1529 case DevFmtMono:
1530 case DevFmtStereo:
1531 case DevFmtQuad:
1532 case DevFmtX51:
1533 case DevFmtX61:
1534 case DevFmtAmbi3D:
1535 SetDefaultWFXChannelOrder(device);
1536 break;
1541 void ALCcontext::processUpdates()
1543 std::lock_guard<std::mutex> _{mPropLock};
1544 if(mDeferUpdates.exchange(false))
1546 /* Tell the mixer to stop applying updates, then wait for any active
1547 * updating to finish, before providing updates.
1549 mHoldUpdates.store(true, std::memory_order_release);
1550 while((mUpdateCount.load(std::memory_order_acquire)&1) != 0)
1551 std::this_thread::yield();
1553 if(!mPropsClean.test_and_set(std::memory_order_acq_rel))
1554 UpdateContextProps(this);
1555 if(!mListener.PropsClean.test_and_set(std::memory_order_acq_rel))
1556 UpdateListenerProps(this);
1557 UpdateAllEffectSlotProps(this);
1558 UpdateAllSourceProps(this);
1560 /* Now with all updates declared, let the mixer continue applying them
1561 * so they all happen at once.
1563 mHoldUpdates.store(false, std::memory_order_release);
1568 /* alcSetError
1570 * Stores the latest ALC device error
1572 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1574 WARN("Error generated on device %p, code 0x%04x\n", decltype(std::declval<void*>()){device},
1575 errorCode);
1576 if(TrapALCError)
1578 #ifdef _WIN32
1579 /* DebugBreak() will cause an exception if there is no debugger */
1580 if(IsDebuggerPresent())
1581 DebugBreak();
1582 #elif defined(SIGTRAP)
1583 raise(SIGTRAP);
1584 #endif
1587 if(device)
1588 device->LastError.store(errorCode);
1589 else
1590 LastNullDeviceError.store(errorCode);
1594 static std::unique_ptr<Compressor> CreateDeviceLimiter(const ALCdevice *device, const ALfloat threshold)
1596 return CompressorInit(static_cast<ALuint>(device->RealOut.Buffer.size()),
1597 static_cast<float>(device->Frequency), AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, 0.001f,
1598 0.002f, 0.0f, 0.0f, threshold, INFINITY, 0.0f, 0.020f, 0.200f);
1601 /* UpdateClockBase
1603 * Updates the device's base clock time with however many samples have been
1604 * done. This is used so frequency changes on the device don't cause the time
1605 * to jump forward or back. Must not be called while the device is running/
1606 * mixing.
1608 static inline void UpdateClockBase(ALCdevice *device)
1610 IncrementRef(device->MixCount);
1611 device->ClockBase += nanoseconds{seconds{device->SamplesDone}} / device->Frequency;
1612 device->SamplesDone = 0;
1613 IncrementRef(device->MixCount);
1616 /* UpdateDeviceParams
1618 * Updates device parameters according to the attribute list (caller is
1619 * responsible for holding the list lock).
1621 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1623 HrtfRequestMode hrtf_userreq{Hrtf_Default};
1624 HrtfRequestMode hrtf_appreq{Hrtf_Default};
1625 ALCenum gainLimiter{device->LimiterState};
1626 const ALCuint old_sends{device->NumAuxSends};
1627 ALCuint new_sends{device->NumAuxSends};
1628 DevFmtChannels oldChans;
1629 DevFmtType oldType;
1630 ALboolean update_failed;
1631 ALCsizei hrtf_id{-1};
1632 ALCuint oldFreq;
1634 if((!attrList || !attrList[0]) && device->Type == Loopback)
1636 WARN("Missing attributes for loopback device\n");
1637 return ALC_INVALID_VALUE;
1640 // Check for attributes
1641 if(attrList && attrList[0])
1643 ALCenum alayout{AL_NONE};
1644 ALCenum ascale{AL_NONE};
1645 ALCenum schans{AL_NONE};
1646 ALCenum stype{AL_NONE};
1647 ALCsizei attrIdx{0};
1648 ALCuint aorder{0};
1649 ALCuint freq{0u};
1651 ALuint numMono{device->NumMonoSources};
1652 ALuint numStereo{device->NumStereoSources};
1653 ALuint numSends{old_sends};
1655 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1656 while(attrList[attrIdx])
1658 switch(attrList[attrIdx])
1660 case ALC_FORMAT_CHANNELS_SOFT:
1661 schans = attrList[attrIdx + 1];
1662 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1663 break;
1665 case ALC_FORMAT_TYPE_SOFT:
1666 stype = attrList[attrIdx + 1];
1667 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1668 break;
1670 case ALC_FREQUENCY:
1671 freq = static_cast<ALuint>(attrList[attrIdx + 1]);
1672 TRACE_ATTR(ALC_FREQUENCY, freq);
1673 break;
1675 case ALC_AMBISONIC_LAYOUT_SOFT:
1676 alayout = attrList[attrIdx + 1];
1677 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1678 break;
1680 case ALC_AMBISONIC_SCALING_SOFT:
1681 ascale = attrList[attrIdx + 1];
1682 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1683 break;
1685 case ALC_AMBISONIC_ORDER_SOFT:
1686 aorder = static_cast<ALuint>(attrList[attrIdx + 1]);
1687 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1688 break;
1690 case ALC_MONO_SOURCES:
1691 numMono = static_cast<ALuint>(attrList[attrIdx + 1]);
1692 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1693 if(numMono > INT_MAX) numMono = 0;
1694 break;
1696 case ALC_STEREO_SOURCES:
1697 numStereo = static_cast<ALuint>(attrList[attrIdx + 1]);
1698 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1699 if(numStereo > INT_MAX) numStereo = 0;
1700 break;
1702 case ALC_MAX_AUXILIARY_SENDS:
1703 numSends = static_cast<ALuint>(attrList[attrIdx + 1]);
1704 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1705 if(numSends > INT_MAX) numSends = 0;
1706 else numSends = minu(numSends, MAX_SENDS);
1707 break;
1709 case ALC_HRTF_SOFT:
1710 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1711 if(attrList[attrIdx + 1] == ALC_FALSE)
1712 hrtf_appreq = Hrtf_Disable;
1713 else if(attrList[attrIdx + 1] == ALC_TRUE)
1714 hrtf_appreq = Hrtf_Enable;
1715 else
1716 hrtf_appreq = Hrtf_Default;
1717 break;
1719 case ALC_HRTF_ID_SOFT:
1720 hrtf_id = attrList[attrIdx + 1];
1721 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1722 break;
1724 case ALC_OUTPUT_LIMITER_SOFT:
1725 gainLimiter = attrList[attrIdx + 1];
1726 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1727 break;
1729 default:
1730 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1731 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1732 break;
1735 attrIdx += 2;
1737 #undef TRACE_ATTR
1739 const bool loopback{device->Type == Loopback};
1740 if(loopback)
1742 if(!schans || !stype || !freq)
1744 WARN("Missing format for loopback device\n");
1745 return ALC_INVALID_VALUE;
1747 if(!IsValidALCChannels(schans) || !IsValidALCType(stype) || freq < MIN_OUTPUT_RATE)
1748 return ALC_INVALID_VALUE;
1749 if(schans == ALC_BFORMAT3D_SOFT)
1751 if(!alayout || !ascale || !aorder)
1753 WARN("Missing ambisonic info for loopback device\n");
1754 return ALC_INVALID_VALUE;
1756 if(!IsValidAmbiLayout(alayout) || !IsValidAmbiScaling(ascale))
1757 return ALC_INVALID_VALUE;
1758 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1759 return ALC_INVALID_VALUE;
1760 if((alayout == ALC_FUMA_SOFT || ascale == ALC_FUMA_SOFT) && aorder > 3)
1761 return ALC_INVALID_VALUE;
1765 /* If a context is already running on the device, stop playback so the
1766 * device attributes can be updated.
1768 if(device->Flags.get<DeviceRunning>())
1769 device->Backend->stop();
1770 device->Flags.unset<DeviceRunning>();
1772 UpdateClockBase(device);
1774 const char *devname{nullptr};
1775 if(!loopback)
1777 devname = device->DeviceName.c_str();
1779 device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
1780 device->UpdateSize = DEFAULT_UPDATE_SIZE;
1781 device->Frequency = DEFAULT_OUTPUT_RATE;
1783 freq = ConfigValueUInt(devname, nullptr, "frequency").value_or(freq);
1784 if(freq < 1)
1785 device->Flags.unset<FrequencyRequest>();
1786 else
1788 freq = maxu(freq, MIN_OUTPUT_RATE);
1790 device->UpdateSize = (device->UpdateSize*freq + device->Frequency/2) /
1791 device->Frequency;
1792 device->BufferSize = (device->BufferSize*freq + device->Frequency/2) /
1793 device->Frequency;
1795 device->Frequency = freq;
1796 device->Flags.set<FrequencyRequest>();
1799 if(auto persizeopt = ConfigValueUInt(devname, nullptr, "period_size"))
1800 device->UpdateSize = clampu(*persizeopt, 64, 8192);
1802 if(auto peropt = ConfigValueUInt(devname, nullptr, "periods"))
1803 device->BufferSize = device->UpdateSize * clampu(*peropt, 2, 16);
1804 else
1805 device->BufferSize = maxu(device->BufferSize, device->UpdateSize*2);
1807 else
1809 device->Frequency = freq;
1810 device->FmtChans = static_cast<DevFmtChannels>(schans);
1811 device->FmtType = static_cast<DevFmtType>(stype);
1812 if(schans == ALC_BFORMAT3D_SOFT)
1814 device->mAmbiOrder = aorder;
1815 device->mAmbiLayout = static_cast<AmbiLayout>(alayout);
1816 device->mAmbiScale = static_cast<AmbiNorm>(ascale);
1820 if(numMono > INT_MAX-numStereo)
1821 numMono = INT_MAX-numStereo;
1822 numMono += numStereo;
1823 if(auto srcsopt = ConfigValueUInt(devname, nullptr, "sources"))
1825 if(*srcsopt <= 0) numMono = 256;
1826 else numMono = *srcsopt;
1828 else
1829 numMono = maxu(numMono, 256);
1830 numStereo = minu(numStereo, numMono);
1831 numMono -= numStereo;
1832 device->SourcesMax = numMono + numStereo;
1834 device->NumMonoSources = numMono;
1835 device->NumStereoSources = numStereo;
1837 if(auto sendsopt = ConfigValueInt(devname, nullptr, "sends"))
1838 new_sends = minu(numSends, static_cast<ALuint>(clampi(*sendsopt, 0, MAX_SENDS)));
1839 else
1840 new_sends = numSends;
1843 if(device->Flags.get<DeviceRunning>())
1844 return ALC_NO_ERROR;
1846 device->AvgSpeakerDist = 0.0f;
1847 device->Uhj_Encoder = nullptr;
1848 device->AmbiDecoder = nullptr;
1849 device->Bs2b = nullptr;
1850 device->PostProcess = nullptr;
1852 device->Stablizer = nullptr;
1853 device->Limiter = nullptr;
1854 device->ChannelDelay.clear();
1856 device->Dry.AmbiMap.fill(BFChannelConfig{});
1857 device->Dry.Buffer = {};
1858 std::fill(std::begin(device->NumChannelsPerOrder), std::end(device->NumChannelsPerOrder), 0u);
1859 device->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
1860 device->RealOut.Buffer = {};
1861 device->MixBuffer.clear();
1862 device->MixBuffer.shrink_to_fit();
1864 UpdateClockBase(device);
1865 device->FixedLatency = nanoseconds::zero();
1867 device->DitherDepth = 0.0f;
1868 device->DitherSeed = DitherRNGSeed;
1870 /*************************************************************************
1871 * Update device format request if HRTF is requested
1873 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
1874 if(device->Type != Loopback)
1876 if(auto hrtfopt = ConfigValueStr(device->DeviceName.c_str(), nullptr, "hrtf"))
1878 const char *hrtf{hrtfopt->c_str()};
1879 if(al::strcasecmp(hrtf, "true") == 0)
1880 hrtf_userreq = Hrtf_Enable;
1881 else if(al::strcasecmp(hrtf, "false") == 0)
1882 hrtf_userreq = Hrtf_Disable;
1883 else if(al::strcasecmp(hrtf, "auto") != 0)
1884 ERR("Unexpected hrtf value: %s\n", hrtf);
1887 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
1889 HrtfEntry *hrtf{nullptr};
1890 if(device->HrtfList.empty())
1891 device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
1892 if(!device->HrtfList.empty())
1894 if(hrtf_id >= 0 && static_cast<ALuint>(hrtf_id) < device->HrtfList.size())
1895 hrtf = GetLoadedHrtf(device->HrtfList[static_cast<ALuint>(hrtf_id)].hrtf);
1896 else
1897 hrtf = GetLoadedHrtf(device->HrtfList.front().hrtf);
1900 if(hrtf)
1902 device->FmtChans = DevFmtStereo;
1903 device->Frequency = hrtf->sampleRate;
1904 device->Flags.set<ChannelsRequest, FrequencyRequest>();
1905 if(HrtfEntry *oldhrtf{device->mHrtf})
1906 oldhrtf->DecRef();
1907 device->mHrtf = hrtf;
1909 else
1911 hrtf_userreq = Hrtf_Default;
1912 hrtf_appreq = Hrtf_Disable;
1913 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
1918 oldFreq = device->Frequency;
1919 oldChans = device->FmtChans;
1920 oldType = device->FmtType;
1922 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u / %u buffer\n",
1923 device->Flags.get<ChannelsRequest>()?"*":"", DevFmtChannelsString(device->FmtChans),
1924 device->Flags.get<SampleTypeRequest>()?"*":"", DevFmtTypeString(device->FmtType),
1925 device->Flags.get<FrequencyRequest>()?"*":"", device->Frequency,
1926 device->UpdateSize, device->BufferSize);
1928 try {
1929 if(device->Backend->reset() == false)
1930 return ALC_INVALID_DEVICE;
1932 catch(std::exception &e) {
1933 ERR("Device reset failed: %s\n", e.what());
1934 return ALC_INVALID_DEVICE;
1937 if(device->FmtChans != oldChans && device->Flags.get<ChannelsRequest>())
1939 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1940 DevFmtChannelsString(device->FmtChans));
1941 device->Flags.unset<ChannelsRequest>();
1943 if(device->FmtType != oldType && device->Flags.get<SampleTypeRequest>())
1945 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1946 DevFmtTypeString(device->FmtType));
1947 device->Flags.unset<SampleTypeRequest>();
1949 if(device->Frequency != oldFreq && device->Flags.get<FrequencyRequest>())
1951 WARN("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1952 device->Flags.unset<FrequencyRequest>();
1955 TRACE("Post-reset: %s, %s, %uhz, %u / %u buffer\n",
1956 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
1957 device->Frequency, device->UpdateSize, device->BufferSize);
1959 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
1961 device->NumAuxSends = new_sends;
1962 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
1963 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
1964 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
1966 /* Enable the stablizer only for formats that have front-left, front-right,
1967 * and front-center outputs.
1969 switch(device->FmtChans)
1971 case DevFmtX51:
1972 case DevFmtX51Rear:
1973 case DevFmtX61:
1974 case DevFmtX71:
1975 if(GetConfigValueBool(device->DeviceName.c_str(), nullptr, "front-stablizer", 0))
1977 auto stablizer = al::make_unique<FrontStablizer>();
1978 /* Initialize band-splitting filters for the front-left and front-
1979 * right channels, with a crossover at 5khz (could be higher).
1981 const ALfloat scale{5000.0f / static_cast<ALfloat>(device->Frequency)};
1983 stablizer->LFilter.init(scale);
1984 stablizer->RFilter = stablizer->LFilter;
1986 device->Stablizer = std::move(stablizer);
1987 /* NOTE: Don't know why this has to be "copied" into a local static
1988 * constexpr variable to avoid a reference on
1989 * FrontStablizer::DelayLength...
1991 static constexpr size_t StablizerDelay{FrontStablizer::DelayLength};
1992 device->FixedLatency += nanoseconds{seconds{StablizerDelay}} / device->Frequency;
1994 break;
1995 case DevFmtMono:
1996 case DevFmtStereo:
1997 case DevFmtQuad:
1998 case DevFmtAmbi3D:
1999 break;
2001 TRACE("Front stablizer %s\n", device->Stablizer ? "enabled" : "disabled");
2003 if(GetConfigValueBool(device->DeviceName.c_str(), nullptr, "dither", 1))
2005 ALint depth{
2006 ConfigValueInt(device->DeviceName.c_str(), nullptr, "dither-depth").value_or(0)};
2007 if(depth <= 0)
2009 switch(device->FmtType)
2011 case DevFmtByte:
2012 case DevFmtUByte:
2013 depth = 8;
2014 break;
2015 case DevFmtShort:
2016 case DevFmtUShort:
2017 depth = 16;
2018 break;
2019 case DevFmtInt:
2020 case DevFmtUInt:
2021 case DevFmtFloat:
2022 break;
2026 if(depth > 0)
2028 depth = clampi(depth, 2, 24);
2029 device->DitherDepth = std::pow(2.0f, static_cast<ALfloat>(depth-1));
2032 if(!(device->DitherDepth > 0.0f))
2033 TRACE("Dithering disabled\n");
2034 else
2035 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device->DitherDepth)+0.5f)+1,
2036 device->DitherDepth);
2038 device->LimiterState = gainLimiter;
2039 if(auto limopt = ConfigValueBool(device->DeviceName.c_str(), nullptr, "output-limiter"))
2040 gainLimiter = *limopt ? ALC_TRUE : ALC_FALSE;
2042 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2043 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2044 * output (where samples must be clamped), and don't for floating-point
2045 * (which can take unclamped samples).
2047 if(gainLimiter == ALC_DONT_CARE_SOFT)
2049 switch(device->FmtType)
2051 case DevFmtByte:
2052 case DevFmtUByte:
2053 case DevFmtShort:
2054 case DevFmtUShort:
2055 case DevFmtInt:
2056 case DevFmtUInt:
2057 gainLimiter = ALC_TRUE;
2058 break;
2059 case DevFmtFloat:
2060 gainLimiter = ALC_FALSE;
2061 break;
2064 if(gainLimiter == ALC_FALSE)
2065 TRACE("Output limiter disabled\n");
2066 else
2068 ALfloat thrshld = 1.0f;
2069 switch(device->FmtType)
2071 case DevFmtByte:
2072 case DevFmtUByte:
2073 thrshld = 127.0f / 128.0f;
2074 break;
2075 case DevFmtShort:
2076 case DevFmtUShort:
2077 thrshld = 32767.0f / 32768.0f;
2078 break;
2079 case DevFmtInt:
2080 case DevFmtUInt:
2081 case DevFmtFloat:
2082 break;
2084 if(device->DitherDepth > 0.0f)
2085 thrshld -= 1.0f / device->DitherDepth;
2087 const float thrshld_dB{std::log10(thrshld) * 20.0f};
2088 auto limiter = CreateDeviceLimiter(device, thrshld_dB);
2089 /* Convert the lookahead from samples to nanosamples to nanoseconds. */
2090 device->FixedLatency += nanoseconds{seconds{limiter->getLookAhead()}} / device->Frequency;
2091 device->Limiter = std::move(limiter);
2092 TRACE("Output limiter enabled, %.4fdB limit\n", thrshld_dB);
2095 TRACE("Fixed device latency: %" PRId64 "ns\n", int64_t{device->FixedLatency.count()});
2097 /* Need to delay returning failure until replacement Send arrays have been
2098 * allocated with the appropriate size.
2100 update_failed = AL_FALSE;
2101 FPUCtl mixer_mode{};
2102 for(ALCcontext *context : *device->mContexts.load())
2104 if(context->mDefaultSlot)
2106 ALeffectslot *slot = context->mDefaultSlot.get();
2107 aluInitEffectPanning(slot, device);
2109 EffectState *state{slot->Effect.State};
2110 state->mOutTarget = device->Dry.Buffer;
2111 if(state->deviceUpdate(device) == AL_FALSE)
2112 update_failed = AL_TRUE;
2113 else
2114 UpdateEffectSlotProps(slot, context);
2117 std::unique_lock<std::mutex> proplock{context->mPropLock};
2118 std::unique_lock<std::mutex> slotlock{context->mEffectSlotLock};
2119 for(auto &sublist : context->mEffectSlotList)
2121 uint64_t usemask = ~sublist.FreeMask;
2122 while(usemask)
2124 ALsizei idx = CTZ64(usemask);
2125 ALeffectslot *slot = sublist.EffectSlots + idx;
2127 usemask &= ~(1_u64 << idx);
2129 aluInitEffectPanning(slot, device);
2131 EffectState *state{slot->Effect.State};
2132 state->mOutTarget = device->Dry.Buffer;
2133 if(state->deviceUpdate(device) == AL_FALSE)
2134 update_failed = AL_TRUE;
2135 else
2136 UpdateEffectSlotProps(slot, context);
2139 slotlock.unlock();
2141 std::unique_lock<std::mutex> srclock{context->mSourceLock};
2142 for(auto &sublist : context->mSourceList)
2144 uint64_t usemask = ~sublist.FreeMask;
2145 while(usemask)
2147 ALsizei idx = CTZ64(usemask);
2148 ALsource *source = sublist.Sources + idx;
2150 usemask &= ~(1_u64 << idx);
2152 if(old_sends != device->NumAuxSends)
2154 if(source->Send.size() > device->NumAuxSends)
2156 auto clear_send = [](ALsource::SendData &send) -> void
2158 if(send.Slot)
2159 DecrementRef(send.Slot->ref);
2160 send.Slot = nullptr;
2162 auto send_begin = source->Send.begin() +
2163 static_cast<ptrdiff_t>(device->NumAuxSends);
2164 std::for_each(send_begin, source->Send.end(), clear_send);
2167 source->Send.resize(device->NumAuxSends,
2168 {nullptr, 1.0f, 1.0f, LOWPASSFREQREF, 1.0f, HIGHPASSFREQREF});
2169 source->Send.shrink_to_fit();
2172 source->PropsClean.clear(std::memory_order_release);
2176 /* Clear any pre-existing voice property structs, in case the number of
2177 * auxiliary sends is changing. Active sources will have updates
2178 * respecified in UpdateAllSourceProps.
2180 ALvoiceProps *vprops{context->mFreeVoiceProps.exchange(nullptr, std::memory_order_acq_rel)};
2181 while(vprops)
2183 ALvoiceProps *next = vprops->next.load(std::memory_order_relaxed);
2184 delete vprops;
2185 vprops = next;
2188 if(device->NumAuxSends < old_sends)
2190 const ALuint num_sends{device->NumAuxSends};
2191 /* Clear extraneous property set sends. */
2192 auto clear_sends = [num_sends](ALvoice &voice) -> void
2194 std::fill(std::begin(voice.mProps.Send)+num_sends, std::end(voice.mProps.Send),
2195 ALvoiceProps::SendData{});
2197 std::fill(voice.mSend.begin()+num_sends, voice.mSend.end(), ALvoice::TargetData{});
2198 auto clear_chan_sends = [num_sends](ALvoice::ChannelData &chandata) -> void
2200 std::fill(chandata.mWetParams.begin()+num_sends, chandata.mWetParams.end(),
2201 SendParams{});
2203 std::for_each(voice.mChans.begin(), voice.mChans.end(), clear_chan_sends);
2205 std::for_each(context->mVoices.begin(), context->mVoices.end(), clear_sends);
2207 auto reset_voice = [device](ALvoice &voice) -> void
2209 delete voice.mUpdate.exchange(nullptr, std::memory_order_acq_rel);
2211 /* Force the voice to stopped if it was stopping. */
2212 ALvoice::State vstate{ALvoice::Stopping};
2213 voice.mPlayState.compare_exchange_strong(vstate, ALvoice::Stopped,
2214 std::memory_order_acquire, std::memory_order_acquire);
2215 if(voice.mSourceID.load(std::memory_order_relaxed) == 0u)
2216 return;
2218 if(device->AvgSpeakerDist > 0.0f)
2220 /* Reinitialize the NFC filters for new parameters. */
2221 const ALfloat w1{SPEEDOFSOUNDMETRESPERSEC /
2222 (device->AvgSpeakerDist * static_cast<float>(device->Frequency))};
2223 auto init_nfc = [w1](ALvoice::ChannelData &chandata) -> void
2224 { chandata.mDryParams.NFCtrlFilter.init(w1); };
2225 std::for_each(voice.mChans.begin(), voice.mChans.begin()+voice.mNumChannels,
2226 init_nfc);
2229 std::for_each(context->mVoices.begin(), context->mVoices.end(), reset_voice);
2230 srclock.unlock();
2232 context->mPropsClean.test_and_set(std::memory_order_release);
2233 UpdateContextProps(context);
2234 context->mListener.PropsClean.test_and_set(std::memory_order_release);
2235 UpdateListenerProps(context);
2236 UpdateAllSourceProps(context);
2238 mixer_mode.leave();
2239 if(update_failed)
2240 return ALC_INVALID_DEVICE;
2242 if(!device->Flags.get<DevicePaused>())
2244 try {
2245 auto backend = device->Backend.get();
2246 if(!backend->start())
2247 throw al::backend_exception{ALC_INVALID_DEVICE, "Backend error"};
2248 device->Flags.set<DeviceRunning>();
2250 catch(al::backend_exception& e) {
2251 WARN("Failed to start playback: %s\n", e.what());
2252 return ALC_INVALID_DEVICE;
2256 return ALC_NO_ERROR;
2260 ALCdevice::ALCdevice(DeviceType type) : Type{type}, mContexts{&EmptyContextArray}
2264 /* ALCdevice::~ALCdevice
2266 * Frees the device structure, and destroys any objects the app failed to
2267 * delete. Called once there's no more references on the device.
2269 ALCdevice::~ALCdevice()
2271 TRACE("Freeing device %p\n", decltype(std::declval<void*>()){this});
2273 Backend = nullptr;
2275 size_t count{std::accumulate(BufferList.cbegin(), BufferList.cend(), size_t{0u},
2276 [](size_t cur, const BufferSubList &sublist) noexcept -> size_t
2277 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2279 if(count > 0)
2280 WARN("%zu Buffer%s not deleted\n", count, (count==1)?"":"s");
2282 count = std::accumulate(EffectList.cbegin(), EffectList.cend(), size_t{0u},
2283 [](size_t cur, const EffectSubList &sublist) noexcept -> size_t
2284 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2286 if(count > 0)
2287 WARN("%zu Effect%s not deleted\n", count, (count==1)?"":"s");
2289 count = std::accumulate(FilterList.cbegin(), FilterList.cend(), size_t{0u},
2290 [](size_t cur, const FilterSubList &sublist) noexcept -> size_t
2291 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2293 if(count > 0)
2294 WARN("%zu Filter%s not deleted\n", count, (count==1)?"":"s");
2296 if(mHrtf)
2297 mHrtf->DecRef();
2298 mHrtf = nullptr;
2300 auto *oldarray = mContexts.exchange(nullptr, std::memory_order_relaxed);
2301 if(oldarray != &EmptyContextArray) delete oldarray;
2305 /* VerifyDevice
2307 * Checks if the device handle is valid, and returns a new reference if so.
2309 static DeviceRef VerifyDevice(ALCdevice *device)
2311 std::lock_guard<std::recursive_mutex> _{ListLock};
2312 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device);
2313 if(iter != DeviceList.cend() && *iter == device)
2314 return *iter;
2315 return nullptr;
2319 ALCcontext::ALCcontext(al::intrusive_ptr<ALCdevice> device) : mDevice{std::move(device)}
2321 mPropsClean.test_and_set(std::memory_order_relaxed);
2324 ALCcontext::~ALCcontext()
2326 TRACE("Freeing context %p\n", decltype(std::declval<void*>()){this});
2328 size_t count{0};
2329 ALcontextProps *cprops{mUpdate.exchange(nullptr, std::memory_order_relaxed)};
2330 if(cprops)
2332 ++count;
2333 delete cprops;
2335 cprops = mFreeContextProps.exchange(nullptr, std::memory_order_acquire);
2336 while(cprops)
2338 ALcontextProps *next{cprops->next.load(std::memory_order_relaxed)};
2339 delete cprops;
2340 cprops = next;
2341 ++count;
2343 TRACE("Freed %zu context property object%s\n", count, (count==1)?"":"s");
2345 count = std::accumulate(mSourceList.cbegin(), mSourceList.cend(), size_t{0u},
2346 [](size_t cur, const SourceSubList &sublist) noexcept -> size_t
2347 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2349 if(count > 0)
2350 WARN("%zu Source%s not deleted\n", count, (count==1)?"":"s");
2351 mSourceList.clear();
2352 mNumSources = 0;
2354 count = 0;
2355 ALeffectslotProps *eprops{mFreeEffectslotProps.exchange(nullptr, std::memory_order_acquire)};
2356 while(eprops)
2358 ALeffectslotProps *next{eprops->next.load(std::memory_order_relaxed)};
2359 if(eprops->State) eprops->State->release();
2360 delete eprops;
2361 eprops = next;
2362 ++count;
2364 TRACE("Freed %zu AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2366 delete mActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed);
2367 mDefaultSlot = nullptr;
2369 count = std::accumulate(mEffectSlotList.cbegin(), mEffectSlotList.cend(), size_t{0u},
2370 [](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t
2371 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2373 if(count > 0)
2374 WARN("%zu AuxiliaryEffectSlot%s not deleted\n", count, (count==1)?"":"s");
2375 mEffectSlotList.clear();
2376 mNumEffectSlots = 0;
2378 count = 0;
2379 ALvoiceProps *vprops{mFreeVoiceProps.exchange(nullptr, std::memory_order_acquire)};
2380 while(vprops)
2382 ALvoiceProps *next{vprops->next.load(std::memory_order_relaxed)};
2383 delete vprops;
2384 vprops = next;
2385 ++count;
2387 TRACE("Freed %zu voice property object%s\n", count, (count==1)?"":"s");
2389 mVoices.clear();
2391 count = 0;
2392 ALlistenerProps *lprops{mListener.Params.Update.exchange(nullptr, std::memory_order_relaxed)};
2393 if(lprops)
2395 ++count;
2396 delete lprops;
2398 lprops = mFreeListenerProps.exchange(nullptr, std::memory_order_acquire);
2399 while(lprops)
2401 ALlistenerProps *next{lprops->next.load(std::memory_order_relaxed)};
2402 delete lprops;
2403 lprops = next;
2404 ++count;
2406 TRACE("Freed %zu listener property object%s\n", count, (count==1)?"":"s");
2408 if(mAsyncEvents)
2410 count = 0;
2411 auto evt_vec = mAsyncEvents->getReadVector();
2412 if(evt_vec.first.len > 0)
2414 al::destroy_n(reinterpret_cast<AsyncEvent*>(evt_vec.first.buf), evt_vec.first.len);
2415 count += evt_vec.first.len;
2417 if(evt_vec.second.len > 0)
2419 al::destroy_n(reinterpret_cast<AsyncEvent*>(evt_vec.second.buf), evt_vec.second.len);
2420 count += evt_vec.second.len;
2422 if(count > 0)
2423 TRACE("Destructed %zu orphaned event%s\n", count, (count==1)?"":"s");
2424 mAsyncEvents->readAdvance(count);
2428 void ALCcontext::init()
2430 if(DefaultEffect.type != AL_EFFECT_NULL && mDevice->Type == Playback)
2432 mDefaultSlot = std::unique_ptr<ALeffectslot>{new ALeffectslot{}};
2433 if(InitEffectSlot(mDefaultSlot.get()) == AL_NO_ERROR)
2434 aluInitEffectPanning(mDefaultSlot.get(), mDevice.get());
2435 else
2437 mDefaultSlot = nullptr;
2438 ERR("Failed to initialize the default effect slot\n");
2442 ALeffectslotArray *auxslots;
2443 if(!mDefaultSlot)
2444 auxslots = ALeffectslot::CreatePtrArray(0);
2445 else
2447 auxslots = ALeffectslot::CreatePtrArray(1);
2448 (*auxslots)[0] = mDefaultSlot.get();
2450 mActiveAuxSlots.store(auxslots, std::memory_order_relaxed);
2452 mExtensionList = alExtList;
2455 mListener.Params.Matrix = alu::Matrix::Identity();
2456 mListener.Params.Velocity = alu::Vector{};
2457 mListener.Params.Gain = mListener.Gain;
2458 mListener.Params.MetersPerUnit = mListener.mMetersPerUnit;
2459 mListener.Params.DopplerFactor = mDopplerFactor;
2460 mListener.Params.SpeedOfSound = mSpeedOfSound * mDopplerVelocity;
2461 mListener.Params.SourceDistanceModel = mSourceDistanceModel;
2462 mListener.Params.mDistanceModel = mDistanceModel;
2465 mAsyncEvents = CreateRingBuffer(511, sizeof(AsyncEvent), false);
2466 StartEventThrd(this);
2469 mVoices.reserve(256);
2470 mVoices.resize(64);
2473 bool ALCcontext::deinit()
2475 if(LocalContext.get() == this)
2477 WARN("%p released while current on thread\n", decltype(std::declval<void*>()){this});
2478 LocalContext.set(nullptr);
2479 release();
2482 ALCcontext *origctx{this};
2483 if(GlobalContext.compare_exchange_strong(origctx, nullptr))
2484 release();
2486 bool ret{};
2487 /* First make sure this context exists in the device's list. */
2488 auto *oldarray = mDevice->mContexts.load(std::memory_order_acquire);
2489 if(auto toremove = static_cast<size_t>(std::count(oldarray->begin(), oldarray->end(), this)))
2491 using ContextArray = al::FlexArray<ALCcontext*>;
2492 auto alloc_ctx_array = [](const size_t count) -> ContextArray*
2494 if(count == 0) return &EmptyContextArray;
2495 return ContextArray::Create(count).release();
2497 auto *newarray = alloc_ctx_array(oldarray->size() - toremove);
2499 /* Copy the current/old context handles to the new array, excluding the
2500 * given context.
2502 std::copy_if(oldarray->begin(), oldarray->end(), newarray->begin(),
2503 std::bind(std::not_equal_to<ALCcontext*>{}, _1, this));
2505 /* Store the new context array in the device. Wait for any current mix
2506 * to finish before deleting the old array.
2508 mDevice->mContexts.store(newarray);
2509 if(oldarray != &EmptyContextArray)
2511 while((mDevice->MixCount.load(std::memory_order_acquire)&1))
2512 std::this_thread::yield();
2513 delete oldarray;
2516 ret = !newarray->empty();
2518 else
2519 ret = !oldarray->empty();
2521 StopEventThrd(this);
2523 return ret;
2527 /* VerifyContext
2529 * Checks if the given context is valid, returning a new reference to it if so.
2531 static ContextRef VerifyContext(ALCcontext *context)
2533 std::lock_guard<std::recursive_mutex> _{ListLock};
2534 auto iter = std::lower_bound(ContextList.cbegin(), ContextList.cend(), context);
2535 if(iter != ContextList.cend() && *iter == context)
2536 return *iter;
2537 return nullptr;
2540 /* GetContextRef
2542 * Returns a new reference to the currently active context for this thread.
2544 ContextRef GetContextRef(void)
2546 ALCcontext *context{LocalContext.get()};
2547 if(context)
2548 context->add_ref();
2549 else
2551 std::lock_guard<std::recursive_mutex> _{ListLock};
2552 context = GlobalContext.load(std::memory_order_acquire);
2553 if(context) context->add_ref();
2555 return ContextRef{context};
2559 /************************************************
2560 * Standard ALC functions
2561 ************************************************/
2563 /* alcGetError
2565 * Return last ALC generated error code for the given device
2567 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2568 START_API_FUNC
2570 DeviceRef dev{VerifyDevice(device)};
2571 if(dev) return dev->LastError.exchange(ALC_NO_ERROR);
2572 return LastNullDeviceError.exchange(ALC_NO_ERROR);
2574 END_API_FUNC
2577 /* alcSuspendContext
2579 * Suspends updates for the given context
2581 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2582 START_API_FUNC
2584 if(!SuspendDefers)
2585 return;
2587 ContextRef ctx{VerifyContext(context)};
2588 if(!ctx)
2589 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2590 else
2591 ctx->deferUpdates();
2593 END_API_FUNC
2595 /* alcProcessContext
2597 * Resumes processing updates for the given context
2599 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2600 START_API_FUNC
2602 if(!SuspendDefers)
2603 return;
2605 ContextRef ctx{VerifyContext(context)};
2606 if(!ctx)
2607 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2608 else
2609 ctx->processUpdates();
2611 END_API_FUNC
2614 /* alcGetString
2616 * Returns information about the device, and error strings
2618 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2619 START_API_FUNC
2621 const ALCchar *value = nullptr;
2623 switch(param)
2625 case ALC_NO_ERROR:
2626 value = alcNoError;
2627 break;
2629 case ALC_INVALID_ENUM:
2630 value = alcErrInvalidEnum;
2631 break;
2633 case ALC_INVALID_VALUE:
2634 value = alcErrInvalidValue;
2635 break;
2637 case ALC_INVALID_DEVICE:
2638 value = alcErrInvalidDevice;
2639 break;
2641 case ALC_INVALID_CONTEXT:
2642 value = alcErrInvalidContext;
2643 break;
2645 case ALC_OUT_OF_MEMORY:
2646 value = alcErrOutOfMemory;
2647 break;
2649 case ALC_DEVICE_SPECIFIER:
2650 value = alcDefaultName;
2651 break;
2653 case ALC_ALL_DEVICES_SPECIFIER:
2654 if(DeviceRef dev{VerifyDevice(Device)})
2655 value = dev->DeviceName.c_str();
2656 else
2658 ProbeAllDevicesList();
2659 value = alcAllDevicesList.c_str();
2661 break;
2663 case ALC_CAPTURE_DEVICE_SPECIFIER:
2664 if(DeviceRef dev{VerifyDevice(Device)})
2665 value = dev->DeviceName.c_str();
2666 else
2668 ProbeCaptureDeviceList();
2669 value = alcCaptureDeviceList.c_str();
2671 break;
2673 /* Default devices are always first in the list */
2674 case ALC_DEFAULT_DEVICE_SPECIFIER:
2675 value = alcDefaultName;
2676 break;
2678 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2679 if(alcAllDevicesList.empty())
2680 ProbeAllDevicesList();
2682 /* Copy first entry as default. */
2683 alcDefaultAllDevicesSpecifier = alcAllDevicesList.c_str();
2684 value = alcDefaultAllDevicesSpecifier.c_str();
2685 break;
2687 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2688 if(alcCaptureDeviceList.empty())
2689 ProbeCaptureDeviceList();
2691 /* Copy first entry as default. */
2692 alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList.c_str();
2693 value = alcCaptureDefaultDeviceSpecifier.c_str();
2694 break;
2696 case ALC_EXTENSIONS:
2697 if(VerifyDevice(Device))
2698 value = alcExtensionList;
2699 else
2700 value = alcNoDeviceExtList;
2701 break;
2703 case ALC_HRTF_SPECIFIER_SOFT:
2704 if(DeviceRef dev{VerifyDevice(Device)})
2706 std::lock_guard<std::mutex> _{dev->StateLock};
2707 value = (dev->mHrtf ? dev->HrtfName.c_str() : "");
2709 else
2710 alcSetError(nullptr, ALC_INVALID_DEVICE);
2711 break;
2713 default:
2714 alcSetError(VerifyDevice(Device).get(), ALC_INVALID_ENUM);
2715 break;
2718 return value;
2720 END_API_FUNC
2723 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
2725 if(device->Type == Capture) return 9;
2726 if(device->Type != Loopback) return 29;
2727 if(device->FmtChans == DevFmtAmbi3D)
2728 return 35;
2729 return 29;
2732 static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span<ALCint> values)
2734 size_t i;
2736 if(values.empty())
2738 alcSetError(device, ALC_INVALID_VALUE);
2739 return 0;
2742 if(!device)
2744 switch(param)
2746 case ALC_MAJOR_VERSION:
2747 values[0] = alcMajorVersion;
2748 return 1;
2749 case ALC_MINOR_VERSION:
2750 values[0] = alcMinorVersion;
2751 return 1;
2753 case ALC_ATTRIBUTES_SIZE:
2754 case ALC_ALL_ATTRIBUTES:
2755 case ALC_FREQUENCY:
2756 case ALC_REFRESH:
2757 case ALC_SYNC:
2758 case ALC_MONO_SOURCES:
2759 case ALC_STEREO_SOURCES:
2760 case ALC_CAPTURE_SAMPLES:
2761 case ALC_FORMAT_CHANNELS_SOFT:
2762 case ALC_FORMAT_TYPE_SOFT:
2763 case ALC_AMBISONIC_LAYOUT_SOFT:
2764 case ALC_AMBISONIC_SCALING_SOFT:
2765 case ALC_AMBISONIC_ORDER_SOFT:
2766 case ALC_MAX_AMBISONIC_ORDER_SOFT:
2767 alcSetError(nullptr, ALC_INVALID_DEVICE);
2768 return 0;
2770 default:
2771 alcSetError(nullptr, ALC_INVALID_ENUM);
2772 return 0;
2774 return 0;
2777 if(device->Type == Capture)
2779 switch(param)
2781 case ALC_ATTRIBUTES_SIZE:
2782 values[0] = NumAttrsForDevice(device);
2783 return 1;
2785 case ALC_ALL_ATTRIBUTES:
2786 i = 0;
2787 if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2788 alcSetError(device, ALC_INVALID_VALUE);
2789 else
2791 std::lock_guard<std::mutex> _{device->StateLock};
2792 values[i++] = ALC_MAJOR_VERSION;
2793 values[i++] = alcMajorVersion;
2794 values[i++] = ALC_MINOR_VERSION;
2795 values[i++] = alcMinorVersion;
2796 values[i++] = ALC_CAPTURE_SAMPLES;
2797 values[i++] = static_cast<int>(device->Backend->availableSamples());
2798 values[i++] = ALC_CONNECTED;
2799 values[i++] = device->Connected.load(std::memory_order_relaxed);
2800 values[i++] = 0;
2802 return i;
2804 case ALC_MAJOR_VERSION:
2805 values[0] = alcMajorVersion;
2806 return 1;
2807 case ALC_MINOR_VERSION:
2808 values[0] = alcMinorVersion;
2809 return 1;
2811 case ALC_CAPTURE_SAMPLES:
2813 std::lock_guard<std::mutex> _{device->StateLock};
2814 values[0] = static_cast<int>(device->Backend->availableSamples());
2816 return 1;
2818 case ALC_CONNECTED:
2820 std::lock_guard<std::mutex> _{device->StateLock};
2821 values[0] = device->Connected.load(std::memory_order_acquire);
2823 return 1;
2825 default:
2826 alcSetError(device, ALC_INVALID_ENUM);
2828 return 0;
2831 /* render device */
2832 switch(param)
2834 case ALC_ATTRIBUTES_SIZE:
2835 values[0] = NumAttrsForDevice(device);
2836 return 1;
2838 case ALC_ALL_ATTRIBUTES:
2839 i = 0;
2840 if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2841 alcSetError(device, ALC_INVALID_VALUE);
2842 else
2844 std::lock_guard<std::mutex> _{device->StateLock};
2845 values[i++] = ALC_MAJOR_VERSION;
2846 values[i++] = alcMajorVersion;
2847 values[i++] = ALC_MINOR_VERSION;
2848 values[i++] = alcMinorVersion;
2849 values[i++] = ALC_EFX_MAJOR_VERSION;
2850 values[i++] = alcEFXMajorVersion;
2851 values[i++] = ALC_EFX_MINOR_VERSION;
2852 values[i++] = alcEFXMinorVersion;
2854 values[i++] = ALC_FREQUENCY;
2855 values[i++] = static_cast<int>(device->Frequency);
2856 if(device->Type != Loopback)
2858 values[i++] = ALC_REFRESH;
2859 values[i++] = static_cast<int>(device->Frequency / device->UpdateSize);
2861 values[i++] = ALC_SYNC;
2862 values[i++] = ALC_FALSE;
2864 else
2866 if(device->FmtChans == DevFmtAmbi3D)
2868 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
2869 values[i++] = static_cast<ALCint>(device->mAmbiLayout);
2871 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
2872 values[i++] = static_cast<ALCint>(device->mAmbiScale);
2874 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
2875 values[i++] = static_cast<ALCint>(device->mAmbiOrder);
2878 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2879 values[i++] = device->FmtChans;
2881 values[i++] = ALC_FORMAT_TYPE_SOFT;
2882 values[i++] = device->FmtType;
2885 values[i++] = ALC_MONO_SOURCES;
2886 values[i++] = static_cast<int>(device->NumMonoSources);
2888 values[i++] = ALC_STEREO_SOURCES;
2889 values[i++] = static_cast<int>(device->NumStereoSources);
2891 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2892 values[i++] = static_cast<ALCint>(device->NumAuxSends);
2894 values[i++] = ALC_HRTF_SOFT;
2895 values[i++] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
2897 values[i++] = ALC_HRTF_STATUS_SOFT;
2898 values[i++] = device->HrtfStatus;
2900 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
2901 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
2903 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
2904 values[i++] = MAX_AMBI_ORDER;
2906 values[i++] = 0;
2908 return i;
2910 case ALC_MAJOR_VERSION:
2911 values[0] = alcMajorVersion;
2912 return 1;
2914 case ALC_MINOR_VERSION:
2915 values[0] = alcMinorVersion;
2916 return 1;
2918 case ALC_EFX_MAJOR_VERSION:
2919 values[0] = alcEFXMajorVersion;
2920 return 1;
2922 case ALC_EFX_MINOR_VERSION:
2923 values[0] = alcEFXMinorVersion;
2924 return 1;
2926 case ALC_FREQUENCY:
2927 values[0] = static_cast<int>(device->Frequency);
2928 return 1;
2930 case ALC_REFRESH:
2931 if(device->Type == Loopback)
2933 alcSetError(device, ALC_INVALID_DEVICE);
2934 return 0;
2937 std::lock_guard<std::mutex> _{device->StateLock};
2938 values[0] = static_cast<int>(device->Frequency / device->UpdateSize);
2940 return 1;
2942 case ALC_SYNC:
2943 if(device->Type == Loopback)
2945 alcSetError(device, ALC_INVALID_DEVICE);
2946 return 0;
2948 values[0] = ALC_FALSE;
2949 return 1;
2951 case ALC_FORMAT_CHANNELS_SOFT:
2952 if(device->Type != Loopback)
2954 alcSetError(device, ALC_INVALID_DEVICE);
2955 return 0;
2957 values[0] = device->FmtChans;
2958 return 1;
2960 case ALC_FORMAT_TYPE_SOFT:
2961 if(device->Type != Loopback)
2963 alcSetError(device, ALC_INVALID_DEVICE);
2964 return 0;
2966 values[0] = device->FmtType;
2967 return 1;
2969 case ALC_AMBISONIC_LAYOUT_SOFT:
2970 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
2972 alcSetError(device, ALC_INVALID_DEVICE);
2973 return 0;
2975 values[0] = static_cast<ALCint>(device->mAmbiLayout);
2976 return 1;
2978 case ALC_AMBISONIC_SCALING_SOFT:
2979 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
2981 alcSetError(device, ALC_INVALID_DEVICE);
2982 return 0;
2984 values[0] = static_cast<ALCint>(device->mAmbiScale);
2985 return 1;
2987 case ALC_AMBISONIC_ORDER_SOFT:
2988 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
2990 alcSetError(device, ALC_INVALID_DEVICE);
2991 return 0;
2993 values[0] = static_cast<int>(device->mAmbiOrder);
2994 return 1;
2996 case ALC_MONO_SOURCES:
2997 values[0] = static_cast<int>(device->NumMonoSources);
2998 return 1;
3000 case ALC_STEREO_SOURCES:
3001 values[0] = static_cast<int>(device->NumStereoSources);
3002 return 1;
3004 case ALC_MAX_AUXILIARY_SENDS:
3005 values[0] = static_cast<ALCint>(device->NumAuxSends);
3006 return 1;
3008 case ALC_CONNECTED:
3010 std::lock_guard<std::mutex> _{device->StateLock};
3011 values[0] = device->Connected.load(std::memory_order_acquire);
3013 return 1;
3015 case ALC_HRTF_SOFT:
3016 values[0] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
3017 return 1;
3019 case ALC_HRTF_STATUS_SOFT:
3020 values[0] = device->HrtfStatus;
3021 return 1;
3023 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3025 std::lock_guard<std::mutex> _{device->StateLock};
3026 device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
3027 values[0] = static_cast<ALCint>(minz(device->HrtfList.size(),
3028 std::numeric_limits<ALCint>::max()));
3030 return 1;
3032 case ALC_OUTPUT_LIMITER_SOFT:
3033 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3034 return 1;
3036 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3037 values[0] = MAX_AMBI_ORDER;
3038 return 1;
3040 default:
3041 alcSetError(device, ALC_INVALID_ENUM);
3043 return 0;
3046 /* alcGetIntegerv
3048 * Returns information about the device and the version of OpenAL
3050 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3051 START_API_FUNC
3053 DeviceRef dev{VerifyDevice(device)};
3054 if(size <= 0 || values == nullptr)
3055 alcSetError(dev.get(), ALC_INVALID_VALUE);
3056 else
3057 GetIntegerv(dev.get(), param, {values, values+size});
3059 END_API_FUNC
3061 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3062 START_API_FUNC
3064 DeviceRef dev{VerifyDevice(device)};
3065 if(size <= 0 || values == nullptr)
3066 alcSetError(dev.get(), ALC_INVALID_VALUE);
3067 else if(!dev || dev->Type == Capture)
3069 auto ivals = al::vector<ALCint>(static_cast<ALuint>(size));
3070 size_t got{GetIntegerv(dev.get(), pname, {ivals.data(), ivals.size()})};
3071 std::copy_n(ivals.begin(), got, values);
3072 return;
3074 /* render device */
3075 switch(pname)
3077 case ALC_ATTRIBUTES_SIZE:
3078 *values = NumAttrsForDevice(dev.get())+4;
3079 break;
3081 case ALC_ALL_ATTRIBUTES:
3082 if(size < NumAttrsForDevice(dev.get())+4)
3083 alcSetError(dev.get(), ALC_INVALID_VALUE);
3084 else
3086 size_t i{0};
3087 std::lock_guard<std::mutex> _{dev->StateLock};
3088 values[i++] = ALC_FREQUENCY;
3089 values[i++] = dev->Frequency;
3091 if(dev->Type != Loopback)
3093 values[i++] = ALC_REFRESH;
3094 values[i++] = dev->Frequency / dev->UpdateSize;
3096 values[i++] = ALC_SYNC;
3097 values[i++] = ALC_FALSE;
3099 else
3101 if(dev->FmtChans == DevFmtAmbi3D)
3103 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3104 values[i++] = static_cast<ALCint64SOFT>(dev->mAmbiLayout);
3106 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3107 values[i++] = static_cast<ALCint64SOFT>(dev->mAmbiScale);
3109 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3110 values[i++] = dev->mAmbiOrder;
3113 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3114 values[i++] = dev->FmtChans;
3116 values[i++] = ALC_FORMAT_TYPE_SOFT;
3117 values[i++] = dev->FmtType;
3120 values[i++] = ALC_MONO_SOURCES;
3121 values[i++] = dev->NumMonoSources;
3123 values[i++] = ALC_STEREO_SOURCES;
3124 values[i++] = dev->NumStereoSources;
3126 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3127 values[i++] = dev->NumAuxSends;
3129 values[i++] = ALC_HRTF_SOFT;
3130 values[i++] = (dev->mHrtf ? ALC_TRUE : ALC_FALSE);
3132 values[i++] = ALC_HRTF_STATUS_SOFT;
3133 values[i++] = dev->HrtfStatus;
3135 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3136 values[i++] = dev->Limiter ? ALC_TRUE : ALC_FALSE;
3138 ClockLatency clock{GetClockLatency(dev.get())};
3139 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3140 values[i++] = clock.ClockTime.count();
3142 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3143 values[i++] = clock.Latency.count();
3145 values[i++] = 0;
3147 break;
3149 case ALC_DEVICE_CLOCK_SOFT:
3150 { std::lock_guard<std::mutex> _{dev->StateLock};
3151 nanoseconds basecount;
3152 ALuint samplecount;
3153 ALuint refcount;
3154 do {
3155 while(((refcount=ReadRef(dev->MixCount))&1) != 0)
3156 std::this_thread::yield();
3157 basecount = dev->ClockBase;
3158 samplecount = dev->SamplesDone;
3159 } while(refcount != ReadRef(dev->MixCount));
3160 basecount += nanoseconds{seconds{samplecount}} / dev->Frequency;
3161 *values = basecount.count();
3163 break;
3165 case ALC_DEVICE_LATENCY_SOFT:
3166 { std::lock_guard<std::mutex> _{dev->StateLock};
3167 ClockLatency clock{GetClockLatency(dev.get())};
3168 *values = clock.Latency.count();
3170 break;
3172 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3173 if(size < 2)
3174 alcSetError(dev.get(), ALC_INVALID_VALUE);
3175 else
3177 std::lock_guard<std::mutex> _{dev->StateLock};
3178 ClockLatency clock{GetClockLatency(dev.get())};
3179 values[0] = clock.ClockTime.count();
3180 values[1] = clock.Latency.count();
3182 break;
3184 default:
3185 auto ivals = al::vector<ALCint>(static_cast<ALuint>(size));
3186 size_t got{GetIntegerv(dev.get(), pname, {ivals.data(), ivals.size()})};
3187 std::copy_n(ivals.begin(), got, values);
3188 break;
3191 END_API_FUNC
3194 /* alcIsExtensionPresent
3196 * Determines if there is support for a particular extension
3198 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3199 START_API_FUNC
3201 DeviceRef dev{VerifyDevice(device)};
3202 if(!extName)
3203 alcSetError(dev.get(), ALC_INVALID_VALUE);
3204 else
3206 size_t len = strlen(extName);
3207 const char *ptr = (dev ? alcExtensionList : alcNoDeviceExtList);
3208 while(ptr && *ptr)
3210 if(al::strncasecmp(ptr, extName, len) == 0 && (ptr[len] == '\0' || isspace(ptr[len])))
3211 return ALC_TRUE;
3213 if((ptr=strchr(ptr, ' ')) != nullptr)
3215 do {
3216 ++ptr;
3217 } while(isspace(*ptr));
3221 return ALC_FALSE;
3223 END_API_FUNC
3226 /* alcGetProcAddress
3228 * Retrieves the function address for a particular extension function
3230 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3231 START_API_FUNC
3233 if(!funcName)
3235 DeviceRef dev{VerifyDevice(device)};
3236 alcSetError(dev.get(), ALC_INVALID_VALUE);
3238 else
3240 for(const auto &func : alcFunctions)
3242 if(strcmp(func.funcName, funcName) == 0)
3243 return func.address;
3246 return nullptr;
3248 END_API_FUNC
3251 /* alcGetEnumValue
3253 * Get the value for a particular ALC enumeration name
3255 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3256 START_API_FUNC
3258 if(!enumName)
3260 DeviceRef dev{VerifyDevice(device)};
3261 alcSetError(dev.get(), ALC_INVALID_VALUE);
3263 else
3265 for(const auto &enm : alcEnumerations)
3267 if(strcmp(enm.enumName, enumName) == 0)
3268 return enm.value;
3271 return 0;
3273 END_API_FUNC
3276 /* alcCreateContext
3278 * Create and attach a context to the given device.
3280 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3281 START_API_FUNC
3283 /* Explicitly hold the list lock while taking the StateLock in case the
3284 * device is asynchronously destroyed, to ensure this new context is
3285 * properly cleaned up after being made.
3287 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3288 DeviceRef dev{VerifyDevice(device)};
3289 if(!dev || dev->Type == Capture || !dev->Connected.load(std::memory_order_relaxed))
3291 listlock.unlock();
3292 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3293 return nullptr;
3295 std::unique_lock<std::mutex> statelock{dev->StateLock};
3296 listlock.unlock();
3298 dev->LastError.store(ALC_NO_ERROR);
3300 ALCenum err{UpdateDeviceParams(dev.get(), attrList)};
3301 if(err != ALC_NO_ERROR)
3303 alcSetError(dev.get(), err);
3304 if(err == ALC_INVALID_DEVICE)
3305 aluHandleDisconnect(dev.get(), "Device update failure");
3306 return nullptr;
3309 ContextRef context{new ALCcontext{dev}};
3310 context->init();
3312 if(auto volopt = ConfigValueFloat(dev->DeviceName.c_str(), nullptr, "volume-adjust"))
3314 const ALfloat valf{*volopt};
3315 if(!std::isfinite(valf))
3316 ERR("volume-adjust must be finite: %f\n", valf);
3317 else
3319 const ALfloat db{clampf(valf, -24.0f, 24.0f)};
3320 if(db != valf)
3321 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3322 context->mGainBoost = std::pow(10.0f, db/20.0f);
3323 TRACE("volume-adjust gain: %f\n", context->mGainBoost);
3326 UpdateListenerProps(context.get());
3329 using ContextArray = al::FlexArray<ALCcontext*>;
3331 /* Allocate a new context array, which holds 1 more than the current/
3332 * old array.
3334 auto *oldarray = device->mContexts.load();
3335 const size_t newcount{oldarray->size()+1};
3336 std::unique_ptr<ContextArray> newarray{ContextArray::Create(newcount)};
3338 /* Copy the current/old context handles to the new array, appending the
3339 * new context.
3341 auto iter = std::copy(oldarray->begin(), oldarray->end(), newarray->begin());
3342 *iter = context.get();
3344 /* Store the new context array in the device. Wait for any current mix
3345 * to finish before deleting the old array.
3347 dev->mContexts.store(newarray.release());
3348 if(oldarray != &EmptyContextArray)
3350 while((dev->MixCount.load(std::memory_order_acquire)&1))
3351 std::this_thread::yield();
3352 delete oldarray;
3355 statelock.unlock();
3358 std::lock_guard<std::recursive_mutex> _{ListLock};
3359 auto iter = std::lower_bound(ContextList.cbegin(), ContextList.cend(), context.get());
3360 ContextList.emplace(iter, context);
3363 if(context->mDefaultSlot)
3365 if(InitializeEffect(context.get(), context->mDefaultSlot.get(), &DefaultEffect) == AL_NO_ERROR)
3366 UpdateEffectSlotProps(context->mDefaultSlot.get(), context.get());
3367 else
3368 ERR("Failed to initialize the default effect\n");
3371 TRACE("Created context %p\n", decltype(std::declval<void*>()){context.get()});
3372 return context.get();
3374 END_API_FUNC
3376 /* alcDestroyContext
3378 * Remove a context from its device
3380 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3381 START_API_FUNC
3383 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3384 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
3385 if(iter == ContextList.end() || *iter != context)
3387 listlock.unlock();
3388 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3389 return;
3391 /* Hold an extra reference to this context so it remains valid until the
3392 * ListLock is released.
3394 ContextRef ctx{std::move(*iter)};
3395 ContextList.erase(iter);
3397 ALCdevice *Device{ctx->mDevice.get()};
3399 std::lock_guard<std::mutex> _{Device->StateLock};
3400 if(!ctx->deinit() && Device->Flags.get<DeviceRunning>())
3402 Device->Backend->stop();
3403 Device->Flags.unset<DeviceRunning>();
3406 END_API_FUNC
3409 /* alcGetCurrentContext
3411 * Returns the currently active context on the calling thread
3413 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3414 START_API_FUNC
3416 ALCcontext *Context{LocalContext.get()};
3417 if(!Context) Context = GlobalContext.load();
3418 return Context;
3420 END_API_FUNC
3422 /* alcGetThreadContext
3424 * Returns the currently active thread-local context
3426 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3427 START_API_FUNC
3428 { return LocalContext.get(); }
3429 END_API_FUNC
3431 /* alcMakeContextCurrent
3433 * Makes the given context the active process-wide context, and removes the
3434 * thread-local context for the calling thread.
3436 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3437 START_API_FUNC
3439 /* context must be valid or nullptr */
3440 ContextRef ctx;
3441 if(context)
3443 ctx = VerifyContext(context);
3444 if(!ctx)
3446 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3447 return ALC_FALSE;
3450 /* Release this reference (if any) to store it in the GlobalContext
3451 * pointer. Take ownership of the reference (if any) that was previously
3452 * stored there.
3454 ctx = ContextRef{GlobalContext.exchange(ctx.release())};
3456 /* Reset (decrement) the previous global reference by replacing it with the
3457 * thread-local context. Take ownership of the thread-local context
3458 * reference (if any), clearing the storage to null.
3460 ctx = ContextRef{LocalContext.get()};
3461 if(ctx) LocalContext.set(nullptr);
3462 /* Reset (decrement) the previous thread-local reference. */
3464 return ALC_TRUE;
3466 END_API_FUNC
3468 /* alcSetThreadContext
3470 * Makes the given context the active context for the current thread
3472 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3473 START_API_FUNC
3475 /* context must be valid or nullptr */
3476 ContextRef ctx;
3477 if(context)
3479 ctx = VerifyContext(context);
3480 if(!ctx)
3482 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3483 return ALC_FALSE;
3486 /* context's reference count is already incremented */
3487 ContextRef old{LocalContext.get()};
3488 LocalContext.set(ctx.release());
3490 return ALC_TRUE;
3492 END_API_FUNC
3495 /* alcGetContextsDevice
3497 * Returns the device that a particular context is attached to
3499 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3500 START_API_FUNC
3502 ContextRef ctx{VerifyContext(Context)};
3503 if(!ctx)
3505 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3506 return nullptr;
3508 return ctx->mDevice.get();
3510 END_API_FUNC
3513 /* alcOpenDevice
3515 * Opens the named device.
3517 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3518 START_API_FUNC
3520 DO_INITCONFIG();
3522 if(!PlaybackFactory)
3524 alcSetError(nullptr, ALC_INVALID_VALUE);
3525 return nullptr;
3528 if(deviceName)
3530 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3531 #ifdef _WIN32
3532 /* Some old Windows apps hardcode these expecting OpenAL to use a
3533 * specific audio API, even when they're not enumerated. Creative's
3534 * router effectively ignores them too.
3536 || al::strcasecmp(deviceName, "DirectSound3D") == 0
3537 || al::strcasecmp(deviceName, "DirectSound") == 0
3538 || al::strcasecmp(deviceName, "MMSYSTEM") == 0
3539 #endif
3540 || al::strcasecmp(deviceName, "openal-soft") == 0)
3541 deviceName = nullptr;
3544 DeviceRef device{new ALCdevice{Playback}};
3546 /* Set output format */
3547 device->FmtChans = DevFmtChannelsDefault;
3548 device->FmtType = DevFmtTypeDefault;
3549 device->Frequency = DEFAULT_OUTPUT_RATE;
3550 device->UpdateSize = DEFAULT_UPDATE_SIZE;
3551 device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
3553 device->SourcesMax = 256;
3554 device->AuxiliaryEffectSlotMax = 64;
3555 device->NumAuxSends = DEFAULT_SENDS;
3557 try {
3558 auto backend = PlaybackFactory->createBackend(device.get(), BackendType::Playback);
3559 backend->open(deviceName);
3560 device->Backend = std::move(backend);
3562 catch(al::backend_exception &e) {
3563 WARN("Failed to open playback device: %s\n", e.what());
3564 alcSetError(nullptr, e.errorCode());
3565 return nullptr;
3568 deviceName = device->DeviceName.c_str();
3569 if(auto chanopt = ConfigValueStr(deviceName, nullptr, "channels"))
3571 static constexpr struct ChannelMap {
3572 const char name[16];
3573 DevFmtChannels chans;
3574 ALuint order;
3575 } chanlist[] = {
3576 { "mono", DevFmtMono, 0 },
3577 { "stereo", DevFmtStereo, 0 },
3578 { "quad", DevFmtQuad, 0 },
3579 { "surround51", DevFmtX51, 0 },
3580 { "surround61", DevFmtX61, 0 },
3581 { "surround71", DevFmtX71, 0 },
3582 { "surround51rear", DevFmtX51Rear, 0 },
3583 { "ambi1", DevFmtAmbi3D, 1 },
3584 { "ambi2", DevFmtAmbi3D, 2 },
3585 { "ambi3", DevFmtAmbi3D, 3 },
3588 const ALCchar *fmt{chanopt->c_str()};
3589 auto iter = std::find_if(std::begin(chanlist), std::end(chanlist),
3590 [fmt](const ChannelMap &entry) -> bool
3591 { return al::strcasecmp(entry.name, fmt) == 0; }
3593 if(iter == std::end(chanlist))
3594 ERR("Unsupported channels: %s\n", fmt);
3595 else
3597 device->FmtChans = iter->chans;
3598 device->mAmbiOrder = iter->order;
3599 device->Flags.set<ChannelsRequest>();
3602 if(auto typeopt = ConfigValueStr(deviceName, nullptr, "sample-type"))
3604 static constexpr struct TypeMap {
3605 const char name[16];
3606 DevFmtType type;
3607 } typelist[] = {
3608 { "int8", DevFmtByte },
3609 { "uint8", DevFmtUByte },
3610 { "int16", DevFmtShort },
3611 { "uint16", DevFmtUShort },
3612 { "int32", DevFmtInt },
3613 { "uint32", DevFmtUInt },
3614 { "float32", DevFmtFloat },
3617 const ALCchar *fmt{typeopt->c_str()};
3618 auto iter = std::find_if(std::begin(typelist), std::end(typelist),
3619 [fmt](const TypeMap &entry) -> bool
3620 { return al::strcasecmp(entry.name, fmt) == 0; }
3622 if(iter == std::end(typelist))
3623 ERR("Unsupported sample-type: %s\n", fmt);
3624 else
3626 device->FmtType = iter->type;
3627 device->Flags.set<SampleTypeRequest>();
3631 if(ALuint freq{ConfigValueUInt(deviceName, nullptr, "frequency").value_or(0)})
3633 if(freq < MIN_OUTPUT_RATE)
3635 ERR("%uhz request clamped to %uhz minimum\n", freq, MIN_OUTPUT_RATE);
3636 freq = MIN_OUTPUT_RATE;
3638 device->UpdateSize = (device->UpdateSize*freq + device->Frequency/2) / device->Frequency;
3639 device->BufferSize = (device->BufferSize*freq + device->Frequency/2) / device->Frequency;
3640 device->Frequency = freq;
3641 device->Flags.set<FrequencyRequest>();
3644 if(auto persizeopt = ConfigValueUInt(deviceName, nullptr, "period_size"))
3645 device->UpdateSize = clampu(*persizeopt, 64, 8192);
3647 if(auto peropt = ConfigValueUInt(deviceName, nullptr, "periods"))
3648 device->BufferSize = device->UpdateSize * clampu(*peropt, 2, 16);
3649 else
3650 device->BufferSize = maxu(device->BufferSize, device->UpdateSize*2);
3652 if(auto srcsopt = ConfigValueUInt(deviceName, nullptr, "sources"))
3654 if(*srcsopt > 0) device->SourcesMax = *srcsopt;
3657 if(auto slotsopt = ConfigValueUInt(deviceName, nullptr, "slots"))
3659 if(*slotsopt > 0)
3660 device->AuxiliaryEffectSlotMax = minu(*slotsopt, INT_MAX);
3663 if(auto sendsopt = ConfigValueInt(deviceName, nullptr, "sends"))
3664 device->NumAuxSends = clampu(DEFAULT_SENDS, 0,
3665 static_cast<ALuint>(clampi(*sendsopt, 0, MAX_SENDS)));
3667 device->NumStereoSources = 1;
3668 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3670 if(auto ambiopt = ConfigValueStr(deviceName, nullptr, "ambi-format"))
3672 const ALCchar *fmt{ambiopt->c_str()};
3673 if(al::strcasecmp(fmt, "fuma") == 0)
3675 if(device->mAmbiOrder > 3)
3676 ERR("FuMa is incompatible with %d%s order ambisonics (up to third-order only)\n",
3677 device->mAmbiOrder,
3678 (((device->mAmbiOrder%100)/10) == 1) ? "th" :
3679 ((device->mAmbiOrder%10) == 1) ? "st" :
3680 ((device->mAmbiOrder%10) == 2) ? "nd" :
3681 ((device->mAmbiOrder%10) == 3) ? "rd" : "th");
3682 else
3684 device->mAmbiLayout = AmbiLayout::FuMa;
3685 device->mAmbiScale = AmbiNorm::FuMa;
3688 else if(al::strcasecmp(fmt, "ambix") == 0 || al::strcasecmp(fmt, "acn+sn3d") == 0)
3690 device->mAmbiLayout = AmbiLayout::ACN;
3691 device->mAmbiScale = AmbiNorm::SN3D;
3693 else if(al::strcasecmp(fmt, "acn+n3d") == 0)
3695 device->mAmbiLayout = AmbiLayout::ACN;
3696 device->mAmbiScale = AmbiNorm::N3D;
3698 else
3699 ERR("Unsupported ambi-format: %s\n", fmt);
3703 std::lock_guard<std::recursive_mutex> _{ListLock};
3704 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3705 DeviceList.emplace(iter, device);
3708 TRACE("Created device %p, \"%s\"\n", decltype(std::declval<void*>()){device.get()},
3709 device->DeviceName.c_str());
3710 return device.get();
3712 END_API_FUNC
3714 /* alcCloseDevice
3716 * Closes the given device.
3718 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3719 START_API_FUNC
3721 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3722 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3723 if(iter == DeviceList.end() || *iter != device)
3725 alcSetError(nullptr, ALC_INVALID_DEVICE);
3726 return ALC_FALSE;
3728 if((*iter)->Type == Capture)
3730 alcSetError(iter->get(), ALC_INVALID_DEVICE);
3731 return ALC_FALSE;
3734 /* Erase the device, and any remaining contexts left on it, from their
3735 * respective lists.
3737 DeviceRef dev{std::move(*iter)};
3738 DeviceList.erase(iter);
3740 std::unique_lock<std::mutex> statelock{dev->StateLock};
3741 al::vector<ContextRef> orphanctxs;
3742 for(ALCcontext *ctx : *dev->mContexts.load())
3744 auto ctxiter = std::lower_bound(ContextList.begin(), ContextList.end(), ctx);
3745 if(ctxiter != ContextList.end() && *ctxiter == ctx)
3747 orphanctxs.emplace_back(std::move(*ctxiter));
3748 ContextList.erase(ctxiter);
3751 listlock.unlock();
3753 for(ContextRef &context : orphanctxs)
3755 WARN("Releasing orphaned context %p\n", decltype(std::declval<void*>()){context.get()});
3756 context->deinit();
3758 orphanctxs.clear();
3760 if(dev->Flags.get<DeviceRunning>())
3761 dev->Backend->stop();
3762 dev->Flags.unset<DeviceRunning>();
3764 return ALC_TRUE;
3766 END_API_FUNC
3769 /************************************************
3770 * ALC capture functions
3771 ************************************************/
3772 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3773 START_API_FUNC
3775 DO_INITCONFIG();
3777 if(!CaptureFactory)
3779 alcSetError(nullptr, ALC_INVALID_VALUE);
3780 return nullptr;
3783 if(samples <= 0)
3785 alcSetError(nullptr, ALC_INVALID_VALUE);
3786 return nullptr;
3789 if(deviceName)
3791 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3792 || al::strcasecmp(deviceName, "openal-soft") == 0)
3793 deviceName = nullptr;
3796 DeviceRef device{new ALCdevice{Capture}};
3798 auto decompfmt = DecomposeDevFormat(format);
3799 if(!decompfmt)
3801 alcSetError(nullptr, ALC_INVALID_ENUM);
3802 return nullptr;
3805 device->Frequency = frequency;
3806 device->FmtChans = decompfmt->chans;
3807 device->FmtType = decompfmt->type;
3808 device->Flags.set<FrequencyRequest, ChannelsRequest, SampleTypeRequest>();
3810 device->UpdateSize = static_cast<ALuint>(samples);
3811 device->BufferSize = static_cast<ALuint>(samples);
3813 try {
3814 TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n",
3815 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
3816 device->Frequency, device->UpdateSize, device->BufferSize);
3818 auto backend = CaptureFactory->createBackend(device.get(), BackendType::Capture);
3819 backend->open(deviceName);
3820 device->Backend = std::move(backend);
3822 catch(al::backend_exception &e) {
3823 WARN("Failed to open capture device: %s\n", e.what());
3824 alcSetError(nullptr, e.errorCode());
3825 return nullptr;
3829 std::lock_guard<std::recursive_mutex> _{ListLock};
3830 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3831 DeviceList.emplace(iter, device);
3834 TRACE("Created capture device %p, \"%s\"\n", decltype(std::declval<void*>()){device.get()},
3835 device->DeviceName.c_str());
3836 return device.get();
3838 END_API_FUNC
3840 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3841 START_API_FUNC
3843 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3844 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3845 if(iter == DeviceList.end() || *iter != device)
3847 alcSetError(nullptr, ALC_INVALID_DEVICE);
3848 return ALC_FALSE;
3850 if((*iter)->Type != Capture)
3852 alcSetError(iter->get(), ALC_INVALID_DEVICE);
3853 return ALC_FALSE;
3856 DeviceRef dev{std::move(*iter)};
3857 DeviceList.erase(iter);
3858 listlock.unlock();
3860 std::lock_guard<std::mutex> _{dev->StateLock};
3861 if(dev->Flags.get<DeviceRunning>())
3862 dev->Backend->stop();
3863 dev->Flags.unset<DeviceRunning>();
3865 return ALC_TRUE;
3867 END_API_FUNC
3869 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3870 START_API_FUNC
3872 DeviceRef dev{VerifyDevice(device)};
3873 if(!dev || dev->Type != Capture)
3875 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3876 return;
3879 std::lock_guard<std::mutex> _{dev->StateLock};
3880 if(!dev->Connected.load(std::memory_order_acquire))
3881 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3882 else if(!dev->Flags.get<DeviceRunning>())
3884 try {
3885 auto backend = dev->Backend.get();
3886 if(!backend->start())
3887 throw al::backend_exception{ALC_INVALID_DEVICE, "Device start failure"};
3888 dev->Flags.set<DeviceRunning>();
3890 catch(al::backend_exception& e) {
3891 aluHandleDisconnect(dev.get(), "%s", e.what());
3892 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3896 END_API_FUNC
3898 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3899 START_API_FUNC
3901 DeviceRef dev{VerifyDevice(device)};
3902 if(!dev || dev->Type != Capture)
3903 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3904 else
3906 std::lock_guard<std::mutex> _{dev->StateLock};
3907 if(dev->Flags.get<DeviceRunning>())
3908 dev->Backend->stop();
3909 dev->Flags.unset<DeviceRunning>();
3912 END_API_FUNC
3914 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3915 START_API_FUNC
3917 DeviceRef dev{VerifyDevice(device)};
3918 if(!dev || dev->Type != Capture)
3920 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3921 return;
3924 if(samples < 0 || (samples > 0 && buffer == nullptr))
3926 alcSetError(dev.get(), ALC_INVALID_VALUE);
3927 return;
3929 if(samples < 1)
3930 return;
3932 std::lock_guard<std::mutex> _{dev->StateLock};
3933 BackendBase *backend{dev->Backend.get()};
3935 const auto usamples = static_cast<ALCuint>(samples);
3936 if(usamples > backend->availableSamples())
3938 alcSetError(dev.get(), ALC_INVALID_VALUE);
3939 return;
3942 auto *bbuffer = static_cast<al::byte*>(buffer);
3943 if(ALCenum err{backend->captureSamples(bbuffer, usamples)})
3944 alcSetError(dev.get(), err);
3946 END_API_FUNC
3949 /************************************************
3950 * ALC loopback functions
3951 ************************************************/
3953 /* alcLoopbackOpenDeviceSOFT
3955 * Open a loopback device, for manual rendering.
3957 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3958 START_API_FUNC
3960 DO_INITCONFIG();
3962 /* Make sure the device name, if specified, is us. */
3963 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3965 alcSetError(nullptr, ALC_INVALID_VALUE);
3966 return nullptr;
3969 DeviceRef device{new ALCdevice{Loopback}};
3971 device->SourcesMax = 256;
3972 device->AuxiliaryEffectSlotMax = 64;
3973 device->NumAuxSends = DEFAULT_SENDS;
3975 //Set output format
3976 device->BufferSize = 0;
3977 device->UpdateSize = 0;
3979 device->Frequency = DEFAULT_OUTPUT_RATE;
3980 device->FmtChans = DevFmtChannelsDefault;
3981 device->FmtType = DevFmtTypeDefault;
3983 if(auto srcsopt = ConfigValueUInt(nullptr, nullptr, "sources"))
3985 if(*srcsopt > 0) device->SourcesMax = *srcsopt;
3988 if(auto slotsopt = ConfigValueUInt(nullptr, nullptr, "slots"))
3990 if(*slotsopt > 0)
3991 device->AuxiliaryEffectSlotMax = minu(*slotsopt, INT_MAX);
3994 if(auto sendsopt = ConfigValueInt(nullptr, nullptr, "sends"))
3995 device->NumAuxSends = clampu(DEFAULT_SENDS, 0,
3996 static_cast<ALuint>(clampi(*sendsopt, 0, MAX_SENDS)));
3998 device->NumStereoSources = 1;
3999 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4001 try {
4002 auto backend = LoopbackBackendFactory::getFactory().createBackend(device.get(),
4003 BackendType::Playback);
4004 backend->open("Loopback");
4005 device->Backend = std::move(backend);
4007 catch(al::backend_exception &e) {
4008 WARN("Failed to open loopback device: %s\n", e.what());
4009 alcSetError(nullptr, e.errorCode());
4010 return nullptr;
4014 std::lock_guard<std::recursive_mutex> _{ListLock};
4015 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
4016 DeviceList.emplace(iter, device);
4019 TRACE("Created loopback device %p\n", decltype(std::declval<void*>()){device.get()});
4020 return device.get();
4022 END_API_FUNC
4024 /* alcIsRenderFormatSupportedSOFT
4026 * Determines if the loopback device supports the given format for rendering.
4028 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4029 START_API_FUNC
4031 DeviceRef dev{VerifyDevice(device)};
4032 if(!dev || dev->Type != Loopback)
4033 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4034 else if(freq <= 0)
4035 alcSetError(dev.get(), ALC_INVALID_VALUE);
4036 else
4038 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4039 return ALC_TRUE;
4042 return ALC_FALSE;
4044 END_API_FUNC
4046 /* alcRenderSamplesSOFT
4048 * Renders some samples into a buffer, using the format last set by the
4049 * attributes given to alcCreateContext.
4051 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4052 START_API_FUNC
4054 DeviceRef dev{VerifyDevice(device)};
4055 if(!dev || dev->Type != Loopback)
4056 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4057 else if(samples < 0 || (samples > 0 && buffer == nullptr))
4058 alcSetError(dev.get(), ALC_INVALID_VALUE);
4059 else
4061 BackendLockGuard _{*dev->Backend};
4062 aluMixData(dev.get(), buffer, static_cast<ALuint>(samples));
4065 END_API_FUNC
4068 /************************************************
4069 * ALC DSP pause/resume functions
4070 ************************************************/
4072 /* alcDevicePauseSOFT
4074 * Pause the DSP to stop audio processing.
4076 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4077 START_API_FUNC
4079 DeviceRef dev{VerifyDevice(device)};
4080 if(!dev || dev->Type != Playback)
4081 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4082 else
4084 std::lock_guard<std::mutex> _{dev->StateLock};
4085 if(dev->Flags.get<DeviceRunning>())
4086 dev->Backend->stop();
4087 dev->Flags.unset<DeviceRunning>();
4088 dev->Flags.set<DevicePaused>();
4091 END_API_FUNC
4093 /* alcDeviceResumeSOFT
4095 * Resume the DSP to restart audio processing.
4097 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4098 START_API_FUNC
4100 DeviceRef dev{VerifyDevice(device)};
4101 if(!dev || dev->Type != Playback)
4103 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4104 return;
4107 std::lock_guard<std::mutex> _{dev->StateLock};
4108 if(!dev->Flags.get<DevicePaused>())
4109 return;
4110 dev->Flags.unset<DevicePaused>();
4111 if(dev->mContexts.load()->empty())
4112 return;
4114 try {
4115 auto backend = dev->Backend.get();
4116 if(!backend->start())
4117 throw al::backend_exception{ALC_INVALID_DEVICE, "Device start failure"};
4118 dev->Flags.set<DeviceRunning>();
4120 catch(al::backend_exception& e) {
4121 aluHandleDisconnect(dev.get(), "%s", e.what());
4122 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4125 END_API_FUNC
4128 /************************************************
4129 * ALC HRTF functions
4130 ************************************************/
4132 /* alcGetStringiSOFT
4134 * Gets a string parameter at the given index.
4136 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4137 START_API_FUNC
4139 DeviceRef dev{VerifyDevice(device)};
4140 if(!dev || dev->Type == Capture)
4141 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4142 else switch(paramName)
4144 case ALC_HRTF_SPECIFIER_SOFT:
4145 if(index >= 0 && static_cast<size_t>(index) < dev->HrtfList.size())
4146 return dev->HrtfList[static_cast<ALuint>(index)].name.c_str();
4147 alcSetError(dev.get(), ALC_INVALID_VALUE);
4148 break;
4150 default:
4151 alcSetError(dev.get(), ALC_INVALID_ENUM);
4152 break;
4155 return nullptr;
4157 END_API_FUNC
4159 /* alcResetDeviceSOFT
4161 * Resets the given device output, using the specified attribute list.
4163 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4164 START_API_FUNC
4166 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4167 DeviceRef dev{VerifyDevice(device)};
4168 if(!dev || dev->Type == Capture)
4170 listlock.unlock();
4171 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4172 return ALC_FALSE;
4174 std::lock_guard<std::mutex> _{dev->StateLock};
4175 listlock.unlock();
4177 /* Force the backend to stop mixing first since we're resetting. Also reset
4178 * the connected state so lost devices can attempt recover.
4180 if(dev->Flags.get<DeviceRunning>())
4181 dev->Backend->stop();
4182 dev->Flags.unset<DeviceRunning>();
4183 device->Connected.store(true);
4185 ALCenum err{UpdateDeviceParams(dev.get(), attribs)};
4186 if LIKELY(err == ALC_NO_ERROR) return ALC_TRUE;
4188 alcSetError(dev.get(), err);
4189 if(err == ALC_INVALID_DEVICE)
4190 aluHandleDisconnect(dev.get(), "Device start failure");
4191 return ALC_FALSE;
4193 END_API_FUNC