Merge pull request #342 from Lopuska/patch-1
[openal-soft.git] / alc / alc.cpp
blob408b3ca36a4df2136b7c9a344c7f8883fb0195b3
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 "alu.h"
71 #include "ambidefs.h"
72 #include "atomic.h"
73 #include "bformatdec.h"
74 #include "bs2b.h"
75 #include "compat.h"
76 #include "cpu_caps.h"
77 #include "devformat.h"
78 #include "effects/base.h"
79 #include "filters/nfc.h"
80 #include "filters/splitter.h"
81 #include "fpu_modes.h"
82 #include "hrtf.h"
83 #include "inprogext.h"
84 #include "intrusive_ptr.h"
85 #include "logging.h"
86 #include "mastering.h"
87 #include "opthelpers.h"
88 #include "ringbuffer.h"
89 #include "strutils.h"
90 #include "threads.h"
91 #include "uhjfilter.h"
92 #include "vecmat.h"
93 #include "vector.h"
95 #include "backends/base.h"
96 #include "backends/null.h"
97 #include "backends/loopback.h"
98 #ifdef HAVE_JACK
99 #include "backends/jack.h"
100 #endif
101 #ifdef HAVE_PULSEAUDIO
102 #include "backends/pulseaudio.h"
103 #endif
104 #ifdef HAVE_ALSA
105 #include "backends/alsa.h"
106 #endif
107 #ifdef HAVE_WASAPI
108 #include "backends/wasapi.h"
109 #endif
110 #ifdef HAVE_COREAUDIO
111 #include "backends/coreaudio.h"
112 #endif
113 #ifdef HAVE_OPENSL
114 #include "backends/opensl.h"
115 #endif
116 #ifdef HAVE_SOLARIS
117 #include "backends/solaris.h"
118 #endif
119 #ifdef HAVE_SNDIO
120 #include "backends/sndio.h"
121 #endif
122 #ifdef HAVE_OSS
123 #include "backends/oss.h"
124 #endif
125 #ifdef HAVE_QSA
126 #include "backends/qsa.h"
127 #endif
128 #ifdef HAVE_DSOUND
129 #include "backends/dsound.h"
130 #endif
131 #ifdef HAVE_WINMM
132 #include "backends/winmm.h"
133 #endif
134 #ifdef HAVE_PORTAUDIO
135 #include "backends/portaudio.h"
136 #endif
137 #ifdef HAVE_SDL2
138 #include "backends/sdl2.h"
139 #endif
140 #ifdef HAVE_WAVE
141 #include "backends/wave.h"
142 #endif
145 namespace {
147 using namespace std::placeholders;
148 using std::chrono::seconds;
149 using std::chrono::nanoseconds;
152 /************************************************
153 * Backends
154 ************************************************/
155 struct BackendInfo {
156 const char *name;
157 BackendFactory& (*getFactory)(void);
160 BackendInfo BackendList[] = {
161 #ifdef HAVE_JACK
162 { "jack", JackBackendFactory::getFactory },
163 #endif
164 #ifdef HAVE_PULSEAUDIO
165 { "pulse", PulseBackendFactory::getFactory },
166 #endif
167 #ifdef HAVE_ALSA
168 { "alsa", AlsaBackendFactory::getFactory },
169 #endif
170 #ifdef HAVE_WASAPI
171 { "wasapi", WasapiBackendFactory::getFactory },
172 #endif
173 #ifdef HAVE_COREAUDIO
174 { "core", CoreAudioBackendFactory::getFactory },
175 #endif
176 #ifdef HAVE_OPENSL
177 { "opensl", OSLBackendFactory::getFactory },
178 #endif
179 #ifdef HAVE_SOLARIS
180 { "solaris", SolarisBackendFactory::getFactory },
181 #endif
182 #ifdef HAVE_SNDIO
183 { "sndio", SndIOBackendFactory::getFactory },
184 #endif
185 #ifdef HAVE_OSS
186 { "oss", OSSBackendFactory::getFactory },
187 #endif
188 #ifdef HAVE_QSA
189 { "qsa", QSABackendFactory::getFactory },
190 #endif
191 #ifdef HAVE_DSOUND
192 { "dsound", DSoundBackendFactory::getFactory },
193 #endif
194 #ifdef HAVE_WINMM
195 { "winmm", WinMMBackendFactory::getFactory },
196 #endif
197 #ifdef HAVE_PORTAUDIO
198 { "port", PortBackendFactory::getFactory },
199 #endif
200 #ifdef HAVE_SDL2
201 { "sdl2", SDL2BackendFactory::getFactory },
202 #endif
204 { "null", NullBackendFactory::getFactory },
205 #ifdef HAVE_WAVE
206 { "wave", WaveBackendFactory::getFactory },
207 #endif
209 auto BackendListEnd = std::end(BackendList);
211 BackendFactory *PlaybackFactory{};
212 BackendFactory *CaptureFactory{};
215 /************************************************
216 * Functions, enums, and errors
217 ************************************************/
218 #define DECL(x) { #x, reinterpret_cast<void*>(x) }
219 const struct {
220 const ALCchar *funcName;
221 ALCvoid *address;
222 } alcFunctions[] = {
223 DECL(alcCreateContext),
224 DECL(alcMakeContextCurrent),
225 DECL(alcProcessContext),
226 DECL(alcSuspendContext),
227 DECL(alcDestroyContext),
228 DECL(alcGetCurrentContext),
229 DECL(alcGetContextsDevice),
230 DECL(alcOpenDevice),
231 DECL(alcCloseDevice),
232 DECL(alcGetError),
233 DECL(alcIsExtensionPresent),
234 DECL(alcGetProcAddress),
235 DECL(alcGetEnumValue),
236 DECL(alcGetString),
237 DECL(alcGetIntegerv),
238 DECL(alcCaptureOpenDevice),
239 DECL(alcCaptureCloseDevice),
240 DECL(alcCaptureStart),
241 DECL(alcCaptureStop),
242 DECL(alcCaptureSamples),
244 DECL(alcSetThreadContext),
245 DECL(alcGetThreadContext),
247 DECL(alcLoopbackOpenDeviceSOFT),
248 DECL(alcIsRenderFormatSupportedSOFT),
249 DECL(alcRenderSamplesSOFT),
251 DECL(alcDevicePauseSOFT),
252 DECL(alcDeviceResumeSOFT),
254 DECL(alcGetStringiSOFT),
255 DECL(alcResetDeviceSOFT),
257 DECL(alcGetInteger64vSOFT),
259 DECL(alEnable),
260 DECL(alDisable),
261 DECL(alIsEnabled),
262 DECL(alGetString),
263 DECL(alGetBooleanv),
264 DECL(alGetIntegerv),
265 DECL(alGetFloatv),
266 DECL(alGetDoublev),
267 DECL(alGetBoolean),
268 DECL(alGetInteger),
269 DECL(alGetFloat),
270 DECL(alGetDouble),
271 DECL(alGetError),
272 DECL(alIsExtensionPresent),
273 DECL(alGetProcAddress),
274 DECL(alGetEnumValue),
275 DECL(alListenerf),
276 DECL(alListener3f),
277 DECL(alListenerfv),
278 DECL(alListeneri),
279 DECL(alListener3i),
280 DECL(alListeneriv),
281 DECL(alGetListenerf),
282 DECL(alGetListener3f),
283 DECL(alGetListenerfv),
284 DECL(alGetListeneri),
285 DECL(alGetListener3i),
286 DECL(alGetListeneriv),
287 DECL(alGenSources),
288 DECL(alDeleteSources),
289 DECL(alIsSource),
290 DECL(alSourcef),
291 DECL(alSource3f),
292 DECL(alSourcefv),
293 DECL(alSourcei),
294 DECL(alSource3i),
295 DECL(alSourceiv),
296 DECL(alGetSourcef),
297 DECL(alGetSource3f),
298 DECL(alGetSourcefv),
299 DECL(alGetSourcei),
300 DECL(alGetSource3i),
301 DECL(alGetSourceiv),
302 DECL(alSourcePlayv),
303 DECL(alSourceStopv),
304 DECL(alSourceRewindv),
305 DECL(alSourcePausev),
306 DECL(alSourcePlay),
307 DECL(alSourceStop),
308 DECL(alSourceRewind),
309 DECL(alSourcePause),
310 DECL(alSourceQueueBuffers),
311 DECL(alSourceUnqueueBuffers),
312 DECL(alGenBuffers),
313 DECL(alDeleteBuffers),
314 DECL(alIsBuffer),
315 DECL(alBufferData),
316 DECL(alBufferf),
317 DECL(alBuffer3f),
318 DECL(alBufferfv),
319 DECL(alBufferi),
320 DECL(alBuffer3i),
321 DECL(alBufferiv),
322 DECL(alGetBufferf),
323 DECL(alGetBuffer3f),
324 DECL(alGetBufferfv),
325 DECL(alGetBufferi),
326 DECL(alGetBuffer3i),
327 DECL(alGetBufferiv),
328 DECL(alDopplerFactor),
329 DECL(alDopplerVelocity),
330 DECL(alSpeedOfSound),
331 DECL(alDistanceModel),
333 DECL(alGenFilters),
334 DECL(alDeleteFilters),
335 DECL(alIsFilter),
336 DECL(alFilteri),
337 DECL(alFilteriv),
338 DECL(alFilterf),
339 DECL(alFilterfv),
340 DECL(alGetFilteri),
341 DECL(alGetFilteriv),
342 DECL(alGetFilterf),
343 DECL(alGetFilterfv),
344 DECL(alGenEffects),
345 DECL(alDeleteEffects),
346 DECL(alIsEffect),
347 DECL(alEffecti),
348 DECL(alEffectiv),
349 DECL(alEffectf),
350 DECL(alEffectfv),
351 DECL(alGetEffecti),
352 DECL(alGetEffectiv),
353 DECL(alGetEffectf),
354 DECL(alGetEffectfv),
355 DECL(alGenAuxiliaryEffectSlots),
356 DECL(alDeleteAuxiliaryEffectSlots),
357 DECL(alIsAuxiliaryEffectSlot),
358 DECL(alAuxiliaryEffectSloti),
359 DECL(alAuxiliaryEffectSlotiv),
360 DECL(alAuxiliaryEffectSlotf),
361 DECL(alAuxiliaryEffectSlotfv),
362 DECL(alGetAuxiliaryEffectSloti),
363 DECL(alGetAuxiliaryEffectSlotiv),
364 DECL(alGetAuxiliaryEffectSlotf),
365 DECL(alGetAuxiliaryEffectSlotfv),
367 DECL(alDeferUpdatesSOFT),
368 DECL(alProcessUpdatesSOFT),
370 DECL(alSourcedSOFT),
371 DECL(alSource3dSOFT),
372 DECL(alSourcedvSOFT),
373 DECL(alGetSourcedSOFT),
374 DECL(alGetSource3dSOFT),
375 DECL(alGetSourcedvSOFT),
376 DECL(alSourcei64SOFT),
377 DECL(alSource3i64SOFT),
378 DECL(alSourcei64vSOFT),
379 DECL(alGetSourcei64SOFT),
380 DECL(alGetSource3i64SOFT),
381 DECL(alGetSourcei64vSOFT),
383 DECL(alGetStringiSOFT),
385 DECL(alBufferStorageSOFT),
386 DECL(alMapBufferSOFT),
387 DECL(alUnmapBufferSOFT),
388 DECL(alFlushMappedBufferSOFT),
390 DECL(alEventControlSOFT),
391 DECL(alEventCallbackSOFT),
392 DECL(alGetPointerSOFT),
393 DECL(alGetPointervSOFT),
395 #undef DECL
397 #define DECL(x) { #x, (x) }
398 constexpr struct {
399 const ALCchar *enumName;
400 ALCenum value;
401 } alcEnumerations[] = {
402 DECL(ALC_INVALID),
403 DECL(ALC_FALSE),
404 DECL(ALC_TRUE),
406 DECL(ALC_MAJOR_VERSION),
407 DECL(ALC_MINOR_VERSION),
408 DECL(ALC_ATTRIBUTES_SIZE),
409 DECL(ALC_ALL_ATTRIBUTES),
410 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
411 DECL(ALC_DEVICE_SPECIFIER),
412 DECL(ALC_ALL_DEVICES_SPECIFIER),
413 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
414 DECL(ALC_EXTENSIONS),
415 DECL(ALC_FREQUENCY),
416 DECL(ALC_REFRESH),
417 DECL(ALC_SYNC),
418 DECL(ALC_MONO_SOURCES),
419 DECL(ALC_STEREO_SOURCES),
420 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
421 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
422 DECL(ALC_CAPTURE_SAMPLES),
423 DECL(ALC_CONNECTED),
425 DECL(ALC_EFX_MAJOR_VERSION),
426 DECL(ALC_EFX_MINOR_VERSION),
427 DECL(ALC_MAX_AUXILIARY_SENDS),
429 DECL(ALC_FORMAT_CHANNELS_SOFT),
430 DECL(ALC_FORMAT_TYPE_SOFT),
432 DECL(ALC_MONO_SOFT),
433 DECL(ALC_STEREO_SOFT),
434 DECL(ALC_QUAD_SOFT),
435 DECL(ALC_5POINT1_SOFT),
436 DECL(ALC_6POINT1_SOFT),
437 DECL(ALC_7POINT1_SOFT),
438 DECL(ALC_BFORMAT3D_SOFT),
440 DECL(ALC_BYTE_SOFT),
441 DECL(ALC_UNSIGNED_BYTE_SOFT),
442 DECL(ALC_SHORT_SOFT),
443 DECL(ALC_UNSIGNED_SHORT_SOFT),
444 DECL(ALC_INT_SOFT),
445 DECL(ALC_UNSIGNED_INT_SOFT),
446 DECL(ALC_FLOAT_SOFT),
448 DECL(ALC_HRTF_SOFT),
449 DECL(ALC_DONT_CARE_SOFT),
450 DECL(ALC_HRTF_STATUS_SOFT),
451 DECL(ALC_HRTF_DISABLED_SOFT),
452 DECL(ALC_HRTF_ENABLED_SOFT),
453 DECL(ALC_HRTF_DENIED_SOFT),
454 DECL(ALC_HRTF_REQUIRED_SOFT),
455 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
456 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
457 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
458 DECL(ALC_HRTF_SPECIFIER_SOFT),
459 DECL(ALC_HRTF_ID_SOFT),
461 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
462 DECL(ALC_AMBISONIC_SCALING_SOFT),
463 DECL(ALC_AMBISONIC_ORDER_SOFT),
464 DECL(ALC_ACN_SOFT),
465 DECL(ALC_FUMA_SOFT),
466 DECL(ALC_N3D_SOFT),
467 DECL(ALC_SN3D_SOFT),
469 DECL(ALC_OUTPUT_LIMITER_SOFT),
471 DECL(ALC_NO_ERROR),
472 DECL(ALC_INVALID_DEVICE),
473 DECL(ALC_INVALID_CONTEXT),
474 DECL(ALC_INVALID_ENUM),
475 DECL(ALC_INVALID_VALUE),
476 DECL(ALC_OUT_OF_MEMORY),
479 DECL(AL_INVALID),
480 DECL(AL_NONE),
481 DECL(AL_FALSE),
482 DECL(AL_TRUE),
484 DECL(AL_SOURCE_RELATIVE),
485 DECL(AL_CONE_INNER_ANGLE),
486 DECL(AL_CONE_OUTER_ANGLE),
487 DECL(AL_PITCH),
488 DECL(AL_POSITION),
489 DECL(AL_DIRECTION),
490 DECL(AL_VELOCITY),
491 DECL(AL_LOOPING),
492 DECL(AL_BUFFER),
493 DECL(AL_GAIN),
494 DECL(AL_MIN_GAIN),
495 DECL(AL_MAX_GAIN),
496 DECL(AL_ORIENTATION),
497 DECL(AL_REFERENCE_DISTANCE),
498 DECL(AL_ROLLOFF_FACTOR),
499 DECL(AL_CONE_OUTER_GAIN),
500 DECL(AL_MAX_DISTANCE),
501 DECL(AL_SEC_OFFSET),
502 DECL(AL_SAMPLE_OFFSET),
503 DECL(AL_BYTE_OFFSET),
504 DECL(AL_SOURCE_TYPE),
505 DECL(AL_STATIC),
506 DECL(AL_STREAMING),
507 DECL(AL_UNDETERMINED),
508 DECL(AL_METERS_PER_UNIT),
509 DECL(AL_LOOP_POINTS_SOFT),
510 DECL(AL_DIRECT_CHANNELS_SOFT),
512 DECL(AL_DIRECT_FILTER),
513 DECL(AL_AUXILIARY_SEND_FILTER),
514 DECL(AL_AIR_ABSORPTION_FACTOR),
515 DECL(AL_ROOM_ROLLOFF_FACTOR),
516 DECL(AL_CONE_OUTER_GAINHF),
517 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
518 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
519 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
521 DECL(AL_SOURCE_STATE),
522 DECL(AL_INITIAL),
523 DECL(AL_PLAYING),
524 DECL(AL_PAUSED),
525 DECL(AL_STOPPED),
527 DECL(AL_BUFFERS_QUEUED),
528 DECL(AL_BUFFERS_PROCESSED),
530 DECL(AL_FORMAT_MONO8),
531 DECL(AL_FORMAT_MONO16),
532 DECL(AL_FORMAT_MONO_FLOAT32),
533 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
534 DECL(AL_FORMAT_STEREO8),
535 DECL(AL_FORMAT_STEREO16),
536 DECL(AL_FORMAT_STEREO_FLOAT32),
537 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
538 DECL(AL_FORMAT_MONO_IMA4),
539 DECL(AL_FORMAT_STEREO_IMA4),
540 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
541 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
542 DECL(AL_FORMAT_QUAD8_LOKI),
543 DECL(AL_FORMAT_QUAD16_LOKI),
544 DECL(AL_FORMAT_QUAD8),
545 DECL(AL_FORMAT_QUAD16),
546 DECL(AL_FORMAT_QUAD32),
547 DECL(AL_FORMAT_51CHN8),
548 DECL(AL_FORMAT_51CHN16),
549 DECL(AL_FORMAT_51CHN32),
550 DECL(AL_FORMAT_61CHN8),
551 DECL(AL_FORMAT_61CHN16),
552 DECL(AL_FORMAT_61CHN32),
553 DECL(AL_FORMAT_71CHN8),
554 DECL(AL_FORMAT_71CHN16),
555 DECL(AL_FORMAT_71CHN32),
556 DECL(AL_FORMAT_REAR8),
557 DECL(AL_FORMAT_REAR16),
558 DECL(AL_FORMAT_REAR32),
559 DECL(AL_FORMAT_MONO_MULAW),
560 DECL(AL_FORMAT_MONO_MULAW_EXT),
561 DECL(AL_FORMAT_STEREO_MULAW),
562 DECL(AL_FORMAT_STEREO_MULAW_EXT),
563 DECL(AL_FORMAT_QUAD_MULAW),
564 DECL(AL_FORMAT_51CHN_MULAW),
565 DECL(AL_FORMAT_61CHN_MULAW),
566 DECL(AL_FORMAT_71CHN_MULAW),
567 DECL(AL_FORMAT_REAR_MULAW),
568 DECL(AL_FORMAT_MONO_ALAW_EXT),
569 DECL(AL_FORMAT_STEREO_ALAW_EXT),
571 DECL(AL_FORMAT_BFORMAT2D_8),
572 DECL(AL_FORMAT_BFORMAT2D_16),
573 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
574 DECL(AL_FORMAT_BFORMAT2D_MULAW),
575 DECL(AL_FORMAT_BFORMAT3D_8),
576 DECL(AL_FORMAT_BFORMAT3D_16),
577 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
578 DECL(AL_FORMAT_BFORMAT3D_MULAW),
580 DECL(AL_FREQUENCY),
581 DECL(AL_BITS),
582 DECL(AL_CHANNELS),
583 DECL(AL_SIZE),
584 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
585 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
587 DECL(AL_SOURCE_RADIUS),
589 DECL(AL_STEREO_ANGLES),
591 DECL(AL_UNUSED),
592 DECL(AL_PENDING),
593 DECL(AL_PROCESSED),
595 DECL(AL_NO_ERROR),
596 DECL(AL_INVALID_NAME),
597 DECL(AL_INVALID_ENUM),
598 DECL(AL_INVALID_VALUE),
599 DECL(AL_INVALID_OPERATION),
600 DECL(AL_OUT_OF_MEMORY),
602 DECL(AL_VENDOR),
603 DECL(AL_VERSION),
604 DECL(AL_RENDERER),
605 DECL(AL_EXTENSIONS),
607 DECL(AL_DOPPLER_FACTOR),
608 DECL(AL_DOPPLER_VELOCITY),
609 DECL(AL_DISTANCE_MODEL),
610 DECL(AL_SPEED_OF_SOUND),
611 DECL(AL_SOURCE_DISTANCE_MODEL),
612 DECL(AL_DEFERRED_UPDATES_SOFT),
613 DECL(AL_GAIN_LIMIT_SOFT),
615 DECL(AL_INVERSE_DISTANCE),
616 DECL(AL_INVERSE_DISTANCE_CLAMPED),
617 DECL(AL_LINEAR_DISTANCE),
618 DECL(AL_LINEAR_DISTANCE_CLAMPED),
619 DECL(AL_EXPONENT_DISTANCE),
620 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
622 DECL(AL_FILTER_TYPE),
623 DECL(AL_FILTER_NULL),
624 DECL(AL_FILTER_LOWPASS),
625 DECL(AL_FILTER_HIGHPASS),
626 DECL(AL_FILTER_BANDPASS),
628 DECL(AL_LOWPASS_GAIN),
629 DECL(AL_LOWPASS_GAINHF),
631 DECL(AL_HIGHPASS_GAIN),
632 DECL(AL_HIGHPASS_GAINLF),
634 DECL(AL_BANDPASS_GAIN),
635 DECL(AL_BANDPASS_GAINHF),
636 DECL(AL_BANDPASS_GAINLF),
638 DECL(AL_EFFECT_TYPE),
639 DECL(AL_EFFECT_NULL),
640 DECL(AL_EFFECT_REVERB),
641 DECL(AL_EFFECT_EAXREVERB),
642 DECL(AL_EFFECT_CHORUS),
643 DECL(AL_EFFECT_DISTORTION),
644 DECL(AL_EFFECT_ECHO),
645 DECL(AL_EFFECT_FLANGER),
646 DECL(AL_EFFECT_PITCH_SHIFTER),
647 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
648 DECL(AL_EFFECT_VOCAL_MORPHER),
649 DECL(AL_EFFECT_RING_MODULATOR),
650 DECL(AL_EFFECT_AUTOWAH),
651 DECL(AL_EFFECT_COMPRESSOR),
652 DECL(AL_EFFECT_EQUALIZER),
653 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
654 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
656 DECL(AL_EFFECTSLOT_EFFECT),
657 DECL(AL_EFFECTSLOT_GAIN),
658 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
659 DECL(AL_EFFECTSLOT_NULL),
661 DECL(AL_EAXREVERB_DENSITY),
662 DECL(AL_EAXREVERB_DIFFUSION),
663 DECL(AL_EAXREVERB_GAIN),
664 DECL(AL_EAXREVERB_GAINHF),
665 DECL(AL_EAXREVERB_GAINLF),
666 DECL(AL_EAXREVERB_DECAY_TIME),
667 DECL(AL_EAXREVERB_DECAY_HFRATIO),
668 DECL(AL_EAXREVERB_DECAY_LFRATIO),
669 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
670 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
671 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
672 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
673 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
674 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
675 DECL(AL_EAXREVERB_ECHO_TIME),
676 DECL(AL_EAXREVERB_ECHO_DEPTH),
677 DECL(AL_EAXREVERB_MODULATION_TIME),
678 DECL(AL_EAXREVERB_MODULATION_DEPTH),
679 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
680 DECL(AL_EAXREVERB_HFREFERENCE),
681 DECL(AL_EAXREVERB_LFREFERENCE),
682 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
683 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
685 DECL(AL_REVERB_DENSITY),
686 DECL(AL_REVERB_DIFFUSION),
687 DECL(AL_REVERB_GAIN),
688 DECL(AL_REVERB_GAINHF),
689 DECL(AL_REVERB_DECAY_TIME),
690 DECL(AL_REVERB_DECAY_HFRATIO),
691 DECL(AL_REVERB_REFLECTIONS_GAIN),
692 DECL(AL_REVERB_REFLECTIONS_DELAY),
693 DECL(AL_REVERB_LATE_REVERB_GAIN),
694 DECL(AL_REVERB_LATE_REVERB_DELAY),
695 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
696 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
697 DECL(AL_REVERB_DECAY_HFLIMIT),
699 DECL(AL_CHORUS_WAVEFORM),
700 DECL(AL_CHORUS_PHASE),
701 DECL(AL_CHORUS_RATE),
702 DECL(AL_CHORUS_DEPTH),
703 DECL(AL_CHORUS_FEEDBACK),
704 DECL(AL_CHORUS_DELAY),
706 DECL(AL_DISTORTION_EDGE),
707 DECL(AL_DISTORTION_GAIN),
708 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
709 DECL(AL_DISTORTION_EQCENTER),
710 DECL(AL_DISTORTION_EQBANDWIDTH),
712 DECL(AL_ECHO_DELAY),
713 DECL(AL_ECHO_LRDELAY),
714 DECL(AL_ECHO_DAMPING),
715 DECL(AL_ECHO_FEEDBACK),
716 DECL(AL_ECHO_SPREAD),
718 DECL(AL_FLANGER_WAVEFORM),
719 DECL(AL_FLANGER_PHASE),
720 DECL(AL_FLANGER_RATE),
721 DECL(AL_FLANGER_DEPTH),
722 DECL(AL_FLANGER_FEEDBACK),
723 DECL(AL_FLANGER_DELAY),
725 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY),
726 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION),
727 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION),
729 DECL(AL_RING_MODULATOR_FREQUENCY),
730 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
731 DECL(AL_RING_MODULATOR_WAVEFORM),
733 DECL(AL_PITCH_SHIFTER_COARSE_TUNE),
734 DECL(AL_PITCH_SHIFTER_FINE_TUNE),
736 DECL(AL_COMPRESSOR_ONOFF),
738 DECL(AL_EQUALIZER_LOW_GAIN),
739 DECL(AL_EQUALIZER_LOW_CUTOFF),
740 DECL(AL_EQUALIZER_MID1_GAIN),
741 DECL(AL_EQUALIZER_MID1_CENTER),
742 DECL(AL_EQUALIZER_MID1_WIDTH),
743 DECL(AL_EQUALIZER_MID2_GAIN),
744 DECL(AL_EQUALIZER_MID2_CENTER),
745 DECL(AL_EQUALIZER_MID2_WIDTH),
746 DECL(AL_EQUALIZER_HIGH_GAIN),
747 DECL(AL_EQUALIZER_HIGH_CUTOFF),
749 DECL(AL_DEDICATED_GAIN),
751 DECL(AL_AUTOWAH_ATTACK_TIME),
752 DECL(AL_AUTOWAH_RELEASE_TIME),
753 DECL(AL_AUTOWAH_RESONANCE),
754 DECL(AL_AUTOWAH_PEAK_GAIN),
756 DECL(AL_VOCAL_MORPHER_PHONEMEA),
757 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING),
758 DECL(AL_VOCAL_MORPHER_PHONEMEB),
759 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING),
760 DECL(AL_VOCAL_MORPHER_WAVEFORM),
761 DECL(AL_VOCAL_MORPHER_RATE),
763 DECL(AL_NUM_RESAMPLERS_SOFT),
764 DECL(AL_DEFAULT_RESAMPLER_SOFT),
765 DECL(AL_SOURCE_RESAMPLER_SOFT),
766 DECL(AL_RESAMPLER_NAME_SOFT),
768 DECL(AL_SOURCE_SPATIALIZE_SOFT),
769 DECL(AL_AUTO_SOFT),
771 DECL(AL_MAP_READ_BIT_SOFT),
772 DECL(AL_MAP_WRITE_BIT_SOFT),
773 DECL(AL_MAP_PERSISTENT_BIT_SOFT),
774 DECL(AL_PRESERVE_DATA_BIT_SOFT),
776 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT),
777 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT),
778 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT),
779 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT),
780 DECL(AL_EVENT_TYPE_ERROR_SOFT),
781 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT),
782 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT),
784 #undef DECL
786 constexpr ALCchar alcNoError[] = "No Error";
787 constexpr ALCchar alcErrInvalidDevice[] = "Invalid Device";
788 constexpr ALCchar alcErrInvalidContext[] = "Invalid Context";
789 constexpr ALCchar alcErrInvalidEnum[] = "Invalid Enum";
790 constexpr ALCchar alcErrInvalidValue[] = "Invalid Value";
791 constexpr ALCchar alcErrOutOfMemory[] = "Out of Memory";
794 /************************************************
795 * Global variables
796 ************************************************/
798 /* Enumerated device names */
799 constexpr ALCchar alcDefaultName[] = "OpenAL Soft\0";
801 std::string alcAllDevicesList;
802 std::string alcCaptureDeviceList;
804 /* Default is always the first in the list */
805 std::string alcDefaultAllDevicesSpecifier;
806 std::string alcCaptureDefaultDeviceSpecifier;
808 /* Default context extensions */
809 constexpr ALchar alExtList[] =
810 "AL_EXT_ALAW "
811 "AL_EXT_BFORMAT "
812 "AL_EXT_DOUBLE "
813 "AL_EXT_EXPONENT_DISTANCE "
814 "AL_EXT_FLOAT32 "
815 "AL_EXT_IMA4 "
816 "AL_EXT_LINEAR_DISTANCE "
817 "AL_EXT_MCFORMATS "
818 "AL_EXT_MULAW "
819 "AL_EXT_MULAW_BFORMAT "
820 "AL_EXT_MULAW_MCFORMATS "
821 "AL_EXT_OFFSET "
822 "AL_EXT_source_distance_model "
823 "AL_EXT_SOURCE_RADIUS "
824 "AL_EXT_STEREO_ANGLES "
825 "AL_LOKI_quadriphonic "
826 "AL_SOFT_block_alignment "
827 "AL_SOFT_deferred_updates "
828 "AL_SOFT_direct_channels "
829 "AL_SOFTX_effect_chain "
830 "AL_SOFTX_events "
831 "AL_SOFTX_filter_gain_ex "
832 "AL_SOFT_gain_clamp_ex "
833 "AL_SOFT_loop_points "
834 "AL_SOFTX_map_buffer "
835 "AL_SOFT_MSADPCM "
836 "AL_SOFT_source_latency "
837 "AL_SOFT_source_length "
838 "AL_SOFT_source_resampler "
839 "AL_SOFT_source_spatialize";
841 std::atomic<ALCenum> LastNullDeviceError{ALC_NO_ERROR};
843 /* Thread-local current context */
844 void ReleaseThreadCtx(ALCcontext *context)
846 const bool result{context->releaseIfNoDelete()};
847 ERR("Context %p current for thread being destroyed%s!\n", context,
848 result ? "" : ", leak detected");
851 class ThreadCtx {
852 ALCcontext *ctx{nullptr};
854 public:
855 ~ThreadCtx()
857 if(ctx)
858 ReleaseThreadCtx(ctx);
859 ctx = nullptr;
862 ALCcontext *get() const noexcept { return ctx; }
863 void set(ALCcontext *ctx_) noexcept { ctx = ctx_; }
865 thread_local ThreadCtx LocalContext;
866 /* Process-wide current context */
867 std::atomic<ALCcontext*> GlobalContext{nullptr};
869 /* Flag to trap ALC device errors */
870 bool TrapALCError{false};
872 /* One-time configuration init control */
873 std::once_flag alc_config_once{};
875 /* Default effect that applies to sources that don't have an effect on send 0 */
876 ALeffect DefaultEffect;
878 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
879 * updates.
881 bool SuspendDefers{true};
884 /************************************************
885 * ALC information
886 ************************************************/
887 constexpr ALCchar alcNoDeviceExtList[] =
888 "ALC_ENUMERATE_ALL_EXT "
889 "ALC_ENUMERATION_EXT "
890 "ALC_EXT_CAPTURE "
891 "ALC_EXT_thread_local_context "
892 "ALC_SOFT_loopback";
893 constexpr ALCchar alcExtensionList[] =
894 "ALC_ENUMERATE_ALL_EXT "
895 "ALC_ENUMERATION_EXT "
896 "ALC_EXT_CAPTURE "
897 "ALC_EXT_DEDICATED "
898 "ALC_EXT_disconnect "
899 "ALC_EXT_EFX "
900 "ALC_EXT_thread_local_context "
901 "ALC_SOFT_device_clock "
902 "ALC_SOFT_HRTF "
903 "ALC_SOFT_loopback "
904 "ALC_SOFT_output_limiter "
905 "ALC_SOFT_pause_device";
906 constexpr ALCint alcMajorVersion = 1;
907 constexpr ALCint alcMinorVersion = 1;
909 constexpr ALCint alcEFXMajorVersion = 1;
910 constexpr ALCint alcEFXMinorVersion = 0;
913 /* To avoid extraneous allocations, a 0-sized FlexArray<ALCcontext*> is defined
914 * globally as a sharable object.
916 al::FlexArray<ALCcontext*> EmptyContextArray{0u};
919 using DeviceRef = al::intrusive_ptr<ALCdevice>;
922 /************************************************
923 * Device lists
924 ************************************************/
925 al::vector<DeviceRef> DeviceList;
926 al::vector<ContextRef> ContextList;
928 std::recursive_mutex ListLock;
931 void alc_initconfig(void)
933 if(auto loglevel = al::getenv("ALSOFT_LOGLEVEL"))
935 long lvl = strtol(loglevel->c_str(), nullptr, 0);
936 if(lvl >= NoLog && lvl <= LogRef)
937 gLogLevel = static_cast<LogLevel>(lvl);
940 if(auto logfile = al::getenv("ALSOFT_LOGFILE"))
942 #ifdef _WIN32
943 std::wstring wname{utf8_to_wstr(logfile->c_str())};
944 FILE *logf{_wfopen(wname.c_str(), L"wt")};
945 #else
946 FILE *logf{fopen(logfile->c_str(), "wt")};
947 #endif
948 if(logf) gLogFile = logf;
949 else ERR("Failed to open log file '%s'\n", logfile->c_str());
952 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION, ALSOFT_GIT_COMMIT_HASH,
953 ALSOFT_GIT_BRANCH);
955 std::string names;
956 if(std::begin(BackendList) == BackendListEnd)
957 names += "(none)";
958 else
960 const al::span<const BackendInfo> infos{std::begin(BackendList), BackendListEnd};
961 names += infos[0].name;
962 for(const auto &backend : infos.subspan(1))
964 names += ", ";
965 names += backend.name;
968 TRACE("Supported backends: %s\n", names.c_str());
970 ReadALConfig();
972 if(auto suspendmode = al::getenv("__ALSOFT_SUSPEND_CONTEXT"))
974 if(strcasecmp(suspendmode->c_str(), "ignore") == 0)
976 SuspendDefers = false;
977 TRACE("Selected context suspend behavior, \"ignore\"\n");
979 else
980 ERR("Unhandled context suspend behavior setting: \"%s\"\n", suspendmode->c_str());
983 int capfilter{0};
984 #if defined(HAVE_SSE4_1)
985 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
986 #elif defined(HAVE_SSE3)
987 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
988 #elif defined(HAVE_SSE2)
989 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
990 #elif defined(HAVE_SSE)
991 capfilter |= CPU_CAP_SSE;
992 #endif
993 #ifdef HAVE_NEON
994 capfilter |= CPU_CAP_NEON;
995 #endif
996 if(auto cpuopt = ConfigValueStr(nullptr, nullptr, "disable-cpu-exts"))
998 const char *str{cpuopt->c_str()};
999 if(strcasecmp(str, "all") == 0)
1000 capfilter = 0;
1001 else
1003 const char *next = str;
1004 do {
1005 str = next;
1006 while(isspace(str[0]))
1007 str++;
1008 next = strchr(str, ',');
1010 if(!str[0] || str[0] == ',')
1011 continue;
1013 size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1014 while(len > 0 && isspace(str[len-1]))
1015 len--;
1016 if(len == 3 && strncasecmp(str, "sse", len) == 0)
1017 capfilter &= ~CPU_CAP_SSE;
1018 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
1019 capfilter &= ~CPU_CAP_SSE2;
1020 else if(len == 4 && strncasecmp(str, "sse3", len) == 0)
1021 capfilter &= ~CPU_CAP_SSE3;
1022 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
1023 capfilter &= ~CPU_CAP_SSE4_1;
1024 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
1025 capfilter &= ~CPU_CAP_NEON;
1026 else
1027 WARN("Invalid CPU extension \"%s\"\n", str);
1028 } while(next++);
1031 FillCPUCaps(capfilter);
1033 #ifdef _WIN32
1034 #define DEF_MIXER_PRIO 1
1035 #else
1036 #define DEF_MIXER_PRIO 0
1037 #endif
1038 RTPrioLevel = ConfigValueInt(nullptr, nullptr, "rt-prio").value_or(DEF_MIXER_PRIO);
1039 #undef DEF_MIXER_PRIO
1041 aluInit();
1042 aluInitMixer();
1044 auto traperr = al::getenv("ALSOFT_TRAP_ERROR");
1045 if(traperr && (strcasecmp(traperr->c_str(), "true") == 0
1046 || strtol(traperr->c_str(), nullptr, 0) == 1))
1048 TrapALError = true;
1049 TrapALCError = true;
1051 else
1053 traperr = al::getenv("ALSOFT_TRAP_AL_ERROR");
1054 if(traperr)
1055 TrapALError = strcasecmp(traperr->c_str(), "true") == 0
1056 || strtol(traperr->c_str(), nullptr, 0) == 1;
1057 else
1058 TrapALError = !!GetConfigValueBool(nullptr, nullptr, "trap-al-error", false);
1060 traperr = al::getenv("ALSOFT_TRAP_ALC_ERROR");
1061 if(traperr)
1062 TrapALCError = strcasecmp(traperr->c_str(), "true") == 0
1063 || strtol(traperr->c_str(), nullptr, 0) == 1;
1064 else
1065 TrapALCError = !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", false);
1068 if(auto boostopt = ConfigValueFloat(nullptr, "reverb", "boost"))
1070 const float valf{std::isfinite(*boostopt) ? clampf(*boostopt, -24.0f, 24.0f) : 0.0f};
1071 ReverbBoost *= std::pow(10.0f, valf / 20.0f);
1074 auto devopt = al::getenv("ALSOFT_DRIVERS");
1075 if(devopt || (devopt=ConfigValueStr(nullptr, nullptr, "drivers")))
1077 auto backendlist_cur = std::begin(BackendList);
1079 bool endlist{true};
1080 const char *next{devopt->c_str()};
1081 do {
1082 const char *devs{next};
1083 while(isspace(devs[0]))
1084 devs++;
1085 next = strchr(devs, ',');
1087 const bool delitem{devs[0] == '-'};
1088 if(devs[0] == '-') devs++;
1090 if(!devs[0] || devs[0] == ',')
1092 endlist = false;
1093 continue;
1095 endlist = true;
1097 size_t len{next ? (static_cast<size_t>(next-devs)) : strlen(devs)};
1098 while(len > 0 && isspace(devs[len-1])) --len;
1099 #ifdef HAVE_WASAPI
1100 /* HACK: For backwards compatibility, convert backend references of
1101 * mmdevapi to wasapi. This should eventually be removed.
1103 if(len == 8 && strncmp(devs, "mmdevapi", len) == 0)
1105 devs = "wasapi";
1106 len = 6;
1108 #endif
1110 auto find_backend = [devs,len](const BackendInfo &backend) -> bool
1111 { return len == strlen(backend.name) && strncmp(backend.name, devs, len) == 0; };
1112 auto this_backend = std::find_if(std::begin(BackendList), BackendListEnd,
1113 find_backend);
1115 if(this_backend == BackendListEnd)
1116 continue;
1118 if(delitem)
1119 BackendListEnd = std::move(this_backend+1, BackendListEnd, this_backend);
1120 else
1121 backendlist_cur = std::rotate(backendlist_cur, this_backend, this_backend+1);
1122 } while(next++);
1124 if(endlist)
1125 BackendListEnd = backendlist_cur;
1128 auto init_backend = [](BackendInfo &backend) -> bool
1130 if(PlaybackFactory && CaptureFactory)
1131 return true;
1133 BackendFactory &factory = backend.getFactory();
1134 if(!factory.init())
1136 WARN("Failed to initialize backend \"%s\"\n", backend.name);
1137 return true;
1140 TRACE("Initialized backend \"%s\"\n", backend.name);
1141 if(!PlaybackFactory && factory.querySupport(BackendType::Playback))
1143 PlaybackFactory = &factory;
1144 TRACE("Added \"%s\" for playback\n", backend.name);
1146 if(!CaptureFactory && factory.querySupport(BackendType::Capture))
1148 CaptureFactory = &factory;
1149 TRACE("Added \"%s\" for capture\n", backend.name);
1151 return false;
1153 BackendListEnd = std::remove_if(std::begin(BackendList), BackendListEnd, init_backend);
1155 LoopbackBackendFactory::getFactory().init();
1157 if(!PlaybackFactory)
1158 WARN("No playback backend available!\n");
1159 if(!CaptureFactory)
1160 WARN("No capture backend available!\n");
1162 if(auto exclopt = ConfigValueStr(nullptr, nullptr, "excludefx"))
1164 const char *next{exclopt->c_str()};
1165 do {
1166 const char *str{next};
1167 next = strchr(str, ',');
1169 if(!str[0] || next == str)
1170 continue;
1172 size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1173 for(const EffectList &effectitem : gEffectList)
1175 if(len == strlen(effectitem.name) &&
1176 strncmp(effectitem.name, str, len) == 0)
1177 DisabledEffects[effectitem.type] = AL_TRUE;
1179 } while(next++);
1182 InitEffect(&DefaultEffect);
1183 auto defrevopt = al::getenv("ALSOFT_DEFAULT_REVERB");
1184 if(defrevopt || (defrevopt=ConfigValueStr(nullptr, nullptr, "default-reverb")))
1185 LoadReverbPreset(defrevopt->c_str(), &DefaultEffect);
1187 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1190 /************************************************
1191 * Device enumeration
1192 ************************************************/
1193 void ProbeAllDevicesList()
1195 DO_INITCONFIG();
1197 std::lock_guard<std::recursive_mutex> _{ListLock};
1198 alcAllDevicesList.clear();
1199 if(PlaybackFactory)
1200 PlaybackFactory->probe(DevProbe::Playback, &alcAllDevicesList);
1202 void ProbeCaptureDeviceList()
1204 DO_INITCONFIG();
1206 std::lock_guard<std::recursive_mutex> _{ListLock};
1207 alcCaptureDeviceList.clear();
1208 if(CaptureFactory)
1209 CaptureFactory->probe(DevProbe::Capture, &alcCaptureDeviceList);
1212 } // namespace
1214 /* Mixing thread piority level */
1215 ALint RTPrioLevel;
1217 FILE *gLogFile{stderr};
1218 #ifdef _DEBUG
1219 LogLevel gLogLevel{LogWarning};
1220 #else
1221 LogLevel gLogLevel{LogError};
1222 #endif
1224 /************************************************
1225 * Library initialization
1226 ************************************************/
1227 #if defined(_WIN32) && !defined(AL_LIBTYPE_STATIC)
1228 BOOL APIENTRY DllMain(HINSTANCE module, DWORD reason, LPVOID /*reserved*/)
1230 switch(reason)
1232 case DLL_PROCESS_ATTACH:
1233 /* Pin the DLL so we won't get unloaded until the process terminates */
1234 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
1235 reinterpret_cast<WCHAR*>(module), &module);
1236 break;
1238 return TRUE;
1240 #endif
1242 /************************************************
1243 * Device format information
1244 ************************************************/
1245 const ALCchar *DevFmtTypeString(DevFmtType type) noexcept
1247 switch(type)
1249 case DevFmtByte: return "Signed Byte";
1250 case DevFmtUByte: return "Unsigned Byte";
1251 case DevFmtShort: return "Signed Short";
1252 case DevFmtUShort: return "Unsigned Short";
1253 case DevFmtInt: return "Signed Int";
1254 case DevFmtUInt: return "Unsigned Int";
1255 case DevFmtFloat: return "Float";
1257 return "(unknown type)";
1259 const ALCchar *DevFmtChannelsString(DevFmtChannels chans) noexcept
1261 switch(chans)
1263 case DevFmtMono: return "Mono";
1264 case DevFmtStereo: return "Stereo";
1265 case DevFmtQuad: return "Quadraphonic";
1266 case DevFmtX51: return "5.1 Surround";
1267 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1268 case DevFmtX61: return "6.1 Surround";
1269 case DevFmtX71: return "7.1 Surround";
1270 case DevFmtAmbi3D: return "Ambisonic 3D";
1272 return "(unknown channels)";
1275 ALuint BytesFromDevFmt(DevFmtType type) noexcept
1277 switch(type)
1279 case DevFmtByte: return sizeof(ALbyte);
1280 case DevFmtUByte: return sizeof(ALubyte);
1281 case DevFmtShort: return sizeof(ALshort);
1282 case DevFmtUShort: return sizeof(ALushort);
1283 case DevFmtInt: return sizeof(ALint);
1284 case DevFmtUInt: return sizeof(ALuint);
1285 case DevFmtFloat: return sizeof(ALfloat);
1287 return 0;
1289 ALuint ChannelsFromDevFmt(DevFmtChannels chans, ALuint ambiorder) noexcept
1291 switch(chans)
1293 case DevFmtMono: return 1;
1294 case DevFmtStereo: return 2;
1295 case DevFmtQuad: return 4;
1296 case DevFmtX51: return 6;
1297 case DevFmtX51Rear: return 6;
1298 case DevFmtX61: return 7;
1299 case DevFmtX71: return 8;
1300 case DevFmtAmbi3D: return (ambiorder+1) * (ambiorder+1);
1302 return 0;
1305 struct DevFmtPair { DevFmtChannels chans; DevFmtType type; };
1306 static al::optional<DevFmtPair> DecomposeDevFormat(ALenum format)
1308 static const struct {
1309 ALenum format;
1310 DevFmtChannels channels;
1311 DevFmtType type;
1312 } list[] = {
1313 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1314 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1315 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1317 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1318 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1319 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1321 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1322 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1323 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1325 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1326 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1327 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1329 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1330 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1331 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1333 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1334 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1335 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1338 for(const auto &item : list)
1340 if(item.format == format)
1341 return al::make_optional(DevFmtPair{item.channels, item.type});
1344 return al::nullopt;
1347 static ALCboolean IsValidALCType(ALCenum type)
1349 switch(type)
1351 case ALC_BYTE_SOFT:
1352 case ALC_UNSIGNED_BYTE_SOFT:
1353 case ALC_SHORT_SOFT:
1354 case ALC_UNSIGNED_SHORT_SOFT:
1355 case ALC_INT_SOFT:
1356 case ALC_UNSIGNED_INT_SOFT:
1357 case ALC_FLOAT_SOFT:
1358 return ALC_TRUE;
1360 return ALC_FALSE;
1363 static ALCboolean IsValidALCChannels(ALCenum channels)
1365 switch(channels)
1367 case ALC_MONO_SOFT:
1368 case ALC_STEREO_SOFT:
1369 case ALC_QUAD_SOFT:
1370 case ALC_5POINT1_SOFT:
1371 case ALC_6POINT1_SOFT:
1372 case ALC_7POINT1_SOFT:
1373 case ALC_BFORMAT3D_SOFT:
1374 return ALC_TRUE;
1376 return ALC_FALSE;
1379 static ALCboolean IsValidAmbiLayout(ALCenum layout)
1381 switch(layout)
1383 case ALC_ACN_SOFT:
1384 case ALC_FUMA_SOFT:
1385 return ALC_TRUE;
1387 return ALC_FALSE;
1390 static ALCboolean IsValidAmbiScaling(ALCenum scaling)
1392 switch(scaling)
1394 case ALC_N3D_SOFT:
1395 case ALC_SN3D_SOFT:
1396 case ALC_FUMA_SOFT:
1397 return ALC_TRUE;
1399 return ALC_FALSE;
1402 /************************************************
1403 * Miscellaneous ALC helpers
1404 ************************************************/
1406 /* SetDefaultWFXChannelOrder
1408 * Sets the default channel order used by WaveFormatEx.
1410 void SetDefaultWFXChannelOrder(ALCdevice *device)
1412 device->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
1414 switch(device->FmtChans)
1416 case DevFmtMono:
1417 device->RealOut.ChannelIndex[FrontCenter] = 0;
1418 break;
1419 case DevFmtStereo:
1420 device->RealOut.ChannelIndex[FrontLeft] = 0;
1421 device->RealOut.ChannelIndex[FrontRight] = 1;
1422 break;
1423 case DevFmtQuad:
1424 device->RealOut.ChannelIndex[FrontLeft] = 0;
1425 device->RealOut.ChannelIndex[FrontRight] = 1;
1426 device->RealOut.ChannelIndex[BackLeft] = 2;
1427 device->RealOut.ChannelIndex[BackRight] = 3;
1428 break;
1429 case DevFmtX51:
1430 device->RealOut.ChannelIndex[FrontLeft] = 0;
1431 device->RealOut.ChannelIndex[FrontRight] = 1;
1432 device->RealOut.ChannelIndex[FrontCenter] = 2;
1433 device->RealOut.ChannelIndex[LFE] = 3;
1434 device->RealOut.ChannelIndex[SideLeft] = 4;
1435 device->RealOut.ChannelIndex[SideRight] = 5;
1436 break;
1437 case DevFmtX51Rear:
1438 device->RealOut.ChannelIndex[FrontLeft] = 0;
1439 device->RealOut.ChannelIndex[FrontRight] = 1;
1440 device->RealOut.ChannelIndex[FrontCenter] = 2;
1441 device->RealOut.ChannelIndex[LFE] = 3;
1442 device->RealOut.ChannelIndex[BackLeft] = 4;
1443 device->RealOut.ChannelIndex[BackRight] = 5;
1444 break;
1445 case DevFmtX61:
1446 device->RealOut.ChannelIndex[FrontLeft] = 0;
1447 device->RealOut.ChannelIndex[FrontRight] = 1;
1448 device->RealOut.ChannelIndex[FrontCenter] = 2;
1449 device->RealOut.ChannelIndex[LFE] = 3;
1450 device->RealOut.ChannelIndex[BackCenter] = 4;
1451 device->RealOut.ChannelIndex[SideLeft] = 5;
1452 device->RealOut.ChannelIndex[SideRight] = 6;
1453 break;
1454 case DevFmtX71:
1455 device->RealOut.ChannelIndex[FrontLeft] = 0;
1456 device->RealOut.ChannelIndex[FrontRight] = 1;
1457 device->RealOut.ChannelIndex[FrontCenter] = 2;
1458 device->RealOut.ChannelIndex[LFE] = 3;
1459 device->RealOut.ChannelIndex[BackLeft] = 4;
1460 device->RealOut.ChannelIndex[BackRight] = 5;
1461 device->RealOut.ChannelIndex[SideLeft] = 6;
1462 device->RealOut.ChannelIndex[SideRight] = 7;
1463 break;
1464 case DevFmtAmbi3D:
1465 device->RealOut.ChannelIndex[Aux0] = 0;
1466 if(device->mAmbiOrder > 0)
1468 device->RealOut.ChannelIndex[Aux1] = 1;
1469 device->RealOut.ChannelIndex[Aux2] = 2;
1470 device->RealOut.ChannelIndex[Aux3] = 3;
1472 if(device->mAmbiOrder > 1)
1474 device->RealOut.ChannelIndex[Aux4] = 4;
1475 device->RealOut.ChannelIndex[Aux5] = 5;
1476 device->RealOut.ChannelIndex[Aux6] = 6;
1477 device->RealOut.ChannelIndex[Aux7] = 7;
1478 device->RealOut.ChannelIndex[Aux8] = 8;
1480 if(device->mAmbiOrder > 2)
1482 device->RealOut.ChannelIndex[Aux9] = 9;
1483 device->RealOut.ChannelIndex[Aux10] = 10;
1484 device->RealOut.ChannelIndex[Aux11] = 11;
1485 device->RealOut.ChannelIndex[Aux12] = 12;
1486 device->RealOut.ChannelIndex[Aux13] = 13;
1487 device->RealOut.ChannelIndex[Aux14] = 14;
1488 device->RealOut.ChannelIndex[Aux15] = 15;
1490 break;
1494 /* SetDefaultChannelOrder
1496 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1498 void SetDefaultChannelOrder(ALCdevice *device)
1500 device->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
1502 switch(device->FmtChans)
1504 case DevFmtX51Rear:
1505 device->RealOut.ChannelIndex[FrontLeft] = 0;
1506 device->RealOut.ChannelIndex[FrontRight] = 1;
1507 device->RealOut.ChannelIndex[BackLeft] = 2;
1508 device->RealOut.ChannelIndex[BackRight] = 3;
1509 device->RealOut.ChannelIndex[FrontCenter] = 4;
1510 device->RealOut.ChannelIndex[LFE] = 5;
1511 return;
1512 case DevFmtX71:
1513 device->RealOut.ChannelIndex[FrontLeft] = 0;
1514 device->RealOut.ChannelIndex[FrontRight] = 1;
1515 device->RealOut.ChannelIndex[BackLeft] = 2;
1516 device->RealOut.ChannelIndex[BackRight] = 3;
1517 device->RealOut.ChannelIndex[FrontCenter] = 4;
1518 device->RealOut.ChannelIndex[LFE] = 5;
1519 device->RealOut.ChannelIndex[SideLeft] = 6;
1520 device->RealOut.ChannelIndex[SideRight] = 7;
1521 return;
1523 /* Same as WFX order */
1524 case DevFmtMono:
1525 case DevFmtStereo:
1526 case DevFmtQuad:
1527 case DevFmtX51:
1528 case DevFmtX61:
1529 case DevFmtAmbi3D:
1530 SetDefaultWFXChannelOrder(device);
1531 break;
1536 void ALCcontext::processUpdates()
1538 std::lock_guard<std::mutex> _{mPropLock};
1539 if(mDeferUpdates.exchange(false))
1541 /* Tell the mixer to stop applying updates, then wait for any active
1542 * updating to finish, before providing updates.
1544 mHoldUpdates.store(true, std::memory_order_release);
1545 while((mUpdateCount.load(std::memory_order_acquire)&1) != 0)
1546 std::this_thread::yield();
1548 if(!mPropsClean.test_and_set(std::memory_order_acq_rel))
1549 UpdateContextProps(this);
1550 if(!mListener.PropsClean.test_and_set(std::memory_order_acq_rel))
1551 UpdateListenerProps(this);
1552 UpdateAllEffectSlotProps(this);
1553 UpdateAllSourceProps(this);
1555 /* Now with all updates declared, let the mixer continue applying them
1556 * so they all happen at once.
1558 mHoldUpdates.store(false, std::memory_order_release);
1563 /* alcSetError
1565 * Stores the latest ALC device error
1567 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1569 WARN("Error generated on device %p, code 0x%04x\n", device, errorCode);
1570 if(TrapALCError)
1572 #ifdef _WIN32
1573 /* DebugBreak() will cause an exception if there is no debugger */
1574 if(IsDebuggerPresent())
1575 DebugBreak();
1576 #elif defined(SIGTRAP)
1577 raise(SIGTRAP);
1578 #endif
1581 if(device)
1582 device->LastError.store(errorCode);
1583 else
1584 LastNullDeviceError.store(errorCode);
1588 static std::unique_ptr<Compressor> CreateDeviceLimiter(const ALCdevice *device, const ALfloat threshold)
1590 return CompressorInit(static_cast<ALuint>(device->RealOut.Buffer.size()), device->Frequency,
1591 AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, 0.001f, 0.002f, 0.0f, 0.0f, threshold,
1592 INFINITY, 0.0f, 0.020f, 0.200f);
1595 /* UpdateClockBase
1597 * Updates the device's base clock time with however many samples have been
1598 * done. This is used so frequency changes on the device don't cause the time
1599 * to jump forward or back. Must not be called while the device is running/
1600 * mixing.
1602 static inline void UpdateClockBase(ALCdevice *device)
1604 IncrementRef(device->MixCount);
1605 device->ClockBase += nanoseconds{seconds{device->SamplesDone}} / device->Frequency;
1606 device->SamplesDone = 0;
1607 IncrementRef(device->MixCount);
1610 /* UpdateDeviceParams
1612 * Updates device parameters according to the attribute list (caller is
1613 * responsible for holding the list lock).
1615 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1617 HrtfRequestMode hrtf_userreq{Hrtf_Default};
1618 HrtfRequestMode hrtf_appreq{Hrtf_Default};
1619 ALCenum gainLimiter{device->LimiterState};
1620 const ALCuint old_sends{device->NumAuxSends};
1621 ALCuint new_sends{device->NumAuxSends};
1622 DevFmtChannels oldChans;
1623 DevFmtType oldType;
1624 ALboolean update_failed;
1625 ALCsizei hrtf_id{-1};
1626 ALCuint oldFreq;
1628 if((!attrList || !attrList[0]) && device->Type == Loopback)
1630 WARN("Missing attributes for loopback device\n");
1631 return ALC_INVALID_VALUE;
1634 // Check for attributes
1635 if(attrList && attrList[0])
1637 ALCenum alayout{AL_NONE};
1638 ALCenum ascale{AL_NONE};
1639 ALCenum schans{AL_NONE};
1640 ALCenum stype{AL_NONE};
1641 ALCsizei attrIdx{0};
1642 ALCuint aorder{0};
1643 ALCuint freq{0u};
1645 ALuint numMono{device->NumMonoSources};
1646 ALuint numStereo{device->NumStereoSources};
1647 ALuint numSends{old_sends};
1649 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1650 while(attrList[attrIdx])
1652 switch(attrList[attrIdx])
1654 case ALC_FORMAT_CHANNELS_SOFT:
1655 schans = attrList[attrIdx + 1];
1656 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1657 break;
1659 case ALC_FORMAT_TYPE_SOFT:
1660 stype = attrList[attrIdx + 1];
1661 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1662 break;
1664 case ALC_FREQUENCY:
1665 freq = static_cast<ALuint>(attrList[attrIdx + 1]);
1666 TRACE_ATTR(ALC_FREQUENCY, freq);
1667 break;
1669 case ALC_AMBISONIC_LAYOUT_SOFT:
1670 alayout = attrList[attrIdx + 1];
1671 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1672 break;
1674 case ALC_AMBISONIC_SCALING_SOFT:
1675 ascale = attrList[attrIdx + 1];
1676 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1677 break;
1679 case ALC_AMBISONIC_ORDER_SOFT:
1680 aorder = static_cast<ALuint>(attrList[attrIdx + 1]);
1681 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1682 break;
1684 case ALC_MONO_SOURCES:
1685 numMono = static_cast<ALuint>(attrList[attrIdx + 1]);
1686 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1687 if(numMono > INT_MAX) numMono = 0;
1688 break;
1690 case ALC_STEREO_SOURCES:
1691 numStereo = static_cast<ALuint>(attrList[attrIdx + 1]);
1692 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1693 if(numStereo > INT_MAX) numStereo = 0;
1694 break;
1696 case ALC_MAX_AUXILIARY_SENDS:
1697 numSends = static_cast<ALuint>(attrList[attrIdx + 1]);
1698 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1699 if(numSends > INT_MAX) numSends = 0;
1700 else numSends = minu(numSends, MAX_SENDS);
1701 break;
1703 case ALC_HRTF_SOFT:
1704 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1705 if(attrList[attrIdx + 1] == ALC_FALSE)
1706 hrtf_appreq = Hrtf_Disable;
1707 else if(attrList[attrIdx + 1] == ALC_TRUE)
1708 hrtf_appreq = Hrtf_Enable;
1709 else
1710 hrtf_appreq = Hrtf_Default;
1711 break;
1713 case ALC_HRTF_ID_SOFT:
1714 hrtf_id = attrList[attrIdx + 1];
1715 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1716 break;
1718 case ALC_OUTPUT_LIMITER_SOFT:
1719 gainLimiter = attrList[attrIdx + 1];
1720 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1721 break;
1723 default:
1724 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1725 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1726 break;
1729 attrIdx += 2;
1731 #undef TRACE_ATTR
1733 const bool loopback{device->Type == Loopback};
1734 if(loopback)
1736 if(!schans || !stype || !freq)
1738 WARN("Missing format for loopback device\n");
1739 return ALC_INVALID_VALUE;
1741 if(!IsValidALCChannels(schans) || !IsValidALCType(stype) || freq < MIN_OUTPUT_RATE)
1742 return ALC_INVALID_VALUE;
1743 if(schans == ALC_BFORMAT3D_SOFT)
1745 if(!alayout || !ascale || !aorder)
1747 WARN("Missing ambisonic info for loopback device\n");
1748 return ALC_INVALID_VALUE;
1750 if(!IsValidAmbiLayout(alayout) || !IsValidAmbiScaling(ascale))
1751 return ALC_INVALID_VALUE;
1752 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1753 return ALC_INVALID_VALUE;
1754 if((alayout == ALC_FUMA_SOFT || ascale == ALC_FUMA_SOFT) && aorder > 3)
1755 return ALC_INVALID_VALUE;
1759 /* If a context is already running on the device, stop playback so the
1760 * device attributes can be updated.
1762 if(device->Flags.get<DeviceRunning>())
1763 device->Backend->stop();
1764 device->Flags.unset<DeviceRunning>();
1766 UpdateClockBase(device);
1768 const char *devname{nullptr};
1769 if(!loopback)
1771 devname = device->DeviceName.c_str();
1773 device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
1774 device->UpdateSize = DEFAULT_UPDATE_SIZE;
1775 device->Frequency = DEFAULT_OUTPUT_RATE;
1777 freq = ConfigValueUInt(devname, nullptr, "frequency").value_or(freq);
1778 if(freq < 1)
1779 device->Flags.unset<FrequencyRequest>();
1780 else
1782 freq = maxu(freq, MIN_OUTPUT_RATE);
1784 device->UpdateSize = (device->UpdateSize*freq + device->Frequency/2) /
1785 device->Frequency;
1786 device->BufferSize = (device->BufferSize*freq + device->Frequency/2) /
1787 device->Frequency;
1789 device->Frequency = freq;
1790 device->Flags.set<FrequencyRequest>();
1793 if(auto persizeopt = ConfigValueUInt(devname, nullptr, "period_size"))
1794 device->UpdateSize = clampu(*persizeopt, 64, 8192);
1796 if(auto peropt = ConfigValueUInt(devname, nullptr, "periods"))
1797 device->BufferSize = device->UpdateSize * clampu(*peropt, 2, 16);
1798 else
1799 device->BufferSize = maxu(device->BufferSize, device->UpdateSize*2);
1801 else
1803 device->Frequency = freq;
1804 device->FmtChans = static_cast<DevFmtChannels>(schans);
1805 device->FmtType = static_cast<DevFmtType>(stype);
1806 if(schans == ALC_BFORMAT3D_SOFT)
1808 device->mAmbiOrder = aorder;
1809 device->mAmbiLayout = static_cast<AmbiLayout>(alayout);
1810 device->mAmbiScale = static_cast<AmbiNorm>(ascale);
1814 if(numMono > INT_MAX-numStereo)
1815 numMono = INT_MAX-numStereo;
1816 numMono += numStereo;
1817 if(auto srcsopt = ConfigValueUInt(devname, nullptr, "sources"))
1819 if(*srcsopt <= 0) numMono = 256;
1820 else numMono = *srcsopt;
1822 else
1823 numMono = maxu(numMono, 256);
1824 numStereo = minu(numStereo, numMono);
1825 numMono -= numStereo;
1826 device->SourcesMax = numMono + numStereo;
1828 device->NumMonoSources = numMono;
1829 device->NumStereoSources = numStereo;
1831 if(auto sendsopt = ConfigValueInt(devname, nullptr, "sends"))
1832 new_sends = minu(numSends, static_cast<ALuint>(clampi(*sendsopt, 0, MAX_SENDS)));
1833 else
1834 new_sends = numSends;
1837 if(device->Flags.get<DeviceRunning>())
1838 return ALC_NO_ERROR;
1840 device->AvgSpeakerDist = 0.0f;
1841 device->Uhj_Encoder = nullptr;
1842 device->AmbiDecoder = nullptr;
1843 device->Bs2b = nullptr;
1844 device->PostProcess = nullptr;
1846 device->Stablizer = nullptr;
1847 device->Limiter = nullptr;
1848 device->ChannelDelay.clear();
1850 device->Dry.AmbiMap.fill(BFChannelConfig{});
1851 device->Dry.Buffer = {};
1852 std::fill(std::begin(device->NumChannelsPerOrder), std::end(device->NumChannelsPerOrder), 0u);
1853 device->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
1854 device->RealOut.Buffer = {};
1855 device->MixBuffer.clear();
1856 device->MixBuffer.shrink_to_fit();
1858 UpdateClockBase(device);
1859 device->FixedLatency = nanoseconds::zero();
1861 device->DitherDepth = 0.0f;
1862 device->DitherSeed = DITHER_RNG_SEED;
1864 /*************************************************************************
1865 * Update device format request if HRTF is requested
1867 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
1868 if(device->Type != Loopback)
1870 if(auto hrtfopt = ConfigValueStr(device->DeviceName.c_str(), nullptr, "hrtf"))
1872 const char *hrtf{hrtfopt->c_str()};
1873 if(strcasecmp(hrtf, "true") == 0)
1874 hrtf_userreq = Hrtf_Enable;
1875 else if(strcasecmp(hrtf, "false") == 0)
1876 hrtf_userreq = Hrtf_Disable;
1877 else if(strcasecmp(hrtf, "auto") != 0)
1878 ERR("Unexpected hrtf value: %s\n", hrtf);
1881 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
1883 HrtfEntry *hrtf{nullptr};
1884 if(device->HrtfList.empty())
1885 device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
1886 if(!device->HrtfList.empty())
1888 if(hrtf_id >= 0 && static_cast<ALuint>(hrtf_id) < device->HrtfList.size())
1889 hrtf = GetLoadedHrtf(device->HrtfList[static_cast<ALuint>(hrtf_id)].hrtf);
1890 else
1891 hrtf = GetLoadedHrtf(device->HrtfList.front().hrtf);
1894 if(hrtf)
1896 device->FmtChans = DevFmtStereo;
1897 device->Frequency = hrtf->sampleRate;
1898 device->Flags.set<ChannelsRequest, FrequencyRequest>();
1899 if(HrtfEntry *oldhrtf{device->mHrtf})
1900 oldhrtf->DecRef();
1901 device->mHrtf = hrtf;
1903 else
1905 hrtf_userreq = Hrtf_Default;
1906 hrtf_appreq = Hrtf_Disable;
1907 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
1912 oldFreq = device->Frequency;
1913 oldChans = device->FmtChans;
1914 oldType = device->FmtType;
1916 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u / %u buffer\n",
1917 device->Flags.get<ChannelsRequest>()?"*":"", DevFmtChannelsString(device->FmtChans),
1918 device->Flags.get<SampleTypeRequest>()?"*":"", DevFmtTypeString(device->FmtType),
1919 device->Flags.get<FrequencyRequest>()?"*":"", device->Frequency,
1920 device->UpdateSize, device->BufferSize);
1922 try {
1923 if(device->Backend->reset() == ALC_FALSE)
1924 return ALC_INVALID_DEVICE;
1926 catch(std::exception &e) {
1927 ERR("Device reset failed: %s\n", e.what());
1928 return ALC_INVALID_DEVICE;
1931 if(device->FmtChans != oldChans && device->Flags.get<ChannelsRequest>())
1933 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1934 DevFmtChannelsString(device->FmtChans));
1935 device->Flags.unset<ChannelsRequest>();
1937 if(device->FmtType != oldType && device->Flags.get<SampleTypeRequest>())
1939 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1940 DevFmtTypeString(device->FmtType));
1941 device->Flags.unset<SampleTypeRequest>();
1943 if(device->Frequency != oldFreq && device->Flags.get<FrequencyRequest>())
1945 WARN("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1946 device->Flags.unset<FrequencyRequest>();
1949 TRACE("Post-reset: %s, %s, %uhz, %u / %u buffer\n",
1950 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
1951 device->Frequency, device->UpdateSize, device->BufferSize);
1953 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
1955 device->NumAuxSends = new_sends;
1956 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
1957 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
1958 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
1960 /* Enable the stablizer only for formats that have front-left, front-right,
1961 * and front-center outputs.
1963 switch(device->FmtChans)
1965 case DevFmtX51:
1966 case DevFmtX51Rear:
1967 case DevFmtX61:
1968 case DevFmtX71:
1969 if(GetConfigValueBool(device->DeviceName.c_str(), nullptr, "front-stablizer", 0))
1971 auto stablizer = al::make_unique<FrontStablizer>();
1972 /* Initialize band-splitting filters for the front-left and front-
1973 * right channels, with a crossover at 5khz (could be higher).
1975 const ALfloat scale{5000.0f / static_cast<ALfloat>(device->Frequency)};
1977 stablizer->LFilter.init(scale);
1978 stablizer->RFilter = stablizer->LFilter;
1980 device->Stablizer = std::move(stablizer);
1981 /* NOTE: Don't know why this has to be "copied" into a local static
1982 * constexpr variable to avoid a reference on
1983 * FrontStablizer::DelayLength...
1985 static constexpr size_t StablizerDelay{FrontStablizer::DelayLength};
1986 device->FixedLatency += nanoseconds{seconds{StablizerDelay}} / device->Frequency;
1988 break;
1989 case DevFmtMono:
1990 case DevFmtStereo:
1991 case DevFmtQuad:
1992 case DevFmtAmbi3D:
1993 break;
1995 TRACE("Front stablizer %s\n", device->Stablizer ? "enabled" : "disabled");
1997 if(GetConfigValueBool(device->DeviceName.c_str(), nullptr, "dither", 1))
1999 ALint depth{
2000 ConfigValueInt(device->DeviceName.c_str(), nullptr, "dither-depth").value_or(0)};
2001 if(depth <= 0)
2003 switch(device->FmtType)
2005 case DevFmtByte:
2006 case DevFmtUByte:
2007 depth = 8;
2008 break;
2009 case DevFmtShort:
2010 case DevFmtUShort:
2011 depth = 16;
2012 break;
2013 case DevFmtInt:
2014 case DevFmtUInt:
2015 case DevFmtFloat:
2016 break;
2020 if(depth > 0)
2022 depth = clampi(depth, 2, 24);
2023 device->DitherDepth = std::pow(2.0f, static_cast<ALfloat>(depth-1));
2026 if(!(device->DitherDepth > 0.0f))
2027 TRACE("Dithering disabled\n");
2028 else
2029 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device->DitherDepth)+0.5f)+1,
2030 device->DitherDepth);
2032 device->LimiterState = gainLimiter;
2033 if(auto limopt = ConfigValueBool(device->DeviceName.c_str(), nullptr, "output-limiter"))
2034 gainLimiter = *limopt ? ALC_TRUE : ALC_FALSE;
2036 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2037 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2038 * output (where samples must be clamped), and don't for floating-point
2039 * (which can take unclamped samples).
2041 if(gainLimiter == ALC_DONT_CARE_SOFT)
2043 switch(device->FmtType)
2045 case DevFmtByte:
2046 case DevFmtUByte:
2047 case DevFmtShort:
2048 case DevFmtUShort:
2049 case DevFmtInt:
2050 case DevFmtUInt:
2051 gainLimiter = ALC_TRUE;
2052 break;
2053 case DevFmtFloat:
2054 gainLimiter = ALC_FALSE;
2055 break;
2058 if(gainLimiter == ALC_FALSE)
2059 TRACE("Output limiter disabled\n");
2060 else
2062 ALfloat thrshld = 1.0f;
2063 switch(device->FmtType)
2065 case DevFmtByte:
2066 case DevFmtUByte:
2067 thrshld = 127.0f / 128.0f;
2068 break;
2069 case DevFmtShort:
2070 case DevFmtUShort:
2071 thrshld = 32767.0f / 32768.0f;
2072 break;
2073 case DevFmtInt:
2074 case DevFmtUInt:
2075 case DevFmtFloat:
2076 break;
2078 if(device->DitherDepth > 0.0f)
2079 thrshld -= 1.0f / device->DitherDepth;
2081 const float thrshld_dB{std::log10(thrshld) * 20.0f};
2082 auto limiter = CreateDeviceLimiter(device, thrshld_dB);
2083 /* Convert the lookahead from samples to nanosamples to nanoseconds. */
2084 device->FixedLatency += nanoseconds{seconds{limiter->getLookAhead()}} / device->Frequency;
2085 device->Limiter = std::move(limiter);
2086 TRACE("Output limiter enabled, %.4fdB limit\n", thrshld_dB);
2089 TRACE("Fixed device latency: %" PRId64 "ns\n", int64_t{device->FixedLatency.count()});
2091 /* Need to delay returning failure until replacement Send arrays have been
2092 * allocated with the appropriate size.
2094 update_failed = AL_FALSE;
2095 FPUCtl mixer_mode{};
2096 for(ALCcontext *context : *device->mContexts.load())
2098 if(context->mDefaultSlot)
2100 ALeffectslot *slot = context->mDefaultSlot.get();
2101 aluInitEffectPanning(slot, device);
2103 EffectState *state{slot->Effect.State};
2104 state->mOutTarget = device->Dry.Buffer;
2105 if(state->deviceUpdate(device) == AL_FALSE)
2106 update_failed = AL_TRUE;
2107 else
2108 UpdateEffectSlotProps(slot, context);
2111 std::unique_lock<std::mutex> proplock{context->mPropLock};
2112 std::unique_lock<std::mutex> slotlock{context->mEffectSlotLock};
2113 for(auto &sublist : context->mEffectSlotList)
2115 uint64_t usemask = ~sublist.FreeMask;
2116 while(usemask)
2118 ALsizei idx = CTZ64(usemask);
2119 ALeffectslot *slot = sublist.EffectSlots + idx;
2121 usemask &= ~(1_u64 << idx);
2123 aluInitEffectPanning(slot, device);
2125 EffectState *state{slot->Effect.State};
2126 state->mOutTarget = device->Dry.Buffer;
2127 if(state->deviceUpdate(device) == AL_FALSE)
2128 update_failed = AL_TRUE;
2129 else
2130 UpdateEffectSlotProps(slot, context);
2133 slotlock.unlock();
2135 std::unique_lock<std::mutex> srclock{context->mSourceLock};
2136 for(auto &sublist : context->mSourceList)
2138 uint64_t usemask = ~sublist.FreeMask;
2139 while(usemask)
2141 ALsizei idx = CTZ64(usemask);
2142 ALsource *source = sublist.Sources + idx;
2144 usemask &= ~(1_u64 << idx);
2146 if(old_sends != device->NumAuxSends)
2148 if(source->Send.size() > static_cast<ALuint>(device->NumAuxSends))
2149 std::for_each(source->Send.begin()+device->NumAuxSends, source->Send.end(),
2150 [](ALsource::SendData &send) -> void
2152 if(send.Slot)
2153 DecrementRef(send.Slot->ref);
2154 send.Slot = nullptr;
2157 source->Send.resize(static_cast<ALuint>(device->NumAuxSends),
2158 ALsource::SendData{nullptr, 1.0f, 1.0f, LOWPASSFREQREF, 1.0f, HIGHPASSFREQREF});
2159 source->Send.shrink_to_fit();
2162 source->PropsClean.clear(std::memory_order_release);
2166 /* Clear any pre-existing voice property structs, in case the number of
2167 * auxiliary sends is changing. Active sources will have updates
2168 * respecified in UpdateAllSourceProps.
2170 ALvoiceProps *vprops{context->mFreeVoiceProps.exchange(nullptr, std::memory_order_acq_rel)};
2171 while(vprops)
2173 ALvoiceProps *next = vprops->next.load(std::memory_order_relaxed);
2174 delete vprops;
2175 vprops = next;
2178 if(device->NumAuxSends < old_sends)
2180 const ALuint num_sends{device->NumAuxSends};
2181 /* Clear extraneous property set sends. */
2182 auto clear_sends = [num_sends](ALvoice &voice) -> void
2184 std::fill(std::begin(voice.mProps.Send)+num_sends, std::end(voice.mProps.Send),
2185 ALvoiceProps::SendData{});
2187 std::fill(voice.mSend.begin()+num_sends, voice.mSend.end(), ALvoice::SendData{});
2188 auto clear_chan_sends = [num_sends](ALvoice::ChannelData &chandata) -> void
2190 std::fill(chandata.mWetParams.begin()+num_sends, chandata.mWetParams.end(),
2191 SendParams{});
2193 std::for_each(voice.mChans.begin(), voice.mChans.end(), clear_chan_sends);
2195 std::for_each(context->mVoices.begin(), context->mVoices.end(), clear_sends);
2197 auto reset_voice = [device](ALvoice &voice) -> void
2199 delete voice.mUpdate.exchange(nullptr, std::memory_order_acq_rel);
2201 /* Force the voice to stopped if it was stopping. */
2202 ALvoice::State vstate{ALvoice::Stopping};
2203 voice.mPlayState.compare_exchange_strong(vstate, ALvoice::Stopped,
2204 std::memory_order_acquire, std::memory_order_acquire);
2205 if(voice.mSourceID.load(std::memory_order_relaxed) == 0u)
2206 return;
2208 if(device->AvgSpeakerDist > 0.0f)
2210 /* Reinitialize the NFC filters for new parameters. */
2211 const ALfloat w1{SPEEDOFSOUNDMETRESPERSEC /
2212 (device->AvgSpeakerDist * device->Frequency)};
2213 auto init_nfc = [w1](ALvoice::ChannelData &chandata) -> void
2214 { chandata.mDryParams.NFCtrlFilter.init(w1); };
2215 std::for_each(voice.mChans.begin(), voice.mChans.begin()+voice.mNumChannels,
2216 init_nfc);
2219 std::for_each(context->mVoices.begin(), context->mVoices.end(), reset_voice);
2220 srclock.unlock();
2222 context->mPropsClean.test_and_set(std::memory_order_release);
2223 UpdateContextProps(context);
2224 context->mListener.PropsClean.test_and_set(std::memory_order_release);
2225 UpdateListenerProps(context);
2226 UpdateAllSourceProps(context);
2228 mixer_mode.leave();
2229 if(update_failed)
2230 return ALC_INVALID_DEVICE;
2232 if(!device->Flags.get<DevicePaused>())
2234 if(device->Backend->start() == ALC_FALSE)
2235 return ALC_INVALID_DEVICE;
2236 device->Flags.set<DeviceRunning>();
2239 return ALC_NO_ERROR;
2243 ALCdevice::ALCdevice(DeviceType type) : Type{type}, mContexts{&EmptyContextArray}
2247 /* ALCdevice::~ALCdevice
2249 * Frees the device structure, and destroys any objects the app failed to
2250 * delete. Called once there's no more references on the device.
2252 ALCdevice::~ALCdevice()
2254 TRACE("Freeing device %p\n", this);
2256 Backend = nullptr;
2258 size_t count{std::accumulate(BufferList.cbegin(), BufferList.cend(), size_t{0u},
2259 [](size_t cur, const BufferSubList &sublist) noexcept -> size_t
2260 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2262 if(count > 0)
2263 WARN("%zu Buffer%s not deleted\n", count, (count==1)?"":"s");
2265 count = std::accumulate(EffectList.cbegin(), EffectList.cend(), size_t{0u},
2266 [](size_t cur, const EffectSubList &sublist) noexcept -> size_t
2267 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2269 if(count > 0)
2270 WARN("%zu Effect%s not deleted\n", count, (count==1)?"":"s");
2272 count = std::accumulate(FilterList.cbegin(), FilterList.cend(), size_t{0u},
2273 [](size_t cur, const FilterSubList &sublist) noexcept -> size_t
2274 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2276 if(count > 0)
2277 WARN("%zu Filter%s not deleted\n", count, (count==1)?"":"s");
2279 if(mHrtf)
2280 mHrtf->DecRef();
2281 mHrtf = nullptr;
2283 auto *oldarray = mContexts.exchange(nullptr, std::memory_order_relaxed);
2284 if(oldarray != &EmptyContextArray) delete oldarray;
2288 /* VerifyDevice
2290 * Checks if the device handle is valid, and returns a new reference if so.
2292 static DeviceRef VerifyDevice(ALCdevice *device)
2294 std::lock_guard<std::recursive_mutex> _{ListLock};
2295 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device);
2296 if(iter != DeviceList.cend() && *iter == device)
2297 return *iter;
2298 return nullptr;
2302 ALCcontext::ALCcontext(al::intrusive_ptr<ALCdevice> device) : mDevice{std::move(device)}
2304 mPropsClean.test_and_set(std::memory_order_relaxed);
2307 ALCcontext::~ALCcontext()
2309 TRACE("Freeing context %p\n", this);
2311 ALcontextProps *cprops{mUpdate.exchange(nullptr, std::memory_order_relaxed)};
2312 if(cprops)
2314 TRACE("Freed unapplied context update %p\n", cprops);
2315 delete cprops;
2317 size_t count{0};
2318 cprops = mFreeContextProps.exchange(nullptr, std::memory_order_acquire);
2319 while(cprops)
2321 ALcontextProps *next{cprops->next.load(std::memory_order_relaxed)};
2322 delete cprops;
2323 cprops = next;
2324 ++count;
2326 TRACE("Freed %zu context property object%s\n", count, (count==1)?"":"s");
2328 count = std::accumulate(mSourceList.cbegin(), mSourceList.cend(), size_t{0u},
2329 [](size_t cur, const SourceSubList &sublist) noexcept -> size_t
2330 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2332 if(count > 0)
2333 WARN("%zu Source%s not deleted\n", count, (count==1)?"":"s");
2334 mSourceList.clear();
2335 mNumSources = 0;
2337 count = 0;
2338 ALeffectslotProps *eprops{mFreeEffectslotProps.exchange(nullptr, std::memory_order_acquire)};
2339 while(eprops)
2341 ALeffectslotProps *next{eprops->next.load(std::memory_order_relaxed)};
2342 if(eprops->State) eprops->State->release();
2343 delete eprops;
2344 eprops = next;
2345 ++count;
2347 TRACE("Freed %zu AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2349 delete mActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed);
2350 mDefaultSlot = nullptr;
2352 count = std::accumulate(mEffectSlotList.cbegin(), mEffectSlotList.cend(), size_t{0u},
2353 [](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t
2354 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2356 if(count > 0)
2357 WARN("%zu AuxiliaryEffectSlot%s not deleted\n", count, (count==1)?"":"s");
2358 mEffectSlotList.clear();
2359 mNumEffectSlots = 0;
2361 count = 0;
2362 ALvoiceProps *vprops{mFreeVoiceProps.exchange(nullptr, std::memory_order_acquire)};
2363 while(vprops)
2365 ALvoiceProps *next{vprops->next.load(std::memory_order_relaxed)};
2366 delete vprops;
2367 vprops = next;
2368 ++count;
2370 TRACE("Freed %zu voice property object%s\n", count, (count==1)?"":"s");
2372 mVoices.clear();
2374 ALlistenerProps *lprops{mListener.Params.Update.exchange(nullptr, std::memory_order_relaxed)};
2375 if(lprops)
2377 TRACE("Freed unapplied listener update %p\n", lprops);
2378 delete lprops;
2380 count = 0;
2381 lprops = mFreeListenerProps.exchange(nullptr, std::memory_order_acquire);
2382 while(lprops)
2384 ALlistenerProps *next{lprops->next.load(std::memory_order_relaxed)};
2385 delete lprops;
2386 lprops = next;
2387 ++count;
2389 TRACE("Freed %zu listener property object%s\n", count, (count==1)?"":"s");
2391 if(mAsyncEvents)
2393 count = 0;
2394 auto evt_vec = mAsyncEvents->getReadVector();
2395 if(evt_vec.first.len > 0)
2397 al::destroy_n(reinterpret_cast<AsyncEvent*>(evt_vec.first.buf), evt_vec.first.len);
2398 count += evt_vec.first.len;
2400 if(evt_vec.second.len > 0)
2402 al::destroy_n(reinterpret_cast<AsyncEvent*>(evt_vec.second.buf), evt_vec.second.len);
2403 count += evt_vec.second.len;
2405 if(count > 0)
2406 TRACE("Destructed %zu orphaned event%s\n", count, (count==1)?"":"s");
2407 mAsyncEvents->readAdvance(count);
2411 void ALCcontext::init()
2413 if(DefaultEffect.type != AL_EFFECT_NULL && mDevice->Type == Playback)
2415 mDefaultSlot = std::unique_ptr<ALeffectslot>{new ALeffectslot{}};
2416 if(InitEffectSlot(mDefaultSlot.get()) == AL_NO_ERROR)
2417 aluInitEffectPanning(mDefaultSlot.get(), mDevice.get());
2418 else
2420 mDefaultSlot = nullptr;
2421 ERR("Failed to initialize the default effect slot\n");
2425 ALeffectslotArray *auxslots;
2426 if(!mDefaultSlot)
2427 auxslots = ALeffectslot::CreatePtrArray(0);
2428 else
2430 auxslots = ALeffectslot::CreatePtrArray(1);
2431 (*auxslots)[0] = mDefaultSlot.get();
2433 mActiveAuxSlots.store(auxslots, std::memory_order_relaxed);
2435 mExtensionList = alExtList;
2438 mListener.Params.Matrix = alu::Matrix::Identity();
2439 mListener.Params.Velocity = alu::Vector{};
2440 mListener.Params.Gain = mListener.Gain;
2441 mListener.Params.MetersPerUnit = mListener.mMetersPerUnit;
2442 mListener.Params.DopplerFactor = mDopplerFactor;
2443 mListener.Params.SpeedOfSound = mSpeedOfSound * mDopplerVelocity;
2444 mListener.Params.SourceDistanceModel = mSourceDistanceModel;
2445 mListener.Params.mDistanceModel = mDistanceModel;
2448 mAsyncEvents = CreateRingBuffer(511, sizeof(AsyncEvent), false);
2449 StartEventThrd(this);
2452 mVoices.reserve(256);
2453 mVoices.resize(64);
2456 bool ALCcontext::deinit()
2458 if(LocalContext.get() == this)
2460 WARN("%p released while current on thread\n", this);
2461 LocalContext.set(nullptr);
2462 release();
2465 ALCcontext *origctx{this};
2466 if(GlobalContext.compare_exchange_strong(origctx, nullptr))
2467 release();
2469 bool ret{};
2470 /* First make sure this context exists in the device's list. */
2471 auto *oldarray = mDevice->mContexts.load(std::memory_order_acquire);
2472 if(auto toremove = static_cast<size_t>(std::count(oldarray->begin(), oldarray->end(), this)))
2474 using ContextArray = al::FlexArray<ALCcontext*>;
2475 auto alloc_ctx_array = [](const size_t count) -> ContextArray*
2477 if(count == 0) return &EmptyContextArray;
2478 return ContextArray::Create(count).release();
2480 auto *newarray = alloc_ctx_array(oldarray->size() - toremove);
2482 /* Copy the current/old context handles to the new array, excluding the
2483 * given context.
2485 std::copy_if(oldarray->begin(), oldarray->end(), newarray->begin(),
2486 std::bind(std::not_equal_to<ALCcontext*>{}, _1, this));
2488 /* Store the new context array in the device. Wait for any current mix
2489 * to finish before deleting the old array.
2491 mDevice->mContexts.store(newarray);
2492 if(oldarray != &EmptyContextArray)
2494 while((mDevice->MixCount.load(std::memory_order_acquire)&1))
2495 std::this_thread::yield();
2496 delete oldarray;
2499 ret = !newarray->empty();
2501 else
2502 ret = !oldarray->empty();
2504 StopEventThrd(this);
2506 return ret;
2510 /* VerifyContext
2512 * Checks if the given context is valid, returning a new reference to it if so.
2514 static ContextRef VerifyContext(ALCcontext *context)
2516 std::lock_guard<std::recursive_mutex> _{ListLock};
2517 auto iter = std::lower_bound(ContextList.cbegin(), ContextList.cend(), context);
2518 if(iter != ContextList.cend() && *iter == context)
2519 return *iter;
2520 return nullptr;
2523 /* GetContextRef
2525 * Returns a new reference to the currently active context for this thread.
2527 ContextRef GetContextRef(void)
2529 ALCcontext *context{LocalContext.get()};
2530 if(context)
2531 context->add_ref();
2532 else
2534 std::lock_guard<std::recursive_mutex> _{ListLock};
2535 context = GlobalContext.load(std::memory_order_acquire);
2536 if(context) context->add_ref();
2538 return ContextRef{context};
2542 /************************************************
2543 * Standard ALC functions
2544 ************************************************/
2546 /* alcGetError
2548 * Return last ALC generated error code for the given device
2550 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2551 START_API_FUNC
2553 DeviceRef dev{VerifyDevice(device)};
2554 if(dev) return dev->LastError.exchange(ALC_NO_ERROR);
2555 return LastNullDeviceError.exchange(ALC_NO_ERROR);
2557 END_API_FUNC
2560 /* alcSuspendContext
2562 * Suspends updates for the given context
2564 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2565 START_API_FUNC
2567 if(!SuspendDefers)
2568 return;
2570 ContextRef ctx{VerifyContext(context)};
2571 if(!ctx)
2572 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2573 else
2574 ctx->deferUpdates();
2576 END_API_FUNC
2578 /* alcProcessContext
2580 * Resumes processing updates for the given context
2582 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2583 START_API_FUNC
2585 if(!SuspendDefers)
2586 return;
2588 ContextRef ctx{VerifyContext(context)};
2589 if(!ctx)
2590 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2591 else
2592 ctx->processUpdates();
2594 END_API_FUNC
2597 /* alcGetString
2599 * Returns information about the device, and error strings
2601 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2602 START_API_FUNC
2604 const ALCchar *value = nullptr;
2606 switch(param)
2608 case ALC_NO_ERROR:
2609 value = alcNoError;
2610 break;
2612 case ALC_INVALID_ENUM:
2613 value = alcErrInvalidEnum;
2614 break;
2616 case ALC_INVALID_VALUE:
2617 value = alcErrInvalidValue;
2618 break;
2620 case ALC_INVALID_DEVICE:
2621 value = alcErrInvalidDevice;
2622 break;
2624 case ALC_INVALID_CONTEXT:
2625 value = alcErrInvalidContext;
2626 break;
2628 case ALC_OUT_OF_MEMORY:
2629 value = alcErrOutOfMemory;
2630 break;
2632 case ALC_DEVICE_SPECIFIER:
2633 value = alcDefaultName;
2634 break;
2636 case ALC_ALL_DEVICES_SPECIFIER:
2637 if(DeviceRef dev{VerifyDevice(Device)})
2638 value = dev->DeviceName.c_str();
2639 else
2641 ProbeAllDevicesList();
2642 value = alcAllDevicesList.c_str();
2644 break;
2646 case ALC_CAPTURE_DEVICE_SPECIFIER:
2647 if(DeviceRef dev{VerifyDevice(Device)})
2648 value = dev->DeviceName.c_str();
2649 else
2651 ProbeCaptureDeviceList();
2652 value = alcCaptureDeviceList.c_str();
2654 break;
2656 /* Default devices are always first in the list */
2657 case ALC_DEFAULT_DEVICE_SPECIFIER:
2658 value = alcDefaultName;
2659 break;
2661 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2662 if(alcAllDevicesList.empty())
2663 ProbeAllDevicesList();
2665 /* Copy first entry as default. */
2666 alcDefaultAllDevicesSpecifier = alcAllDevicesList.c_str();
2667 value = alcDefaultAllDevicesSpecifier.c_str();
2668 break;
2670 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2671 if(alcCaptureDeviceList.empty())
2672 ProbeCaptureDeviceList();
2674 /* Copy first entry as default. */
2675 alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList.c_str();
2676 value = alcCaptureDefaultDeviceSpecifier.c_str();
2677 break;
2679 case ALC_EXTENSIONS:
2680 if(VerifyDevice(Device))
2681 value = alcExtensionList;
2682 else
2683 value = alcNoDeviceExtList;
2684 break;
2686 case ALC_HRTF_SPECIFIER_SOFT:
2687 if(DeviceRef dev{VerifyDevice(Device)})
2689 std::lock_guard<std::mutex> _{dev->StateLock};
2690 value = (dev->mHrtf ? dev->HrtfName.c_str() : "");
2692 else
2693 alcSetError(nullptr, ALC_INVALID_DEVICE);
2694 break;
2696 default:
2697 alcSetError(VerifyDevice(Device).get(), ALC_INVALID_ENUM);
2698 break;
2701 return value;
2703 END_API_FUNC
2706 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
2708 if(device->Type == Capture) return 9;
2709 if(device->Type != Loopback) return 29;
2710 if(device->FmtChans == DevFmtAmbi3D)
2711 return 35;
2712 return 29;
2715 static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span<ALCint> values)
2717 size_t i;
2719 if(values.empty())
2721 alcSetError(device, ALC_INVALID_VALUE);
2722 return 0;
2725 if(!device)
2727 switch(param)
2729 case ALC_MAJOR_VERSION:
2730 values[0] = alcMajorVersion;
2731 return 1;
2732 case ALC_MINOR_VERSION:
2733 values[0] = alcMinorVersion;
2734 return 1;
2736 case ALC_ATTRIBUTES_SIZE:
2737 case ALC_ALL_ATTRIBUTES:
2738 case ALC_FREQUENCY:
2739 case ALC_REFRESH:
2740 case ALC_SYNC:
2741 case ALC_MONO_SOURCES:
2742 case ALC_STEREO_SOURCES:
2743 case ALC_CAPTURE_SAMPLES:
2744 case ALC_FORMAT_CHANNELS_SOFT:
2745 case ALC_FORMAT_TYPE_SOFT:
2746 case ALC_AMBISONIC_LAYOUT_SOFT:
2747 case ALC_AMBISONIC_SCALING_SOFT:
2748 case ALC_AMBISONIC_ORDER_SOFT:
2749 case ALC_MAX_AMBISONIC_ORDER_SOFT:
2750 alcSetError(nullptr, ALC_INVALID_DEVICE);
2751 return 0;
2753 default:
2754 alcSetError(nullptr, ALC_INVALID_ENUM);
2755 return 0;
2757 return 0;
2760 if(device->Type == Capture)
2762 switch(param)
2764 case ALC_ATTRIBUTES_SIZE:
2765 values[0] = NumAttrsForDevice(device);
2766 return 1;
2768 case ALC_ALL_ATTRIBUTES:
2769 i = 0;
2770 if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2771 alcSetError(device, ALC_INVALID_VALUE);
2772 else
2774 std::lock_guard<std::mutex> _{device->StateLock};
2775 values[i++] = ALC_MAJOR_VERSION;
2776 values[i++] = alcMajorVersion;
2777 values[i++] = ALC_MINOR_VERSION;
2778 values[i++] = alcMinorVersion;
2779 values[i++] = ALC_CAPTURE_SAMPLES;
2780 values[i++] = static_cast<int>(device->Backend->availableSamples());
2781 values[i++] = ALC_CONNECTED;
2782 values[i++] = device->Connected.load(std::memory_order_relaxed);
2783 values[i++] = 0;
2785 return i;
2787 case ALC_MAJOR_VERSION:
2788 values[0] = alcMajorVersion;
2789 return 1;
2790 case ALC_MINOR_VERSION:
2791 values[0] = alcMinorVersion;
2792 return 1;
2794 case ALC_CAPTURE_SAMPLES:
2796 std::lock_guard<std::mutex> _{device->StateLock};
2797 values[0] = static_cast<int>(device->Backend->availableSamples());
2799 return 1;
2801 case ALC_CONNECTED:
2803 std::lock_guard<std::mutex> _{device->StateLock};
2804 values[0] = device->Connected.load(std::memory_order_acquire);
2806 return 1;
2808 default:
2809 alcSetError(device, ALC_INVALID_ENUM);
2811 return 0;
2814 /* render device */
2815 switch(param)
2817 case ALC_ATTRIBUTES_SIZE:
2818 values[0] = NumAttrsForDevice(device);
2819 return 1;
2821 case ALC_ALL_ATTRIBUTES:
2822 i = 0;
2823 if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2824 alcSetError(device, ALC_INVALID_VALUE);
2825 else
2827 std::lock_guard<std::mutex> _{device->StateLock};
2828 values[i++] = ALC_MAJOR_VERSION;
2829 values[i++] = alcMajorVersion;
2830 values[i++] = ALC_MINOR_VERSION;
2831 values[i++] = alcMinorVersion;
2832 values[i++] = ALC_EFX_MAJOR_VERSION;
2833 values[i++] = alcEFXMajorVersion;
2834 values[i++] = ALC_EFX_MINOR_VERSION;
2835 values[i++] = alcEFXMinorVersion;
2837 values[i++] = ALC_FREQUENCY;
2838 values[i++] = static_cast<int>(device->Frequency);
2839 if(device->Type != Loopback)
2841 values[i++] = ALC_REFRESH;
2842 values[i++] = static_cast<int>(device->Frequency / device->UpdateSize);
2844 values[i++] = ALC_SYNC;
2845 values[i++] = ALC_FALSE;
2847 else
2849 if(device->FmtChans == DevFmtAmbi3D)
2851 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
2852 values[i++] = static_cast<ALCint>(device->mAmbiLayout);
2854 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
2855 values[i++] = static_cast<ALCint>(device->mAmbiScale);
2857 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
2858 values[i++] = static_cast<ALCint>(device->mAmbiOrder);
2861 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2862 values[i++] = device->FmtChans;
2864 values[i++] = ALC_FORMAT_TYPE_SOFT;
2865 values[i++] = device->FmtType;
2868 values[i++] = ALC_MONO_SOURCES;
2869 values[i++] = static_cast<int>(device->NumMonoSources);
2871 values[i++] = ALC_STEREO_SOURCES;
2872 values[i++] = static_cast<int>(device->NumStereoSources);
2874 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2875 values[i++] = static_cast<ALCint>(device->NumAuxSends);
2877 values[i++] = ALC_HRTF_SOFT;
2878 values[i++] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
2880 values[i++] = ALC_HRTF_STATUS_SOFT;
2881 values[i++] = device->HrtfStatus;
2883 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
2884 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
2886 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
2887 values[i++] = MAX_AMBI_ORDER;
2889 values[i++] = 0;
2891 return i;
2893 case ALC_MAJOR_VERSION:
2894 values[0] = alcMajorVersion;
2895 return 1;
2897 case ALC_MINOR_VERSION:
2898 values[0] = alcMinorVersion;
2899 return 1;
2901 case ALC_EFX_MAJOR_VERSION:
2902 values[0] = alcEFXMajorVersion;
2903 return 1;
2905 case ALC_EFX_MINOR_VERSION:
2906 values[0] = alcEFXMinorVersion;
2907 return 1;
2909 case ALC_FREQUENCY:
2910 values[0] = static_cast<int>(device->Frequency);
2911 return 1;
2913 case ALC_REFRESH:
2914 if(device->Type == Loopback)
2916 alcSetError(device, ALC_INVALID_DEVICE);
2917 return 0;
2920 std::lock_guard<std::mutex> _{device->StateLock};
2921 values[0] = static_cast<int>(device->Frequency / device->UpdateSize);
2923 return 1;
2925 case ALC_SYNC:
2926 if(device->Type == Loopback)
2928 alcSetError(device, ALC_INVALID_DEVICE);
2929 return 0;
2931 values[0] = ALC_FALSE;
2932 return 1;
2934 case ALC_FORMAT_CHANNELS_SOFT:
2935 if(device->Type != Loopback)
2937 alcSetError(device, ALC_INVALID_DEVICE);
2938 return 0;
2940 values[0] = device->FmtChans;
2941 return 1;
2943 case ALC_FORMAT_TYPE_SOFT:
2944 if(device->Type != Loopback)
2946 alcSetError(device, ALC_INVALID_DEVICE);
2947 return 0;
2949 values[0] = device->FmtType;
2950 return 1;
2952 case ALC_AMBISONIC_LAYOUT_SOFT:
2953 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
2955 alcSetError(device, ALC_INVALID_DEVICE);
2956 return 0;
2958 values[0] = static_cast<ALCint>(device->mAmbiLayout);
2959 return 1;
2961 case ALC_AMBISONIC_SCALING_SOFT:
2962 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
2964 alcSetError(device, ALC_INVALID_DEVICE);
2965 return 0;
2967 values[0] = static_cast<ALCint>(device->mAmbiScale);
2968 return 1;
2970 case ALC_AMBISONIC_ORDER_SOFT:
2971 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
2973 alcSetError(device, ALC_INVALID_DEVICE);
2974 return 0;
2976 values[0] = static_cast<int>(device->mAmbiOrder);
2977 return 1;
2979 case ALC_MONO_SOURCES:
2980 values[0] = static_cast<int>(device->NumMonoSources);
2981 return 1;
2983 case ALC_STEREO_SOURCES:
2984 values[0] = static_cast<int>(device->NumStereoSources);
2985 return 1;
2987 case ALC_MAX_AUXILIARY_SENDS:
2988 values[0] = static_cast<ALCint>(device->NumAuxSends);
2989 return 1;
2991 case ALC_CONNECTED:
2993 std::lock_guard<std::mutex> _{device->StateLock};
2994 values[0] = device->Connected.load(std::memory_order_acquire);
2996 return 1;
2998 case ALC_HRTF_SOFT:
2999 values[0] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
3000 return 1;
3002 case ALC_HRTF_STATUS_SOFT:
3003 values[0] = device->HrtfStatus;
3004 return 1;
3006 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3008 std::lock_guard<std::mutex> _{device->StateLock};
3009 device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
3010 values[0] = static_cast<ALCint>(minz(device->HrtfList.size(),
3011 std::numeric_limits<ALCint>::max()));
3013 return 1;
3015 case ALC_OUTPUT_LIMITER_SOFT:
3016 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3017 return 1;
3019 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3020 values[0] = MAX_AMBI_ORDER;
3021 return 1;
3023 default:
3024 alcSetError(device, ALC_INVALID_ENUM);
3026 return 0;
3029 /* alcGetIntegerv
3031 * Returns information about the device and the version of OpenAL
3033 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3034 START_API_FUNC
3036 DeviceRef dev{VerifyDevice(device)};
3037 if(size <= 0 || values == nullptr)
3038 alcSetError(dev.get(), ALC_INVALID_VALUE);
3039 else
3040 GetIntegerv(dev.get(), param, {values, values+size});
3042 END_API_FUNC
3044 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3045 START_API_FUNC
3047 DeviceRef dev{VerifyDevice(device)};
3048 if(size <= 0 || values == nullptr)
3049 alcSetError(dev.get(), ALC_INVALID_VALUE);
3050 else if(!dev || dev->Type == Capture)
3052 auto ivals = al::vector<ALCint>(static_cast<ALuint>(size));
3053 size_t got{GetIntegerv(dev.get(), pname, {ivals.data(), ivals.size()})};
3054 std::copy_n(ivals.begin(), got, values);
3055 return;
3057 /* render device */
3058 switch(pname)
3060 case ALC_ATTRIBUTES_SIZE:
3061 *values = NumAttrsForDevice(dev.get())+4;
3062 break;
3064 case ALC_ALL_ATTRIBUTES:
3065 if(size < NumAttrsForDevice(dev.get())+4)
3066 alcSetError(dev.get(), ALC_INVALID_VALUE);
3067 else
3069 size_t i{0};
3070 std::lock_guard<std::mutex> _{dev->StateLock};
3071 values[i++] = ALC_FREQUENCY;
3072 values[i++] = dev->Frequency;
3074 if(dev->Type != Loopback)
3076 values[i++] = ALC_REFRESH;
3077 values[i++] = dev->Frequency / dev->UpdateSize;
3079 values[i++] = ALC_SYNC;
3080 values[i++] = ALC_FALSE;
3082 else
3084 if(dev->FmtChans == DevFmtAmbi3D)
3086 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3087 values[i++] = static_cast<ALCint64SOFT>(dev->mAmbiLayout);
3089 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3090 values[i++] = static_cast<ALCint64SOFT>(dev->mAmbiScale);
3092 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3093 values[i++] = dev->mAmbiOrder;
3096 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3097 values[i++] = dev->FmtChans;
3099 values[i++] = ALC_FORMAT_TYPE_SOFT;
3100 values[i++] = dev->FmtType;
3103 values[i++] = ALC_MONO_SOURCES;
3104 values[i++] = dev->NumMonoSources;
3106 values[i++] = ALC_STEREO_SOURCES;
3107 values[i++] = dev->NumStereoSources;
3109 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3110 values[i++] = dev->NumAuxSends;
3112 values[i++] = ALC_HRTF_SOFT;
3113 values[i++] = (dev->mHrtf ? ALC_TRUE : ALC_FALSE);
3115 values[i++] = ALC_HRTF_STATUS_SOFT;
3116 values[i++] = dev->HrtfStatus;
3118 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3119 values[i++] = dev->Limiter ? ALC_TRUE : ALC_FALSE;
3121 ClockLatency clock{GetClockLatency(dev.get())};
3122 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3123 values[i++] = clock.ClockTime.count();
3125 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3126 values[i++] = clock.Latency.count();
3128 values[i++] = 0;
3130 break;
3132 case ALC_DEVICE_CLOCK_SOFT:
3133 { std::lock_guard<std::mutex> _{dev->StateLock};
3134 nanoseconds basecount;
3135 ALuint samplecount;
3136 ALuint refcount;
3137 do {
3138 while(((refcount=ReadRef(dev->MixCount))&1) != 0)
3139 std::this_thread::yield();
3140 basecount = dev->ClockBase;
3141 samplecount = dev->SamplesDone;
3142 } while(refcount != ReadRef(dev->MixCount));
3143 basecount += nanoseconds{seconds{samplecount}} / dev->Frequency;
3144 *values = basecount.count();
3146 break;
3148 case ALC_DEVICE_LATENCY_SOFT:
3149 { std::lock_guard<std::mutex> _{dev->StateLock};
3150 ClockLatency clock{GetClockLatency(dev.get())};
3151 *values = clock.Latency.count();
3153 break;
3155 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3156 if(size < 2)
3157 alcSetError(dev.get(), ALC_INVALID_VALUE);
3158 else
3160 std::lock_guard<std::mutex> _{dev->StateLock};
3161 ClockLatency clock{GetClockLatency(dev.get())};
3162 values[0] = clock.ClockTime.count();
3163 values[1] = clock.Latency.count();
3165 break;
3167 default:
3168 auto ivals = al::vector<ALCint>(static_cast<ALuint>(size));
3169 size_t got{GetIntegerv(dev.get(), pname, {ivals.data(), ivals.size()})};
3170 std::copy_n(ivals.begin(), got, values);
3171 break;
3174 END_API_FUNC
3177 /* alcIsExtensionPresent
3179 * Determines if there is support for a particular extension
3181 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3182 START_API_FUNC
3184 DeviceRef dev{VerifyDevice(device)};
3185 if(!extName)
3186 alcSetError(dev.get(), ALC_INVALID_VALUE);
3187 else
3189 size_t len = strlen(extName);
3190 const char *ptr = (dev ? alcExtensionList : alcNoDeviceExtList);
3191 while(ptr && *ptr)
3193 if(strncasecmp(ptr, extName, len) == 0 &&
3194 (ptr[len] == '\0' || isspace(ptr[len])))
3195 return ALC_TRUE;
3197 if((ptr=strchr(ptr, ' ')) != nullptr)
3199 do {
3200 ++ptr;
3201 } while(isspace(*ptr));
3205 return ALC_FALSE;
3207 END_API_FUNC
3210 /* alcGetProcAddress
3212 * Retrieves the function address for a particular extension function
3214 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3215 START_API_FUNC
3217 if(!funcName)
3219 DeviceRef dev{VerifyDevice(device)};
3220 alcSetError(dev.get(), ALC_INVALID_VALUE);
3222 else
3224 for(const auto &func : alcFunctions)
3226 if(strcmp(func.funcName, funcName) == 0)
3227 return func.address;
3230 return nullptr;
3232 END_API_FUNC
3235 /* alcGetEnumValue
3237 * Get the value for a particular ALC enumeration name
3239 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3240 START_API_FUNC
3242 if(!enumName)
3244 DeviceRef dev{VerifyDevice(device)};
3245 alcSetError(dev.get(), ALC_INVALID_VALUE);
3247 else
3249 for(const auto &enm : alcEnumerations)
3251 if(strcmp(enm.enumName, enumName) == 0)
3252 return enm.value;
3255 return 0;
3257 END_API_FUNC
3260 /* alcCreateContext
3262 * Create and attach a context to the given device.
3264 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3265 START_API_FUNC
3267 /* Explicitly hold the list lock while taking the StateLock in case the
3268 * device is asynchronously destroyed, to ensure this new context is
3269 * properly cleaned up after being made.
3271 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3272 DeviceRef dev{VerifyDevice(device)};
3273 if(!dev || dev->Type == Capture || !dev->Connected.load(std::memory_order_relaxed))
3275 listlock.unlock();
3276 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3277 return nullptr;
3279 std::unique_lock<std::mutex> statelock{dev->StateLock};
3280 listlock.unlock();
3282 dev->LastError.store(ALC_NO_ERROR);
3284 ALCenum err{UpdateDeviceParams(dev.get(), attrList)};
3285 if(err != ALC_NO_ERROR)
3287 alcSetError(dev.get(), err);
3288 if(err == ALC_INVALID_DEVICE)
3289 aluHandleDisconnect(dev.get(), "Device update failure");
3290 return nullptr;
3293 ContextRef context{new ALCcontext{dev}};
3294 context->init();
3296 if(auto volopt = ConfigValueFloat(dev->DeviceName.c_str(), nullptr, "volume-adjust"))
3298 const ALfloat valf{*volopt};
3299 if(!std::isfinite(valf))
3300 ERR("volume-adjust must be finite: %f\n", valf);
3301 else
3303 const ALfloat db{clampf(valf, -24.0f, 24.0f)};
3304 if(db != valf)
3305 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3306 context->mGainBoost = std::pow(10.0f, db/20.0f);
3307 TRACE("volume-adjust gain: %f\n", context->mGainBoost);
3310 UpdateListenerProps(context.get());
3313 using ContextArray = al::FlexArray<ALCcontext*>;
3315 /* Allocate a new context array, which holds 1 more than the current/
3316 * old array.
3318 auto *oldarray = device->mContexts.load();
3319 const size_t newcount{oldarray->size()+1};
3320 std::unique_ptr<ContextArray> newarray{ContextArray::Create(newcount)};
3322 /* Copy the current/old context handles to the new array, appending the
3323 * new context.
3325 auto iter = std::copy(oldarray->begin(), oldarray->end(), newarray->begin());
3326 *iter = context.get();
3328 /* Store the new context array in the device. Wait for any current mix
3329 * to finish before deleting the old array.
3331 dev->mContexts.store(newarray.release());
3332 if(oldarray != &EmptyContextArray)
3334 while((dev->MixCount.load(std::memory_order_acquire)&1))
3335 std::this_thread::yield();
3336 delete oldarray;
3339 statelock.unlock();
3342 std::lock_guard<std::recursive_mutex> _{ListLock};
3343 auto iter = std::lower_bound(ContextList.cbegin(), ContextList.cend(), context.get());
3344 ContextList.emplace(iter, context);
3347 if(context->mDefaultSlot)
3349 if(InitializeEffect(context.get(), context->mDefaultSlot.get(), &DefaultEffect) == AL_NO_ERROR)
3350 UpdateEffectSlotProps(context->mDefaultSlot.get(), context.get());
3351 else
3352 ERR("Failed to initialize the default effect\n");
3355 TRACE("Created context %p\n", context.get());
3356 return context.get();
3358 END_API_FUNC
3360 /* alcDestroyContext
3362 * Remove a context from its device
3364 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3365 START_API_FUNC
3367 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3368 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
3369 if(iter == ContextList.end() || *iter != context)
3371 listlock.unlock();
3372 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3373 return;
3375 /* Hold an extra reference to this context so it remains valid until the
3376 * ListLock is released.
3378 ContextRef ctx{std::move(*iter)};
3379 ContextList.erase(iter);
3381 ALCdevice *Device{ctx->mDevice.get()};
3383 std::lock_guard<std::mutex> _{Device->StateLock};
3384 if(!ctx->deinit() && Device->Flags.get<DeviceRunning>())
3386 Device->Backend->stop();
3387 Device->Flags.unset<DeviceRunning>();
3390 END_API_FUNC
3393 /* alcGetCurrentContext
3395 * Returns the currently active context on the calling thread
3397 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3398 START_API_FUNC
3400 ALCcontext *Context{LocalContext.get()};
3401 if(!Context) Context = GlobalContext.load();
3402 return Context;
3404 END_API_FUNC
3406 /* alcGetThreadContext
3408 * Returns the currently active thread-local context
3410 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3411 START_API_FUNC
3412 { return LocalContext.get(); }
3413 END_API_FUNC
3415 /* alcMakeContextCurrent
3417 * Makes the given context the active process-wide context, and removes the
3418 * thread-local context for the calling thread.
3420 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3421 START_API_FUNC
3423 /* context must be valid or nullptr */
3424 ContextRef ctx;
3425 if(context)
3427 ctx = VerifyContext(context);
3428 if(!ctx)
3430 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3431 return ALC_FALSE;
3434 /* Release this reference (if any) to store it in the GlobalContext
3435 * pointer. Take ownership of the reference (if any) that was previously
3436 * stored there.
3438 ctx = ContextRef{GlobalContext.exchange(ctx.release())};
3440 /* Reset (decrement) the previous global reference by replacing it with the
3441 * thread-local context. Take ownership of the thread-local context
3442 * reference (if any), clearing the storage to null.
3444 ctx = ContextRef{LocalContext.get()};
3445 if(ctx) LocalContext.set(nullptr);
3446 /* Reset (decrement) the previous thread-local reference. */
3448 return ALC_TRUE;
3450 END_API_FUNC
3452 /* alcSetThreadContext
3454 * Makes the given context the active context for the current thread
3456 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3457 START_API_FUNC
3459 /* context must be valid or nullptr */
3460 ContextRef ctx;
3461 if(context)
3463 ctx = VerifyContext(context);
3464 if(!ctx)
3466 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3467 return ALC_FALSE;
3470 /* context's reference count is already incremented */
3471 ContextRef old{LocalContext.get()};
3472 LocalContext.set(ctx.release());
3474 return ALC_TRUE;
3476 END_API_FUNC
3479 /* alcGetContextsDevice
3481 * Returns the device that a particular context is attached to
3483 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3484 START_API_FUNC
3486 ContextRef ctx{VerifyContext(Context)};
3487 if(!ctx)
3489 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3490 return nullptr;
3492 return ctx->mDevice.get();
3494 END_API_FUNC
3497 /* alcOpenDevice
3499 * Opens the named device.
3501 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3502 START_API_FUNC
3504 DO_INITCONFIG();
3506 if(!PlaybackFactory)
3508 alcSetError(nullptr, ALC_INVALID_VALUE);
3509 return nullptr;
3512 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
3513 #ifdef _WIN32
3514 /* Some old Windows apps hardcode these expecting OpenAL to use a
3515 * specific audio API, even when they're not enumerated. Creative's
3516 * router effectively ignores them too.
3518 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
3519 || strcasecmp(deviceName, "MMSYSTEM") == 0
3520 #endif
3522 deviceName = nullptr;
3524 DeviceRef device{new ALCdevice{Playback}};
3526 /* Set output format */
3527 device->FmtChans = DevFmtChannelsDefault;
3528 device->FmtType = DevFmtTypeDefault;
3529 device->Frequency = DEFAULT_OUTPUT_RATE;
3530 device->UpdateSize = DEFAULT_UPDATE_SIZE;
3531 device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
3533 device->SourcesMax = 256;
3534 device->AuxiliaryEffectSlotMax = 64;
3535 device->NumAuxSends = DEFAULT_SENDS;
3537 try {
3538 /* Create the device backend. */
3539 device->Backend = PlaybackFactory->createBackend(device.get(), BackendType::Playback);
3541 /* Find a playback device to open */
3542 ALCenum err{device->Backend->open(deviceName)};
3543 if(err != ALC_NO_ERROR)
3545 alcSetError(nullptr, err);
3546 return nullptr;
3549 catch(al::backend_exception &e) {
3550 WARN("Failed to open playback device: %s\n", e.what());
3551 alcSetError(nullptr, e.errorCode());
3552 return nullptr;
3555 deviceName = device->DeviceName.c_str();
3556 if(auto chanopt = ConfigValueStr(deviceName, nullptr, "channels"))
3558 static constexpr struct ChannelMap {
3559 const char name[16];
3560 DevFmtChannels chans;
3561 ALuint order;
3562 } chanlist[] = {
3563 { "mono", DevFmtMono, 0 },
3564 { "stereo", DevFmtStereo, 0 },
3565 { "quad", DevFmtQuad, 0 },
3566 { "surround51", DevFmtX51, 0 },
3567 { "surround61", DevFmtX61, 0 },
3568 { "surround71", DevFmtX71, 0 },
3569 { "surround51rear", DevFmtX51Rear, 0 },
3570 { "ambi1", DevFmtAmbi3D, 1 },
3571 { "ambi2", DevFmtAmbi3D, 2 },
3572 { "ambi3", DevFmtAmbi3D, 3 },
3575 const ALCchar *fmt{chanopt->c_str()};
3576 auto iter = std::find_if(std::begin(chanlist), std::end(chanlist),
3577 [fmt](const ChannelMap &entry) -> bool
3578 { return strcasecmp(entry.name, fmt) == 0; }
3580 if(iter == std::end(chanlist))
3581 ERR("Unsupported channels: %s\n", fmt);
3582 else
3584 device->FmtChans = iter->chans;
3585 device->mAmbiOrder = iter->order;
3586 device->Flags.set<ChannelsRequest>();
3589 if(auto typeopt = ConfigValueStr(deviceName, nullptr, "sample-type"))
3591 static constexpr struct TypeMap {
3592 const char name[16];
3593 DevFmtType type;
3594 } typelist[] = {
3595 { "int8", DevFmtByte },
3596 { "uint8", DevFmtUByte },
3597 { "int16", DevFmtShort },
3598 { "uint16", DevFmtUShort },
3599 { "int32", DevFmtInt },
3600 { "uint32", DevFmtUInt },
3601 { "float32", DevFmtFloat },
3604 const ALCchar *fmt{typeopt->c_str()};
3605 auto iter = std::find_if(std::begin(typelist), std::end(typelist),
3606 [fmt](const TypeMap &entry) -> bool
3607 { return strcasecmp(entry.name, fmt) == 0; }
3609 if(iter == std::end(typelist))
3610 ERR("Unsupported sample-type: %s\n", fmt);
3611 else
3613 device->FmtType = iter->type;
3614 device->Flags.set<SampleTypeRequest>();
3618 if(ALuint freq{ConfigValueUInt(deviceName, nullptr, "frequency").value_or(0)})
3620 if(freq < MIN_OUTPUT_RATE)
3622 ERR("%uhz request clamped to %uhz minimum\n", freq, MIN_OUTPUT_RATE);
3623 freq = MIN_OUTPUT_RATE;
3625 device->UpdateSize = (device->UpdateSize*freq + device->Frequency/2) / device->Frequency;
3626 device->BufferSize = (device->BufferSize*freq + device->Frequency/2) / device->Frequency;
3627 device->Frequency = freq;
3628 device->Flags.set<FrequencyRequest>();
3631 if(auto persizeopt = ConfigValueUInt(deviceName, nullptr, "period_size"))
3632 device->UpdateSize = clampu(*persizeopt, 64, 8192);
3634 if(auto peropt = ConfigValueUInt(deviceName, nullptr, "periods"))
3635 device->BufferSize = device->UpdateSize * clampu(*peropt, 2, 16);
3636 else
3637 device->BufferSize = maxu(device->BufferSize, device->UpdateSize*2);
3639 if(auto srcsopt = ConfigValueUInt(deviceName, nullptr, "sources"))
3641 if(*srcsopt > 0) device->SourcesMax = *srcsopt;
3644 if(auto slotsopt = ConfigValueUInt(deviceName, nullptr, "slots"))
3646 if(*slotsopt > 0)
3647 device->AuxiliaryEffectSlotMax = minu(*slotsopt, INT_MAX);
3650 if(auto sendsopt = ConfigValueInt(deviceName, nullptr, "sends"))
3651 device->NumAuxSends = clampu(DEFAULT_SENDS, 0,
3652 static_cast<ALuint>(clampi(*sendsopt, 0, MAX_SENDS)));
3654 device->NumStereoSources = 1;
3655 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3657 if(auto ambiopt = ConfigValueStr(deviceName, nullptr, "ambi-format"))
3659 const ALCchar *fmt{ambiopt->c_str()};
3660 if(strcasecmp(fmt, "fuma") == 0)
3662 if(device->mAmbiOrder > 3)
3663 ERR("FuMa is incompatible with %d%s order ambisonics (up to third-order only)\n",
3664 device->mAmbiOrder,
3665 (((device->mAmbiOrder%100)/10) == 1) ? "th" :
3666 ((device->mAmbiOrder%10) == 1) ? "st" :
3667 ((device->mAmbiOrder%10) == 2) ? "nd" :
3668 ((device->mAmbiOrder%10) == 3) ? "rd" : "th");
3669 else
3671 device->mAmbiLayout = AmbiLayout::FuMa;
3672 device->mAmbiScale = AmbiNorm::FuMa;
3675 else if(strcasecmp(fmt, "ambix") == 0 || strcasecmp(fmt, "acn+sn3d") == 0)
3677 device->mAmbiLayout = AmbiLayout::ACN;
3678 device->mAmbiScale = AmbiNorm::SN3D;
3680 else if(strcasecmp(fmt, "acn+n3d") == 0)
3682 device->mAmbiLayout = AmbiLayout::ACN;
3683 device->mAmbiScale = AmbiNorm::N3D;
3685 else
3686 ERR("Unsupported ambi-format: %s\n", fmt);
3690 std::lock_guard<std::recursive_mutex> _{ListLock};
3691 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3692 DeviceList.emplace(iter, device);
3695 TRACE("Created device %p, \"%s\"\n", device.get(), device->DeviceName.c_str());
3696 return device.get();
3698 END_API_FUNC
3700 /* alcCloseDevice
3702 * Closes the given device.
3704 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3705 START_API_FUNC
3707 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3708 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3709 if(iter == DeviceList.end() || *iter != device)
3711 alcSetError(nullptr, ALC_INVALID_DEVICE);
3712 return ALC_FALSE;
3714 if((*iter)->Type == Capture)
3716 alcSetError(iter->get(), ALC_INVALID_DEVICE);
3717 return ALC_FALSE;
3720 /* Erase the device, and any remaining contexts left on it, from their
3721 * respective lists.
3723 DeviceRef dev{std::move(*iter)};
3724 DeviceList.erase(iter);
3726 std::unique_lock<std::mutex> statelock{dev->StateLock};
3727 al::vector<ContextRef> orphanctxs;
3728 for(ALCcontext *ctx : *dev->mContexts.load())
3730 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), ctx);
3731 if(iter != ContextList.end() && *iter == ctx)
3733 orphanctxs.emplace_back(std::move(*iter));
3734 ContextList.erase(iter);
3737 listlock.unlock();
3739 for(ContextRef &context : orphanctxs)
3741 WARN("Releasing orphaned context %p\n", context.get());
3742 context->deinit();
3744 orphanctxs.clear();
3746 if(dev->Flags.get<DeviceRunning>())
3747 dev->Backend->stop();
3748 dev->Flags.unset<DeviceRunning>();
3750 return ALC_TRUE;
3752 END_API_FUNC
3755 /************************************************
3756 * ALC capture functions
3757 ************************************************/
3758 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3759 START_API_FUNC
3761 DO_INITCONFIG();
3763 if(!CaptureFactory)
3765 alcSetError(nullptr, ALC_INVALID_VALUE);
3766 return nullptr;
3769 if(samples <= 0)
3771 alcSetError(nullptr, ALC_INVALID_VALUE);
3772 return nullptr;
3775 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3776 deviceName = nullptr;
3778 DeviceRef device{new ALCdevice{Capture}};
3780 auto decompfmt = DecomposeDevFormat(format);
3781 if(!decompfmt)
3783 alcSetError(nullptr, ALC_INVALID_ENUM);
3784 return nullptr;
3787 device->Frequency = frequency;
3788 device->FmtChans = decompfmt->chans;
3789 device->FmtType = decompfmt->type;
3790 device->Flags.set<FrequencyRequest, ChannelsRequest, SampleTypeRequest>();
3792 device->UpdateSize = static_cast<ALuint>(samples);
3793 device->BufferSize = static_cast<ALuint>(samples);
3795 try {
3796 device->Backend = CaptureFactory->createBackend(device.get(), BackendType::Capture);
3798 TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n",
3799 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
3800 device->Frequency, device->UpdateSize, device->BufferSize);
3801 ALCenum err{device->Backend->open(deviceName)};
3802 if(err != ALC_NO_ERROR)
3804 alcSetError(nullptr, err);
3805 return nullptr;
3808 catch(al::backend_exception &e) {
3809 WARN("Failed to open capture device: %s\n", e.what());
3810 alcSetError(nullptr, e.errorCode());
3811 return nullptr;
3815 std::lock_guard<std::recursive_mutex> _{ListLock};
3816 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3817 DeviceList.emplace(iter, device);
3820 TRACE("Created device %p, \"%s\"\n", device.get(), device->DeviceName.c_str());
3821 return device.get();
3823 END_API_FUNC
3825 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3826 START_API_FUNC
3828 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3829 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3830 if(iter == DeviceList.end() || *iter != device)
3832 alcSetError(nullptr, ALC_INVALID_DEVICE);
3833 return ALC_FALSE;
3835 if((*iter)->Type != Capture)
3837 alcSetError(iter->get(), ALC_INVALID_DEVICE);
3838 return ALC_FALSE;
3841 DeviceRef dev{std::move(*iter)};
3842 DeviceList.erase(iter);
3843 listlock.unlock();
3845 std::lock_guard<std::mutex> _{dev->StateLock};
3846 if(dev->Flags.get<DeviceRunning>())
3847 dev->Backend->stop();
3848 dev->Flags.unset<DeviceRunning>();
3850 return ALC_TRUE;
3852 END_API_FUNC
3854 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3855 START_API_FUNC
3857 DeviceRef dev{VerifyDevice(device)};
3858 if(!dev || dev->Type != Capture)
3860 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3861 return;
3864 std::lock_guard<std::mutex> _{dev->StateLock};
3865 if(!dev->Connected.load(std::memory_order_acquire))
3866 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3867 else if(!dev->Flags.get<DeviceRunning>())
3869 if(dev->Backend->start())
3870 dev->Flags.set<DeviceRunning>();
3871 else
3873 aluHandleDisconnect(dev.get(), "Device start failure");
3874 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3878 END_API_FUNC
3880 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3881 START_API_FUNC
3883 DeviceRef dev{VerifyDevice(device)};
3884 if(!dev || dev->Type != Capture)
3885 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3886 else
3888 std::lock_guard<std::mutex> _{dev->StateLock};
3889 if(dev->Flags.get<DeviceRunning>())
3890 dev->Backend->stop();
3891 dev->Flags.unset<DeviceRunning>();
3894 END_API_FUNC
3896 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3897 START_API_FUNC
3899 DeviceRef dev{VerifyDevice(device)};
3900 if(!dev || dev->Type != Capture)
3902 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3903 return;
3906 ALCenum err{ALC_INVALID_VALUE};
3907 { std::lock_guard<std::mutex> _{dev->StateLock};
3908 BackendBase *backend{dev->Backend.get()};
3909 if(samples >= 0 && backend->availableSamples() >= static_cast<ALCuint>(samples))
3910 err = backend->captureSamples(buffer, static_cast<ALuint>(samples));
3912 if(err != ALC_NO_ERROR)
3913 alcSetError(dev.get(), err);
3915 END_API_FUNC
3918 /************************************************
3919 * ALC loopback functions
3920 ************************************************/
3922 /* alcLoopbackOpenDeviceSOFT
3924 * Open a loopback device, for manual rendering.
3926 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3927 START_API_FUNC
3929 DO_INITCONFIG();
3931 /* Make sure the device name, if specified, is us. */
3932 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3934 alcSetError(nullptr, ALC_INVALID_VALUE);
3935 return nullptr;
3938 DeviceRef device{new ALCdevice{Loopback}};
3940 device->SourcesMax = 256;
3941 device->AuxiliaryEffectSlotMax = 64;
3942 device->NumAuxSends = DEFAULT_SENDS;
3944 //Set output format
3945 device->BufferSize = 0;
3946 device->UpdateSize = 0;
3948 device->Frequency = DEFAULT_OUTPUT_RATE;
3949 device->FmtChans = DevFmtChannelsDefault;
3950 device->FmtType = DevFmtTypeDefault;
3952 if(auto srcsopt = ConfigValueUInt(nullptr, nullptr, "sources"))
3954 if(*srcsopt > 0) device->SourcesMax = *srcsopt;
3957 if(auto slotsopt = ConfigValueUInt(nullptr, nullptr, "slots"))
3959 if(*slotsopt > 0)
3960 device->AuxiliaryEffectSlotMax = minu(*slotsopt, INT_MAX);
3963 if(auto sendsopt = ConfigValueInt(nullptr, nullptr, "sends"))
3964 device->NumAuxSends = clampu(DEFAULT_SENDS, 0,
3965 static_cast<ALuint>(clampi(*sendsopt, 0, MAX_SENDS)));
3967 device->NumStereoSources = 1;
3968 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3970 try {
3971 device->Backend = LoopbackBackendFactory::getFactory().createBackend(device.get(),
3972 BackendType::Playback);
3974 // Open the "backend"
3975 device->Backend->open("Loopback");
3977 catch(al::backend_exception &e) {
3978 WARN("Failed to open loopback device: %s\n", e.what());
3979 alcSetError(nullptr, e.errorCode());
3980 return nullptr;
3984 std::lock_guard<std::recursive_mutex> _{ListLock};
3985 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3986 DeviceList.emplace(iter, device);
3989 TRACE("Created device %p\n", device.get());
3990 return device.get();
3992 END_API_FUNC
3994 /* alcIsRenderFormatSupportedSOFT
3996 * Determines if the loopback device supports the given format for rendering.
3998 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3999 START_API_FUNC
4001 DeviceRef dev{VerifyDevice(device)};
4002 if(!dev || dev->Type != Loopback)
4003 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4004 else if(freq <= 0)
4005 alcSetError(dev.get(), ALC_INVALID_VALUE);
4006 else
4008 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4009 return ALC_TRUE;
4012 return ALC_FALSE;
4014 END_API_FUNC
4016 /* alcRenderSamplesSOFT
4018 * Renders some samples into a buffer, using the format last set by the
4019 * attributes given to alcCreateContext.
4021 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4022 START_API_FUNC
4024 DeviceRef dev{VerifyDevice(device)};
4025 if(!dev || dev->Type != Loopback)
4026 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4027 else if(samples < 0 || (samples > 0 && buffer == nullptr))
4028 alcSetError(dev.get(), ALC_INVALID_VALUE);
4029 else
4031 BackendLockGuard _{*dev->Backend};
4032 aluMixData(dev.get(), buffer, static_cast<ALuint>(samples));
4035 END_API_FUNC
4038 /************************************************
4039 * ALC DSP pause/resume functions
4040 ************************************************/
4042 /* alcDevicePauseSOFT
4044 * Pause the DSP to stop audio processing.
4046 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4047 START_API_FUNC
4049 DeviceRef dev{VerifyDevice(device)};
4050 if(!dev || dev->Type != Playback)
4051 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4052 else
4054 std::lock_guard<std::mutex> _{dev->StateLock};
4055 if(dev->Flags.get<DeviceRunning>())
4056 dev->Backend->stop();
4057 dev->Flags.unset<DeviceRunning>();
4058 dev->Flags.set<DevicePaused>();
4061 END_API_FUNC
4063 /* alcDeviceResumeSOFT
4065 * Resume the DSP to restart audio processing.
4067 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4068 START_API_FUNC
4070 DeviceRef dev{VerifyDevice(device)};
4071 if(!dev || dev->Type != Playback)
4073 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4074 return;
4077 std::lock_guard<std::mutex> _{dev->StateLock};
4078 if(!dev->Flags.get<DevicePaused>())
4079 return;
4080 dev->Flags.unset<DevicePaused>();
4081 if(dev->mContexts.load()->empty())
4082 return;
4084 if(dev->Backend->start() == ALC_FALSE)
4086 aluHandleDisconnect(dev.get(), "Device start failure");
4087 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4088 return;
4090 dev->Flags.set<DeviceRunning>();
4092 END_API_FUNC
4095 /************************************************
4096 * ALC HRTF functions
4097 ************************************************/
4099 /* alcGetStringiSOFT
4101 * Gets a string parameter at the given index.
4103 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4104 START_API_FUNC
4106 DeviceRef dev{VerifyDevice(device)};
4107 if(!dev || dev->Type == Capture)
4108 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4109 else switch(paramName)
4111 case ALC_HRTF_SPECIFIER_SOFT:
4112 if(index >= 0 && static_cast<size_t>(index) < dev->HrtfList.size())
4113 return dev->HrtfList[static_cast<ALuint>(index)].name.c_str();
4114 alcSetError(dev.get(), ALC_INVALID_VALUE);
4115 break;
4117 default:
4118 alcSetError(dev.get(), ALC_INVALID_ENUM);
4119 break;
4122 return nullptr;
4124 END_API_FUNC
4126 /* alcResetDeviceSOFT
4128 * Resets the given device output, using the specified attribute list.
4130 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4131 START_API_FUNC
4133 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4134 DeviceRef dev{VerifyDevice(device)};
4135 if(!dev || dev->Type == Capture)
4137 listlock.unlock();
4138 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4139 return ALC_FALSE;
4141 std::lock_guard<std::mutex> _{dev->StateLock};
4142 listlock.unlock();
4144 /* Force the backend to stop mixing first since we're resetting. Also reset
4145 * the connected state so lost devices can attempt recover.
4147 if(dev->Flags.get<DeviceRunning>())
4148 dev->Backend->stop();
4149 dev->Flags.unset<DeviceRunning>();
4150 device->Connected.store(true);
4152 ALCenum err{UpdateDeviceParams(dev.get(), attribs)};
4153 if LIKELY(err == ALC_NO_ERROR) return ALC_TRUE;
4155 alcSetError(dev.get(), err);
4156 if(err == ALC_INVALID_DEVICE)
4157 aluHandleDisconnect(dev.get(), "Device start failure");
4158 return ALC_FALSE;
4160 END_API_FUNC