Finalize ALC_SOFT_output_mode
[openal-soft.git] / alc / alc.cpp
blob3bbe43d05c731c27917e8804ac70fe650316498d
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 #ifdef _WIN32
26 #define WIN32_LEAN_AND_MEAN
27 #include <windows.h>
28 #endif
30 #include <algorithm>
31 #include <array>
32 #include <atomic>
33 #include <bitset>
34 #include <cassert>
35 #include <cctype>
36 #include <chrono>
37 #include <cinttypes>
38 #include <climits>
39 #include <cmath>
40 #include <csignal>
41 #include <cstdint>
42 #include <cstdio>
43 #include <cstdlib>
44 #include <cstring>
45 #include <functional>
46 #include <iterator>
47 #include <limits>
48 #include <memory>
49 #include <mutex>
50 #include <new>
51 #include <stddef.h>
52 #include <stdexcept>
53 #include <string>
54 #include <type_traits>
55 #include <utility>
57 #include "AL/al.h"
58 #include "AL/alc.h"
59 #include "AL/alext.h"
60 #include "AL/efx.h"
62 #include "al/auxeffectslot.h"
63 #include "al/buffer.h"
64 #include "al/effect.h"
65 #include "al/filter.h"
66 #include "al/listener.h"
67 #include "al/source.h"
68 #include "albit.h"
69 #include "albyte.h"
70 #include "alconfig.h"
71 #include "almalloc.h"
72 #include "alnumeric.h"
73 #include "aloptional.h"
74 #include "alspan.h"
75 #include "alstring.h"
76 #include "alu.h"
77 #include "atomic.h"
78 #include "context.h"
79 #include "core/ambidefs.h"
80 #include "core/bformatdec.h"
81 #include "core/bs2b.h"
82 #include "core/context.h"
83 #include "core/cpu_caps.h"
84 #include "core/devformat.h"
85 #include "core/device.h"
86 #include "core/effectslot.h"
87 #include "core/except.h"
88 #include "core/helpers.h"
89 #include "core/mastering.h"
90 #include "core/mixer/hrtfdefs.h"
91 #include "core/fpu_ctrl.h"
92 #include "core/front_stablizer.h"
93 #include "core/logging.h"
94 #include "core/uhjfilter.h"
95 #include "core/voice.h"
96 #include "core/voice_change.h"
97 #include "device.h"
98 #include "effects/base.h"
99 #include "inprogext.h"
100 #include "intrusive_ptr.h"
101 #include "opthelpers.h"
102 #include "strutils.h"
103 #include "threads.h"
104 #include "vector.h"
106 #include "backends/base.h"
107 #include "backends/null.h"
108 #include "backends/loopback.h"
109 #ifdef HAVE_PIPEWIRE
110 #include "backends/pipewire.h"
111 #endif
112 #ifdef HAVE_JACK
113 #include "backends/jack.h"
114 #endif
115 #ifdef HAVE_PULSEAUDIO
116 #include "backends/pulseaudio.h"
117 #endif
118 #ifdef HAVE_ALSA
119 #include "backends/alsa.h"
120 #endif
121 #ifdef HAVE_WASAPI
122 #include "backends/wasapi.h"
123 #endif
124 #ifdef HAVE_COREAUDIO
125 #include "backends/coreaudio.h"
126 #endif
127 #ifdef HAVE_OPENSL
128 #include "backends/opensl.h"
129 #endif
130 #ifdef HAVE_OBOE
131 #include "backends/oboe.h"
132 #endif
133 #ifdef HAVE_SOLARIS
134 #include "backends/solaris.h"
135 #endif
136 #ifdef HAVE_SNDIO
137 #include "backends/sndio.h"
138 #endif
139 #ifdef HAVE_OSS
140 #include "backends/oss.h"
141 #endif
142 #ifdef HAVE_DSOUND
143 #include "backends/dsound.h"
144 #endif
145 #ifdef HAVE_WINMM
146 #include "backends/winmm.h"
147 #endif
148 #ifdef HAVE_PORTAUDIO
149 #include "backends/portaudio.h"
150 #endif
151 #ifdef HAVE_SDL2
152 #include "backends/sdl2.h"
153 #endif
154 #ifdef HAVE_WAVE
155 #include "backends/wave.h"
156 #endif
158 #ifdef ALSOFT_EAX
159 #include "al/eax_globals.h"
160 #include "al/eax_x_ram.h"
161 #endif // ALSOFT_EAX
164 FILE *gLogFile{stderr};
165 #ifdef _DEBUG
166 LogLevel gLogLevel{LogLevel::Warning};
167 #else
168 LogLevel gLogLevel{LogLevel::Error};
169 #endif
171 /************************************************
172 * Library initialization
173 ************************************************/
174 #if defined(_WIN32) && !defined(AL_LIBTYPE_STATIC)
175 BOOL APIENTRY DllMain(HINSTANCE module, DWORD reason, LPVOID /*reserved*/)
177 switch(reason)
179 case DLL_PROCESS_ATTACH:
180 /* Pin the DLL so we won't get unloaded until the process terminates */
181 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
182 reinterpret_cast<WCHAR*>(module), &module);
183 break;
185 return TRUE;
187 #endif
189 namespace {
191 using namespace std::placeholders;
192 using std::chrono::seconds;
193 using std::chrono::nanoseconds;
195 using voidp = void*;
196 using float2 = std::array<float,2>;
199 /************************************************
200 * Backends
201 ************************************************/
202 struct BackendInfo {
203 const char *name;
204 BackendFactory& (*getFactory)(void);
207 BackendInfo BackendList[] = {
208 #ifdef HAVE_PIPEWIRE
209 { "pipewire", PipeWireBackendFactory::getFactory },
210 #endif
211 #ifdef HAVE_PULSEAUDIO
212 { "pulse", PulseBackendFactory::getFactory },
213 #endif
214 #ifdef HAVE_WASAPI
215 { "wasapi", WasapiBackendFactory::getFactory },
216 #endif
217 #ifdef HAVE_COREAUDIO
218 { "core", CoreAudioBackendFactory::getFactory },
219 #endif
220 #ifdef HAVE_OBOE
221 { "oboe", OboeBackendFactory::getFactory },
222 #endif
223 #ifdef HAVE_OPENSL
224 { "opensl", OSLBackendFactory::getFactory },
225 #endif
226 #ifdef HAVE_SOLARIS
227 { "solaris", SolarisBackendFactory::getFactory },
228 #endif
229 #ifdef HAVE_SNDIO
230 { "sndio", SndIOBackendFactory::getFactory },
231 #endif
232 #ifdef HAVE_ALSA
233 { "alsa", AlsaBackendFactory::getFactory },
234 #endif
235 #ifdef HAVE_OSS
236 { "oss", OSSBackendFactory::getFactory },
237 #endif
238 #ifdef HAVE_JACK
239 { "jack", JackBackendFactory::getFactory },
240 #endif
241 #ifdef HAVE_DSOUND
242 { "dsound", DSoundBackendFactory::getFactory },
243 #endif
244 #ifdef HAVE_WINMM
245 { "winmm", WinMMBackendFactory::getFactory },
246 #endif
247 #ifdef HAVE_PORTAUDIO
248 { "port", PortBackendFactory::getFactory },
249 #endif
250 #ifdef HAVE_SDL2
251 { "sdl2", SDL2BackendFactory::getFactory },
252 #endif
254 { "null", NullBackendFactory::getFactory },
255 #ifdef HAVE_WAVE
256 { "wave", WaveBackendFactory::getFactory },
257 #endif
260 BackendFactory *PlaybackFactory{};
261 BackendFactory *CaptureFactory{};
264 /************************************************
265 * Functions, enums, and errors
266 ************************************************/
267 #define DECL(x) { #x, reinterpret_cast<void*>(x) }
268 const struct {
269 const char *funcName;
270 void *address;
271 } alcFunctions[] = {
272 DECL(alcCreateContext),
273 DECL(alcMakeContextCurrent),
274 DECL(alcProcessContext),
275 DECL(alcSuspendContext),
276 DECL(alcDestroyContext),
277 DECL(alcGetCurrentContext),
278 DECL(alcGetContextsDevice),
279 DECL(alcOpenDevice),
280 DECL(alcCloseDevice),
281 DECL(alcGetError),
282 DECL(alcIsExtensionPresent),
283 DECL(alcGetProcAddress),
284 DECL(alcGetEnumValue),
285 DECL(alcGetString),
286 DECL(alcGetIntegerv),
287 DECL(alcCaptureOpenDevice),
288 DECL(alcCaptureCloseDevice),
289 DECL(alcCaptureStart),
290 DECL(alcCaptureStop),
291 DECL(alcCaptureSamples),
293 DECL(alcSetThreadContext),
294 DECL(alcGetThreadContext),
296 DECL(alcLoopbackOpenDeviceSOFT),
297 DECL(alcIsRenderFormatSupportedSOFT),
298 DECL(alcRenderSamplesSOFT),
300 DECL(alcDevicePauseSOFT),
301 DECL(alcDeviceResumeSOFT),
303 DECL(alcGetStringiSOFT),
304 DECL(alcResetDeviceSOFT),
306 DECL(alcGetInteger64vSOFT),
308 DECL(alcReopenDeviceSOFT),
310 DECL(alEnable),
311 DECL(alDisable),
312 DECL(alIsEnabled),
313 DECL(alGetString),
314 DECL(alGetBooleanv),
315 DECL(alGetIntegerv),
316 DECL(alGetFloatv),
317 DECL(alGetDoublev),
318 DECL(alGetBoolean),
319 DECL(alGetInteger),
320 DECL(alGetFloat),
321 DECL(alGetDouble),
322 DECL(alGetError),
323 DECL(alIsExtensionPresent),
324 DECL(alGetProcAddress),
325 DECL(alGetEnumValue),
326 DECL(alListenerf),
327 DECL(alListener3f),
328 DECL(alListenerfv),
329 DECL(alListeneri),
330 DECL(alListener3i),
331 DECL(alListeneriv),
332 DECL(alGetListenerf),
333 DECL(alGetListener3f),
334 DECL(alGetListenerfv),
335 DECL(alGetListeneri),
336 DECL(alGetListener3i),
337 DECL(alGetListeneriv),
338 DECL(alGenSources),
339 DECL(alDeleteSources),
340 DECL(alIsSource),
341 DECL(alSourcef),
342 DECL(alSource3f),
343 DECL(alSourcefv),
344 DECL(alSourcei),
345 DECL(alSource3i),
346 DECL(alSourceiv),
347 DECL(alGetSourcef),
348 DECL(alGetSource3f),
349 DECL(alGetSourcefv),
350 DECL(alGetSourcei),
351 DECL(alGetSource3i),
352 DECL(alGetSourceiv),
353 DECL(alSourcePlayv),
354 DECL(alSourceStopv),
355 DECL(alSourceRewindv),
356 DECL(alSourcePausev),
357 DECL(alSourcePlay),
358 DECL(alSourceStop),
359 DECL(alSourceRewind),
360 DECL(alSourcePause),
361 DECL(alSourceQueueBuffers),
362 DECL(alSourceUnqueueBuffers),
363 DECL(alGenBuffers),
364 DECL(alDeleteBuffers),
365 DECL(alIsBuffer),
366 DECL(alBufferData),
367 DECL(alBufferf),
368 DECL(alBuffer3f),
369 DECL(alBufferfv),
370 DECL(alBufferi),
371 DECL(alBuffer3i),
372 DECL(alBufferiv),
373 DECL(alGetBufferf),
374 DECL(alGetBuffer3f),
375 DECL(alGetBufferfv),
376 DECL(alGetBufferi),
377 DECL(alGetBuffer3i),
378 DECL(alGetBufferiv),
379 DECL(alDopplerFactor),
380 DECL(alDopplerVelocity),
381 DECL(alSpeedOfSound),
382 DECL(alDistanceModel),
384 DECL(alGenFilters),
385 DECL(alDeleteFilters),
386 DECL(alIsFilter),
387 DECL(alFilteri),
388 DECL(alFilteriv),
389 DECL(alFilterf),
390 DECL(alFilterfv),
391 DECL(alGetFilteri),
392 DECL(alGetFilteriv),
393 DECL(alGetFilterf),
394 DECL(alGetFilterfv),
395 DECL(alGenEffects),
396 DECL(alDeleteEffects),
397 DECL(alIsEffect),
398 DECL(alEffecti),
399 DECL(alEffectiv),
400 DECL(alEffectf),
401 DECL(alEffectfv),
402 DECL(alGetEffecti),
403 DECL(alGetEffectiv),
404 DECL(alGetEffectf),
405 DECL(alGetEffectfv),
406 DECL(alGenAuxiliaryEffectSlots),
407 DECL(alDeleteAuxiliaryEffectSlots),
408 DECL(alIsAuxiliaryEffectSlot),
409 DECL(alAuxiliaryEffectSloti),
410 DECL(alAuxiliaryEffectSlotiv),
411 DECL(alAuxiliaryEffectSlotf),
412 DECL(alAuxiliaryEffectSlotfv),
413 DECL(alGetAuxiliaryEffectSloti),
414 DECL(alGetAuxiliaryEffectSlotiv),
415 DECL(alGetAuxiliaryEffectSlotf),
416 DECL(alGetAuxiliaryEffectSlotfv),
418 DECL(alDeferUpdatesSOFT),
419 DECL(alProcessUpdatesSOFT),
421 DECL(alSourcedSOFT),
422 DECL(alSource3dSOFT),
423 DECL(alSourcedvSOFT),
424 DECL(alGetSourcedSOFT),
425 DECL(alGetSource3dSOFT),
426 DECL(alGetSourcedvSOFT),
427 DECL(alSourcei64SOFT),
428 DECL(alSource3i64SOFT),
429 DECL(alSourcei64vSOFT),
430 DECL(alGetSourcei64SOFT),
431 DECL(alGetSource3i64SOFT),
432 DECL(alGetSourcei64vSOFT),
434 DECL(alGetStringiSOFT),
436 DECL(alBufferStorageSOFT),
437 DECL(alMapBufferSOFT),
438 DECL(alUnmapBufferSOFT),
439 DECL(alFlushMappedBufferSOFT),
441 DECL(alEventControlSOFT),
442 DECL(alEventCallbackSOFT),
443 DECL(alGetPointerSOFT),
444 DECL(alGetPointervSOFT),
446 DECL(alBufferCallbackSOFT),
447 DECL(alGetBufferPtrSOFT),
448 DECL(alGetBuffer3PtrSOFT),
449 DECL(alGetBufferPtrvSOFT),
451 DECL(alAuxiliaryEffectSlotPlaySOFT),
452 DECL(alAuxiliaryEffectSlotPlayvSOFT),
453 DECL(alAuxiliaryEffectSlotStopSOFT),
454 DECL(alAuxiliaryEffectSlotStopvSOFT),
455 #ifdef ALSOFT_EAX
456 }, eaxFunctions[] = {
457 DECL(EAXGet),
458 DECL(EAXSet),
459 DECL(EAXGetBufferMode),
460 DECL(EAXSetBufferMode),
461 #endif
463 #undef DECL
465 #define DECL(x) { #x, (x) }
466 constexpr struct {
467 const ALCchar *enumName;
468 ALCenum value;
469 } alcEnumerations[] = {
470 DECL(ALC_INVALID),
471 DECL(ALC_FALSE),
472 DECL(ALC_TRUE),
474 DECL(ALC_MAJOR_VERSION),
475 DECL(ALC_MINOR_VERSION),
476 DECL(ALC_ATTRIBUTES_SIZE),
477 DECL(ALC_ALL_ATTRIBUTES),
478 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
479 DECL(ALC_DEVICE_SPECIFIER),
480 DECL(ALC_ALL_DEVICES_SPECIFIER),
481 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
482 DECL(ALC_EXTENSIONS),
483 DECL(ALC_FREQUENCY),
484 DECL(ALC_REFRESH),
485 DECL(ALC_SYNC),
486 DECL(ALC_MONO_SOURCES),
487 DECL(ALC_STEREO_SOURCES),
488 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
489 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
490 DECL(ALC_CAPTURE_SAMPLES),
491 DECL(ALC_CONNECTED),
493 DECL(ALC_EFX_MAJOR_VERSION),
494 DECL(ALC_EFX_MINOR_VERSION),
495 DECL(ALC_MAX_AUXILIARY_SENDS),
497 DECL(ALC_FORMAT_CHANNELS_SOFT),
498 DECL(ALC_FORMAT_TYPE_SOFT),
500 DECL(ALC_MONO_SOFT),
501 DECL(ALC_STEREO_SOFT),
502 DECL(ALC_QUAD_SOFT),
503 DECL(ALC_5POINT1_SOFT),
504 DECL(ALC_6POINT1_SOFT),
505 DECL(ALC_7POINT1_SOFT),
506 DECL(ALC_BFORMAT3D_SOFT),
508 DECL(ALC_BYTE_SOFT),
509 DECL(ALC_UNSIGNED_BYTE_SOFT),
510 DECL(ALC_SHORT_SOFT),
511 DECL(ALC_UNSIGNED_SHORT_SOFT),
512 DECL(ALC_INT_SOFT),
513 DECL(ALC_UNSIGNED_INT_SOFT),
514 DECL(ALC_FLOAT_SOFT),
516 DECL(ALC_HRTF_SOFT),
517 DECL(ALC_DONT_CARE_SOFT),
518 DECL(ALC_HRTF_STATUS_SOFT),
519 DECL(ALC_HRTF_DISABLED_SOFT),
520 DECL(ALC_HRTF_ENABLED_SOFT),
521 DECL(ALC_HRTF_DENIED_SOFT),
522 DECL(ALC_HRTF_REQUIRED_SOFT),
523 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
524 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
525 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
526 DECL(ALC_HRTF_SPECIFIER_SOFT),
527 DECL(ALC_HRTF_ID_SOFT),
529 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
530 DECL(ALC_AMBISONIC_SCALING_SOFT),
531 DECL(ALC_AMBISONIC_ORDER_SOFT),
532 DECL(ALC_ACN_SOFT),
533 DECL(ALC_FUMA_SOFT),
534 DECL(ALC_N3D_SOFT),
535 DECL(ALC_SN3D_SOFT),
537 DECL(ALC_OUTPUT_LIMITER_SOFT),
539 DECL(ALC_OUTPUT_MODE_SOFT),
540 DECL(ALC_ANY_SOFT),
541 DECL(ALC_STEREO_BASIC_SOFT),
542 DECL(ALC_STEREO_UHJ_SOFT),
543 DECL(ALC_STEREO_HRTF_SOFT),
544 DECL(ALC_SURROUND_5_1_SOFT),
545 DECL(ALC_SURROUND_6_1_SOFT),
546 DECL(ALC_SURROUND_7_1_SOFT),
548 DECL(ALC_NO_ERROR),
549 DECL(ALC_INVALID_DEVICE),
550 DECL(ALC_INVALID_CONTEXT),
551 DECL(ALC_INVALID_ENUM),
552 DECL(ALC_INVALID_VALUE),
553 DECL(ALC_OUT_OF_MEMORY),
556 DECL(AL_INVALID),
557 DECL(AL_NONE),
558 DECL(AL_FALSE),
559 DECL(AL_TRUE),
561 DECL(AL_SOURCE_RELATIVE),
562 DECL(AL_CONE_INNER_ANGLE),
563 DECL(AL_CONE_OUTER_ANGLE),
564 DECL(AL_PITCH),
565 DECL(AL_POSITION),
566 DECL(AL_DIRECTION),
567 DECL(AL_VELOCITY),
568 DECL(AL_LOOPING),
569 DECL(AL_BUFFER),
570 DECL(AL_GAIN),
571 DECL(AL_MIN_GAIN),
572 DECL(AL_MAX_GAIN),
573 DECL(AL_ORIENTATION),
574 DECL(AL_REFERENCE_DISTANCE),
575 DECL(AL_ROLLOFF_FACTOR),
576 DECL(AL_CONE_OUTER_GAIN),
577 DECL(AL_MAX_DISTANCE),
578 DECL(AL_SEC_OFFSET),
579 DECL(AL_SAMPLE_OFFSET),
580 DECL(AL_BYTE_OFFSET),
581 DECL(AL_SOURCE_TYPE),
582 DECL(AL_STATIC),
583 DECL(AL_STREAMING),
584 DECL(AL_UNDETERMINED),
585 DECL(AL_METERS_PER_UNIT),
586 DECL(AL_LOOP_POINTS_SOFT),
587 DECL(AL_DIRECT_CHANNELS_SOFT),
589 DECL(AL_DIRECT_FILTER),
590 DECL(AL_AUXILIARY_SEND_FILTER),
591 DECL(AL_AIR_ABSORPTION_FACTOR),
592 DECL(AL_ROOM_ROLLOFF_FACTOR),
593 DECL(AL_CONE_OUTER_GAINHF),
594 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
595 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
596 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
598 DECL(AL_SOURCE_STATE),
599 DECL(AL_INITIAL),
600 DECL(AL_PLAYING),
601 DECL(AL_PAUSED),
602 DECL(AL_STOPPED),
604 DECL(AL_BUFFERS_QUEUED),
605 DECL(AL_BUFFERS_PROCESSED),
607 DECL(AL_FORMAT_MONO8),
608 DECL(AL_FORMAT_MONO16),
609 DECL(AL_FORMAT_MONO_FLOAT32),
610 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
611 DECL(AL_FORMAT_STEREO8),
612 DECL(AL_FORMAT_STEREO16),
613 DECL(AL_FORMAT_STEREO_FLOAT32),
614 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
615 DECL(AL_FORMAT_MONO_IMA4),
616 DECL(AL_FORMAT_STEREO_IMA4),
617 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
618 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
619 DECL(AL_FORMAT_QUAD8_LOKI),
620 DECL(AL_FORMAT_QUAD16_LOKI),
621 DECL(AL_FORMAT_QUAD8),
622 DECL(AL_FORMAT_QUAD16),
623 DECL(AL_FORMAT_QUAD32),
624 DECL(AL_FORMAT_51CHN8),
625 DECL(AL_FORMAT_51CHN16),
626 DECL(AL_FORMAT_51CHN32),
627 DECL(AL_FORMAT_61CHN8),
628 DECL(AL_FORMAT_61CHN16),
629 DECL(AL_FORMAT_61CHN32),
630 DECL(AL_FORMAT_71CHN8),
631 DECL(AL_FORMAT_71CHN16),
632 DECL(AL_FORMAT_71CHN32),
633 DECL(AL_FORMAT_REAR8),
634 DECL(AL_FORMAT_REAR16),
635 DECL(AL_FORMAT_REAR32),
636 DECL(AL_FORMAT_MONO_MULAW),
637 DECL(AL_FORMAT_MONO_MULAW_EXT),
638 DECL(AL_FORMAT_STEREO_MULAW),
639 DECL(AL_FORMAT_STEREO_MULAW_EXT),
640 DECL(AL_FORMAT_QUAD_MULAW),
641 DECL(AL_FORMAT_51CHN_MULAW),
642 DECL(AL_FORMAT_61CHN_MULAW),
643 DECL(AL_FORMAT_71CHN_MULAW),
644 DECL(AL_FORMAT_REAR_MULAW),
645 DECL(AL_FORMAT_MONO_ALAW_EXT),
646 DECL(AL_FORMAT_STEREO_ALAW_EXT),
648 DECL(AL_FORMAT_BFORMAT2D_8),
649 DECL(AL_FORMAT_BFORMAT2D_16),
650 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
651 DECL(AL_FORMAT_BFORMAT2D_MULAW),
652 DECL(AL_FORMAT_BFORMAT3D_8),
653 DECL(AL_FORMAT_BFORMAT3D_16),
654 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
655 DECL(AL_FORMAT_BFORMAT3D_MULAW),
657 DECL(AL_FREQUENCY),
658 DECL(AL_BITS),
659 DECL(AL_CHANNELS),
660 DECL(AL_SIZE),
661 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
662 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
664 DECL(AL_SOURCE_RADIUS),
666 DECL(AL_STEREO_ANGLES),
668 DECL(AL_UNUSED),
669 DECL(AL_PENDING),
670 DECL(AL_PROCESSED),
672 DECL(AL_NO_ERROR),
673 DECL(AL_INVALID_NAME),
674 DECL(AL_INVALID_ENUM),
675 DECL(AL_INVALID_VALUE),
676 DECL(AL_INVALID_OPERATION),
677 DECL(AL_OUT_OF_MEMORY),
679 DECL(AL_VENDOR),
680 DECL(AL_VERSION),
681 DECL(AL_RENDERER),
682 DECL(AL_EXTENSIONS),
684 DECL(AL_DOPPLER_FACTOR),
685 DECL(AL_DOPPLER_VELOCITY),
686 DECL(AL_DISTANCE_MODEL),
687 DECL(AL_SPEED_OF_SOUND),
688 DECL(AL_SOURCE_DISTANCE_MODEL),
689 DECL(AL_DEFERRED_UPDATES_SOFT),
690 DECL(AL_GAIN_LIMIT_SOFT),
692 DECL(AL_INVERSE_DISTANCE),
693 DECL(AL_INVERSE_DISTANCE_CLAMPED),
694 DECL(AL_LINEAR_DISTANCE),
695 DECL(AL_LINEAR_DISTANCE_CLAMPED),
696 DECL(AL_EXPONENT_DISTANCE),
697 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
699 DECL(AL_FILTER_TYPE),
700 DECL(AL_FILTER_NULL),
701 DECL(AL_FILTER_LOWPASS),
702 DECL(AL_FILTER_HIGHPASS),
703 DECL(AL_FILTER_BANDPASS),
705 DECL(AL_LOWPASS_GAIN),
706 DECL(AL_LOWPASS_GAINHF),
708 DECL(AL_HIGHPASS_GAIN),
709 DECL(AL_HIGHPASS_GAINLF),
711 DECL(AL_BANDPASS_GAIN),
712 DECL(AL_BANDPASS_GAINHF),
713 DECL(AL_BANDPASS_GAINLF),
715 DECL(AL_EFFECT_TYPE),
716 DECL(AL_EFFECT_NULL),
717 DECL(AL_EFFECT_REVERB),
718 DECL(AL_EFFECT_EAXREVERB),
719 DECL(AL_EFFECT_CHORUS),
720 DECL(AL_EFFECT_DISTORTION),
721 DECL(AL_EFFECT_ECHO),
722 DECL(AL_EFFECT_FLANGER),
723 DECL(AL_EFFECT_PITCH_SHIFTER),
724 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
725 DECL(AL_EFFECT_VOCAL_MORPHER),
726 DECL(AL_EFFECT_RING_MODULATOR),
727 DECL(AL_EFFECT_AUTOWAH),
728 DECL(AL_EFFECT_COMPRESSOR),
729 DECL(AL_EFFECT_EQUALIZER),
730 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
731 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
733 DECL(AL_EFFECTSLOT_EFFECT),
734 DECL(AL_EFFECTSLOT_GAIN),
735 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
736 DECL(AL_EFFECTSLOT_NULL),
738 DECL(AL_EAXREVERB_DENSITY),
739 DECL(AL_EAXREVERB_DIFFUSION),
740 DECL(AL_EAXREVERB_GAIN),
741 DECL(AL_EAXREVERB_GAINHF),
742 DECL(AL_EAXREVERB_GAINLF),
743 DECL(AL_EAXREVERB_DECAY_TIME),
744 DECL(AL_EAXREVERB_DECAY_HFRATIO),
745 DECL(AL_EAXREVERB_DECAY_LFRATIO),
746 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
747 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
748 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
749 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
750 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
751 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
752 DECL(AL_EAXREVERB_ECHO_TIME),
753 DECL(AL_EAXREVERB_ECHO_DEPTH),
754 DECL(AL_EAXREVERB_MODULATION_TIME),
755 DECL(AL_EAXREVERB_MODULATION_DEPTH),
756 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
757 DECL(AL_EAXREVERB_HFREFERENCE),
758 DECL(AL_EAXREVERB_LFREFERENCE),
759 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
760 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
762 DECL(AL_REVERB_DENSITY),
763 DECL(AL_REVERB_DIFFUSION),
764 DECL(AL_REVERB_GAIN),
765 DECL(AL_REVERB_GAINHF),
766 DECL(AL_REVERB_DECAY_TIME),
767 DECL(AL_REVERB_DECAY_HFRATIO),
768 DECL(AL_REVERB_REFLECTIONS_GAIN),
769 DECL(AL_REVERB_REFLECTIONS_DELAY),
770 DECL(AL_REVERB_LATE_REVERB_GAIN),
771 DECL(AL_REVERB_LATE_REVERB_DELAY),
772 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
773 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
774 DECL(AL_REVERB_DECAY_HFLIMIT),
776 DECL(AL_CHORUS_WAVEFORM),
777 DECL(AL_CHORUS_PHASE),
778 DECL(AL_CHORUS_RATE),
779 DECL(AL_CHORUS_DEPTH),
780 DECL(AL_CHORUS_FEEDBACK),
781 DECL(AL_CHORUS_DELAY),
783 DECL(AL_DISTORTION_EDGE),
784 DECL(AL_DISTORTION_GAIN),
785 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
786 DECL(AL_DISTORTION_EQCENTER),
787 DECL(AL_DISTORTION_EQBANDWIDTH),
789 DECL(AL_ECHO_DELAY),
790 DECL(AL_ECHO_LRDELAY),
791 DECL(AL_ECHO_DAMPING),
792 DECL(AL_ECHO_FEEDBACK),
793 DECL(AL_ECHO_SPREAD),
795 DECL(AL_FLANGER_WAVEFORM),
796 DECL(AL_FLANGER_PHASE),
797 DECL(AL_FLANGER_RATE),
798 DECL(AL_FLANGER_DEPTH),
799 DECL(AL_FLANGER_FEEDBACK),
800 DECL(AL_FLANGER_DELAY),
802 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY),
803 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION),
804 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION),
806 DECL(AL_RING_MODULATOR_FREQUENCY),
807 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
808 DECL(AL_RING_MODULATOR_WAVEFORM),
810 DECL(AL_PITCH_SHIFTER_COARSE_TUNE),
811 DECL(AL_PITCH_SHIFTER_FINE_TUNE),
813 DECL(AL_COMPRESSOR_ONOFF),
815 DECL(AL_EQUALIZER_LOW_GAIN),
816 DECL(AL_EQUALIZER_LOW_CUTOFF),
817 DECL(AL_EQUALIZER_MID1_GAIN),
818 DECL(AL_EQUALIZER_MID1_CENTER),
819 DECL(AL_EQUALIZER_MID1_WIDTH),
820 DECL(AL_EQUALIZER_MID2_GAIN),
821 DECL(AL_EQUALIZER_MID2_CENTER),
822 DECL(AL_EQUALIZER_MID2_WIDTH),
823 DECL(AL_EQUALIZER_HIGH_GAIN),
824 DECL(AL_EQUALIZER_HIGH_CUTOFF),
826 DECL(AL_DEDICATED_GAIN),
828 DECL(AL_AUTOWAH_ATTACK_TIME),
829 DECL(AL_AUTOWAH_RELEASE_TIME),
830 DECL(AL_AUTOWAH_RESONANCE),
831 DECL(AL_AUTOWAH_PEAK_GAIN),
833 DECL(AL_VOCAL_MORPHER_PHONEMEA),
834 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING),
835 DECL(AL_VOCAL_MORPHER_PHONEMEB),
836 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING),
837 DECL(AL_VOCAL_MORPHER_WAVEFORM),
838 DECL(AL_VOCAL_MORPHER_RATE),
840 DECL(AL_EFFECTSLOT_TARGET_SOFT),
842 DECL(AL_NUM_RESAMPLERS_SOFT),
843 DECL(AL_DEFAULT_RESAMPLER_SOFT),
844 DECL(AL_SOURCE_RESAMPLER_SOFT),
845 DECL(AL_RESAMPLER_NAME_SOFT),
847 DECL(AL_SOURCE_SPATIALIZE_SOFT),
848 DECL(AL_AUTO_SOFT),
850 DECL(AL_MAP_READ_BIT_SOFT),
851 DECL(AL_MAP_WRITE_BIT_SOFT),
852 DECL(AL_MAP_PERSISTENT_BIT_SOFT),
853 DECL(AL_PRESERVE_DATA_BIT_SOFT),
855 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT),
856 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT),
857 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT),
858 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT),
859 DECL(AL_EVENT_TYPE_DISCONNECTED_SOFT),
861 DECL(AL_DROP_UNMATCHED_SOFT),
862 DECL(AL_REMIX_UNMATCHED_SOFT),
864 DECL(AL_AMBISONIC_LAYOUT_SOFT),
865 DECL(AL_AMBISONIC_SCALING_SOFT),
866 DECL(AL_FUMA_SOFT),
867 DECL(AL_ACN_SOFT),
868 DECL(AL_SN3D_SOFT),
869 DECL(AL_N3D_SOFT),
871 DECL(AL_BUFFER_CALLBACK_FUNCTION_SOFT),
872 DECL(AL_BUFFER_CALLBACK_USER_PARAM_SOFT),
874 DECL(AL_UNPACK_AMBISONIC_ORDER_SOFT),
876 DECL(AL_EFFECT_CONVOLUTION_REVERB_SOFT),
877 DECL(AL_EFFECTSLOT_STATE_SOFT),
879 DECL(AL_FORMAT_UHJ2CHN8_SOFT),
880 DECL(AL_FORMAT_UHJ2CHN16_SOFT),
881 DECL(AL_FORMAT_UHJ2CHN_FLOAT32_SOFT),
882 DECL(AL_FORMAT_UHJ3CHN8_SOFT),
883 DECL(AL_FORMAT_UHJ3CHN16_SOFT),
884 DECL(AL_FORMAT_UHJ3CHN_FLOAT32_SOFT),
885 DECL(AL_FORMAT_UHJ4CHN8_SOFT),
886 DECL(AL_FORMAT_UHJ4CHN16_SOFT),
887 DECL(AL_FORMAT_UHJ4CHN_FLOAT32_SOFT),
888 DECL(AL_STEREO_MODE_SOFT),
889 DECL(AL_NORMAL_SOFT),
890 DECL(AL_SUPER_STEREO_SOFT),
891 DECL(AL_SUPER_STEREO_WIDTH_SOFT),
893 DECL(AL_STOP_SOURCES_ON_DISCONNECT_SOFT),
895 #ifdef ALSOFT_EAX
896 }, eaxEnumerations[] = {
897 DECL(AL_EAX_RAM_SIZE),
898 DECL(AL_EAX_RAM_FREE),
899 DECL(AL_STORAGE_AUTOMATIC),
900 DECL(AL_STORAGE_HARDWARE),
901 DECL(AL_STORAGE_ACCESSIBLE),
902 #endif // ALSOFT_EAX
904 #undef DECL
906 constexpr ALCchar alcNoError[] = "No Error";
907 constexpr ALCchar alcErrInvalidDevice[] = "Invalid Device";
908 constexpr ALCchar alcErrInvalidContext[] = "Invalid Context";
909 constexpr ALCchar alcErrInvalidEnum[] = "Invalid Enum";
910 constexpr ALCchar alcErrInvalidValue[] = "Invalid Value";
911 constexpr ALCchar alcErrOutOfMemory[] = "Out of Memory";
914 /************************************************
915 * Global variables
916 ************************************************/
918 /* Enumerated device names */
919 constexpr ALCchar alcDefaultName[] = "OpenAL Soft\0";
921 std::string alcAllDevicesList;
922 std::string alcCaptureDeviceList;
924 /* Default is always the first in the list */
925 std::string alcDefaultAllDevicesSpecifier;
926 std::string alcCaptureDefaultDeviceSpecifier;
928 std::atomic<ALCenum> LastNullDeviceError{ALC_NO_ERROR};
930 /* Flag to trap ALC device errors */
931 bool TrapALCError{false};
933 /* One-time configuration init control */
934 std::once_flag alc_config_once{};
936 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
937 * updates.
939 bool SuspendDefers{true};
941 /* Initial seed for dithering. */
942 constexpr uint DitherRNGSeed{22222u};
945 /************************************************
946 * ALC information
947 ************************************************/
948 constexpr ALCchar alcNoDeviceExtList[] =
949 "ALC_ENUMERATE_ALL_EXT "
950 "ALC_ENUMERATION_EXT "
951 "ALC_EXT_CAPTURE "
952 "ALC_EXT_EFX "
953 "ALC_EXT_thread_local_context "
954 "ALC_SOFT_loopback "
955 "ALC_SOFT_loopback_bformat "
956 "ALC_SOFT_reopen_device";
957 constexpr ALCchar alcExtensionList[] =
958 "ALC_ENUMERATE_ALL_EXT "
959 "ALC_ENUMERATION_EXT "
960 "ALC_EXT_CAPTURE "
961 "ALC_EXT_DEDICATED "
962 "ALC_EXT_disconnect "
963 "ALC_EXT_EFX "
964 "ALC_EXT_thread_local_context "
965 "ALC_SOFT_device_clock "
966 "ALC_SOFT_HRTF "
967 "ALC_SOFT_loopback "
968 "ALC_SOFT_loopback_bformat "
969 "ALC_SOFT_output_limiter "
970 "ALC_SOFT_output_mode "
971 "ALC_SOFT_pause_device "
972 "ALC_SOFT_reopen_device";
973 constexpr int alcMajorVersion{1};
974 constexpr int alcMinorVersion{1};
976 constexpr int alcEFXMajorVersion{1};
977 constexpr int alcEFXMinorVersion{0};
980 using DeviceRef = al::intrusive_ptr<ALCdevice>;
983 /************************************************
984 * Device lists
985 ************************************************/
986 al::vector<ALCdevice*> DeviceList;
987 al::vector<ALCcontext*> ContextList;
989 std::recursive_mutex ListLock;
992 void alc_initconfig(void)
994 if(auto loglevel = al::getenv("ALSOFT_LOGLEVEL"))
996 long lvl = strtol(loglevel->c_str(), nullptr, 0);
997 if(lvl >= static_cast<long>(LogLevel::Trace))
998 gLogLevel = LogLevel::Trace;
999 else if(lvl <= static_cast<long>(LogLevel::Disable))
1000 gLogLevel = LogLevel::Disable;
1001 else
1002 gLogLevel = static_cast<LogLevel>(lvl);
1005 #ifdef _WIN32
1006 if(const auto logfile = al::getenv(L"ALSOFT_LOGFILE"))
1008 FILE *logf{_wfopen(logfile->c_str(), L"wt")};
1009 if(logf) gLogFile = logf;
1010 else
1012 auto u8name = wstr_to_utf8(logfile->c_str());
1013 ERR("Failed to open log file '%s'\n", u8name.c_str());
1016 #else
1017 if(const auto logfile = al::getenv("ALSOFT_LOGFILE"))
1019 FILE *logf{fopen(logfile->c_str(), "wt")};
1020 if(logf) gLogFile = logf;
1021 else ERR("Failed to open log file '%s'\n", logfile->c_str());
1023 #endif
1025 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION, ALSOFT_GIT_COMMIT_HASH,
1026 ALSOFT_GIT_BRANCH);
1028 std::string names;
1029 if(al::size(BackendList) < 1)
1030 names = "(none)";
1031 else
1033 const al::span<const BackendInfo> infos{BackendList};
1034 names = infos[0].name;
1035 for(const auto &backend : infos.subspan<1>())
1037 names += ", ";
1038 names += backend.name;
1041 TRACE("Supported backends: %s\n", names.c_str());
1043 ReadALConfig();
1045 if(auto suspendmode = al::getenv("__ALSOFT_SUSPEND_CONTEXT"))
1047 if(al::strcasecmp(suspendmode->c_str(), "ignore") == 0)
1049 SuspendDefers = false;
1050 TRACE("Selected context suspend behavior, \"ignore\"\n");
1052 else
1053 ERR("Unhandled context suspend behavior setting: \"%s\"\n", suspendmode->c_str());
1056 int capfilter{0};
1057 #if defined(HAVE_SSE4_1)
1058 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
1059 #elif defined(HAVE_SSE3)
1060 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
1061 #elif defined(HAVE_SSE2)
1062 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
1063 #elif defined(HAVE_SSE)
1064 capfilter |= CPU_CAP_SSE;
1065 #endif
1066 #ifdef HAVE_NEON
1067 capfilter |= CPU_CAP_NEON;
1068 #endif
1069 if(auto cpuopt = ConfigValueStr(nullptr, nullptr, "disable-cpu-exts"))
1071 const char *str{cpuopt->c_str()};
1072 if(al::strcasecmp(str, "all") == 0)
1073 capfilter = 0;
1074 else
1076 const char *next = str;
1077 do {
1078 str = next;
1079 while(isspace(str[0]))
1080 str++;
1081 next = strchr(str, ',');
1083 if(!str[0] || str[0] == ',')
1084 continue;
1086 size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1087 while(len > 0 && isspace(str[len-1]))
1088 len--;
1089 if(len == 3 && al::strncasecmp(str, "sse", len) == 0)
1090 capfilter &= ~CPU_CAP_SSE;
1091 else if(len == 4 && al::strncasecmp(str, "sse2", len) == 0)
1092 capfilter &= ~CPU_CAP_SSE2;
1093 else if(len == 4 && al::strncasecmp(str, "sse3", len) == 0)
1094 capfilter &= ~CPU_CAP_SSE3;
1095 else if(len == 6 && al::strncasecmp(str, "sse4.1", len) == 0)
1096 capfilter &= ~CPU_CAP_SSE4_1;
1097 else if(len == 4 && al::strncasecmp(str, "neon", len) == 0)
1098 capfilter &= ~CPU_CAP_NEON;
1099 else
1100 WARN("Invalid CPU extension \"%s\"\n", str);
1101 } while(next++);
1104 if(auto cpuopt = GetCPUInfo())
1106 if(!cpuopt->mVendor.empty() || !cpuopt->mName.empty())
1108 TRACE("Vendor ID: \"%s\"\n", cpuopt->mVendor.c_str());
1109 TRACE("Name: \"%s\"\n", cpuopt->mName.c_str());
1111 const int caps{cpuopt->mCaps};
1112 TRACE("Extensions:%s%s%s%s%s%s\n",
1113 ((capfilter&CPU_CAP_SSE) ? ((caps&CPU_CAP_SSE) ? " +SSE" : " -SSE") : ""),
1114 ((capfilter&CPU_CAP_SSE2) ? ((caps&CPU_CAP_SSE2) ? " +SSE2" : " -SSE2") : ""),
1115 ((capfilter&CPU_CAP_SSE3) ? ((caps&CPU_CAP_SSE3) ? " +SSE3" : " -SSE3") : ""),
1116 ((capfilter&CPU_CAP_SSE4_1) ? ((caps&CPU_CAP_SSE4_1) ? " +SSE4.1" : " -SSE4.1") : ""),
1117 ((capfilter&CPU_CAP_NEON) ? ((caps&CPU_CAP_NEON) ? " +NEON" : " -NEON") : ""),
1118 ((!capfilter) ? " -none-" : ""));
1119 CPUCapFlags = caps & capfilter;
1122 if(auto priopt = ConfigValueInt(nullptr, nullptr, "rt-prio"))
1123 RTPrioLevel = *priopt;
1124 if(auto limopt = ConfigValueBool(nullptr, nullptr, "rt-time-limit"))
1125 AllowRTTimeLimit = *limopt;
1127 CompatFlagBitset compatflags{};
1128 auto checkflag = [](const char *envname, const char *optname) -> bool
1130 if(auto optval = al::getenv(envname))
1132 if(al::strcasecmp(optval->c_str(), "true") == 0
1133 || strtol(optval->c_str(), nullptr, 0) == 1)
1134 return true;
1135 return false;
1137 return GetConfigValueBool(nullptr, "game_compat", optname, false);
1139 compatflags.set(CompatFlags::ReverseX, checkflag("__ALSOFT_REVERSE_X", "reverse-x"));
1140 compatflags.set(CompatFlags::ReverseY, checkflag("__ALSOFT_REVERSE_Y", "reverse-y"));
1141 compatflags.set(CompatFlags::ReverseZ, checkflag("__ALSOFT_REVERSE_Z", "reverse-z"));
1143 aluInit(compatflags);
1144 Voice::InitMixer(ConfigValueStr(nullptr, nullptr, "resampler"));
1146 auto traperr = al::getenv("ALSOFT_TRAP_ERROR");
1147 if(traperr && (al::strcasecmp(traperr->c_str(), "true") == 0
1148 || std::strtol(traperr->c_str(), nullptr, 0) == 1))
1150 TrapALError = true;
1151 TrapALCError = true;
1153 else
1155 traperr = al::getenv("ALSOFT_TRAP_AL_ERROR");
1156 if(traperr)
1157 TrapALError = al::strcasecmp(traperr->c_str(), "true") == 0
1158 || strtol(traperr->c_str(), nullptr, 0) == 1;
1159 else
1160 TrapALError = !!GetConfigValueBool(nullptr, nullptr, "trap-al-error", false);
1162 traperr = al::getenv("ALSOFT_TRAP_ALC_ERROR");
1163 if(traperr)
1164 TrapALCError = al::strcasecmp(traperr->c_str(), "true") == 0
1165 || strtol(traperr->c_str(), nullptr, 0) == 1;
1166 else
1167 TrapALCError = !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", false);
1170 if(auto boostopt = ConfigValueFloat(nullptr, "reverb", "boost"))
1172 const float valf{std::isfinite(*boostopt) ? clampf(*boostopt, -24.0f, 24.0f) : 0.0f};
1173 ReverbBoost *= std::pow(10.0f, valf / 20.0f);
1176 auto BackendListEnd = std::end(BackendList);
1177 auto devopt = al::getenv("ALSOFT_DRIVERS");
1178 if(devopt || (devopt=ConfigValueStr(nullptr, nullptr, "drivers")))
1180 auto backendlist_cur = std::begin(BackendList);
1182 bool endlist{true};
1183 const char *next{devopt->c_str()};
1184 do {
1185 const char *devs{next};
1186 while(isspace(devs[0]))
1187 devs++;
1188 next = strchr(devs, ',');
1190 const bool delitem{devs[0] == '-'};
1191 if(devs[0] == '-') devs++;
1193 if(!devs[0] || devs[0] == ',')
1195 endlist = false;
1196 continue;
1198 endlist = true;
1200 size_t len{next ? (static_cast<size_t>(next-devs)) : strlen(devs)};
1201 while(len > 0 && isspace(devs[len-1])) --len;
1202 #ifdef HAVE_WASAPI
1203 /* HACK: For backwards compatibility, convert backend references of
1204 * mmdevapi to wasapi. This should eventually be removed.
1206 if(len == 8 && strncmp(devs, "mmdevapi", len) == 0)
1208 devs = "wasapi";
1209 len = 6;
1211 #endif
1213 auto find_backend = [devs,len](const BackendInfo &backend) -> bool
1214 { return len == strlen(backend.name) && strncmp(backend.name, devs, len) == 0; };
1215 auto this_backend = std::find_if(std::begin(BackendList), BackendListEnd,
1216 find_backend);
1218 if(this_backend == BackendListEnd)
1219 continue;
1221 if(delitem)
1222 BackendListEnd = std::move(this_backend+1, BackendListEnd, this_backend);
1223 else
1224 backendlist_cur = std::rotate(backendlist_cur, this_backend, this_backend+1);
1225 } while(next++);
1227 if(endlist)
1228 BackendListEnd = backendlist_cur;
1231 auto init_backend = [](BackendInfo &backend) -> void
1233 if(PlaybackFactory && CaptureFactory)
1234 return;
1236 BackendFactory &factory = backend.getFactory();
1237 if(!factory.init())
1239 WARN("Failed to initialize backend \"%s\"\n", backend.name);
1240 return;
1243 TRACE("Initialized backend \"%s\"\n", backend.name);
1244 if(!PlaybackFactory && factory.querySupport(BackendType::Playback))
1246 PlaybackFactory = &factory;
1247 TRACE("Added \"%s\" for playback\n", backend.name);
1249 if(!CaptureFactory && factory.querySupport(BackendType::Capture))
1251 CaptureFactory = &factory;
1252 TRACE("Added \"%s\" for capture\n", backend.name);
1255 std::for_each(std::begin(BackendList), BackendListEnd, init_backend);
1257 LoopbackBackendFactory::getFactory().init();
1259 if(!PlaybackFactory)
1260 WARN("No playback backend available!\n");
1261 if(!CaptureFactory)
1262 WARN("No capture backend available!\n");
1264 if(auto exclopt = ConfigValueStr(nullptr, nullptr, "excludefx"))
1266 const char *next{exclopt->c_str()};
1267 do {
1268 const char *str{next};
1269 next = strchr(str, ',');
1271 if(!str[0] || next == str)
1272 continue;
1274 size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1275 for(const EffectList &effectitem : gEffectList)
1277 if(len == strlen(effectitem.name) &&
1278 strncmp(effectitem.name, str, len) == 0)
1279 DisabledEffects[effectitem.type] = true;
1281 } while(next++);
1284 InitEffect(&ALCcontext::sDefaultEffect);
1285 auto defrevopt = al::getenv("ALSOFT_DEFAULT_REVERB");
1286 if(defrevopt || (defrevopt=ConfigValueStr(nullptr, nullptr, "default-reverb")))
1287 LoadReverbPreset(defrevopt->c_str(), &ALCcontext::sDefaultEffect);
1289 #ifdef ALSOFT_EAX
1291 static constexpr char eax_block_name[] = "eax";
1293 if(const auto eax_enable_opt = ConfigValueBool(nullptr, eax_block_name, "enable"))
1295 eax_g_is_enabled = *eax_enable_opt;
1296 if(!eax_g_is_enabled)
1297 TRACE("%s\n", "EAX disabled by a configuration.");
1299 else
1300 eax_g_is_enabled = true;
1302 if(eax_g_is_enabled && DisabledEffects[EAXREVERB_EFFECT])
1304 eax_g_is_enabled = false;
1305 TRACE("%s\n", "EAX disabled because EAXReverb is disabled.");
1308 #endif // ALSOFT_EAX
1310 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1313 /************************************************
1314 * Device enumeration
1315 ************************************************/
1316 void ProbeAllDevicesList()
1318 DO_INITCONFIG();
1320 std::lock_guard<std::recursive_mutex> _{ListLock};
1321 if(!PlaybackFactory)
1322 decltype(alcAllDevicesList){}.swap(alcAllDevicesList);
1323 else
1325 std::string names{PlaybackFactory->probe(BackendType::Playback)};
1326 if(names.empty()) names += '\0';
1327 names.swap(alcAllDevicesList);
1330 void ProbeCaptureDeviceList()
1332 DO_INITCONFIG();
1334 std::lock_guard<std::recursive_mutex> _{ListLock};
1335 if(!CaptureFactory)
1336 decltype(alcCaptureDeviceList){}.swap(alcCaptureDeviceList);
1337 else
1339 std::string names{CaptureFactory->probe(BackendType::Capture)};
1340 if(names.empty()) names += '\0';
1341 names.swap(alcCaptureDeviceList);
1346 struct DevFmtPair { DevFmtChannels chans; DevFmtType type; };
1347 al::optional<DevFmtPair> DecomposeDevFormat(ALenum format)
1349 static const struct {
1350 ALenum format;
1351 DevFmtChannels channels;
1352 DevFmtType type;
1353 } list[] = {
1354 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1355 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1356 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1358 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1359 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1360 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1362 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1363 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1364 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1366 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1367 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1368 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1370 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1371 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1372 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1374 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1375 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1376 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1379 for(const auto &item : list)
1381 if(item.format == format)
1382 return al::make_optional(DevFmtPair{item.channels, item.type});
1385 return al::nullopt;
1388 al::optional<DevFmtType> DevFmtTypeFromEnum(ALCenum type)
1390 switch(type)
1392 case ALC_BYTE_SOFT: return al::make_optional(DevFmtByte);
1393 case ALC_UNSIGNED_BYTE_SOFT: return al::make_optional(DevFmtUByte);
1394 case ALC_SHORT_SOFT: return al::make_optional(DevFmtShort);
1395 case ALC_UNSIGNED_SHORT_SOFT: return al::make_optional(DevFmtUShort);
1396 case ALC_INT_SOFT: return al::make_optional(DevFmtInt);
1397 case ALC_UNSIGNED_INT_SOFT: return al::make_optional(DevFmtUInt);
1398 case ALC_FLOAT_SOFT: return al::make_optional(DevFmtFloat);
1400 WARN("Unsupported format type: 0x%04x\n", type);
1401 return al::nullopt;
1403 ALCenum EnumFromDevFmt(DevFmtType type)
1405 switch(type)
1407 case DevFmtByte: return ALC_BYTE_SOFT;
1408 case DevFmtUByte: return ALC_UNSIGNED_BYTE_SOFT;
1409 case DevFmtShort: return ALC_SHORT_SOFT;
1410 case DevFmtUShort: return ALC_UNSIGNED_SHORT_SOFT;
1411 case DevFmtInt: return ALC_INT_SOFT;
1412 case DevFmtUInt: return ALC_UNSIGNED_INT_SOFT;
1413 case DevFmtFloat: return ALC_FLOAT_SOFT;
1415 throw std::runtime_error{"Invalid DevFmtType: "+std::to_string(int(type))};
1418 al::optional<DevFmtChannels> DevFmtChannelsFromEnum(ALCenum channels)
1420 switch(channels)
1422 case ALC_MONO_SOFT: return al::make_optional(DevFmtMono);
1423 case ALC_STEREO_SOFT: return al::make_optional(DevFmtStereo);
1424 case ALC_QUAD_SOFT: return al::make_optional(DevFmtQuad);
1425 case ALC_5POINT1_SOFT: return al::make_optional(DevFmtX51);
1426 case ALC_6POINT1_SOFT: return al::make_optional(DevFmtX61);
1427 case ALC_7POINT1_SOFT: return al::make_optional(DevFmtX71);
1428 case ALC_BFORMAT3D_SOFT: return al::make_optional(DevFmtAmbi3D);
1430 WARN("Unsupported format channels: 0x%04x\n", channels);
1431 return al::nullopt;
1433 ALCenum EnumFromDevFmt(DevFmtChannels channels)
1435 switch(channels)
1437 case DevFmtMono: return ALC_MONO_SOFT;
1438 case DevFmtStereo: return ALC_STEREO_SOFT;
1439 case DevFmtQuad: return ALC_QUAD_SOFT;
1440 case DevFmtX51: return ALC_5POINT1_SOFT;
1441 case DevFmtX61: return ALC_6POINT1_SOFT;
1442 case DevFmtX71: return ALC_7POINT1_SOFT;
1443 case DevFmtAmbi3D: return ALC_BFORMAT3D_SOFT;
1445 throw std::runtime_error{"Invalid DevFmtChannels: "+std::to_string(int(channels))};
1448 al::optional<DevAmbiLayout> DevAmbiLayoutFromEnum(ALCenum layout)
1450 switch(layout)
1452 case ALC_FUMA_SOFT: return al::make_optional(DevAmbiLayout::FuMa);
1453 case ALC_ACN_SOFT: return al::make_optional(DevAmbiLayout::ACN);
1455 WARN("Unsupported ambisonic layout: 0x%04x\n", layout);
1456 return al::nullopt;
1458 ALCenum EnumFromDevAmbi(DevAmbiLayout layout)
1460 switch(layout)
1462 case DevAmbiLayout::FuMa: return ALC_FUMA_SOFT;
1463 case DevAmbiLayout::ACN: return ALC_ACN_SOFT;
1465 throw std::runtime_error{"Invalid DevAmbiLayout: "+std::to_string(int(layout))};
1468 al::optional<DevAmbiScaling> DevAmbiScalingFromEnum(ALCenum scaling)
1470 switch(scaling)
1472 case ALC_FUMA_SOFT: return al::make_optional(DevAmbiScaling::FuMa);
1473 case ALC_SN3D_SOFT: return al::make_optional(DevAmbiScaling::SN3D);
1474 case ALC_N3D_SOFT: return al::make_optional(DevAmbiScaling::N3D);
1476 WARN("Unsupported ambisonic scaling: 0x%04x\n", scaling);
1477 return al::nullopt;
1479 ALCenum EnumFromDevAmbi(DevAmbiScaling scaling)
1481 switch(scaling)
1483 case DevAmbiScaling::FuMa: return ALC_FUMA_SOFT;
1484 case DevAmbiScaling::SN3D: return ALC_SN3D_SOFT;
1485 case DevAmbiScaling::N3D: return ALC_N3D_SOFT;
1487 throw std::runtime_error{"Invalid DevAmbiScaling: "+std::to_string(int(scaling))};
1491 /* Downmixing channel arrays, to map the given format's missing channels to
1492 * existing ones. Based on Wine's DSound downmix values, which are based on
1493 * PulseAudio's.
1495 const std::array<InputRemixMap,6> StereoDownmix{{
1496 { FrontCenter, {{{FrontLeft, 0.5f}, {FrontRight, 0.5f}}} },
1497 { SideLeft, {{{FrontLeft, 1.0f/9.0f}, {FrontRight, 0.0f}}} },
1498 { SideRight, {{{FrontLeft, 0.0f}, {FrontRight, 1.0f/9.0f}}} },
1499 { BackLeft, {{{FrontLeft, 1.0f/9.0f}, {FrontRight, 0.0f}}} },
1500 { BackRight, {{{FrontLeft, 0.0f}, {FrontRight, 1.0f/9.0f}}} },
1501 { BackCenter, {{{FrontLeft, 0.5f/9.0f}, {FrontRight, 0.5f/9.0f}}} },
1503 const std::array<InputRemixMap,4> QuadDownmix{{
1504 { FrontCenter, {{{FrontLeft, 0.5f}, {FrontRight, 0.5f}}} },
1505 { SideLeft, {{{FrontLeft, 0.5f}, {BackLeft, 0.5f}}} },
1506 { SideRight, {{{FrontRight, 0.5f}, {BackRight, 0.5f}}} },
1507 { BackCenter, {{{BackLeft, 0.5f}, {BackRight, 0.5f}}} },
1509 const std::array<InputRemixMap,3> X51Downmix{{
1510 { BackLeft, {{{SideLeft, 1.0f}, {SideRight, 0.0f}}} },
1511 { BackRight, {{{SideLeft, 0.0f}, {SideRight, 1.0f}}} },
1512 { BackCenter, {{{SideLeft, 0.5f}, {SideRight, 0.5f}}} },
1514 const std::array<InputRemixMap,2> X61Downmix{{
1515 { BackLeft, {{{BackCenter, 0.5f}, {SideLeft, 0.5f}}} },
1516 { BackRight, {{{BackCenter, 0.5f}, {SideRight, 0.5f}}} },
1518 const std::array<InputRemixMap,1> X71Downmix{{
1519 { BackCenter, {{{BackLeft, 0.5f}, {BackRight, 0.5f}}} },
1523 /** Stores the latest ALC device error. */
1524 void alcSetError(ALCdevice *device, ALCenum errorCode)
1526 WARN("Error generated on device %p, code 0x%04x\n", voidp{device}, errorCode);
1527 if(TrapALCError)
1529 #ifdef _WIN32
1530 /* DebugBreak() will cause an exception if there is no debugger */
1531 if(IsDebuggerPresent())
1532 DebugBreak();
1533 #elif defined(SIGTRAP)
1534 raise(SIGTRAP);
1535 #endif
1538 if(device)
1539 device->LastError.store(errorCode);
1540 else
1541 LastNullDeviceError.store(errorCode);
1545 std::unique_ptr<Compressor> CreateDeviceLimiter(const ALCdevice *device, const float threshold)
1547 static constexpr bool AutoKnee{true};
1548 static constexpr bool AutoAttack{true};
1549 static constexpr bool AutoRelease{true};
1550 static constexpr bool AutoPostGain{true};
1551 static constexpr bool AutoDeclip{true};
1552 static constexpr float LookAheadTime{0.001f};
1553 static constexpr float HoldTime{0.002f};
1554 static constexpr float PreGainDb{0.0f};
1555 static constexpr float PostGainDb{0.0f};
1556 static constexpr float Ratio{std::numeric_limits<float>::infinity()};
1557 static constexpr float KneeDb{0.0f};
1558 static constexpr float AttackTime{0.02f};
1559 static constexpr float ReleaseTime{0.2f};
1561 return Compressor::Create(device->RealOut.Buffer.size(), static_cast<float>(device->Frequency),
1562 AutoKnee, AutoAttack, AutoRelease, AutoPostGain, AutoDeclip, LookAheadTime, HoldTime,
1563 PreGainDb, PostGainDb, threshold, Ratio, KneeDb, AttackTime, ReleaseTime);
1567 * Updates the device's base clock time with however many samples have been
1568 * done. This is used so frequency changes on the device don't cause the time
1569 * to jump forward or back. Must not be called while the device is running/
1570 * mixing.
1572 static inline void UpdateClockBase(ALCdevice *device)
1574 IncrementRef(device->MixCount);
1575 device->ClockBase += nanoseconds{seconds{device->SamplesDone}} / device->Frequency;
1576 device->SamplesDone = 0;
1577 IncrementRef(device->MixCount);
1581 * Updates device parameters according to the attribute list (caller is
1582 * responsible for holding the list lock).
1584 ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
1586 if((!attrList || !attrList[0]) && device->Type == DeviceType::Loopback)
1588 WARN("Missing attributes for loopback device\n");
1589 return ALC_INVALID_VALUE;
1592 al::optional<StereoEncoding> stereomode{};
1593 al::optional<bool> optlimit{};
1594 int hrtf_id{-1};
1596 // Check for attributes
1597 if(attrList && attrList[0])
1599 uint numMono{device->NumMonoSources};
1600 uint numStereo{device->NumStereoSources};
1601 uint numSends{device->NumAuxSends};
1603 al::optional<DevFmtChannels> optchans;
1604 al::optional<DevFmtType> opttype;
1605 al::optional<DevAmbiLayout> optlayout;
1606 al::optional<DevAmbiScaling> optscale;
1607 al::optional<bool> opthrtf;
1609 ALenum outmode{ALC_ANY_SOFT};
1610 uint aorder{0u};
1611 uint freq{0u};
1613 #define ATTRIBUTE(a) a: TRACE("%s = %d\n", #a, attrList[attrIdx + 1]);
1614 size_t attrIdx{0};
1615 while(attrList[attrIdx])
1617 switch(attrList[attrIdx])
1619 case ATTRIBUTE(ALC_FORMAT_CHANNELS_SOFT)
1620 optchans = DevFmtChannelsFromEnum(attrList[attrIdx + 1]);
1621 break;
1623 case ATTRIBUTE(ALC_FORMAT_TYPE_SOFT)
1624 opttype = DevFmtTypeFromEnum(attrList[attrIdx + 1]);
1625 break;
1627 case ATTRIBUTE(ALC_FREQUENCY)
1628 freq = static_cast<uint>(attrList[attrIdx + 1]);
1629 break;
1631 case ATTRIBUTE(ALC_AMBISONIC_LAYOUT_SOFT)
1632 optlayout = DevAmbiLayoutFromEnum(attrList[attrIdx + 1]);
1633 break;
1635 case ATTRIBUTE(ALC_AMBISONIC_SCALING_SOFT)
1636 optscale = DevAmbiScalingFromEnum(attrList[attrIdx + 1]);
1637 break;
1639 case ATTRIBUTE(ALC_AMBISONIC_ORDER_SOFT)
1640 aorder = static_cast<uint>(attrList[attrIdx + 1]);
1641 break;
1643 case ATTRIBUTE(ALC_MONO_SOURCES)
1644 numMono = static_cast<uint>(attrList[attrIdx + 1]);
1645 if(numMono > INT_MAX) numMono = 0;
1646 break;
1648 case ATTRIBUTE(ALC_STEREO_SOURCES)
1649 numStereo = static_cast<uint>(attrList[attrIdx + 1]);
1650 if(numStereo > INT_MAX) numStereo = 0;
1651 break;
1653 case ATTRIBUTE(ALC_MAX_AUXILIARY_SENDS)
1654 numSends = static_cast<uint>(attrList[attrIdx + 1]);
1655 if(numSends > INT_MAX) numSends = 0;
1656 else numSends = minu(numSends, MAX_SENDS);
1657 break;
1659 case ATTRIBUTE(ALC_HRTF_SOFT)
1660 if(attrList[attrIdx + 1] == ALC_FALSE)
1661 opthrtf = false;
1662 else if(attrList[attrIdx + 1] == ALC_TRUE)
1663 opthrtf = true;
1664 else if(attrList[attrIdx + 1] == ALC_DONT_CARE_SOFT)
1665 opthrtf = al::nullopt;
1666 break;
1668 case ATTRIBUTE(ALC_HRTF_ID_SOFT)
1669 hrtf_id = attrList[attrIdx + 1];
1670 break;
1672 case ATTRIBUTE(ALC_OUTPUT_LIMITER_SOFT)
1673 if(attrList[attrIdx + 1] == ALC_FALSE)
1674 optlimit = false;
1675 else if(attrList[attrIdx + 1] == ALC_TRUE)
1676 optlimit = true;
1677 else if(attrList[attrIdx + 1] == ALC_DONT_CARE_SOFT)
1678 optlimit = al::nullopt;
1679 break;
1681 case ATTRIBUTE(ALC_OUTPUT_MODE_SOFT)
1682 outmode = attrList[attrIdx + 1];
1683 break;
1685 default:
1686 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1687 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1688 break;
1691 attrIdx += 2;
1693 #undef ATTRIBUTE
1695 const bool loopback{device->Type == DeviceType::Loopback};
1696 if(loopback)
1698 if(!optchans || !opttype)
1699 return ALC_INVALID_VALUE;
1700 if(freq < MIN_OUTPUT_RATE || freq > MAX_OUTPUT_RATE)
1701 return ALC_INVALID_VALUE;
1702 if(*optchans == DevFmtAmbi3D)
1704 if(!optlayout || !optscale)
1705 return ALC_INVALID_VALUE;
1706 if(aorder < 1 || aorder > MaxAmbiOrder)
1707 return ALC_INVALID_VALUE;
1708 if((*optlayout == DevAmbiLayout::FuMa || *optscale == DevAmbiScaling::FuMa)
1709 && aorder > 3)
1710 return ALC_INVALID_VALUE;
1714 /* If a context is already running on the device, stop playback so the
1715 * device attributes can be updated.
1717 if(device->Flags.test(DeviceRunning))
1718 device->Backend->stop();
1719 device->Flags.reset(DeviceRunning);
1721 UpdateClockBase(device);
1723 /* Calculate the max number of sources, and split them between the mono
1724 * and stereo count given the requested number of stereo sources.
1726 if(auto srcsopt = device->configValue<uint>(nullptr, "sources"))
1728 if(*srcsopt <= 0) numMono = 256;
1729 else numMono = *srcsopt;
1731 else
1733 if(numMono > INT_MAX-numStereo)
1734 numMono = INT_MAX-numStereo;
1735 numMono = maxu(numMono+numStereo, 256);
1737 numStereo = minu(numStereo, numMono);
1738 numMono -= numStereo;
1739 device->SourcesMax = numMono + numStereo;
1740 device->NumMonoSources = numMono;
1741 device->NumStereoSources = numStereo;
1743 if(auto sendsopt = device->configValue<int>(nullptr, "sends"))
1744 numSends = minu(numSends, static_cast<uint>(clampi(*sendsopt, 0, MAX_SENDS)));
1745 device->NumAuxSends = numSends;
1747 if(loopback)
1749 device->Frequency = freq;
1750 device->FmtChans = *optchans;
1751 device->FmtType = *opttype;
1752 if(device->FmtChans == DevFmtAmbi3D)
1754 device->mAmbiOrder = aorder;
1755 device->mAmbiLayout = *optlayout;
1756 device->mAmbiScale = *optscale;
1758 else if(device->FmtChans == DevFmtStereo)
1760 if(opthrtf)
1761 stereomode = *opthrtf ? StereoEncoding::Hrtf : StereoEncoding::Default;
1763 if(outmode == ALC_STEREO_BASIC_SOFT)
1764 stereomode = StereoEncoding::Basic;
1765 else if(outmode == ALC_STEREO_UHJ_SOFT)
1766 stereomode = StereoEncoding::Uhj;
1767 else if(outmode == ALC_STEREO_HRTF_SOFT)
1768 stereomode = StereoEncoding::Hrtf;
1770 device->Flags.set(FrequencyRequest).set(ChannelsRequest).set(SampleTypeRequest);
1772 else
1774 device->Flags.reset(FrequencyRequest).reset(ChannelsRequest).reset(SampleTypeRequest);
1775 device->FmtType = DevFmtTypeDefault;
1776 device->FmtChans = DevFmtChannelsDefault;
1777 device->mAmbiOrder = 0;
1778 device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
1779 device->UpdateSize = DEFAULT_UPDATE_SIZE;
1780 device->Frequency = DEFAULT_OUTPUT_RATE;
1782 freq = device->configValue<uint>(nullptr, "frequency").value_or(freq);
1783 if(freq > 0)
1785 freq = clampu(freq, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE);
1787 const double scale{static_cast<double>(freq) / device->Frequency};
1788 device->UpdateSize = static_cast<uint>(device->UpdateSize*scale + 0.5);
1789 device->BufferSize = static_cast<uint>(device->BufferSize*scale + 0.5);
1791 device->Frequency = freq;
1792 device->Flags.set(FrequencyRequest);
1795 auto set_device_mode = [device](DevFmtChannels chans) noexcept
1797 device->FmtChans = chans;
1798 device->Flags.set(ChannelsRequest);
1800 if(opthrtf)
1802 if(*opthrtf)
1804 set_device_mode(DevFmtStereo);
1805 stereomode = StereoEncoding::Hrtf;
1807 else
1808 stereomode = StereoEncoding::Default;
1811 using OutputMode = ALCdevice::OutputMode;
1812 switch(OutputMode(outmode))
1814 case OutputMode::Any: break;
1815 case OutputMode::Mono: set_device_mode(DevFmtMono); break;
1816 case OutputMode::Stereo: set_device_mode(DevFmtStereo); break;
1817 case OutputMode::StereoBasic:
1818 set_device_mode(DevFmtStereo);
1819 stereomode = StereoEncoding::Basic;
1820 break;
1821 case OutputMode::Uhj2:
1822 set_device_mode(DevFmtStereo);
1823 stereomode = StereoEncoding::Uhj;
1824 break;
1825 case OutputMode::Hrtf:
1826 set_device_mode(DevFmtStereo);
1827 stereomode = StereoEncoding::Hrtf;
1828 break;
1829 case OutputMode::Quad: set_device_mode(DevFmtQuad); break;
1830 case OutputMode::X51: set_device_mode(DevFmtX51); break;
1831 case OutputMode::X61: set_device_mode(DevFmtX61); break;
1832 case OutputMode::X71: set_device_mode(DevFmtX71); break;
1837 if(device->Flags.test(DeviceRunning))
1838 return ALC_NO_ERROR;
1840 device->AvgSpeakerDist = 0.0f;
1841 device->mNFCtrlFilter = NfcFilter{};
1842 device->mUhjEncoder = nullptr;
1843 device->AmbiDecoder = nullptr;
1844 device->Bs2b = nullptr;
1845 device->PostProcess = nullptr;
1847 device->Limiter = nullptr;
1848 device->ChannelDelays = nullptr;
1850 std::fill(std::begin(device->HrtfAccumData), std::end(device->HrtfAccumData), float2{});
1852 device->Dry.AmbiMap.fill(BFChannelConfig{});
1853 device->Dry.Buffer = {};
1854 std::fill(std::begin(device->NumChannelsPerOrder), std::end(device->NumChannelsPerOrder), 0u);
1855 device->RealOut.RemixMap = {};
1856 device->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
1857 device->RealOut.Buffer = {};
1858 device->MixBuffer.clear();
1859 device->MixBuffer.shrink_to_fit();
1861 UpdateClockBase(device);
1862 device->FixedLatency = nanoseconds::zero();
1864 device->DitherDepth = 0.0f;
1865 device->DitherSeed = DitherRNGSeed;
1867 device->mHrtfStatus = ALC_HRTF_DISABLED_SOFT;
1869 /*************************************************************************
1870 * Update device format request from the user configuration
1872 if(device->Type != DeviceType::Loopback)
1874 if(auto typeopt = device->configValue<std::string>(nullptr, "sample-type"))
1876 static constexpr struct TypeMap {
1877 const char name[8];
1878 DevFmtType type;
1879 } typelist[] = {
1880 { "int8", DevFmtByte },
1881 { "uint8", DevFmtUByte },
1882 { "int16", DevFmtShort },
1883 { "uint16", DevFmtUShort },
1884 { "int32", DevFmtInt },
1885 { "uint32", DevFmtUInt },
1886 { "float32", DevFmtFloat },
1889 const ALCchar *fmt{typeopt->c_str()};
1890 auto iter = std::find_if(std::begin(typelist), std::end(typelist),
1891 [fmt](const TypeMap &entry) -> bool
1892 { return al::strcasecmp(entry.name, fmt) == 0; });
1893 if(iter == std::end(typelist))
1894 ERR("Unsupported sample-type: %s\n", fmt);
1895 else
1897 device->FmtType = iter->type;
1898 device->Flags.set(SampleTypeRequest);
1901 if(auto chanopt = device->configValue<std::string>(nullptr, "channels"))
1903 static constexpr struct ChannelMap {
1904 const char name[16];
1905 DevFmtChannels chans;
1906 uint8_t order;
1907 } chanlist[] = {
1908 { "mono", DevFmtMono, 0 },
1909 { "stereo", DevFmtStereo, 0 },
1910 { "quad", DevFmtQuad, 0 },
1911 { "surround51", DevFmtX51, 0 },
1912 { "surround61", DevFmtX61, 0 },
1913 { "surround71", DevFmtX71, 0 },
1914 { "surround51rear", DevFmtX51, 0 },
1915 { "ambi1", DevFmtAmbi3D, 1 },
1916 { "ambi2", DevFmtAmbi3D, 2 },
1917 { "ambi3", DevFmtAmbi3D, 3 },
1920 const ALCchar *fmt{chanopt->c_str()};
1921 auto iter = std::find_if(std::begin(chanlist), std::end(chanlist),
1922 [fmt](const ChannelMap &entry) -> bool
1923 { return al::strcasecmp(entry.name, fmt) == 0; });
1924 if(iter == std::end(chanlist))
1925 ERR("Unsupported channels: %s\n", fmt);
1926 else
1928 device->FmtChans = iter->chans;
1929 device->mAmbiOrder = iter->order;
1930 device->Flags.set(ChannelsRequest);
1933 if(auto ambiopt = device->configValue<std::string>(nullptr, "ambi-format"))
1935 const ALCchar *fmt{ambiopt->c_str()};
1936 if(al::strcasecmp(fmt, "fuma") == 0)
1938 if(device->mAmbiOrder > 3)
1939 ERR("FuMa is incompatible with %d%s order ambisonics (up to 3rd order only)\n",
1940 device->mAmbiOrder,
1941 (((device->mAmbiOrder%100)/10) == 1) ? "th" :
1942 ((device->mAmbiOrder%10) == 1) ? "st" :
1943 ((device->mAmbiOrder%10) == 2) ? "nd" :
1944 ((device->mAmbiOrder%10) == 3) ? "rd" : "th");
1945 else
1947 device->mAmbiLayout = DevAmbiLayout::FuMa;
1948 device->mAmbiScale = DevAmbiScaling::FuMa;
1951 else if(al::strcasecmp(fmt, "acn+fuma") == 0)
1953 if(device->mAmbiOrder > 3)
1954 ERR("FuMa is incompatible with %d%s order ambisonics (up to 3rd order only)\n",
1955 device->mAmbiOrder,
1956 (((device->mAmbiOrder%100)/10) == 1) ? "th" :
1957 ((device->mAmbiOrder%10) == 1) ? "st" :
1958 ((device->mAmbiOrder%10) == 2) ? "nd" :
1959 ((device->mAmbiOrder%10) == 3) ? "rd" : "th");
1960 else
1962 device->mAmbiLayout = DevAmbiLayout::ACN;
1963 device->mAmbiScale = DevAmbiScaling::FuMa;
1966 else if(al::strcasecmp(fmt, "ambix") == 0 || al::strcasecmp(fmt, "acn+sn3d") == 0)
1968 device->mAmbiLayout = DevAmbiLayout::ACN;
1969 device->mAmbiScale = DevAmbiScaling::SN3D;
1971 else if(al::strcasecmp(fmt, "acn+n3d") == 0)
1973 device->mAmbiLayout = DevAmbiLayout::ACN;
1974 device->mAmbiScale = DevAmbiScaling::N3D;
1976 else
1977 ERR("Unsupported ambi-format: %s\n", fmt);
1980 if(auto persizeopt = device->configValue<uint>(nullptr, "period_size"))
1981 device->UpdateSize = clampu(*persizeopt, 64, 8192);
1983 if(auto peropt = device->configValue<uint>(nullptr, "periods"))
1984 device->BufferSize = device->UpdateSize * clampu(*peropt, 2, 16);
1985 else
1986 device->BufferSize = maxu(device->BufferSize, device->UpdateSize*2);
1988 if(auto hrtfopt = device->configValue<std::string>(nullptr, "hrtf"))
1990 const char *hrtf{hrtfopt->c_str()};
1991 if(al::strcasecmp(hrtf, "true") == 0)
1993 stereomode = StereoEncoding::Hrtf;
1994 device->FmtChans = DevFmtStereo;
1995 device->Flags.set(ChannelsRequest);
1997 else if(al::strcasecmp(hrtf, "false") == 0)
1999 if(!stereomode || *stereomode == StereoEncoding::Hrtf)
2000 stereomode = StereoEncoding::Default;
2002 else if(al::strcasecmp(hrtf, "auto") != 0)
2003 ERR("Unexpected hrtf value: %s\n", hrtf);
2007 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u / %u buffer\n",
2008 device->Flags.test(ChannelsRequest)?"*":"", DevFmtChannelsString(device->FmtChans),
2009 device->Flags.test(SampleTypeRequest)?"*":"", DevFmtTypeString(device->FmtType),
2010 device->Flags.test(FrequencyRequest)?"*":"", device->Frequency,
2011 device->UpdateSize, device->BufferSize);
2013 const uint oldFreq{device->Frequency};
2014 const DevFmtChannels oldChans{device->FmtChans};
2015 const DevFmtType oldType{device->FmtType};
2016 try {
2017 auto backend = device->Backend.get();
2018 if(!backend->reset())
2019 throw al::backend_exception{al::backend_error::DeviceError, "Device reset failure"};
2021 catch(std::exception &e) {
2022 ERR("Device error: %s\n", e.what());
2023 device->handleDisconnect("%s", e.what());
2024 return ALC_INVALID_DEVICE;
2027 if(device->FmtChans != oldChans && device->Flags.test(ChannelsRequest))
2029 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2030 DevFmtChannelsString(device->FmtChans));
2031 device->Flags.reset(ChannelsRequest);
2033 if(device->FmtType != oldType && device->Flags.test(SampleTypeRequest))
2035 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2036 DevFmtTypeString(device->FmtType));
2037 device->Flags.reset(SampleTypeRequest);
2039 if(device->Frequency != oldFreq && device->Flags.test(FrequencyRequest))
2041 WARN("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2042 device->Flags.reset(FrequencyRequest);
2045 TRACE("Post-reset: %s, %s, %uhz, %u / %u buffer\n",
2046 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2047 device->Frequency, device->UpdateSize, device->BufferSize);
2049 if(device->Type != DeviceType::Loopback)
2051 if(auto modeopt = device->configValue<std::string>(nullptr, "stereo-mode"))
2053 const char *mode{modeopt->c_str()};
2054 if(al::strcasecmp(mode, "headphones") == 0)
2055 device->Flags.set(DirectEar);
2056 else if(al::strcasecmp(mode, "speakers") == 0)
2057 device->Flags.reset(DirectEar);
2058 else if(al::strcasecmp(mode, "auto") != 0)
2059 ERR("Unexpected stereo-mode: %s\n", mode);
2062 if(auto encopt = device->configValue<std::string>(nullptr, "stereo-encoding"))
2064 const char *mode{encopt->c_str()};
2065 if(al::strcasecmp(mode, "panpot") == 0)
2066 stereomode = al::make_optional(StereoEncoding::Basic);
2067 else if(al::strcasecmp(mode, "uhj") == 0)
2068 stereomode = al::make_optional(StereoEncoding::Uhj);
2069 else if(al::strcasecmp(mode, "hrtf") == 0)
2070 stereomode = al::make_optional(StereoEncoding::Hrtf);
2071 else
2072 ERR("Unexpected stereo-encoding: %s\n", mode);
2076 aluInitRenderer(device, hrtf_id, stereomode);
2078 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2079 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
2080 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
2082 switch(device->FmtChans)
2084 case DevFmtMono: break;
2085 case DevFmtStereo:
2086 if(!device->mUhjEncoder)
2087 device->RealOut.RemixMap = StereoDownmix;
2088 break;
2089 case DevFmtQuad: device->RealOut.RemixMap = QuadDownmix; break;
2090 case DevFmtX51: device->RealOut.RemixMap = X51Downmix; break;
2091 case DevFmtX61: device->RealOut.RemixMap = X61Downmix; break;
2092 case DevFmtX71: device->RealOut.RemixMap = X71Downmix; break;
2093 case DevFmtAmbi3D: break;
2096 nanoseconds::rep sample_delay{0};
2097 if(device->mUhjEncoder)
2098 sample_delay += UhjEncoder::sFilterDelay;
2099 if(auto *ambidec = device->AmbiDecoder.get())
2101 if(ambidec->hasStablizer())
2102 sample_delay += FrontStablizer::DelayLength;
2105 if(device->getConfigValueBool(nullptr, "dither", true))
2107 int depth{device->configValue<int>(nullptr, "dither-depth").value_or(0)};
2108 if(depth <= 0)
2110 switch(device->FmtType)
2112 case DevFmtByte:
2113 case DevFmtUByte:
2114 depth = 8;
2115 break;
2116 case DevFmtShort:
2117 case DevFmtUShort:
2118 depth = 16;
2119 break;
2120 case DevFmtInt:
2121 case DevFmtUInt:
2122 case DevFmtFloat:
2123 break;
2127 if(depth > 0)
2129 depth = clampi(depth, 2, 24);
2130 device->DitherDepth = std::pow(2.0f, static_cast<float>(depth-1));
2133 if(!(device->DitherDepth > 0.0f))
2134 TRACE("Dithering disabled\n");
2135 else
2136 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device->DitherDepth)+0.5f)+1,
2137 device->DitherDepth);
2139 if(auto limopt = device->configValue<bool>(nullptr, "output-limiter"))
2140 optlimit = limopt;
2142 /* If the gain limiter is unset, use the limiter for integer-based output
2143 * (where samples must be clamped), and don't for floating-point (which can
2144 * take unclamped samples).
2146 if(!optlimit)
2148 switch(device->FmtType)
2150 case DevFmtByte:
2151 case DevFmtUByte:
2152 case DevFmtShort:
2153 case DevFmtUShort:
2154 case DevFmtInt:
2155 case DevFmtUInt:
2156 optlimit = true;
2157 break;
2158 case DevFmtFloat:
2159 break;
2162 if(optlimit.value_or(false) == false)
2163 TRACE("Output limiter disabled\n");
2164 else
2166 float thrshld{1.0f};
2167 switch(device->FmtType)
2169 case DevFmtByte:
2170 case DevFmtUByte:
2171 thrshld = 127.0f / 128.0f;
2172 break;
2173 case DevFmtShort:
2174 case DevFmtUShort:
2175 thrshld = 32767.0f / 32768.0f;
2176 break;
2177 case DevFmtInt:
2178 case DevFmtUInt:
2179 case DevFmtFloat:
2180 break;
2182 if(device->DitherDepth > 0.0f)
2183 thrshld -= 1.0f / device->DitherDepth;
2185 const float thrshld_dB{std::log10(thrshld) * 20.0f};
2186 auto limiter = CreateDeviceLimiter(device, thrshld_dB);
2188 sample_delay += limiter->getLookAhead();
2189 device->Limiter = std::move(limiter);
2190 TRACE("Output limiter enabled, %.4fdB limit\n", thrshld_dB);
2193 /* Convert the sample delay from samples to nanosamples to nanoseconds. */
2194 device->FixedLatency += nanoseconds{seconds{sample_delay}} / device->Frequency;
2195 TRACE("Fixed device latency: %" PRId64 "ns\n", int64_t{device->FixedLatency.count()});
2197 FPUCtl mixer_mode{};
2198 for(ContextBase *ctxbase : *device->mContexts.load())
2200 auto *context = static_cast<ALCcontext*>(ctxbase);
2202 auto GetEffectBuffer = [](ALbuffer *buffer) noexcept -> EffectState::Buffer
2204 if(!buffer) return EffectState::Buffer{};
2205 return EffectState::Buffer{buffer, buffer->mData};
2207 std::unique_lock<std::mutex> proplock{context->mPropLock};
2208 std::unique_lock<std::mutex> slotlock{context->mEffectSlotLock};
2210 /* Clear out unused wet buffers. */
2211 auto buffer_not_in_use = [](WetBufferPtr &wetbuffer) noexcept -> bool
2212 { return !wetbuffer->mInUse; };
2213 auto wetbuffer_iter = std::remove_if(context->mWetBuffers.begin(),
2214 context->mWetBuffers.end(), buffer_not_in_use);
2215 context->mWetBuffers.erase(wetbuffer_iter, context->mWetBuffers.end());
2217 if(ALeffectslot *slot{context->mDefaultSlot.get()})
2219 aluInitEffectPanning(&slot->mSlot, context);
2221 EffectState *state{slot->Effect.State.get()};
2222 state->mOutTarget = device->Dry.Buffer;
2223 state->deviceUpdate(device, GetEffectBuffer(slot->Buffer));
2224 slot->updateProps(context);
2227 if(EffectSlotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_relaxed)})
2228 std::fill_n(curarray->end(), curarray->size(), nullptr);
2229 for(auto &sublist : context->mEffectSlotList)
2231 uint64_t usemask{~sublist.FreeMask};
2232 while(usemask)
2234 const int idx{al::countr_zero(usemask)};
2235 ALeffectslot *slot{sublist.EffectSlots + idx};
2236 usemask &= ~(1_u64 << idx);
2238 aluInitEffectPanning(&slot->mSlot, context);
2240 EffectState *state{slot->Effect.State.get()};
2241 state->mOutTarget = device->Dry.Buffer;
2242 state->deviceUpdate(device, GetEffectBuffer(slot->Buffer));
2243 slot->updateProps(context);
2246 slotlock.unlock();
2248 const uint num_sends{device->NumAuxSends};
2249 std::unique_lock<std::mutex> srclock{context->mSourceLock};
2250 for(auto &sublist : context->mSourceList)
2252 uint64_t usemask{~sublist.FreeMask};
2253 while(usemask)
2255 const int idx{al::countr_zero(usemask)};
2256 ALsource *source{sublist.Sources + idx};
2257 usemask &= ~(1_u64 << idx);
2259 auto clear_send = [](ALsource::SendData &send) -> void
2261 if(send.Slot)
2262 DecrementRef(send.Slot->ref);
2263 send.Slot = nullptr;
2264 send.Gain = 1.0f;
2265 send.GainHF = 1.0f;
2266 send.HFReference = LOWPASSFREQREF;
2267 send.GainLF = 1.0f;
2268 send.LFReference = HIGHPASSFREQREF;
2270 auto send_begin = source->Send.begin() + static_cast<ptrdiff_t>(num_sends);
2271 std::for_each(send_begin, source->Send.end(), clear_send);
2273 source->mPropsDirty = true;
2277 auto voicelist = context->getVoicesSpan();
2278 for(Voice *voice : voicelist)
2280 /* Clear extraneous property set sends. */
2281 std::fill(std::begin(voice->mProps.Send)+num_sends, std::end(voice->mProps.Send),
2282 VoiceProps::SendData{});
2284 std::fill(voice->mSend.begin()+num_sends, voice->mSend.end(), Voice::TargetData{});
2285 for(auto &chandata : voice->mChans)
2287 std::fill(chandata.mWetParams.begin()+num_sends, chandata.mWetParams.end(),
2288 SendParams{});
2291 if(VoicePropsItem *props{voice->mUpdate.exchange(nullptr, std::memory_order_relaxed)})
2292 AtomicReplaceHead(context->mFreeVoiceProps, props);
2294 /* Force the voice to stopped if it was stopping. */
2295 Voice::State vstate{Voice::Stopping};
2296 voice->mPlayState.compare_exchange_strong(vstate, Voice::Stopped,
2297 std::memory_order_acquire, std::memory_order_acquire);
2298 if(voice->mSourceID.load(std::memory_order_relaxed) == 0u)
2299 continue;
2301 voice->prepare(device);
2303 /* Clear all voice props to let them get allocated again. */
2304 context->mVoicePropClusters.clear();
2305 context->mFreeVoiceProps.store(nullptr, std::memory_order_relaxed);
2306 srclock.unlock();
2308 context->mPropsDirty = false;
2309 UpdateContextProps(context);
2310 UpdateAllSourceProps(context);
2312 mixer_mode.leave();
2314 if(!device->Flags.test(DevicePaused))
2316 try {
2317 auto backend = device->Backend.get();
2318 backend->start();
2319 device->Flags.set(DeviceRunning);
2321 catch(al::backend_exception& e) {
2322 ERR("%s\n", e.what());
2323 device->handleDisconnect("%s", e.what());
2324 return ALC_INVALID_DEVICE;
2326 TRACE("Post-start: %s, %s, %uhz, %u / %u buffer\n",
2327 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2328 device->Frequency, device->UpdateSize, device->BufferSize);
2331 return ALC_NO_ERROR;
2335 * Updates device parameters as above, and also first clears the disconnected
2336 * status, if set.
2338 bool ResetDeviceParams(ALCdevice *device, const int *attrList)
2340 /* If the device was disconnected, reset it since we're opened anew. */
2341 if UNLIKELY(!device->Connected.load(std::memory_order_relaxed))
2343 /* Make sure disconnection is finished before continuing on. */
2344 device->waitForMix();
2346 for(ContextBase *ctxbase : *device->mContexts.load(std::memory_order_acquire))
2348 auto *ctx = static_cast<ALCcontext*>(ctxbase);
2349 if(!ctx->mStopVoicesOnDisconnect.load(std::memory_order_acquire))
2350 continue;
2352 /* Clear any pending voice changes and reallocate voices to get a
2353 * clean restart.
2355 std::lock_guard<std::mutex> __{ctx->mSourceLock};
2356 auto *vchg = ctx->mCurrentVoiceChange.load(std::memory_order_acquire);
2357 while(auto *next = vchg->mNext.load(std::memory_order_acquire))
2358 vchg = next;
2359 ctx->mCurrentVoiceChange.store(vchg, std::memory_order_release);
2361 ctx->mVoicePropClusters.clear();
2362 ctx->mFreeVoiceProps.store(nullptr, std::memory_order_relaxed);
2364 ctx->mVoiceClusters.clear();
2365 ctx->allocVoices(std::max<size_t>(256,
2366 ctx->mActiveVoiceCount.load(std::memory_order_relaxed)));
2369 device->Connected.store(true);
2372 ALCenum err{UpdateDeviceParams(device, attrList)};
2373 if LIKELY(err == ALC_NO_ERROR) return ALC_TRUE;
2375 alcSetError(device, err);
2376 return ALC_FALSE;
2380 /** Checks if the device handle is valid, and returns a new reference if so. */
2381 DeviceRef VerifyDevice(ALCdevice *device)
2383 std::lock_guard<std::recursive_mutex> _{ListLock};
2384 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
2385 if(iter != DeviceList.end() && *iter == device)
2387 (*iter)->add_ref();
2388 return DeviceRef{*iter};
2390 return nullptr;
2395 * Checks if the given context is valid, returning a new reference to it if so.
2397 ContextRef VerifyContext(ALCcontext *context)
2399 std::lock_guard<std::recursive_mutex> _{ListLock};
2400 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
2401 if(iter != ContextList.end() && *iter == context)
2403 (*iter)->add_ref();
2404 return ContextRef{*iter};
2406 return nullptr;
2409 } // namespace
2411 /** Returns a new reference to the currently active context for this thread. */
2412 ContextRef GetContextRef(void)
2414 ALCcontext *context{ALCcontext::getThreadContext()};
2415 if(context)
2416 context->add_ref();
2417 else
2419 std::lock_guard<std::recursive_mutex> _{ListLock};
2420 context = ALCcontext::sGlobalContext.load(std::memory_order_acquire);
2421 if(context) context->add_ref();
2423 return ContextRef{context};
2427 /************************************************
2428 * Standard ALC functions
2429 ************************************************/
2431 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2432 START_API_FUNC
2434 DeviceRef dev{VerifyDevice(device)};
2435 if(dev) return dev->LastError.exchange(ALC_NO_ERROR);
2436 return LastNullDeviceError.exchange(ALC_NO_ERROR);
2438 END_API_FUNC
2441 ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2442 START_API_FUNC
2444 if(!SuspendDefers)
2445 return;
2447 ContextRef ctx{VerifyContext(context)};
2448 if(!ctx)
2449 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2450 else
2452 std::lock_guard<std::mutex> _{ctx->mPropLock};
2453 ctx->deferUpdates();
2456 END_API_FUNC
2458 ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context)
2459 START_API_FUNC
2461 if(!SuspendDefers)
2462 return;
2464 ContextRef ctx{VerifyContext(context)};
2465 if(!ctx)
2466 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2467 else
2469 std::lock_guard<std::mutex> _{ctx->mPropLock};
2470 ctx->processUpdates();
2473 END_API_FUNC
2476 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2477 START_API_FUNC
2479 const ALCchar *value{nullptr};
2481 switch(param)
2483 case ALC_NO_ERROR:
2484 value = alcNoError;
2485 break;
2487 case ALC_INVALID_ENUM:
2488 value = alcErrInvalidEnum;
2489 break;
2491 case ALC_INVALID_VALUE:
2492 value = alcErrInvalidValue;
2493 break;
2495 case ALC_INVALID_DEVICE:
2496 value = alcErrInvalidDevice;
2497 break;
2499 case ALC_INVALID_CONTEXT:
2500 value = alcErrInvalidContext;
2501 break;
2503 case ALC_OUT_OF_MEMORY:
2504 value = alcErrOutOfMemory;
2505 break;
2507 case ALC_DEVICE_SPECIFIER:
2508 value = alcDefaultName;
2509 break;
2511 case ALC_ALL_DEVICES_SPECIFIER:
2512 if(DeviceRef dev{VerifyDevice(Device)})
2514 if(dev->Type == DeviceType::Capture)
2515 alcSetError(dev.get(), ALC_INVALID_ENUM);
2516 else if(dev->Type == DeviceType::Loopback)
2517 value = alcDefaultName;
2518 else
2520 std::lock_guard<std::mutex> _{dev->StateLock};
2521 value = dev->DeviceName.c_str();
2524 else
2526 ProbeAllDevicesList();
2527 value = alcAllDevicesList.c_str();
2529 break;
2531 case ALC_CAPTURE_DEVICE_SPECIFIER:
2532 if(DeviceRef dev{VerifyDevice(Device)})
2534 if(dev->Type != DeviceType::Capture)
2535 alcSetError(dev.get(), ALC_INVALID_ENUM);
2536 else
2538 std::lock_guard<std::mutex> _{dev->StateLock};
2539 value = dev->DeviceName.c_str();
2542 else
2544 ProbeCaptureDeviceList();
2545 value = alcCaptureDeviceList.c_str();
2547 break;
2549 /* Default devices are always first in the list */
2550 case ALC_DEFAULT_DEVICE_SPECIFIER:
2551 value = alcDefaultName;
2552 break;
2554 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2555 if(alcAllDevicesList.empty())
2556 ProbeAllDevicesList();
2558 /* Copy first entry as default. */
2559 alcDefaultAllDevicesSpecifier = alcAllDevicesList.c_str();
2560 value = alcDefaultAllDevicesSpecifier.c_str();
2561 break;
2563 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2564 if(alcCaptureDeviceList.empty())
2565 ProbeCaptureDeviceList();
2567 /* Copy first entry as default. */
2568 alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList.c_str();
2569 value = alcCaptureDefaultDeviceSpecifier.c_str();
2570 break;
2572 case ALC_EXTENSIONS:
2573 if(VerifyDevice(Device))
2574 value = alcExtensionList;
2575 else
2576 value = alcNoDeviceExtList;
2577 break;
2579 case ALC_HRTF_SPECIFIER_SOFT:
2580 if(DeviceRef dev{VerifyDevice(Device)})
2582 std::lock_guard<std::mutex> _{dev->StateLock};
2583 value = (dev->mHrtf ? dev->mHrtfName.c_str() : "");
2585 else
2586 alcSetError(nullptr, ALC_INVALID_DEVICE);
2587 break;
2589 default:
2590 alcSetError(VerifyDevice(Device).get(), ALC_INVALID_ENUM);
2591 break;
2594 return value;
2596 END_API_FUNC
2599 static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span<int> values)
2601 size_t i;
2603 if(values.empty())
2605 alcSetError(device, ALC_INVALID_VALUE);
2606 return 0;
2609 if(!device)
2611 switch(param)
2613 case ALC_MAJOR_VERSION:
2614 values[0] = alcMajorVersion;
2615 return 1;
2616 case ALC_MINOR_VERSION:
2617 values[0] = alcMinorVersion;
2618 return 1;
2620 case ALC_EFX_MAJOR_VERSION:
2621 values[0] = alcEFXMajorVersion;
2622 return 1;
2623 case ALC_EFX_MINOR_VERSION:
2624 values[0] = alcEFXMinorVersion;
2625 return 1;
2626 case ALC_MAX_AUXILIARY_SENDS:
2627 values[0] = MAX_SENDS;
2628 return 1;
2630 case ALC_ATTRIBUTES_SIZE:
2631 case ALC_ALL_ATTRIBUTES:
2632 case ALC_FREQUENCY:
2633 case ALC_REFRESH:
2634 case ALC_SYNC:
2635 case ALC_MONO_SOURCES:
2636 case ALC_STEREO_SOURCES:
2637 case ALC_CAPTURE_SAMPLES:
2638 case ALC_FORMAT_CHANNELS_SOFT:
2639 case ALC_FORMAT_TYPE_SOFT:
2640 case ALC_AMBISONIC_LAYOUT_SOFT:
2641 case ALC_AMBISONIC_SCALING_SOFT:
2642 case ALC_AMBISONIC_ORDER_SOFT:
2643 case ALC_MAX_AMBISONIC_ORDER_SOFT:
2644 alcSetError(nullptr, ALC_INVALID_DEVICE);
2645 return 0;
2647 default:
2648 alcSetError(nullptr, ALC_INVALID_ENUM);
2650 return 0;
2653 std::lock_guard<std::mutex> _{device->StateLock};
2654 if(device->Type == DeviceType::Capture)
2656 static constexpr int MaxCaptureAttributes{9};
2657 switch(param)
2659 case ALC_ATTRIBUTES_SIZE:
2660 values[0] = MaxCaptureAttributes;
2661 return 1;
2662 case ALC_ALL_ATTRIBUTES:
2663 i = 0;
2664 if(values.size() < MaxCaptureAttributes)
2665 alcSetError(device, ALC_INVALID_VALUE);
2666 else
2668 values[i++] = ALC_MAJOR_VERSION;
2669 values[i++] = alcMajorVersion;
2670 values[i++] = ALC_MINOR_VERSION;
2671 values[i++] = alcMinorVersion;
2672 values[i++] = ALC_CAPTURE_SAMPLES;
2673 values[i++] = static_cast<int>(device->Backend->availableSamples());
2674 values[i++] = ALC_CONNECTED;
2675 values[i++] = device->Connected.load(std::memory_order_relaxed);
2676 values[i++] = 0;
2677 assert(i == MaxCaptureAttributes);
2679 return i;
2681 case ALC_MAJOR_VERSION:
2682 values[0] = alcMajorVersion;
2683 return 1;
2684 case ALC_MINOR_VERSION:
2685 values[0] = alcMinorVersion;
2686 return 1;
2688 case ALC_CAPTURE_SAMPLES:
2689 values[0] = static_cast<int>(device->Backend->availableSamples());
2690 return 1;
2692 case ALC_CONNECTED:
2693 values[0] = device->Connected.load(std::memory_order_acquire);
2694 return 1;
2696 default:
2697 alcSetError(device, ALC_INVALID_ENUM);
2699 return 0;
2702 /* render device */
2703 auto NumAttrsForDevice = [](ALCdevice *aldev) noexcept
2705 if(aldev->Type == DeviceType::Loopback && aldev->FmtChans == DevFmtAmbi3D)
2706 return 37;
2707 return 31;
2709 switch(param)
2711 case ALC_ATTRIBUTES_SIZE:
2712 values[0] = NumAttrsForDevice(device);
2713 return 1;
2715 case ALC_ALL_ATTRIBUTES:
2716 i = 0;
2717 if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2718 alcSetError(device, ALC_INVALID_VALUE);
2719 else
2721 values[i++] = ALC_MAJOR_VERSION;
2722 values[i++] = alcMajorVersion;
2723 values[i++] = ALC_MINOR_VERSION;
2724 values[i++] = alcMinorVersion;
2725 values[i++] = ALC_EFX_MAJOR_VERSION;
2726 values[i++] = alcEFXMajorVersion;
2727 values[i++] = ALC_EFX_MINOR_VERSION;
2728 values[i++] = alcEFXMinorVersion;
2730 values[i++] = ALC_FREQUENCY;
2731 values[i++] = static_cast<int>(device->Frequency);
2732 if(device->Type != DeviceType::Loopback)
2734 values[i++] = ALC_REFRESH;
2735 values[i++] = static_cast<int>(device->Frequency / device->UpdateSize);
2737 values[i++] = ALC_SYNC;
2738 values[i++] = ALC_FALSE;
2740 else
2742 if(device->FmtChans == DevFmtAmbi3D)
2744 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
2745 values[i++] = EnumFromDevAmbi(device->mAmbiLayout);
2747 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
2748 values[i++] = EnumFromDevAmbi(device->mAmbiScale);
2750 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
2751 values[i++] = static_cast<int>(device->mAmbiOrder);
2754 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2755 values[i++] = EnumFromDevFmt(device->FmtChans);
2757 values[i++] = ALC_FORMAT_TYPE_SOFT;
2758 values[i++] = EnumFromDevFmt(device->FmtType);
2761 values[i++] = ALC_MONO_SOURCES;
2762 values[i++] = static_cast<int>(device->NumMonoSources);
2764 values[i++] = ALC_STEREO_SOURCES;
2765 values[i++] = static_cast<int>(device->NumStereoSources);
2767 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2768 values[i++] = static_cast<int>(device->NumAuxSends);
2770 values[i++] = ALC_HRTF_SOFT;
2771 values[i++] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
2773 values[i++] = ALC_HRTF_STATUS_SOFT;
2774 values[i++] = device->mHrtfStatus;
2776 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
2777 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
2779 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
2780 values[i++] = MaxAmbiOrder;
2782 values[i++] = ALC_OUTPUT_MODE_SOFT;
2783 values[i++] = static_cast<ALCenum>(device->getOutputMode1());
2785 values[i++] = 0;
2787 return i;
2789 case ALC_MAJOR_VERSION:
2790 values[0] = alcMajorVersion;
2791 return 1;
2793 case ALC_MINOR_VERSION:
2794 values[0] = alcMinorVersion;
2795 return 1;
2797 case ALC_EFX_MAJOR_VERSION:
2798 values[0] = alcEFXMajorVersion;
2799 return 1;
2801 case ALC_EFX_MINOR_VERSION:
2802 values[0] = alcEFXMinorVersion;
2803 return 1;
2805 case ALC_FREQUENCY:
2806 values[0] = static_cast<int>(device->Frequency);
2807 return 1;
2809 case ALC_REFRESH:
2810 if(device->Type == DeviceType::Loopback)
2812 alcSetError(device, ALC_INVALID_DEVICE);
2813 return 0;
2815 values[0] = static_cast<int>(device->Frequency / device->UpdateSize);
2816 return 1;
2818 case ALC_SYNC:
2819 if(device->Type == DeviceType::Loopback)
2821 alcSetError(device, ALC_INVALID_DEVICE);
2822 return 0;
2824 values[0] = ALC_FALSE;
2825 return 1;
2827 case ALC_FORMAT_CHANNELS_SOFT:
2828 if(device->Type != DeviceType::Loopback)
2830 alcSetError(device, ALC_INVALID_DEVICE);
2831 return 0;
2833 values[0] = EnumFromDevFmt(device->FmtChans);
2834 return 1;
2836 case ALC_FORMAT_TYPE_SOFT:
2837 if(device->Type != DeviceType::Loopback)
2839 alcSetError(device, ALC_INVALID_DEVICE);
2840 return 0;
2842 values[0] = EnumFromDevFmt(device->FmtType);
2843 return 1;
2845 case ALC_AMBISONIC_LAYOUT_SOFT:
2846 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2848 alcSetError(device, ALC_INVALID_DEVICE);
2849 return 0;
2851 values[0] = EnumFromDevAmbi(device->mAmbiLayout);
2852 return 1;
2854 case ALC_AMBISONIC_SCALING_SOFT:
2855 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2857 alcSetError(device, ALC_INVALID_DEVICE);
2858 return 0;
2860 values[0] = EnumFromDevAmbi(device->mAmbiScale);
2861 return 1;
2863 case ALC_AMBISONIC_ORDER_SOFT:
2864 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2866 alcSetError(device, ALC_INVALID_DEVICE);
2867 return 0;
2869 values[0] = static_cast<int>(device->mAmbiOrder);
2870 return 1;
2872 case ALC_MONO_SOURCES:
2873 values[0] = static_cast<int>(device->NumMonoSources);
2874 return 1;
2876 case ALC_STEREO_SOURCES:
2877 values[0] = static_cast<int>(device->NumStereoSources);
2878 return 1;
2880 case ALC_MAX_AUXILIARY_SENDS:
2881 values[0] = static_cast<int>(device->NumAuxSends);
2882 return 1;
2884 case ALC_CONNECTED:
2885 values[0] = device->Connected.load(std::memory_order_acquire);
2886 return 1;
2888 case ALC_HRTF_SOFT:
2889 values[0] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
2890 return 1;
2892 case ALC_HRTF_STATUS_SOFT:
2893 values[0] = device->mHrtfStatus;
2894 return 1;
2896 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
2897 device->enumerateHrtfs();
2898 values[0] = static_cast<int>(minz(device->mHrtfList.size(),
2899 std::numeric_limits<int>::max()));
2900 return 1;
2902 case ALC_OUTPUT_LIMITER_SOFT:
2903 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
2904 return 1;
2906 case ALC_MAX_AMBISONIC_ORDER_SOFT:
2907 values[0] = MaxAmbiOrder;
2908 return 1;
2910 case ALC_OUTPUT_MODE_SOFT:
2911 values[0] = static_cast<ALCenum>(device->getOutputMode1());
2912 return 1;
2914 default:
2915 alcSetError(device, ALC_INVALID_ENUM);
2917 return 0;
2920 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2921 START_API_FUNC
2923 DeviceRef dev{VerifyDevice(device)};
2924 if(size <= 0 || values == nullptr)
2925 alcSetError(dev.get(), ALC_INVALID_VALUE);
2926 else
2927 GetIntegerv(dev.get(), param, {values, static_cast<uint>(size)});
2929 END_API_FUNC
2931 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
2932 START_API_FUNC
2934 DeviceRef dev{VerifyDevice(device)};
2935 if(size <= 0 || values == nullptr)
2937 alcSetError(dev.get(), ALC_INVALID_VALUE);
2938 return;
2940 if(!dev || dev->Type == DeviceType::Capture)
2942 auto ivals = al::vector<int>(static_cast<uint>(size));
2943 if(size_t got{GetIntegerv(dev.get(), pname, ivals)})
2944 std::copy_n(ivals.begin(), got, values);
2945 return;
2947 /* render device */
2948 auto NumAttrsForDevice = [](ALCdevice *aldev) noexcept
2950 if(aldev->Type == DeviceType::Loopback && aldev->FmtChans == DevFmtAmbi3D)
2951 return 41;
2952 return 35;
2954 std::lock_guard<std::mutex> _{dev->StateLock};
2955 switch(pname)
2957 case ALC_ATTRIBUTES_SIZE:
2958 *values = NumAttrsForDevice(dev.get());
2959 break;
2961 case ALC_ALL_ATTRIBUTES:
2962 if(size < NumAttrsForDevice(dev.get()))
2963 alcSetError(dev.get(), ALC_INVALID_VALUE);
2964 else
2966 size_t i{0};
2967 values[i++] = ALC_FREQUENCY;
2968 values[i++] = dev->Frequency;
2970 if(dev->Type != DeviceType::Loopback)
2972 values[i++] = ALC_REFRESH;
2973 values[i++] = dev->Frequency / dev->UpdateSize;
2975 values[i++] = ALC_SYNC;
2976 values[i++] = ALC_FALSE;
2978 else
2980 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2981 values[i++] = EnumFromDevFmt(dev->FmtChans);
2983 values[i++] = ALC_FORMAT_TYPE_SOFT;
2984 values[i++] = EnumFromDevFmt(dev->FmtType);
2986 if(dev->FmtChans == DevFmtAmbi3D)
2988 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
2989 values[i++] = EnumFromDevAmbi(dev->mAmbiLayout);
2991 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
2992 values[i++] = EnumFromDevAmbi(dev->mAmbiScale);
2994 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
2995 values[i++] = dev->mAmbiOrder;
2999 values[i++] = ALC_MONO_SOURCES;
3000 values[i++] = dev->NumMonoSources;
3002 values[i++] = ALC_STEREO_SOURCES;
3003 values[i++] = dev->NumStereoSources;
3005 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3006 values[i++] = dev->NumAuxSends;
3008 values[i++] = ALC_HRTF_SOFT;
3009 values[i++] = (dev->mHrtf ? ALC_TRUE : ALC_FALSE);
3011 values[i++] = ALC_HRTF_STATUS_SOFT;
3012 values[i++] = dev->mHrtfStatus;
3014 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3015 values[i++] = dev->Limiter ? ALC_TRUE : ALC_FALSE;
3017 ClockLatency clock{GetClockLatency(dev.get(), dev->Backend.get())};
3018 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3019 values[i++] = clock.ClockTime.count();
3021 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3022 values[i++] = clock.Latency.count();
3024 values[i++] = ALC_OUTPUT_MODE_SOFT;
3025 values[i++] = static_cast<ALCenum>(device->getOutputMode1());
3027 values[i++] = 0;
3029 break;
3031 case ALC_DEVICE_CLOCK_SOFT:
3033 uint samplecount, refcount;
3034 nanoseconds basecount;
3035 do {
3036 refcount = dev->waitForMix();
3037 basecount = dev->ClockBase;
3038 samplecount = dev->SamplesDone;
3039 } while(refcount != ReadRef(dev->MixCount));
3040 basecount += nanoseconds{seconds{samplecount}} / dev->Frequency;
3041 *values = basecount.count();
3043 break;
3045 case ALC_DEVICE_LATENCY_SOFT:
3046 *values = GetClockLatency(dev.get(), dev->Backend.get()).Latency.count();
3047 break;
3049 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3050 if(size < 2)
3051 alcSetError(dev.get(), ALC_INVALID_VALUE);
3052 else
3054 ClockLatency clock{GetClockLatency(dev.get(), dev->Backend.get())};
3055 values[0] = clock.ClockTime.count();
3056 values[1] = clock.Latency.count();
3058 break;
3060 default:
3061 auto ivals = al::vector<int>(static_cast<uint>(size));
3062 if(size_t got{GetIntegerv(dev.get(), pname, ivals)})
3063 std::copy_n(ivals.begin(), got, values);
3064 break;
3067 END_API_FUNC
3070 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3071 START_API_FUNC
3073 DeviceRef dev{VerifyDevice(device)};
3074 if(!extName)
3075 alcSetError(dev.get(), ALC_INVALID_VALUE);
3076 else
3078 size_t len = strlen(extName);
3079 const char *ptr = (dev ? alcExtensionList : alcNoDeviceExtList);
3080 while(ptr && *ptr)
3082 if(al::strncasecmp(ptr, extName, len) == 0 && (ptr[len] == '\0' || isspace(ptr[len])))
3083 return ALC_TRUE;
3085 if((ptr=strchr(ptr, ' ')) != nullptr)
3087 do {
3088 ++ptr;
3089 } while(isspace(*ptr));
3093 return ALC_FALSE;
3095 END_API_FUNC
3098 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3099 START_API_FUNC
3101 if(!funcName)
3103 DeviceRef dev{VerifyDevice(device)};
3104 alcSetError(dev.get(), ALC_INVALID_VALUE);
3105 return nullptr;
3107 #ifdef ALSOFT_EAX
3108 if(eax_g_is_enabled)
3110 for(const auto &func : eaxFunctions)
3112 if(strcmp(func.funcName, funcName) == 0)
3113 return func.address;
3116 #endif
3117 for(const auto &func : alcFunctions)
3119 if(strcmp(func.funcName, funcName) == 0)
3120 return func.address;
3122 return nullptr;
3124 END_API_FUNC
3127 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3128 START_API_FUNC
3130 if(!enumName)
3132 DeviceRef dev{VerifyDevice(device)};
3133 alcSetError(dev.get(), ALC_INVALID_VALUE);
3134 return 0;
3136 #ifdef ALSOFT_EAX
3137 if(eax_g_is_enabled)
3139 for(const auto &enm : eaxEnumerations)
3141 if(strcmp(enm.enumName, enumName) == 0)
3142 return enm.value;
3145 #endif
3146 for(const auto &enm : alcEnumerations)
3148 if(strcmp(enm.enumName, enumName) == 0)
3149 return enm.value;
3152 return 0;
3154 END_API_FUNC
3157 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3158 START_API_FUNC
3160 /* Explicitly hold the list lock while taking the StateLock in case the
3161 * device is asynchronously destroyed, to ensure this new context is
3162 * properly cleaned up after being made.
3164 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3165 DeviceRef dev{VerifyDevice(device)};
3166 if(!dev || dev->Type == DeviceType::Capture || !dev->Connected.load(std::memory_order_relaxed))
3168 listlock.unlock();
3169 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3170 return nullptr;
3172 std::unique_lock<std::mutex> statelock{dev->StateLock};
3173 listlock.unlock();
3175 dev->LastError.store(ALC_NO_ERROR);
3177 ALCenum err{UpdateDeviceParams(dev.get(), attrList)};
3178 if(err != ALC_NO_ERROR)
3180 alcSetError(dev.get(), err);
3181 return nullptr;
3184 ContextRef context{new ALCcontext{dev}};
3185 context->init();
3187 if(auto volopt = dev->configValue<float>(nullptr, "volume-adjust"))
3189 const float valf{*volopt};
3190 if(!std::isfinite(valf))
3191 ERR("volume-adjust must be finite: %f\n", valf);
3192 else
3194 const float db{clampf(valf, -24.0f, 24.0f)};
3195 if(db != valf)
3196 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3197 context->mGainBoost = std::pow(10.0f, db/20.0f);
3198 TRACE("volume-adjust gain: %f\n", context->mGainBoost);
3203 using ContextArray = al::FlexArray<ContextBase*>;
3205 /* Allocate a new context array, which holds 1 more than the current/
3206 * old array.
3208 auto *oldarray = device->mContexts.load();
3209 const size_t newcount{oldarray->size()+1};
3210 std::unique_ptr<ContextArray> newarray{ContextArray::Create(newcount)};
3212 /* Copy the current/old context handles to the new array, appending the
3213 * new context.
3215 auto iter = std::copy(oldarray->begin(), oldarray->end(), newarray->begin());
3216 *iter = context.get();
3218 /* Store the new context array in the device. Wait for any current mix
3219 * to finish before deleting the old array.
3221 dev->mContexts.store(newarray.release());
3222 if(oldarray != &DeviceBase::sEmptyContextArray)
3224 dev->waitForMix();
3225 delete oldarray;
3228 statelock.unlock();
3231 std::lock_guard<std::recursive_mutex> _{ListLock};
3232 auto iter = std::lower_bound(ContextList.cbegin(), ContextList.cend(), context.get());
3233 ContextList.emplace(iter, context.get());
3236 if(ALeffectslot *slot{context->mDefaultSlot.get()})
3238 ALenum sloterr{slot->initEffect(ALCcontext::sDefaultEffect.type,
3239 ALCcontext::sDefaultEffect.Props, context.get())};
3240 if(sloterr == AL_NO_ERROR)
3241 slot->updateProps(context.get());
3242 else
3243 ERR("Failed to initialize the default effect\n");
3246 TRACE("Created context %p\n", voidp{context.get()});
3247 return context.release();
3249 END_API_FUNC
3251 ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3252 START_API_FUNC
3254 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3255 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
3256 if(iter == ContextList.end() || *iter != context)
3258 listlock.unlock();
3259 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3260 return;
3263 /* Hold a reference to this context so it remains valid until the ListLock
3264 * is released.
3266 ContextRef ctx{*iter};
3267 ContextList.erase(iter);
3269 ALCdevice *Device{ctx->mALDevice.get()};
3271 std::lock_guard<std::mutex> _{Device->StateLock};
3272 if(!ctx->deinit() && Device->Flags.test(DeviceRunning))
3274 Device->Backend->stop();
3275 Device->Flags.reset(DeviceRunning);
3278 END_API_FUNC
3281 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3282 START_API_FUNC
3284 ALCcontext *Context{ALCcontext::getThreadContext()};
3285 if(!Context) Context = ALCcontext::sGlobalContext.load();
3286 return Context;
3288 END_API_FUNC
3290 /** Returns the currently active thread-local context. */
3291 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3292 START_API_FUNC
3293 { return ALCcontext::getThreadContext(); }
3294 END_API_FUNC
3296 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3297 START_API_FUNC
3299 /* context must be valid or nullptr */
3300 ContextRef ctx;
3301 if(context)
3303 ctx = VerifyContext(context);
3304 if(!ctx)
3306 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3307 return ALC_FALSE;
3310 /* Release this reference (if any) to store it in the GlobalContext
3311 * pointer. Take ownership of the reference (if any) that was previously
3312 * stored there.
3314 ctx = ContextRef{ALCcontext::sGlobalContext.exchange(ctx.release())};
3316 /* Reset (decrement) the previous global reference by replacing it with the
3317 * thread-local context. Take ownership of the thread-local context
3318 * reference (if any), clearing the storage to null.
3320 ctx = ContextRef{ALCcontext::getThreadContext()};
3321 if(ctx) ALCcontext::setThreadContext(nullptr);
3322 /* Reset (decrement) the previous thread-local reference. */
3324 return ALC_TRUE;
3326 END_API_FUNC
3328 /** Makes the given context the active context for the current thread. */
3329 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3330 START_API_FUNC
3332 /* context must be valid or nullptr */
3333 ContextRef ctx;
3334 if(context)
3336 ctx = VerifyContext(context);
3337 if(!ctx)
3339 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3340 return ALC_FALSE;
3343 /* context's reference count is already incremented */
3344 ContextRef old{ALCcontext::getThreadContext()};
3345 ALCcontext::setThreadContext(ctx.release());
3347 return ALC_TRUE;
3349 END_API_FUNC
3352 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3353 START_API_FUNC
3355 ContextRef ctx{VerifyContext(Context)};
3356 if(!ctx)
3358 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3359 return nullptr;
3361 return ctx->mALDevice.get();
3363 END_API_FUNC
3366 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3367 START_API_FUNC
3369 DO_INITCONFIG();
3371 if(!PlaybackFactory)
3373 alcSetError(nullptr, ALC_INVALID_VALUE);
3374 return nullptr;
3377 if(deviceName)
3379 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3380 #ifdef _WIN32
3381 /* Some old Windows apps hardcode these expecting OpenAL to use a
3382 * specific audio API, even when they're not enumerated. Creative's
3383 * router effectively ignores them too.
3385 || al::strcasecmp(deviceName, "DirectSound3D") == 0
3386 || al::strcasecmp(deviceName, "DirectSound") == 0
3387 || al::strcasecmp(deviceName, "MMSYSTEM") == 0
3388 #endif
3389 /* Some old Linux apps hardcode configuration strings that were
3390 * supported by the OpenAL SI. We can't really do anything useful
3391 * with them, so just ignore.
3393 || (deviceName[0] == '\'' && deviceName[1] == '(')
3394 || al::strcasecmp(deviceName, "openal-soft") == 0)
3395 deviceName = nullptr;
3398 DeviceRef device{new ALCdevice{DeviceType::Playback}};
3400 /* Set output format */
3401 device->FmtChans = DevFmtChannelsDefault;
3402 device->FmtType = DevFmtTypeDefault;
3403 device->Frequency = DEFAULT_OUTPUT_RATE;
3404 device->UpdateSize = DEFAULT_UPDATE_SIZE;
3405 device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
3407 device->SourcesMax = 256;
3408 device->AuxiliaryEffectSlotMax = 64;
3409 device->NumAuxSends = DEFAULT_SENDS;
3410 #ifdef ALSOFT_EAX
3411 if(eax_g_is_enabled)
3412 device->NumAuxSends = EAX_MAX_FXSLOTS;
3413 #endif // ALSOFT_EAX
3415 try {
3416 auto backend = PlaybackFactory->createBackend(device.get(), BackendType::Playback);
3417 std::lock_guard<std::recursive_mutex> _{ListLock};
3418 backend->open(deviceName);
3419 device->Backend = std::move(backend);
3421 catch(al::backend_exception &e) {
3422 WARN("Failed to open playback device: %s\n", e.what());
3423 alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory)
3424 ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
3425 return nullptr;
3428 if(uint freq{device->configValue<uint>(nullptr, "frequency").value_or(0u)})
3430 if(freq < MIN_OUTPUT_RATE || freq > MAX_OUTPUT_RATE)
3432 const uint newfreq{clampu(freq, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE)};
3433 ERR("%uhz request clamped to %uhz\n", freq, newfreq);
3434 freq = newfreq;
3436 const double scale{static_cast<double>(freq) / device->Frequency};
3437 device->UpdateSize = static_cast<uint>(device->UpdateSize*scale + 0.5);
3438 device->BufferSize = static_cast<uint>(device->BufferSize*scale + 0.5);
3439 device->Frequency = freq;
3440 device->Flags.set(FrequencyRequest);
3443 if(auto srcsmax = device->configValue<uint>(nullptr, "sources").value_or(0))
3444 device->SourcesMax = srcsmax;
3446 if(auto slotsmax = device->configValue<uint>(nullptr, "slots").value_or(0))
3447 device->AuxiliaryEffectSlotMax = minu(slotsmax, INT_MAX);
3449 if(auto sendsopt = device->configValue<int>(nullptr, "sends"))
3450 device->NumAuxSends = minu(DEFAULT_SENDS,
3451 static_cast<uint>(clampi(*sendsopt, 0, MAX_SENDS)));
3453 device->NumStereoSources = 1;
3454 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3457 std::lock_guard<std::recursive_mutex> _{ListLock};
3458 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3459 DeviceList.emplace(iter, device.get());
3462 TRACE("Created device %p, \"%s\"\n", voidp{device.get()}, device->DeviceName.c_str());
3463 return device.release();
3465 END_API_FUNC
3467 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3468 START_API_FUNC
3470 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3471 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3472 if(iter == DeviceList.end() || *iter != device)
3474 alcSetError(nullptr, ALC_INVALID_DEVICE);
3475 return ALC_FALSE;
3477 if((*iter)->Type == DeviceType::Capture)
3479 alcSetError(*iter, ALC_INVALID_DEVICE);
3480 return ALC_FALSE;
3483 /* Erase the device, and any remaining contexts left on it, from their
3484 * respective lists.
3486 DeviceRef dev{*iter};
3487 DeviceList.erase(iter);
3489 std::unique_lock<std::mutex> statelock{dev->StateLock};
3490 al::vector<ContextRef> orphanctxs;
3491 for(ContextBase *ctx : *dev->mContexts.load())
3493 auto ctxiter = std::lower_bound(ContextList.begin(), ContextList.end(), ctx);
3494 if(ctxiter != ContextList.end() && *ctxiter == ctx)
3496 orphanctxs.emplace_back(ContextRef{*ctxiter});
3497 ContextList.erase(ctxiter);
3500 listlock.unlock();
3502 for(ContextRef &context : orphanctxs)
3504 WARN("Releasing orphaned context %p\n", voidp{context.get()});
3505 context->deinit();
3507 orphanctxs.clear();
3509 if(dev->Flags.test(DeviceRunning))
3510 dev->Backend->stop();
3511 dev->Flags.reset(DeviceRunning);
3513 return ALC_TRUE;
3515 END_API_FUNC
3518 /************************************************
3519 * ALC capture functions
3520 ************************************************/
3521 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3522 START_API_FUNC
3524 DO_INITCONFIG();
3526 if(!CaptureFactory)
3528 alcSetError(nullptr, ALC_INVALID_VALUE);
3529 return nullptr;
3532 if(samples <= 0)
3534 alcSetError(nullptr, ALC_INVALID_VALUE);
3535 return nullptr;
3538 if(deviceName)
3540 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3541 || al::strcasecmp(deviceName, "openal-soft") == 0)
3542 deviceName = nullptr;
3545 DeviceRef device{new ALCdevice{DeviceType::Capture}};
3547 auto decompfmt = DecomposeDevFormat(format);
3548 if(!decompfmt)
3550 alcSetError(nullptr, ALC_INVALID_ENUM);
3551 return nullptr;
3554 device->Frequency = frequency;
3555 device->FmtChans = decompfmt->chans;
3556 device->FmtType = decompfmt->type;
3557 device->Flags.set(FrequencyRequest);
3558 device->Flags.set(ChannelsRequest);
3559 device->Flags.set(SampleTypeRequest);
3561 device->UpdateSize = static_cast<uint>(samples);
3562 device->BufferSize = static_cast<uint>(samples);
3564 try {
3565 TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n",
3566 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
3567 device->Frequency, device->UpdateSize, device->BufferSize);
3569 auto backend = CaptureFactory->createBackend(device.get(), BackendType::Capture);
3570 std::lock_guard<std::recursive_mutex> _{ListLock};
3571 backend->open(deviceName);
3572 device->Backend = std::move(backend);
3574 catch(al::backend_exception &e) {
3575 WARN("Failed to open capture device: %s\n", e.what());
3576 alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory)
3577 ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
3578 return nullptr;
3582 std::lock_guard<std::recursive_mutex> _{ListLock};
3583 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3584 DeviceList.emplace(iter, device.get());
3587 TRACE("Created capture device %p, \"%s\"\n", voidp{device.get()}, device->DeviceName.c_str());
3588 return device.release();
3590 END_API_FUNC
3592 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3593 START_API_FUNC
3595 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3596 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3597 if(iter == DeviceList.end() || *iter != device)
3599 alcSetError(nullptr, ALC_INVALID_DEVICE);
3600 return ALC_FALSE;
3602 if((*iter)->Type != DeviceType::Capture)
3604 alcSetError(*iter, ALC_INVALID_DEVICE);
3605 return ALC_FALSE;
3608 DeviceRef dev{*iter};
3609 DeviceList.erase(iter);
3610 listlock.unlock();
3612 std::lock_guard<std::mutex> _{dev->StateLock};
3613 if(dev->Flags.test(DeviceRunning))
3614 dev->Backend->stop();
3615 dev->Flags.reset(DeviceRunning);
3617 return ALC_TRUE;
3619 END_API_FUNC
3621 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3622 START_API_FUNC
3624 DeviceRef dev{VerifyDevice(device)};
3625 if(!dev || dev->Type != DeviceType::Capture)
3627 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3628 return;
3631 std::lock_guard<std::mutex> _{dev->StateLock};
3632 if(!dev->Connected.load(std::memory_order_acquire))
3633 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3634 else if(!dev->Flags.test(DeviceRunning))
3636 try {
3637 auto backend = dev->Backend.get();
3638 backend->start();
3639 dev->Flags.set(DeviceRunning);
3641 catch(al::backend_exception& e) {
3642 ERR("%s\n", e.what());
3643 dev->handleDisconnect("%s", e.what());
3644 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3648 END_API_FUNC
3650 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3651 START_API_FUNC
3653 DeviceRef dev{VerifyDevice(device)};
3654 if(!dev || dev->Type != DeviceType::Capture)
3655 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3656 else
3658 std::lock_guard<std::mutex> _{dev->StateLock};
3659 if(dev->Flags.test(DeviceRunning))
3660 dev->Backend->stop();
3661 dev->Flags.reset(DeviceRunning);
3664 END_API_FUNC
3666 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3667 START_API_FUNC
3669 DeviceRef dev{VerifyDevice(device)};
3670 if(!dev || dev->Type != DeviceType::Capture)
3672 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3673 return;
3676 if(samples < 0 || (samples > 0 && buffer == nullptr))
3678 alcSetError(dev.get(), ALC_INVALID_VALUE);
3679 return;
3681 if(samples < 1)
3682 return;
3684 std::lock_guard<std::mutex> _{dev->StateLock};
3685 BackendBase *backend{dev->Backend.get()};
3687 const auto usamples = static_cast<uint>(samples);
3688 if(usamples > backend->availableSamples())
3690 alcSetError(dev.get(), ALC_INVALID_VALUE);
3691 return;
3694 backend->captureSamples(static_cast<al::byte*>(buffer), usamples);
3696 END_API_FUNC
3699 /************************************************
3700 * ALC loopback functions
3701 ************************************************/
3703 /** Open a loopback device, for manual rendering. */
3704 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3705 START_API_FUNC
3707 DO_INITCONFIG();
3709 /* Make sure the device name, if specified, is us. */
3710 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3712 alcSetError(nullptr, ALC_INVALID_VALUE);
3713 return nullptr;
3716 DeviceRef device{new ALCdevice{DeviceType::Loopback}};
3718 device->SourcesMax = 256;
3719 device->AuxiliaryEffectSlotMax = 64;
3720 device->NumAuxSends = DEFAULT_SENDS;
3722 //Set output format
3723 device->BufferSize = 0;
3724 device->UpdateSize = 0;
3726 device->Frequency = DEFAULT_OUTPUT_RATE;
3727 device->FmtChans = DevFmtChannelsDefault;
3728 device->FmtType = DevFmtTypeDefault;
3730 if(auto srcsmax = ConfigValueUInt(nullptr, nullptr, "sources").value_or(0))
3731 device->SourcesMax = srcsmax;
3733 if(auto slotsmax = ConfigValueUInt(nullptr, nullptr, "slots").value_or(0))
3734 device->AuxiliaryEffectSlotMax = minu(slotsmax, INT_MAX);
3736 if(auto sendsopt = ConfigValueInt(nullptr, nullptr, "sends"))
3737 device->NumAuxSends = minu(DEFAULT_SENDS,
3738 static_cast<uint>(clampi(*sendsopt, 0, MAX_SENDS)));
3740 device->NumStereoSources = 1;
3741 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3743 try {
3744 auto backend = LoopbackBackendFactory::getFactory().createBackend(device.get(),
3745 BackendType::Playback);
3746 backend->open("Loopback");
3747 device->Backend = std::move(backend);
3749 catch(al::backend_exception &e) {
3750 WARN("Failed to open loopback device: %s\n", e.what());
3751 alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory)
3752 ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
3753 return nullptr;
3757 std::lock_guard<std::recursive_mutex> _{ListLock};
3758 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3759 DeviceList.emplace(iter, device.get());
3762 TRACE("Created loopback device %p\n", voidp{device.get()});
3763 return device.release();
3765 END_API_FUNC
3768 * Determines if the loopback device supports the given format for rendering.
3770 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3771 START_API_FUNC
3773 DeviceRef dev{VerifyDevice(device)};
3774 if(!dev || dev->Type != DeviceType::Loopback)
3775 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3776 else if(freq <= 0)
3777 alcSetError(dev.get(), ALC_INVALID_VALUE);
3778 else
3780 if(DevFmtTypeFromEnum(type).has_value() && DevFmtChannelsFromEnum(channels).has_value()
3781 && freq >= MIN_OUTPUT_RATE && freq <= MAX_OUTPUT_RATE)
3782 return ALC_TRUE;
3785 return ALC_FALSE;
3787 END_API_FUNC
3790 * Renders some samples into a buffer, using the format last set by the
3791 * attributes given to alcCreateContext.
3793 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3794 START_API_FUNC
3796 if(!device || device->Type != DeviceType::Loopback)
3797 alcSetError(device, ALC_INVALID_DEVICE);
3798 else if(samples < 0 || (samples > 0 && buffer == nullptr))
3799 alcSetError(device, ALC_INVALID_VALUE);
3800 else
3801 device->renderSamples(buffer, static_cast<uint>(samples), device->channelsFromFmt());
3803 END_API_FUNC
3806 /************************************************
3807 * ALC DSP pause/resume functions
3808 ************************************************/
3810 /** Pause the DSP to stop audio processing. */
3811 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
3812 START_API_FUNC
3814 DeviceRef dev{VerifyDevice(device)};
3815 if(!dev || dev->Type != DeviceType::Playback)
3816 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3817 else
3819 std::lock_guard<std::mutex> _{dev->StateLock};
3820 if(dev->Flags.test(DeviceRunning))
3821 dev->Backend->stop();
3822 dev->Flags.reset(DeviceRunning);
3823 dev->Flags.set(DevicePaused);
3826 END_API_FUNC
3828 /** Resume the DSP to restart audio processing. */
3829 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
3830 START_API_FUNC
3832 DeviceRef dev{VerifyDevice(device)};
3833 if(!dev || dev->Type != DeviceType::Playback)
3835 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3836 return;
3839 std::lock_guard<std::mutex> _{dev->StateLock};
3840 if(!dev->Flags.test(DevicePaused))
3841 return;
3842 dev->Flags.reset(DevicePaused);
3843 if(dev->mContexts.load()->empty())
3844 return;
3846 try {
3847 auto backend = dev->Backend.get();
3848 backend->start();
3849 dev->Flags.set(DeviceRunning);
3851 catch(al::backend_exception& e) {
3852 ERR("%s\n", e.what());
3853 dev->handleDisconnect("%s", e.what());
3854 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3855 return;
3857 TRACE("Post-resume: %s, %s, %uhz, %u / %u buffer\n",
3858 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
3859 device->Frequency, device->UpdateSize, device->BufferSize);
3861 END_API_FUNC
3864 /************************************************
3865 * ALC HRTF functions
3866 ************************************************/
3868 /** Gets a string parameter at the given index. */
3869 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
3870 START_API_FUNC
3872 DeviceRef dev{VerifyDevice(device)};
3873 if(!dev || dev->Type == DeviceType::Capture)
3874 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3875 else switch(paramName)
3877 case ALC_HRTF_SPECIFIER_SOFT:
3878 if(index >= 0 && static_cast<uint>(index) < dev->mHrtfList.size())
3879 return dev->mHrtfList[static_cast<uint>(index)].c_str();
3880 alcSetError(dev.get(), ALC_INVALID_VALUE);
3881 break;
3883 default:
3884 alcSetError(dev.get(), ALC_INVALID_ENUM);
3885 break;
3888 return nullptr;
3890 END_API_FUNC
3892 /** Resets the given device output, using the specified attribute list. */
3893 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
3894 START_API_FUNC
3896 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3897 DeviceRef dev{VerifyDevice(device)};
3898 if(!dev || dev->Type == DeviceType::Capture)
3900 listlock.unlock();
3901 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3902 return ALC_FALSE;
3904 std::lock_guard<std::mutex> _{dev->StateLock};
3905 listlock.unlock();
3907 /* Force the backend to stop mixing first since we're resetting. Also reset
3908 * the connected state so lost devices can attempt recover.
3910 if(dev->Flags.test(DeviceRunning))
3911 dev->Backend->stop();
3912 dev->Flags.reset(DeviceRunning);
3914 return ResetDeviceParams(dev.get(), attribs) ? ALC_TRUE : ALC_FALSE;
3916 END_API_FUNC
3919 /************************************************
3920 * ALC device reopen functions
3921 ************************************************/
3923 /** Reopens the given device output, using the specified name and attribute list. */
3924 FORCE_ALIGN ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device,
3925 const ALCchar *deviceName, const ALCint *attribs)
3926 START_API_FUNC
3928 if(deviceName)
3930 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0)
3931 deviceName = nullptr;
3934 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3935 DeviceRef dev{VerifyDevice(device)};
3936 if(!dev || dev->Type != DeviceType::Playback)
3938 listlock.unlock();
3939 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3940 return ALC_FALSE;
3942 std::lock_guard<std::mutex> _{dev->StateLock};
3944 /* Force the backend to stop mixing first since we're reopening. */
3945 if(dev->Flags.test(DeviceRunning))
3947 auto backend = dev->Backend.get();
3948 backend->stop();
3949 dev->Flags.reset(DeviceRunning);
3952 BackendPtr newbackend;
3953 try {
3954 newbackend = PlaybackFactory->createBackend(dev.get(), BackendType::Playback);
3955 newbackend->open(deviceName);
3957 catch(al::backend_exception &e) {
3958 listlock.unlock();
3959 newbackend = nullptr;
3961 WARN("Failed to reopen playback device: %s\n", e.what());
3962 alcSetError(dev.get(), (e.errorCode() == al::backend_error::OutOfMemory)
3963 ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
3965 /* If the device is connected, not paused, and has contexts, ensure it
3966 * continues playing.
3968 if(dev->Connected.load(std::memory_order_relaxed) && !dev->Flags.test(DevicePaused)
3969 && !dev->mContexts.load(std::memory_order_relaxed)->empty())
3971 try {
3972 auto backend = dev->Backend.get();
3973 backend->start();
3974 dev->Flags.set(DeviceRunning);
3976 catch(al::backend_exception &be) {
3977 ERR("%s\n", be.what());
3978 dev->handleDisconnect("%s", be.what());
3981 return ALC_FALSE;
3983 listlock.unlock();
3984 dev->Backend = std::move(newbackend);
3985 TRACE("Reopened device %p, \"%s\"\n", voidp{dev.get()}, dev->DeviceName.c_str());
3987 /* Always return true even if resetting fails. It shouldn't fail, but this
3988 * is primarily to avoid confusion by the app seeing the function return
3989 * false while the device is on the new output anyway. We could try to
3990 * restore the old backend if this fails, but the configuration would be
3991 * changed with the new backend and would need to be reset again with the
3992 * old one, and the provided attributes may not be appropriate or desirable
3993 * for the old device.
3995 * In this way, we essentially act as if the function succeeded, but
3996 * immediately disconnects following it.
3998 ResetDeviceParams(dev.get(), attribs);
3999 return ALC_TRUE;
4001 END_API_FUNC