Use explicit arrays for the remix table target mixes
[openal-soft.git] / alc / alc.cpp
blob9915a85358e8a865cd3d916d5b461c75baa0bcf5
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_ALSA
227 { "alsa", AlsaBackendFactory::getFactory },
228 #endif
229 #ifdef HAVE_SOLARIS
230 { "solaris", SolarisBackendFactory::getFactory },
231 #endif
232 #ifdef HAVE_SNDIO
233 { "sndio", SndIOBackendFactory::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),
456 DECL(alSourcePlayAtTimeSOFT),
457 DECL(alSourcePlayAtTimevSOFT),
458 #ifdef ALSOFT_EAX
459 }, eaxFunctions[] = {
460 DECL(EAXGet),
461 DECL(EAXSet),
462 DECL(EAXGetBufferMode),
463 DECL(EAXSetBufferMode),
464 #endif
466 #undef DECL
468 #define DECL(x) { #x, (x) }
469 constexpr struct {
470 const ALCchar *enumName;
471 ALCenum value;
472 } alcEnumerations[] = {
473 DECL(ALC_INVALID),
474 DECL(ALC_FALSE),
475 DECL(ALC_TRUE),
477 DECL(ALC_MAJOR_VERSION),
478 DECL(ALC_MINOR_VERSION),
479 DECL(ALC_ATTRIBUTES_SIZE),
480 DECL(ALC_ALL_ATTRIBUTES),
481 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
482 DECL(ALC_DEVICE_SPECIFIER),
483 DECL(ALC_ALL_DEVICES_SPECIFIER),
484 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
485 DECL(ALC_EXTENSIONS),
486 DECL(ALC_FREQUENCY),
487 DECL(ALC_REFRESH),
488 DECL(ALC_SYNC),
489 DECL(ALC_MONO_SOURCES),
490 DECL(ALC_STEREO_SOURCES),
491 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
492 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
493 DECL(ALC_CAPTURE_SAMPLES),
494 DECL(ALC_CONNECTED),
496 DECL(ALC_EFX_MAJOR_VERSION),
497 DECL(ALC_EFX_MINOR_VERSION),
498 DECL(ALC_MAX_AUXILIARY_SENDS),
500 DECL(ALC_FORMAT_CHANNELS_SOFT),
501 DECL(ALC_FORMAT_TYPE_SOFT),
503 DECL(ALC_MONO_SOFT),
504 DECL(ALC_STEREO_SOFT),
505 DECL(ALC_QUAD_SOFT),
506 DECL(ALC_5POINT1_SOFT),
507 DECL(ALC_6POINT1_SOFT),
508 DECL(ALC_7POINT1_SOFT),
509 DECL(ALC_BFORMAT3D_SOFT),
511 DECL(ALC_BYTE_SOFT),
512 DECL(ALC_UNSIGNED_BYTE_SOFT),
513 DECL(ALC_SHORT_SOFT),
514 DECL(ALC_UNSIGNED_SHORT_SOFT),
515 DECL(ALC_INT_SOFT),
516 DECL(ALC_UNSIGNED_INT_SOFT),
517 DECL(ALC_FLOAT_SOFT),
519 DECL(ALC_HRTF_SOFT),
520 DECL(ALC_DONT_CARE_SOFT),
521 DECL(ALC_HRTF_STATUS_SOFT),
522 DECL(ALC_HRTF_DISABLED_SOFT),
523 DECL(ALC_HRTF_ENABLED_SOFT),
524 DECL(ALC_HRTF_DENIED_SOFT),
525 DECL(ALC_HRTF_REQUIRED_SOFT),
526 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
527 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
528 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
529 DECL(ALC_HRTF_SPECIFIER_SOFT),
530 DECL(ALC_HRTF_ID_SOFT),
532 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
533 DECL(ALC_AMBISONIC_SCALING_SOFT),
534 DECL(ALC_AMBISONIC_ORDER_SOFT),
535 DECL(ALC_ACN_SOFT),
536 DECL(ALC_FUMA_SOFT),
537 DECL(ALC_N3D_SOFT),
538 DECL(ALC_SN3D_SOFT),
540 DECL(ALC_OUTPUT_LIMITER_SOFT),
542 DECL(ALC_DEVICE_CLOCK_SOFT),
543 DECL(ALC_DEVICE_LATENCY_SOFT),
544 DECL(ALC_DEVICE_CLOCK_LATENCY_SOFT),
545 DECL(AL_SAMPLE_OFFSET_CLOCK_SOFT),
546 DECL(AL_SEC_OFFSET_CLOCK_SOFT),
548 DECL(ALC_OUTPUT_MODE_SOFT),
549 DECL(ALC_ANY_SOFT),
550 DECL(ALC_STEREO_BASIC_SOFT),
551 DECL(ALC_STEREO_UHJ_SOFT),
552 DECL(ALC_STEREO_HRTF_SOFT),
553 DECL(ALC_SURROUND_5_1_SOFT),
554 DECL(ALC_SURROUND_6_1_SOFT),
555 DECL(ALC_SURROUND_7_1_SOFT),
557 DECL(ALC_NO_ERROR),
558 DECL(ALC_INVALID_DEVICE),
559 DECL(ALC_INVALID_CONTEXT),
560 DECL(ALC_INVALID_ENUM),
561 DECL(ALC_INVALID_VALUE),
562 DECL(ALC_OUT_OF_MEMORY),
565 DECL(AL_INVALID),
566 DECL(AL_NONE),
567 DECL(AL_FALSE),
568 DECL(AL_TRUE),
570 DECL(AL_SOURCE_RELATIVE),
571 DECL(AL_CONE_INNER_ANGLE),
572 DECL(AL_CONE_OUTER_ANGLE),
573 DECL(AL_PITCH),
574 DECL(AL_POSITION),
575 DECL(AL_DIRECTION),
576 DECL(AL_VELOCITY),
577 DECL(AL_LOOPING),
578 DECL(AL_BUFFER),
579 DECL(AL_GAIN),
580 DECL(AL_MIN_GAIN),
581 DECL(AL_MAX_GAIN),
582 DECL(AL_ORIENTATION),
583 DECL(AL_REFERENCE_DISTANCE),
584 DECL(AL_ROLLOFF_FACTOR),
585 DECL(AL_CONE_OUTER_GAIN),
586 DECL(AL_MAX_DISTANCE),
587 DECL(AL_SEC_OFFSET),
588 DECL(AL_SAMPLE_OFFSET),
589 DECL(AL_BYTE_OFFSET),
590 DECL(AL_SOURCE_TYPE),
591 DECL(AL_STATIC),
592 DECL(AL_STREAMING),
593 DECL(AL_UNDETERMINED),
594 DECL(AL_METERS_PER_UNIT),
595 DECL(AL_LOOP_POINTS_SOFT),
596 DECL(AL_DIRECT_CHANNELS_SOFT),
598 DECL(AL_DIRECT_FILTER),
599 DECL(AL_AUXILIARY_SEND_FILTER),
600 DECL(AL_AIR_ABSORPTION_FACTOR),
601 DECL(AL_ROOM_ROLLOFF_FACTOR),
602 DECL(AL_CONE_OUTER_GAINHF),
603 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
604 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
605 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
607 DECL(AL_SOURCE_STATE),
608 DECL(AL_INITIAL),
609 DECL(AL_PLAYING),
610 DECL(AL_PAUSED),
611 DECL(AL_STOPPED),
613 DECL(AL_BUFFERS_QUEUED),
614 DECL(AL_BUFFERS_PROCESSED),
616 DECL(AL_FORMAT_MONO8),
617 DECL(AL_FORMAT_MONO16),
618 DECL(AL_FORMAT_MONO_FLOAT32),
619 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
620 DECL(AL_FORMAT_STEREO8),
621 DECL(AL_FORMAT_STEREO16),
622 DECL(AL_FORMAT_STEREO_FLOAT32),
623 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
624 DECL(AL_FORMAT_MONO_IMA4),
625 DECL(AL_FORMAT_STEREO_IMA4),
626 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
627 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
628 DECL(AL_FORMAT_QUAD8_LOKI),
629 DECL(AL_FORMAT_QUAD16_LOKI),
630 DECL(AL_FORMAT_QUAD8),
631 DECL(AL_FORMAT_QUAD16),
632 DECL(AL_FORMAT_QUAD32),
633 DECL(AL_FORMAT_51CHN8),
634 DECL(AL_FORMAT_51CHN16),
635 DECL(AL_FORMAT_51CHN32),
636 DECL(AL_FORMAT_61CHN8),
637 DECL(AL_FORMAT_61CHN16),
638 DECL(AL_FORMAT_61CHN32),
639 DECL(AL_FORMAT_71CHN8),
640 DECL(AL_FORMAT_71CHN16),
641 DECL(AL_FORMAT_71CHN32),
642 DECL(AL_FORMAT_REAR8),
643 DECL(AL_FORMAT_REAR16),
644 DECL(AL_FORMAT_REAR32),
645 DECL(AL_FORMAT_MONO_MULAW),
646 DECL(AL_FORMAT_MONO_MULAW_EXT),
647 DECL(AL_FORMAT_STEREO_MULAW),
648 DECL(AL_FORMAT_STEREO_MULAW_EXT),
649 DECL(AL_FORMAT_QUAD_MULAW),
650 DECL(AL_FORMAT_51CHN_MULAW),
651 DECL(AL_FORMAT_61CHN_MULAW),
652 DECL(AL_FORMAT_71CHN_MULAW),
653 DECL(AL_FORMAT_REAR_MULAW),
654 DECL(AL_FORMAT_MONO_ALAW_EXT),
655 DECL(AL_FORMAT_STEREO_ALAW_EXT),
657 DECL(AL_FORMAT_BFORMAT2D_8),
658 DECL(AL_FORMAT_BFORMAT2D_16),
659 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
660 DECL(AL_FORMAT_BFORMAT2D_MULAW),
661 DECL(AL_FORMAT_BFORMAT3D_8),
662 DECL(AL_FORMAT_BFORMAT3D_16),
663 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
664 DECL(AL_FORMAT_BFORMAT3D_MULAW),
666 DECL(AL_FREQUENCY),
667 DECL(AL_BITS),
668 DECL(AL_CHANNELS),
669 DECL(AL_SIZE),
670 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
671 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
673 DECL(AL_SOURCE_RADIUS),
675 DECL(AL_SAMPLE_OFFSET_LATENCY_SOFT),
676 DECL(AL_SEC_OFFSET_LATENCY_SOFT),
678 DECL(AL_STEREO_ANGLES),
680 DECL(AL_UNUSED),
681 DECL(AL_PENDING),
682 DECL(AL_PROCESSED),
684 DECL(AL_NO_ERROR),
685 DECL(AL_INVALID_NAME),
686 DECL(AL_INVALID_ENUM),
687 DECL(AL_INVALID_VALUE),
688 DECL(AL_INVALID_OPERATION),
689 DECL(AL_OUT_OF_MEMORY),
691 DECL(AL_VENDOR),
692 DECL(AL_VERSION),
693 DECL(AL_RENDERER),
694 DECL(AL_EXTENSIONS),
696 DECL(AL_DOPPLER_FACTOR),
697 DECL(AL_DOPPLER_VELOCITY),
698 DECL(AL_DISTANCE_MODEL),
699 DECL(AL_SPEED_OF_SOUND),
700 DECL(AL_SOURCE_DISTANCE_MODEL),
701 DECL(AL_DEFERRED_UPDATES_SOFT),
702 DECL(AL_GAIN_LIMIT_SOFT),
704 DECL(AL_INVERSE_DISTANCE),
705 DECL(AL_INVERSE_DISTANCE_CLAMPED),
706 DECL(AL_LINEAR_DISTANCE),
707 DECL(AL_LINEAR_DISTANCE_CLAMPED),
708 DECL(AL_EXPONENT_DISTANCE),
709 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
711 DECL(AL_FILTER_TYPE),
712 DECL(AL_FILTER_NULL),
713 DECL(AL_FILTER_LOWPASS),
714 DECL(AL_FILTER_HIGHPASS),
715 DECL(AL_FILTER_BANDPASS),
717 DECL(AL_LOWPASS_GAIN),
718 DECL(AL_LOWPASS_GAINHF),
720 DECL(AL_HIGHPASS_GAIN),
721 DECL(AL_HIGHPASS_GAINLF),
723 DECL(AL_BANDPASS_GAIN),
724 DECL(AL_BANDPASS_GAINHF),
725 DECL(AL_BANDPASS_GAINLF),
727 DECL(AL_EFFECT_TYPE),
728 DECL(AL_EFFECT_NULL),
729 DECL(AL_EFFECT_REVERB),
730 DECL(AL_EFFECT_EAXREVERB),
731 DECL(AL_EFFECT_CHORUS),
732 DECL(AL_EFFECT_DISTORTION),
733 DECL(AL_EFFECT_ECHO),
734 DECL(AL_EFFECT_FLANGER),
735 DECL(AL_EFFECT_PITCH_SHIFTER),
736 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
737 DECL(AL_EFFECT_VOCAL_MORPHER),
738 DECL(AL_EFFECT_RING_MODULATOR),
739 DECL(AL_EFFECT_AUTOWAH),
740 DECL(AL_EFFECT_COMPRESSOR),
741 DECL(AL_EFFECT_EQUALIZER),
742 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
743 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
745 DECL(AL_EFFECTSLOT_EFFECT),
746 DECL(AL_EFFECTSLOT_GAIN),
747 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
748 DECL(AL_EFFECTSLOT_NULL),
750 DECL(AL_EAXREVERB_DENSITY),
751 DECL(AL_EAXREVERB_DIFFUSION),
752 DECL(AL_EAXREVERB_GAIN),
753 DECL(AL_EAXREVERB_GAINHF),
754 DECL(AL_EAXREVERB_GAINLF),
755 DECL(AL_EAXREVERB_DECAY_TIME),
756 DECL(AL_EAXREVERB_DECAY_HFRATIO),
757 DECL(AL_EAXREVERB_DECAY_LFRATIO),
758 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
759 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
760 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
761 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
762 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
763 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
764 DECL(AL_EAXREVERB_ECHO_TIME),
765 DECL(AL_EAXREVERB_ECHO_DEPTH),
766 DECL(AL_EAXREVERB_MODULATION_TIME),
767 DECL(AL_EAXREVERB_MODULATION_DEPTH),
768 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
769 DECL(AL_EAXREVERB_HFREFERENCE),
770 DECL(AL_EAXREVERB_LFREFERENCE),
771 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
772 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
774 DECL(AL_REVERB_DENSITY),
775 DECL(AL_REVERB_DIFFUSION),
776 DECL(AL_REVERB_GAIN),
777 DECL(AL_REVERB_GAINHF),
778 DECL(AL_REVERB_DECAY_TIME),
779 DECL(AL_REVERB_DECAY_HFRATIO),
780 DECL(AL_REVERB_REFLECTIONS_GAIN),
781 DECL(AL_REVERB_REFLECTIONS_DELAY),
782 DECL(AL_REVERB_LATE_REVERB_GAIN),
783 DECL(AL_REVERB_LATE_REVERB_DELAY),
784 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
785 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
786 DECL(AL_REVERB_DECAY_HFLIMIT),
788 DECL(AL_CHORUS_WAVEFORM),
789 DECL(AL_CHORUS_PHASE),
790 DECL(AL_CHORUS_RATE),
791 DECL(AL_CHORUS_DEPTH),
792 DECL(AL_CHORUS_FEEDBACK),
793 DECL(AL_CHORUS_DELAY),
795 DECL(AL_DISTORTION_EDGE),
796 DECL(AL_DISTORTION_GAIN),
797 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
798 DECL(AL_DISTORTION_EQCENTER),
799 DECL(AL_DISTORTION_EQBANDWIDTH),
801 DECL(AL_ECHO_DELAY),
802 DECL(AL_ECHO_LRDELAY),
803 DECL(AL_ECHO_DAMPING),
804 DECL(AL_ECHO_FEEDBACK),
805 DECL(AL_ECHO_SPREAD),
807 DECL(AL_FLANGER_WAVEFORM),
808 DECL(AL_FLANGER_PHASE),
809 DECL(AL_FLANGER_RATE),
810 DECL(AL_FLANGER_DEPTH),
811 DECL(AL_FLANGER_FEEDBACK),
812 DECL(AL_FLANGER_DELAY),
814 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY),
815 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION),
816 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION),
818 DECL(AL_RING_MODULATOR_FREQUENCY),
819 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
820 DECL(AL_RING_MODULATOR_WAVEFORM),
822 DECL(AL_PITCH_SHIFTER_COARSE_TUNE),
823 DECL(AL_PITCH_SHIFTER_FINE_TUNE),
825 DECL(AL_COMPRESSOR_ONOFF),
827 DECL(AL_EQUALIZER_LOW_GAIN),
828 DECL(AL_EQUALIZER_LOW_CUTOFF),
829 DECL(AL_EQUALIZER_MID1_GAIN),
830 DECL(AL_EQUALIZER_MID1_CENTER),
831 DECL(AL_EQUALIZER_MID1_WIDTH),
832 DECL(AL_EQUALIZER_MID2_GAIN),
833 DECL(AL_EQUALIZER_MID2_CENTER),
834 DECL(AL_EQUALIZER_MID2_WIDTH),
835 DECL(AL_EQUALIZER_HIGH_GAIN),
836 DECL(AL_EQUALIZER_HIGH_CUTOFF),
838 DECL(AL_DEDICATED_GAIN),
840 DECL(AL_AUTOWAH_ATTACK_TIME),
841 DECL(AL_AUTOWAH_RELEASE_TIME),
842 DECL(AL_AUTOWAH_RESONANCE),
843 DECL(AL_AUTOWAH_PEAK_GAIN),
845 DECL(AL_VOCAL_MORPHER_PHONEMEA),
846 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING),
847 DECL(AL_VOCAL_MORPHER_PHONEMEB),
848 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING),
849 DECL(AL_VOCAL_MORPHER_WAVEFORM),
850 DECL(AL_VOCAL_MORPHER_RATE),
852 DECL(AL_EFFECTSLOT_TARGET_SOFT),
854 DECL(AL_NUM_RESAMPLERS_SOFT),
855 DECL(AL_DEFAULT_RESAMPLER_SOFT),
856 DECL(AL_SOURCE_RESAMPLER_SOFT),
857 DECL(AL_RESAMPLER_NAME_SOFT),
859 DECL(AL_SOURCE_SPATIALIZE_SOFT),
860 DECL(AL_AUTO_SOFT),
862 DECL(AL_MAP_READ_BIT_SOFT),
863 DECL(AL_MAP_WRITE_BIT_SOFT),
864 DECL(AL_MAP_PERSISTENT_BIT_SOFT),
865 DECL(AL_PRESERVE_DATA_BIT_SOFT),
867 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT),
868 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT),
869 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT),
870 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT),
871 DECL(AL_EVENT_TYPE_DISCONNECTED_SOFT),
873 DECL(AL_DROP_UNMATCHED_SOFT),
874 DECL(AL_REMIX_UNMATCHED_SOFT),
876 DECL(AL_AMBISONIC_LAYOUT_SOFT),
877 DECL(AL_AMBISONIC_SCALING_SOFT),
878 DECL(AL_FUMA_SOFT),
879 DECL(AL_ACN_SOFT),
880 DECL(AL_SN3D_SOFT),
881 DECL(AL_N3D_SOFT),
883 DECL(AL_BUFFER_CALLBACK_FUNCTION_SOFT),
884 DECL(AL_BUFFER_CALLBACK_USER_PARAM_SOFT),
886 DECL(AL_UNPACK_AMBISONIC_ORDER_SOFT),
888 DECL(AL_EFFECT_CONVOLUTION_REVERB_SOFT),
889 DECL(AL_EFFECTSLOT_STATE_SOFT),
891 DECL(AL_FORMAT_UHJ2CHN8_SOFT),
892 DECL(AL_FORMAT_UHJ2CHN16_SOFT),
893 DECL(AL_FORMAT_UHJ2CHN_FLOAT32_SOFT),
894 DECL(AL_FORMAT_UHJ3CHN8_SOFT),
895 DECL(AL_FORMAT_UHJ3CHN16_SOFT),
896 DECL(AL_FORMAT_UHJ3CHN_FLOAT32_SOFT),
897 DECL(AL_FORMAT_UHJ4CHN8_SOFT),
898 DECL(AL_FORMAT_UHJ4CHN16_SOFT),
899 DECL(AL_FORMAT_UHJ4CHN_FLOAT32_SOFT),
900 DECL(AL_STEREO_MODE_SOFT),
901 DECL(AL_NORMAL_SOFT),
902 DECL(AL_SUPER_STEREO_SOFT),
903 DECL(AL_SUPER_STEREO_WIDTH_SOFT),
905 DECL(AL_STOP_SOURCES_ON_DISCONNECT_SOFT),
907 #ifdef ALSOFT_EAX
908 }, eaxEnumerations[] = {
909 DECL(AL_EAX_RAM_SIZE),
910 DECL(AL_EAX_RAM_FREE),
911 DECL(AL_STORAGE_AUTOMATIC),
912 DECL(AL_STORAGE_HARDWARE),
913 DECL(AL_STORAGE_ACCESSIBLE),
914 #endif // ALSOFT_EAX
916 #undef DECL
918 constexpr ALCchar alcNoError[] = "No Error";
919 constexpr ALCchar alcErrInvalidDevice[] = "Invalid Device";
920 constexpr ALCchar alcErrInvalidContext[] = "Invalid Context";
921 constexpr ALCchar alcErrInvalidEnum[] = "Invalid Enum";
922 constexpr ALCchar alcErrInvalidValue[] = "Invalid Value";
923 constexpr ALCchar alcErrOutOfMemory[] = "Out of Memory";
926 /************************************************
927 * Global variables
928 ************************************************/
930 /* Enumerated device names */
931 constexpr ALCchar alcDefaultName[] = "OpenAL Soft\0";
933 std::string alcAllDevicesList;
934 std::string alcCaptureDeviceList;
936 /* Default is always the first in the list */
937 std::string alcDefaultAllDevicesSpecifier;
938 std::string alcCaptureDefaultDeviceSpecifier;
940 std::atomic<ALCenum> LastNullDeviceError{ALC_NO_ERROR};
942 /* Flag to trap ALC device errors */
943 bool TrapALCError{false};
945 /* One-time configuration init control */
946 std::once_flag alc_config_once{};
948 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
949 * updates.
951 bool SuspendDefers{true};
953 /* Initial seed for dithering. */
954 constexpr uint DitherRNGSeed{22222u};
957 /************************************************
958 * ALC information
959 ************************************************/
960 constexpr ALCchar alcNoDeviceExtList[] =
961 "ALC_ENUMERATE_ALL_EXT "
962 "ALC_ENUMERATION_EXT "
963 "ALC_EXT_CAPTURE "
964 "ALC_EXT_EFX "
965 "ALC_EXT_thread_local_context "
966 "ALC_SOFT_loopback "
967 "ALC_SOFT_loopback_bformat "
968 "ALC_SOFT_reopen_device";
969 constexpr ALCchar alcExtensionList[] =
970 "ALC_ENUMERATE_ALL_EXT "
971 "ALC_ENUMERATION_EXT "
972 "ALC_EXT_CAPTURE "
973 "ALC_EXT_DEDICATED "
974 "ALC_EXT_disconnect "
975 "ALC_EXT_EFX "
976 "ALC_EXT_thread_local_context "
977 "ALC_SOFT_device_clock "
978 "ALC_SOFT_HRTF "
979 "ALC_SOFT_loopback "
980 "ALC_SOFT_loopback_bformat "
981 "ALC_SOFT_output_limiter "
982 "ALC_SOFT_output_mode "
983 "ALC_SOFT_pause_device "
984 "ALC_SOFT_reopen_device";
985 constexpr int alcMajorVersion{1};
986 constexpr int alcMinorVersion{1};
988 constexpr int alcEFXMajorVersion{1};
989 constexpr int alcEFXMinorVersion{0};
992 using DeviceRef = al::intrusive_ptr<ALCdevice>;
995 /************************************************
996 * Device lists
997 ************************************************/
998 al::vector<ALCdevice*> DeviceList;
999 al::vector<ALCcontext*> ContextList;
1001 std::recursive_mutex ListLock;
1004 void alc_initconfig(void)
1006 if(auto loglevel = al::getenv("ALSOFT_LOGLEVEL"))
1008 long lvl = strtol(loglevel->c_str(), nullptr, 0);
1009 if(lvl >= static_cast<long>(LogLevel::Trace))
1010 gLogLevel = LogLevel::Trace;
1011 else if(lvl <= static_cast<long>(LogLevel::Disable))
1012 gLogLevel = LogLevel::Disable;
1013 else
1014 gLogLevel = static_cast<LogLevel>(lvl);
1017 #ifdef _WIN32
1018 if(const auto logfile = al::getenv(L"ALSOFT_LOGFILE"))
1020 FILE *logf{_wfopen(logfile->c_str(), L"wt")};
1021 if(logf) gLogFile = logf;
1022 else
1024 auto u8name = wstr_to_utf8(logfile->c_str());
1025 ERR("Failed to open log file '%s'\n", u8name.c_str());
1028 #else
1029 if(const auto logfile = al::getenv("ALSOFT_LOGFILE"))
1031 FILE *logf{fopen(logfile->c_str(), "wt")};
1032 if(logf) gLogFile = logf;
1033 else ERR("Failed to open log file '%s'\n", logfile->c_str());
1035 #endif
1037 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION, ALSOFT_GIT_COMMIT_HASH,
1038 ALSOFT_GIT_BRANCH);
1040 std::string names;
1041 if(al::size(BackendList) < 1)
1042 names = "(none)";
1043 else
1045 const al::span<const BackendInfo> infos{BackendList};
1046 names = infos[0].name;
1047 for(const auto &backend : infos.subspan<1>())
1049 names += ", ";
1050 names += backend.name;
1053 TRACE("Supported backends: %s\n", names.c_str());
1055 ReadALConfig();
1057 if(auto suspendmode = al::getenv("__ALSOFT_SUSPEND_CONTEXT"))
1059 if(al::strcasecmp(suspendmode->c_str(), "ignore") == 0)
1061 SuspendDefers = false;
1062 TRACE("Selected context suspend behavior, \"ignore\"\n");
1064 else
1065 ERR("Unhandled context suspend behavior setting: \"%s\"\n", suspendmode->c_str());
1068 int capfilter{0};
1069 #if defined(HAVE_SSE4_1)
1070 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
1071 #elif defined(HAVE_SSE3)
1072 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
1073 #elif defined(HAVE_SSE2)
1074 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
1075 #elif defined(HAVE_SSE)
1076 capfilter |= CPU_CAP_SSE;
1077 #endif
1078 #ifdef HAVE_NEON
1079 capfilter |= CPU_CAP_NEON;
1080 #endif
1081 if(auto cpuopt = ConfigValueStr(nullptr, nullptr, "disable-cpu-exts"))
1083 const char *str{cpuopt->c_str()};
1084 if(al::strcasecmp(str, "all") == 0)
1085 capfilter = 0;
1086 else
1088 const char *next = str;
1089 do {
1090 str = next;
1091 while(isspace(str[0]))
1092 str++;
1093 next = strchr(str, ',');
1095 if(!str[0] || str[0] == ',')
1096 continue;
1098 size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1099 while(len > 0 && isspace(str[len-1]))
1100 len--;
1101 if(len == 3 && al::strncasecmp(str, "sse", len) == 0)
1102 capfilter &= ~CPU_CAP_SSE;
1103 else if(len == 4 && al::strncasecmp(str, "sse2", len) == 0)
1104 capfilter &= ~CPU_CAP_SSE2;
1105 else if(len == 4 && al::strncasecmp(str, "sse3", len) == 0)
1106 capfilter &= ~CPU_CAP_SSE3;
1107 else if(len == 6 && al::strncasecmp(str, "sse4.1", len) == 0)
1108 capfilter &= ~CPU_CAP_SSE4_1;
1109 else if(len == 4 && al::strncasecmp(str, "neon", len) == 0)
1110 capfilter &= ~CPU_CAP_NEON;
1111 else
1112 WARN("Invalid CPU extension \"%s\"\n", str);
1113 } while(next++);
1116 if(auto cpuopt = GetCPUInfo())
1118 if(!cpuopt->mVendor.empty() || !cpuopt->mName.empty())
1120 TRACE("Vendor ID: \"%s\"\n", cpuopt->mVendor.c_str());
1121 TRACE("Name: \"%s\"\n", cpuopt->mName.c_str());
1123 const int caps{cpuopt->mCaps};
1124 TRACE("Extensions:%s%s%s%s%s%s\n",
1125 ((capfilter&CPU_CAP_SSE) ? ((caps&CPU_CAP_SSE) ? " +SSE" : " -SSE") : ""),
1126 ((capfilter&CPU_CAP_SSE2) ? ((caps&CPU_CAP_SSE2) ? " +SSE2" : " -SSE2") : ""),
1127 ((capfilter&CPU_CAP_SSE3) ? ((caps&CPU_CAP_SSE3) ? " +SSE3" : " -SSE3") : ""),
1128 ((capfilter&CPU_CAP_SSE4_1) ? ((caps&CPU_CAP_SSE4_1) ? " +SSE4.1" : " -SSE4.1") : ""),
1129 ((capfilter&CPU_CAP_NEON) ? ((caps&CPU_CAP_NEON) ? " +NEON" : " -NEON") : ""),
1130 ((!capfilter) ? " -none-" : ""));
1131 CPUCapFlags = caps & capfilter;
1134 if(auto priopt = ConfigValueInt(nullptr, nullptr, "rt-prio"))
1135 RTPrioLevel = *priopt;
1136 if(auto limopt = ConfigValueBool(nullptr, nullptr, "rt-time-limit"))
1137 AllowRTTimeLimit = *limopt;
1140 CompatFlagBitset compatflags{};
1141 auto checkflag = [](const char *envname, const char *optname) -> bool
1143 if(auto optval = al::getenv(envname))
1145 if(al::strcasecmp(optval->c_str(), "true") == 0
1146 || strtol(optval->c_str(), nullptr, 0) == 1)
1147 return true;
1148 return false;
1150 return GetConfigValueBool(nullptr, "game_compat", optname, false);
1152 compatflags.set(CompatFlags::ReverseX, checkflag("__ALSOFT_REVERSE_X", "reverse-x"));
1153 compatflags.set(CompatFlags::ReverseY, checkflag("__ALSOFT_REVERSE_Y", "reverse-y"));
1154 compatflags.set(CompatFlags::ReverseZ, checkflag("__ALSOFT_REVERSE_Z", "reverse-z"));
1156 aluInit(compatflags, ConfigValueFloat(nullptr, "game_compat", "nfc-scale").value_or(1.0f));
1158 Voice::InitMixer(ConfigValueStr(nullptr, nullptr, "resampler"));
1160 auto uhjfiltopt = ConfigValueStr(nullptr, "uhj", "decode-filter");
1161 if(!uhjfiltopt)
1163 if((uhjfiltopt = ConfigValueStr(nullptr, "uhj", "filter")))
1164 WARN("uhj/filter is deprecated, please use uhj/decode-filter\n");
1166 if(uhjfiltopt)
1168 if(al::strcasecmp(uhjfiltopt->c_str(), "fir256") == 0)
1169 UhjDecodeQuality = UhjQualityType::FIR256;
1170 else if(al::strcasecmp(uhjfiltopt->c_str(), "fir512") == 0)
1171 UhjDecodeQuality = UhjQualityType::FIR512;
1172 else if(al::strcasecmp(uhjfiltopt->c_str(), "iir") == 0)
1173 UhjDecodeQuality = UhjQualityType::IIR;
1174 else
1175 WARN("Unsupported uhj/decode-filter: %s\n", uhjfiltopt->c_str());
1177 if((uhjfiltopt = ConfigValueStr(nullptr, "uhj", "encode-filter")))
1179 if(al::strcasecmp(uhjfiltopt->c_str(), "fir256") == 0)
1180 UhjEncodeQuality = UhjQualityType::FIR256;
1181 else if(al::strcasecmp(uhjfiltopt->c_str(), "fir512") == 0)
1182 UhjEncodeQuality = UhjQualityType::FIR512;
1183 else if(al::strcasecmp(uhjfiltopt->c_str(), "iir") == 0)
1184 UhjEncodeQuality = UhjQualityType::IIR;
1185 else
1186 WARN("Unsupported uhj/encode-filter: %s\n", uhjfiltopt->c_str());
1189 auto traperr = al::getenv("ALSOFT_TRAP_ERROR");
1190 if(traperr && (al::strcasecmp(traperr->c_str(), "true") == 0
1191 || std::strtol(traperr->c_str(), nullptr, 0) == 1))
1193 TrapALError = true;
1194 TrapALCError = true;
1196 else
1198 traperr = al::getenv("ALSOFT_TRAP_AL_ERROR");
1199 if(traperr)
1200 TrapALError = al::strcasecmp(traperr->c_str(), "true") == 0
1201 || strtol(traperr->c_str(), nullptr, 0) == 1;
1202 else
1203 TrapALError = !!GetConfigValueBool(nullptr, nullptr, "trap-al-error", false);
1205 traperr = al::getenv("ALSOFT_TRAP_ALC_ERROR");
1206 if(traperr)
1207 TrapALCError = al::strcasecmp(traperr->c_str(), "true") == 0
1208 || strtol(traperr->c_str(), nullptr, 0) == 1;
1209 else
1210 TrapALCError = !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", false);
1213 if(auto boostopt = ConfigValueFloat(nullptr, "reverb", "boost"))
1215 const float valf{std::isfinite(*boostopt) ? clampf(*boostopt, -24.0f, 24.0f) : 0.0f};
1216 ReverbBoost *= std::pow(10.0f, valf / 20.0f);
1219 auto BackendListEnd = std::end(BackendList);
1220 auto devopt = al::getenv("ALSOFT_DRIVERS");
1221 if(devopt || (devopt=ConfigValueStr(nullptr, nullptr, "drivers")))
1223 auto backendlist_cur = std::begin(BackendList);
1225 bool endlist{true};
1226 const char *next{devopt->c_str()};
1227 do {
1228 const char *devs{next};
1229 while(isspace(devs[0]))
1230 devs++;
1231 next = strchr(devs, ',');
1233 const bool delitem{devs[0] == '-'};
1234 if(devs[0] == '-') devs++;
1236 if(!devs[0] || devs[0] == ',')
1238 endlist = false;
1239 continue;
1241 endlist = true;
1243 size_t len{next ? (static_cast<size_t>(next-devs)) : strlen(devs)};
1244 while(len > 0 && isspace(devs[len-1])) --len;
1245 #ifdef HAVE_WASAPI
1246 /* HACK: For backwards compatibility, convert backend references of
1247 * mmdevapi to wasapi. This should eventually be removed.
1249 if(len == 8 && strncmp(devs, "mmdevapi", len) == 0)
1251 devs = "wasapi";
1252 len = 6;
1254 #endif
1256 auto find_backend = [devs,len](const BackendInfo &backend) -> bool
1257 { return len == strlen(backend.name) && strncmp(backend.name, devs, len) == 0; };
1258 auto this_backend = std::find_if(std::begin(BackendList), BackendListEnd,
1259 find_backend);
1261 if(this_backend == BackendListEnd)
1262 continue;
1264 if(delitem)
1265 BackendListEnd = std::move(this_backend+1, BackendListEnd, this_backend);
1266 else
1267 backendlist_cur = std::rotate(backendlist_cur, this_backend, this_backend+1);
1268 } while(next++);
1270 if(endlist)
1271 BackendListEnd = backendlist_cur;
1274 auto init_backend = [](BackendInfo &backend) -> void
1276 if(PlaybackFactory && CaptureFactory)
1277 return;
1279 BackendFactory &factory = backend.getFactory();
1280 if(!factory.init())
1282 WARN("Failed to initialize backend \"%s\"\n", backend.name);
1283 return;
1286 TRACE("Initialized backend \"%s\"\n", backend.name);
1287 if(!PlaybackFactory && factory.querySupport(BackendType::Playback))
1289 PlaybackFactory = &factory;
1290 TRACE("Added \"%s\" for playback\n", backend.name);
1292 if(!CaptureFactory && factory.querySupport(BackendType::Capture))
1294 CaptureFactory = &factory;
1295 TRACE("Added \"%s\" for capture\n", backend.name);
1298 std::for_each(std::begin(BackendList), BackendListEnd, init_backend);
1300 LoopbackBackendFactory::getFactory().init();
1302 if(!PlaybackFactory)
1303 WARN("No playback backend available!\n");
1304 if(!CaptureFactory)
1305 WARN("No capture backend available!\n");
1307 if(auto exclopt = ConfigValueStr(nullptr, nullptr, "excludefx"))
1309 const char *next{exclopt->c_str()};
1310 do {
1311 const char *str{next};
1312 next = strchr(str, ',');
1314 if(!str[0] || next == str)
1315 continue;
1317 size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1318 for(const EffectList &effectitem : gEffectList)
1320 if(len == strlen(effectitem.name) &&
1321 strncmp(effectitem.name, str, len) == 0)
1322 DisabledEffects[effectitem.type] = true;
1324 } while(next++);
1327 InitEffect(&ALCcontext::sDefaultEffect);
1328 auto defrevopt = al::getenv("ALSOFT_DEFAULT_REVERB");
1329 if(defrevopt || (defrevopt=ConfigValueStr(nullptr, nullptr, "default-reverb")))
1330 LoadReverbPreset(defrevopt->c_str(), &ALCcontext::sDefaultEffect);
1332 #ifdef ALSOFT_EAX
1334 static constexpr char eax_block_name[] = "eax";
1336 if(const auto eax_enable_opt = ConfigValueBool(nullptr, eax_block_name, "enable"))
1338 eax_g_is_enabled = *eax_enable_opt;
1339 if(!eax_g_is_enabled)
1340 TRACE("%s\n", "EAX disabled by a configuration.");
1342 else
1343 eax_g_is_enabled = true;
1345 if((DisabledEffects[EAXREVERB_EFFECT] || DisabledEffects[CHORUS_EFFECT])
1346 && eax_g_is_enabled)
1348 eax_g_is_enabled = false;
1349 TRACE("EAX disabled because %s disabled.\n",
1350 (DisabledEffects[EAXREVERB_EFFECT] && DisabledEffects[CHORUS_EFFECT])
1351 ? "EAXReverb and Chorus are" :
1352 DisabledEffects[EAXREVERB_EFFECT] ? "EAXReverb is" :
1353 DisabledEffects[CHORUS_EFFECT] ? "Chorus is" : "");
1356 #endif // ALSOFT_EAX
1358 inline void InitConfig()
1359 { std::call_once(alc_config_once, [](){alc_initconfig();}); }
1362 /************************************************
1363 * Device enumeration
1364 ************************************************/
1365 void ProbeAllDevicesList()
1367 InitConfig();
1369 std::lock_guard<std::recursive_mutex> _{ListLock};
1370 if(!PlaybackFactory)
1371 decltype(alcAllDevicesList){}.swap(alcAllDevicesList);
1372 else
1374 std::string names{PlaybackFactory->probe(BackendType::Playback)};
1375 if(names.empty()) names += '\0';
1376 names.swap(alcAllDevicesList);
1379 void ProbeCaptureDeviceList()
1381 InitConfig();
1383 std::lock_guard<std::recursive_mutex> _{ListLock};
1384 if(!CaptureFactory)
1385 decltype(alcCaptureDeviceList){}.swap(alcCaptureDeviceList);
1386 else
1388 std::string names{CaptureFactory->probe(BackendType::Capture)};
1389 if(names.empty()) names += '\0';
1390 names.swap(alcCaptureDeviceList);
1395 struct DevFmtPair { DevFmtChannels chans; DevFmtType type; };
1396 al::optional<DevFmtPair> DecomposeDevFormat(ALenum format)
1398 static const struct {
1399 ALenum format;
1400 DevFmtChannels channels;
1401 DevFmtType type;
1402 } list[] = {
1403 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1404 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1405 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1407 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1408 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1409 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1411 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1412 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1413 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1415 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1416 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1417 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1419 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1420 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1421 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1423 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1424 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1425 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1428 for(const auto &item : list)
1430 if(item.format == format)
1431 return al::make_optional<DevFmtPair>({item.channels, item.type});
1434 return al::nullopt;
1437 al::optional<DevFmtType> DevFmtTypeFromEnum(ALCenum type)
1439 switch(type)
1441 case ALC_BYTE_SOFT: return DevFmtByte;
1442 case ALC_UNSIGNED_BYTE_SOFT: return DevFmtUByte;
1443 case ALC_SHORT_SOFT: return DevFmtShort;
1444 case ALC_UNSIGNED_SHORT_SOFT: return DevFmtUShort;
1445 case ALC_INT_SOFT: return DevFmtInt;
1446 case ALC_UNSIGNED_INT_SOFT: return DevFmtUInt;
1447 case ALC_FLOAT_SOFT: return DevFmtFloat;
1449 WARN("Unsupported format type: 0x%04x\n", type);
1450 return al::nullopt;
1452 ALCenum EnumFromDevFmt(DevFmtType type)
1454 switch(type)
1456 case DevFmtByte: return ALC_BYTE_SOFT;
1457 case DevFmtUByte: return ALC_UNSIGNED_BYTE_SOFT;
1458 case DevFmtShort: return ALC_SHORT_SOFT;
1459 case DevFmtUShort: return ALC_UNSIGNED_SHORT_SOFT;
1460 case DevFmtInt: return ALC_INT_SOFT;
1461 case DevFmtUInt: return ALC_UNSIGNED_INT_SOFT;
1462 case DevFmtFloat: return ALC_FLOAT_SOFT;
1464 throw std::runtime_error{"Invalid DevFmtType: "+std::to_string(int(type))};
1467 al::optional<DevFmtChannels> DevFmtChannelsFromEnum(ALCenum channels)
1469 switch(channels)
1471 case ALC_MONO_SOFT: return DevFmtMono;
1472 case ALC_STEREO_SOFT: return DevFmtStereo;
1473 case ALC_QUAD_SOFT: return DevFmtQuad;
1474 case ALC_5POINT1_SOFT: return DevFmtX51;
1475 case ALC_6POINT1_SOFT: return DevFmtX61;
1476 case ALC_7POINT1_SOFT: return DevFmtX71;
1477 case ALC_BFORMAT3D_SOFT: return DevFmtAmbi3D;
1479 WARN("Unsupported format channels: 0x%04x\n", channels);
1480 return al::nullopt;
1482 ALCenum EnumFromDevFmt(DevFmtChannels channels)
1484 switch(channels)
1486 case DevFmtMono: return ALC_MONO_SOFT;
1487 case DevFmtStereo: return ALC_STEREO_SOFT;
1488 case DevFmtQuad: return ALC_QUAD_SOFT;
1489 case DevFmtX51: return ALC_5POINT1_SOFT;
1490 case DevFmtX61: return ALC_6POINT1_SOFT;
1491 case DevFmtX71: return ALC_7POINT1_SOFT;
1492 case DevFmtAmbi3D: return ALC_BFORMAT3D_SOFT;
1493 /* FIXME: Shouldn't happen. */
1494 case DevFmtX714:
1495 case DevFmtX3D71: break;
1497 throw std::runtime_error{"Invalid DevFmtChannels: "+std::to_string(int(channels))};
1500 al::optional<DevAmbiLayout> DevAmbiLayoutFromEnum(ALCenum layout)
1502 switch(layout)
1504 case ALC_FUMA_SOFT: return DevAmbiLayout::FuMa;
1505 case ALC_ACN_SOFT: return DevAmbiLayout::ACN;
1507 WARN("Unsupported ambisonic layout: 0x%04x\n", layout);
1508 return al::nullopt;
1510 ALCenum EnumFromDevAmbi(DevAmbiLayout layout)
1512 switch(layout)
1514 case DevAmbiLayout::FuMa: return ALC_FUMA_SOFT;
1515 case DevAmbiLayout::ACN: return ALC_ACN_SOFT;
1517 throw std::runtime_error{"Invalid DevAmbiLayout: "+std::to_string(int(layout))};
1520 al::optional<DevAmbiScaling> DevAmbiScalingFromEnum(ALCenum scaling)
1522 switch(scaling)
1524 case ALC_FUMA_SOFT: return DevAmbiScaling::FuMa;
1525 case ALC_SN3D_SOFT: return DevAmbiScaling::SN3D;
1526 case ALC_N3D_SOFT: return DevAmbiScaling::N3D;
1528 WARN("Unsupported ambisonic scaling: 0x%04x\n", scaling);
1529 return al::nullopt;
1531 ALCenum EnumFromDevAmbi(DevAmbiScaling scaling)
1533 switch(scaling)
1535 case DevAmbiScaling::FuMa: return ALC_FUMA_SOFT;
1536 case DevAmbiScaling::SN3D: return ALC_SN3D_SOFT;
1537 case DevAmbiScaling::N3D: return ALC_N3D_SOFT;
1539 throw std::runtime_error{"Invalid DevAmbiScaling: "+std::to_string(int(scaling))};
1543 /* Downmixing channel arrays, to map the given format's missing channels to
1544 * existing ones. Based on Wine's DSound downmix values, which are based on
1545 * PulseAudio's.
1547 constexpr std::array<InputRemixMap::TargetMix,2> FrontStereoSplit{{
1548 {FrontLeft, 0.5f}, {FrontRight, 0.5f}
1550 constexpr std::array<InputRemixMap::TargetMix,1> FrontLeft9{{
1551 {FrontLeft, 1.0f/9.0f}
1553 constexpr std::array<InputRemixMap::TargetMix,1> FrontRight9{{
1554 {FrontRight, 1.0f/9.0f}
1556 constexpr std::array<InputRemixMap::TargetMix,2> BackMonoToFrontSplit{{
1557 {FrontLeft, 0.5f/9.0f}, {FrontRight, 0.5f/9.0f}
1559 constexpr std::array<InputRemixMap::TargetMix,2> LeftStereoSplit{{
1560 {FrontLeft, 0.5f}, {BackLeft, 0.5f}
1562 constexpr std::array<InputRemixMap::TargetMix,2> RightStereoSplit{{
1563 {FrontRight, 0.5f}, {BackRight, 0.5f}
1565 constexpr std::array<InputRemixMap::TargetMix,2> BackStereoSplit{{
1566 {BackLeft, 0.5f}, {BackRight, 0.5f}
1568 constexpr std::array<InputRemixMap::TargetMix,2> SideStereoSplit{{
1569 {SideLeft, 0.5f}, {SideRight, 0.5f}
1571 constexpr std::array<InputRemixMap::TargetMix,1> ToSideLeft{{
1572 {SideLeft, 1.0f}
1574 constexpr std::array<InputRemixMap::TargetMix,1> ToSideRight{{
1575 {SideRight, 1.0f}
1577 constexpr std::array<InputRemixMap::TargetMix,2> BackLeftSplit{{
1578 {SideLeft, 0.5f}, {BackCenter, 0.5f}
1580 constexpr std::array<InputRemixMap::TargetMix,2> BackRightSplit{{
1581 {SideRight, 0.5f}, {BackCenter, 0.5f}
1584 const std::array<InputRemixMap,6> StereoDownmix{{
1585 { FrontCenter, FrontStereoSplit },
1586 { SideLeft, FrontLeft9 },
1587 { SideRight, FrontRight9 },
1588 { BackLeft, FrontLeft9 },
1589 { BackRight, FrontRight9 },
1590 { BackCenter, BackMonoToFrontSplit },
1592 const std::array<InputRemixMap,4> QuadDownmix{{
1593 { FrontCenter, FrontStereoSplit },
1594 { SideLeft, LeftStereoSplit },
1595 { SideRight, RightStereoSplit },
1596 { BackCenter, BackStereoSplit },
1598 const std::array<InputRemixMap,3> X51Downmix{{
1599 { BackLeft, ToSideLeft },
1600 { BackRight, ToSideRight },
1601 { BackCenter, SideStereoSplit },
1603 const std::array<InputRemixMap,2> X61Downmix{{
1604 { BackLeft, BackLeftSplit },
1605 { BackRight, BackRightSplit },
1607 const std::array<InputRemixMap,1> X71Downmix{{
1608 { BackCenter, BackStereoSplit },
1612 /** Stores the latest ALC device error. */
1613 void alcSetError(ALCdevice *device, ALCenum errorCode)
1615 WARN("Error generated on device %p, code 0x%04x\n", voidp{device}, errorCode);
1616 if(TrapALCError)
1618 #ifdef _WIN32
1619 /* DebugBreak() will cause an exception if there is no debugger */
1620 if(IsDebuggerPresent())
1621 DebugBreak();
1622 #elif defined(SIGTRAP)
1623 raise(SIGTRAP);
1624 #endif
1627 if(device)
1628 device->LastError.store(errorCode);
1629 else
1630 LastNullDeviceError.store(errorCode);
1634 std::unique_ptr<Compressor> CreateDeviceLimiter(const ALCdevice *device, const float threshold)
1636 static constexpr bool AutoKnee{true};
1637 static constexpr bool AutoAttack{true};
1638 static constexpr bool AutoRelease{true};
1639 static constexpr bool AutoPostGain{true};
1640 static constexpr bool AutoDeclip{true};
1641 static constexpr float LookAheadTime{0.001f};
1642 static constexpr float HoldTime{0.002f};
1643 static constexpr float PreGainDb{0.0f};
1644 static constexpr float PostGainDb{0.0f};
1645 static constexpr float Ratio{std::numeric_limits<float>::infinity()};
1646 static constexpr float KneeDb{0.0f};
1647 static constexpr float AttackTime{0.02f};
1648 static constexpr float ReleaseTime{0.2f};
1650 return Compressor::Create(device->RealOut.Buffer.size(), static_cast<float>(device->Frequency),
1651 AutoKnee, AutoAttack, AutoRelease, AutoPostGain, AutoDeclip, LookAheadTime, HoldTime,
1652 PreGainDb, PostGainDb, threshold, Ratio, KneeDb, AttackTime, ReleaseTime);
1656 * Updates the device's base clock time with however many samples have been
1657 * done. This is used so frequency changes on the device don't cause the time
1658 * to jump forward or back. Must not be called while the device is running/
1659 * mixing.
1661 inline void UpdateClockBase(ALCdevice *device)
1663 IncrementRef(device->MixCount);
1664 device->ClockBase += nanoseconds{seconds{device->SamplesDone}} / device->Frequency;
1665 device->SamplesDone = 0;
1666 IncrementRef(device->MixCount);
1670 * Updates device parameters according to the attribute list (caller is
1671 * responsible for holding the list lock).
1673 ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
1675 if((!attrList || !attrList[0]) && device->Type == DeviceType::Loopback)
1677 WARN("Missing attributes for loopback device\n");
1678 return ALC_INVALID_VALUE;
1681 uint numMono{device->NumMonoSources};
1682 uint numStereo{device->NumStereoSources};
1683 uint numSends{device->NumAuxSends};
1684 al::optional<StereoEncoding> stereomode;
1685 al::optional<bool> optlimit;
1686 al::optional<uint> optsrate;
1687 al::optional<DevFmtChannels> optchans;
1688 al::optional<DevFmtType> opttype;
1689 al::optional<DevAmbiLayout> optlayout;
1690 al::optional<DevAmbiScaling> optscale;
1691 uint period_size{DEFAULT_UPDATE_SIZE};
1692 uint buffer_size{DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES};
1693 int hrtf_id{-1};
1694 uint aorder{0u};
1696 if(device->Type != DeviceType::Loopback)
1698 /* Get default settings from the user configuration */
1700 if(auto freqopt = device->configValue<uint>(nullptr, "frequency"))
1702 optsrate = clampu(*freqopt, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE);
1704 const double scale{static_cast<double>(*optsrate) / DEFAULT_OUTPUT_RATE};
1705 period_size = static_cast<uint>(period_size*scale + 0.5);
1708 if(auto persizeopt = device->configValue<uint>(nullptr, "period_size"))
1709 period_size = clampu(*persizeopt, 64, 8192);
1710 if(auto numperopt = device->configValue<uint>(nullptr, "periods"))
1711 buffer_size = clampu(*numperopt, 2, 16) * period_size;
1712 else
1713 buffer_size = period_size * DEFAULT_NUM_UPDATES;
1715 if(auto typeopt = device->configValue<std::string>(nullptr, "sample-type"))
1717 static constexpr struct TypeMap {
1718 const char name[8];
1719 DevFmtType type;
1720 } typelist[] = {
1721 { "int8", DevFmtByte },
1722 { "uint8", DevFmtUByte },
1723 { "int16", DevFmtShort },
1724 { "uint16", DevFmtUShort },
1725 { "int32", DevFmtInt },
1726 { "uint32", DevFmtUInt },
1727 { "float32", DevFmtFloat },
1730 const ALCchar *fmt{typeopt->c_str()};
1731 auto iter = std::find_if(std::begin(typelist), std::end(typelist),
1732 [fmt](const TypeMap &entry) -> bool
1733 { return al::strcasecmp(entry.name, fmt) == 0; });
1734 if(iter == std::end(typelist))
1735 ERR("Unsupported sample-type: %s\n", fmt);
1736 else
1737 opttype = iter->type;
1739 if(auto chanopt = device->configValue<std::string>(nullptr, "channels"))
1741 static constexpr struct ChannelMap {
1742 const char name[16];
1743 DevFmtChannels chans;
1744 uint8_t order;
1745 } chanlist[] = {
1746 { "mono", DevFmtMono, 0 },
1747 { "stereo", DevFmtStereo, 0 },
1748 { "quad", DevFmtQuad, 0 },
1749 { "surround51", DevFmtX51, 0 },
1750 { "surround61", DevFmtX61, 0 },
1751 { "surround71", DevFmtX71, 0 },
1752 { "surround714", DevFmtX714, 0 },
1753 { "surround3d71", DevFmtX3D71, 0 },
1754 { "surround51rear", DevFmtX51, 0 },
1755 { "ambi1", DevFmtAmbi3D, 1 },
1756 { "ambi2", DevFmtAmbi3D, 2 },
1757 { "ambi3", DevFmtAmbi3D, 3 },
1760 const ALCchar *fmt{chanopt->c_str()};
1761 auto iter = std::find_if(std::begin(chanlist), std::end(chanlist),
1762 [fmt](const ChannelMap &entry) -> bool
1763 { return al::strcasecmp(entry.name, fmt) == 0; });
1764 if(iter == std::end(chanlist))
1765 ERR("Unsupported channels: %s\n", fmt);
1766 else
1768 optchans = iter->chans;
1769 aorder = iter->order;
1772 if(auto ambiopt = device->configValue<std::string>(nullptr, "ambi-format"))
1774 const ALCchar *fmt{ambiopt->c_str()};
1775 if(al::strcasecmp(fmt, "fuma") == 0)
1777 optlayout = DevAmbiLayout::FuMa;
1778 optscale = DevAmbiScaling::FuMa;
1780 else if(al::strcasecmp(fmt, "acn+fuma") == 0)
1782 optlayout = DevAmbiLayout::ACN;
1783 optscale = DevAmbiScaling::FuMa;
1785 else if(al::strcasecmp(fmt, "ambix") == 0 || al::strcasecmp(fmt, "acn+sn3d") == 0)
1787 optlayout = DevAmbiLayout::ACN;
1788 optscale = DevAmbiScaling::SN3D;
1790 else if(al::strcasecmp(fmt, "acn+n3d") == 0)
1792 optlayout = DevAmbiLayout::ACN;
1793 optscale = DevAmbiScaling::N3D;
1795 else
1796 ERR("Unsupported ambi-format: %s\n", fmt);
1799 if(auto hrtfopt = device->configValue<std::string>(nullptr, "hrtf"))
1801 WARN("general/hrtf is deprecated, please use stereo-encoding instead\n");
1803 const char *hrtf{hrtfopt->c_str()};
1804 if(al::strcasecmp(hrtf, "true") == 0)
1805 stereomode = StereoEncoding::Hrtf;
1806 else if(al::strcasecmp(hrtf, "false") == 0)
1808 if(!stereomode || *stereomode == StereoEncoding::Hrtf)
1809 stereomode = StereoEncoding::Default;
1811 else if(al::strcasecmp(hrtf, "auto") != 0)
1812 ERR("Unexpected hrtf value: %s\n", hrtf);
1816 if(auto encopt = device->configValue<std::string>(nullptr, "stereo-encoding"))
1818 const char *mode{encopt->c_str()};
1819 if(al::strcasecmp(mode, "basic") == 0 || al::strcasecmp(mode, "panpot") == 0)
1820 stereomode = StereoEncoding::Basic;
1821 else if(al::strcasecmp(mode, "uhj") == 0)
1822 stereomode = StereoEncoding::Uhj;
1823 else if(al::strcasecmp(mode, "hrtf") == 0)
1824 stereomode = StereoEncoding::Hrtf;
1825 else
1826 ERR("Unexpected stereo-encoding: %s\n", mode);
1829 // Check for app-specified attributes
1830 if(attrList && attrList[0])
1832 ALenum outmode{ALC_ANY_SOFT};
1833 al::optional<bool> opthrtf;
1834 int freqAttr{};
1836 #define ATTRIBUTE(a) a: TRACE("%s = %d\n", #a, attrList[attrIdx + 1]);
1837 size_t attrIdx{0};
1838 while(attrList[attrIdx])
1840 switch(attrList[attrIdx])
1842 case ATTRIBUTE(ALC_FORMAT_CHANNELS_SOFT)
1843 if(device->Type == DeviceType::Loopback)
1844 optchans = DevFmtChannelsFromEnum(attrList[attrIdx + 1]);
1845 break;
1847 case ATTRIBUTE(ALC_FORMAT_TYPE_SOFT)
1848 if(device->Type == DeviceType::Loopback)
1849 opttype = DevFmtTypeFromEnum(attrList[attrIdx + 1]);
1850 break;
1852 case ATTRIBUTE(ALC_FREQUENCY)
1853 freqAttr = attrList[attrIdx + 1];
1854 break;
1856 case ATTRIBUTE(ALC_AMBISONIC_LAYOUT_SOFT)
1857 if(device->Type == DeviceType::Loopback)
1858 optlayout = DevAmbiLayoutFromEnum(attrList[attrIdx + 1]);
1859 break;
1861 case ATTRIBUTE(ALC_AMBISONIC_SCALING_SOFT)
1862 if(device->Type == DeviceType::Loopback)
1863 optscale = DevAmbiScalingFromEnum(attrList[attrIdx + 1]);
1864 break;
1866 case ATTRIBUTE(ALC_AMBISONIC_ORDER_SOFT)
1867 if(device->Type == DeviceType::Loopback)
1868 aorder = static_cast<uint>(attrList[attrIdx + 1]);
1869 break;
1871 case ATTRIBUTE(ALC_MONO_SOURCES)
1872 numMono = static_cast<uint>(attrList[attrIdx + 1]);
1873 if(numMono > INT_MAX) numMono = 0;
1874 break;
1876 case ATTRIBUTE(ALC_STEREO_SOURCES)
1877 numStereo = static_cast<uint>(attrList[attrIdx + 1]);
1878 if(numStereo > INT_MAX) numStereo = 0;
1879 break;
1881 case ATTRIBUTE(ALC_MAX_AUXILIARY_SENDS)
1882 numSends = static_cast<uint>(attrList[attrIdx + 1]);
1883 if(numSends > INT_MAX) numSends = 0;
1884 else numSends = minu(numSends, MAX_SENDS);
1885 break;
1887 case ATTRIBUTE(ALC_HRTF_SOFT)
1888 if(attrList[attrIdx + 1] == ALC_FALSE)
1889 opthrtf = false;
1890 else if(attrList[attrIdx + 1] == ALC_TRUE)
1891 opthrtf = true;
1892 else if(attrList[attrIdx + 1] == ALC_DONT_CARE_SOFT)
1893 opthrtf = al::nullopt;
1894 break;
1896 case ATTRIBUTE(ALC_HRTF_ID_SOFT)
1897 hrtf_id = attrList[attrIdx + 1];
1898 break;
1900 case ATTRIBUTE(ALC_OUTPUT_LIMITER_SOFT)
1901 if(attrList[attrIdx + 1] == ALC_FALSE)
1902 optlimit = false;
1903 else if(attrList[attrIdx + 1] == ALC_TRUE)
1904 optlimit = true;
1905 else if(attrList[attrIdx + 1] == ALC_DONT_CARE_SOFT)
1906 optlimit = al::nullopt;
1907 break;
1909 case ATTRIBUTE(ALC_OUTPUT_MODE_SOFT)
1910 outmode = attrList[attrIdx + 1];
1911 break;
1913 default:
1914 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1915 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1916 break;
1919 attrIdx += 2;
1921 #undef ATTRIBUTE
1923 if(device->Type == DeviceType::Loopback)
1925 if(!optchans || !opttype)
1926 return ALC_INVALID_VALUE;
1927 if(freqAttr < MIN_OUTPUT_RATE || freqAttr > MAX_OUTPUT_RATE)
1928 return ALC_INVALID_VALUE;
1929 if(*optchans == DevFmtAmbi3D)
1931 if(!optlayout || !optscale)
1932 return ALC_INVALID_VALUE;
1933 if(aorder < 1 || aorder > MaxAmbiOrder)
1934 return ALC_INVALID_VALUE;
1935 if((*optlayout == DevAmbiLayout::FuMa || *optscale == DevAmbiScaling::FuMa)
1936 && aorder > 3)
1937 return ALC_INVALID_VALUE;
1939 else if(*optchans == DevFmtStereo)
1941 if(opthrtf)
1943 if(*opthrtf)
1944 stereomode = StereoEncoding::Hrtf;
1945 else
1947 if(stereomode.value_or(StereoEncoding::Hrtf) == StereoEncoding::Hrtf)
1948 stereomode = StereoEncoding::Default;
1952 if(outmode == ALC_STEREO_BASIC_SOFT)
1953 stereomode = StereoEncoding::Basic;
1954 else if(outmode == ALC_STEREO_UHJ_SOFT)
1955 stereomode = StereoEncoding::Uhj;
1956 else if(outmode == ALC_STEREO_HRTF_SOFT)
1957 stereomode = StereoEncoding::Hrtf;
1960 optsrate = static_cast<uint>(freqAttr);
1962 else
1964 if(opthrtf)
1966 if(*opthrtf)
1967 stereomode = StereoEncoding::Hrtf;
1968 else
1970 if(stereomode.value_or(StereoEncoding::Hrtf) == StereoEncoding::Hrtf)
1971 stereomode = StereoEncoding::Default;
1975 if(outmode != ALC_ANY_SOFT)
1977 using OutputMode = ALCdevice::OutputMode;
1978 switch(OutputMode(outmode))
1980 case OutputMode::Any: break;
1981 case OutputMode::Mono: optchans = DevFmtMono; break;
1982 case OutputMode::Stereo: optchans = DevFmtStereo; break;
1983 case OutputMode::StereoBasic:
1984 optchans = DevFmtStereo;
1985 stereomode = StereoEncoding::Basic;
1986 break;
1987 case OutputMode::Uhj2:
1988 optchans = DevFmtStereo;
1989 stereomode = StereoEncoding::Uhj;
1990 break;
1991 case OutputMode::Hrtf:
1992 optchans = DevFmtStereo;
1993 stereomode = StereoEncoding::Hrtf;
1994 break;
1995 case OutputMode::Quad: optchans = DevFmtQuad; break;
1996 case OutputMode::X51: optchans = DevFmtX51; break;
1997 case OutputMode::X61: optchans = DevFmtX61; break;
1998 case OutputMode::X71: optchans = DevFmtX71; break;
2002 if(freqAttr)
2004 uint oldrate = optsrate.value_or(DEFAULT_OUTPUT_RATE);
2005 freqAttr = clampi(freqAttr, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE);
2007 const double scale{static_cast<double>(freqAttr) / oldrate};
2008 period_size = static_cast<uint>(period_size*scale + 0.5);
2009 buffer_size = static_cast<uint>(buffer_size*scale + 0.5);
2010 optsrate = static_cast<uint>(freqAttr);
2014 /* If a context is already running on the device, stop playback so the
2015 * device attributes can be updated.
2017 if(device->Flags.test(DeviceRunning))
2018 device->Backend->stop();
2019 device->Flags.reset(DeviceRunning);
2021 UpdateClockBase(device);
2024 if(device->Flags.test(DeviceRunning))
2025 return ALC_NO_ERROR;
2027 device->AvgSpeakerDist = 0.0f;
2028 device->mNFCtrlFilter = NfcFilter{};
2029 device->mUhjEncoder = nullptr;
2030 device->AmbiDecoder = nullptr;
2031 device->Bs2b = nullptr;
2032 device->PostProcess = nullptr;
2034 device->Limiter = nullptr;
2035 device->ChannelDelays = nullptr;
2037 std::fill(std::begin(device->HrtfAccumData), std::end(device->HrtfAccumData), float2{});
2039 device->Dry.AmbiMap.fill(BFChannelConfig{});
2040 device->Dry.Buffer = {};
2041 std::fill(std::begin(device->NumChannelsPerOrder), std::end(device->NumChannelsPerOrder), 0u);
2042 device->RealOut.RemixMap = {};
2043 device->RealOut.ChannelIndex.fill(InvalidChannelIndex);
2044 device->RealOut.Buffer = {};
2045 device->MixBuffer.clear();
2046 device->MixBuffer.shrink_to_fit();
2048 UpdateClockBase(device);
2049 device->FixedLatency = nanoseconds::zero();
2051 device->DitherDepth = 0.0f;
2052 device->DitherSeed = DitherRNGSeed;
2054 device->mHrtfStatus = ALC_HRTF_DISABLED_SOFT;
2056 /*************************************************************************
2057 * Update device format request
2060 if(device->Type == DeviceType::Loopback)
2062 device->Frequency = *optsrate;
2063 device->FmtChans = *optchans;
2064 device->FmtType = *opttype;
2065 if(device->FmtChans == DevFmtAmbi3D)
2067 device->mAmbiOrder = aorder;
2068 device->mAmbiLayout = *optlayout;
2069 device->mAmbiScale = *optscale;
2071 device->Flags.set(FrequencyRequest).set(ChannelsRequest).set(SampleTypeRequest);
2073 else
2075 device->FmtType = opttype.value_or(DevFmtTypeDefault);
2076 device->FmtChans = optchans.value_or(DevFmtChannelsDefault);
2077 device->mAmbiOrder = 0;
2078 device->BufferSize = buffer_size;
2079 device->UpdateSize = period_size;
2080 device->Frequency = optsrate.value_or(DEFAULT_OUTPUT_RATE);
2081 device->Flags.set(FrequencyRequest, optsrate.has_value())
2082 .set(ChannelsRequest, optchans.has_value())
2083 .set(SampleTypeRequest, opttype.has_value());
2085 if(device->FmtChans == DevFmtAmbi3D)
2087 device->mAmbiOrder = clampu(aorder, 1, MaxAmbiOrder);
2088 device->mAmbiLayout = optlayout.value_or(DevAmbiLayout::Default);
2089 device->mAmbiScale = optscale.value_or(DevAmbiScaling::Default);
2090 if(device->mAmbiOrder > 3
2091 && (device->mAmbiLayout == DevAmbiLayout::FuMa
2092 || device->mAmbiScale == DevAmbiScaling::FuMa))
2094 ERR("FuMa is incompatible with %d%s order ambisonics (up to 3rd order only)\n",
2095 device->mAmbiOrder,
2096 (((device->mAmbiOrder%100)/10) == 1) ? "th" :
2097 ((device->mAmbiOrder%10) == 1) ? "st" :
2098 ((device->mAmbiOrder%10) == 2) ? "nd" :
2099 ((device->mAmbiOrder%10) == 3) ? "rd" : "th");
2100 device->mAmbiOrder = 3;
2105 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u / %u buffer\n",
2106 device->Flags.test(ChannelsRequest)?"*":"", DevFmtChannelsString(device->FmtChans),
2107 device->Flags.test(SampleTypeRequest)?"*":"", DevFmtTypeString(device->FmtType),
2108 device->Flags.test(FrequencyRequest)?"*":"", device->Frequency,
2109 device->UpdateSize, device->BufferSize);
2111 const uint oldFreq{device->Frequency};
2112 const DevFmtChannels oldChans{device->FmtChans};
2113 const DevFmtType oldType{device->FmtType};
2114 try {
2115 auto backend = device->Backend.get();
2116 if(!backend->reset())
2117 throw al::backend_exception{al::backend_error::DeviceError, "Device reset failure"};
2119 catch(std::exception &e) {
2120 ERR("Device error: %s\n", e.what());
2121 device->handleDisconnect("%s", e.what());
2122 return ALC_INVALID_DEVICE;
2125 if(device->FmtChans != oldChans && device->Flags.test(ChannelsRequest))
2127 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2128 DevFmtChannelsString(device->FmtChans));
2129 device->Flags.reset(ChannelsRequest);
2131 if(device->FmtType != oldType && device->Flags.test(SampleTypeRequest))
2133 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2134 DevFmtTypeString(device->FmtType));
2135 device->Flags.reset(SampleTypeRequest);
2137 if(device->Frequency != oldFreq && device->Flags.test(FrequencyRequest))
2139 WARN("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2140 device->Flags.reset(FrequencyRequest);
2143 TRACE("Post-reset: %s, %s, %uhz, %u / %u buffer\n",
2144 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2145 device->Frequency, device->UpdateSize, device->BufferSize);
2147 if(device->Type != DeviceType::Loopback)
2149 if(auto modeopt = device->configValue<std::string>(nullptr, "stereo-mode"))
2151 const char *mode{modeopt->c_str()};
2152 if(al::strcasecmp(mode, "headphones") == 0)
2153 device->Flags.set(DirectEar);
2154 else if(al::strcasecmp(mode, "speakers") == 0)
2155 device->Flags.reset(DirectEar);
2156 else if(al::strcasecmp(mode, "auto") != 0)
2157 ERR("Unexpected stereo-mode: %s\n", mode);
2161 aluInitRenderer(device, hrtf_id, stereomode);
2163 /* Calculate the max number of sources, and split them between the mono and
2164 * stereo count given the requested number of stereo sources.
2166 if(auto srcsopt = device->configValue<uint>(nullptr, "sources"))
2168 if(*srcsopt <= 0) numMono = 256;
2169 else numMono = maxu(*srcsopt, 16);
2171 else
2173 numMono = minu(numMono, INT_MAX-numStereo);
2174 numMono = maxu(numMono+numStereo, 256);
2176 numStereo = minu(numStereo, numMono);
2177 numMono -= numStereo;
2178 device->SourcesMax = numMono + numStereo;
2179 device->NumMonoSources = numMono;
2180 device->NumStereoSources = numStereo;
2182 if(auto sendsopt = device->configValue<int>(nullptr, "sends"))
2183 numSends = minu(numSends, static_cast<uint>(clampi(*sendsopt, 0, MAX_SENDS)));
2184 device->NumAuxSends = numSends;
2186 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2187 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
2188 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
2190 switch(device->FmtChans)
2192 case DevFmtMono: break;
2193 case DevFmtStereo:
2194 if(!device->mUhjEncoder)
2195 device->RealOut.RemixMap = StereoDownmix;
2196 break;
2197 case DevFmtQuad: device->RealOut.RemixMap = QuadDownmix; break;
2198 case DevFmtX51: device->RealOut.RemixMap = X51Downmix; break;
2199 case DevFmtX61: device->RealOut.RemixMap = X61Downmix; break;
2200 case DevFmtX71: device->RealOut.RemixMap = X71Downmix; break;
2201 case DevFmtX714: device->RealOut.RemixMap = X71Downmix; break;
2202 case DevFmtX3D71: device->RealOut.RemixMap = X51Downmix; break;
2203 case DevFmtAmbi3D: break;
2206 nanoseconds::rep sample_delay{0};
2207 if(auto *encoder{device->mUhjEncoder.get()})
2208 sample_delay += encoder->getDelay();
2210 if(device->getConfigValueBool(nullptr, "dither", true))
2212 int depth{device->configValue<int>(nullptr, "dither-depth").value_or(0)};
2213 if(depth <= 0)
2215 switch(device->FmtType)
2217 case DevFmtByte:
2218 case DevFmtUByte:
2219 depth = 8;
2220 break;
2221 case DevFmtShort:
2222 case DevFmtUShort:
2223 depth = 16;
2224 break;
2225 case DevFmtInt:
2226 case DevFmtUInt:
2227 case DevFmtFloat:
2228 break;
2232 if(depth > 0)
2234 depth = clampi(depth, 2, 24);
2235 device->DitherDepth = std::pow(2.0f, static_cast<float>(depth-1));
2238 if(!(device->DitherDepth > 0.0f))
2239 TRACE("Dithering disabled\n");
2240 else
2241 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device->DitherDepth)+0.5f)+1,
2242 device->DitherDepth);
2244 if(!optlimit)
2245 optlimit = device->configValue<bool>(nullptr, "output-limiter");
2247 /* If the gain limiter is unset, use the limiter for integer-based output
2248 * (where samples must be clamped), and don't for floating-point (which can
2249 * take unclamped samples).
2251 if(!optlimit)
2253 switch(device->FmtType)
2255 case DevFmtByte:
2256 case DevFmtUByte:
2257 case DevFmtShort:
2258 case DevFmtUShort:
2259 case DevFmtInt:
2260 case DevFmtUInt:
2261 optlimit = true;
2262 break;
2263 case DevFmtFloat:
2264 break;
2267 if(optlimit.value_or(false) == false)
2268 TRACE("Output limiter disabled\n");
2269 else
2271 float thrshld{1.0f};
2272 switch(device->FmtType)
2274 case DevFmtByte:
2275 case DevFmtUByte:
2276 thrshld = 127.0f / 128.0f;
2277 break;
2278 case DevFmtShort:
2279 case DevFmtUShort:
2280 thrshld = 32767.0f / 32768.0f;
2281 break;
2282 case DevFmtInt:
2283 case DevFmtUInt:
2284 case DevFmtFloat:
2285 break;
2287 if(device->DitherDepth > 0.0f)
2288 thrshld -= 1.0f / device->DitherDepth;
2290 const float thrshld_dB{std::log10(thrshld) * 20.0f};
2291 auto limiter = CreateDeviceLimiter(device, thrshld_dB);
2293 sample_delay += limiter->getLookAhead();
2294 device->Limiter = std::move(limiter);
2295 TRACE("Output limiter enabled, %.4fdB limit\n", thrshld_dB);
2298 /* Convert the sample delay from samples to nanosamples to nanoseconds. */
2299 device->FixedLatency += nanoseconds{seconds{sample_delay}} / device->Frequency;
2300 TRACE("Fixed device latency: %" PRId64 "ns\n", int64_t{device->FixedLatency.count()});
2302 FPUCtl mixer_mode{};
2303 for(ContextBase *ctxbase : *device->mContexts.load())
2305 auto *context = static_cast<ALCcontext*>(ctxbase);
2307 auto GetEffectBuffer = [](ALbuffer *buffer) noexcept -> EffectState::Buffer
2309 if(!buffer) return EffectState::Buffer{};
2310 return EffectState::Buffer{buffer, buffer->mData};
2312 std::unique_lock<std::mutex> proplock{context->mPropLock};
2313 std::unique_lock<std::mutex> slotlock{context->mEffectSlotLock};
2315 /* Clear out unused effect slot clusters. */
2316 auto slot_cluster_not_in_use = [](ContextBase::EffectSlotCluster &cluster)
2318 for(size_t i{0};i < ContextBase::EffectSlotClusterSize;++i)
2320 if(cluster[i].InUse)
2321 return false;
2323 return true;
2325 auto slotcluster_iter = std::remove_if(context->mEffectSlotClusters.begin(),
2326 context->mEffectSlotClusters.end(), slot_cluster_not_in_use);
2327 context->mEffectSlotClusters.erase(slotcluster_iter, context->mEffectSlotClusters.end());
2329 /* Free all wet buffers. Any in use will be reallocated with an updated
2330 * configuration in aluInitEffectPanning.
2332 for(auto&& slots : context->mEffectSlotClusters)
2334 for(size_t i{0};i < ContextBase::EffectSlotClusterSize;++i)
2336 slots[i].mWetBuffer.clear();
2337 slots[i].mWetBuffer.shrink_to_fit();
2338 slots[i].Wet.Buffer = {};
2342 if(ALeffectslot *slot{context->mDefaultSlot.get()})
2344 aluInitEffectPanning(slot->mSlot, context);
2346 EffectState *state{slot->Effect.State.get()};
2347 state->mOutTarget = device->Dry.Buffer;
2348 state->deviceUpdate(device, GetEffectBuffer(slot->Buffer));
2349 slot->updateProps(context);
2352 if(EffectSlotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_relaxed)})
2353 std::fill_n(curarray->end(), curarray->size(), nullptr);
2354 for(auto &sublist : context->mEffectSlotList)
2356 uint64_t usemask{~sublist.FreeMask};
2357 while(usemask)
2359 const int idx{al::countr_zero(usemask)};
2360 ALeffectslot *slot{sublist.EffectSlots + idx};
2361 usemask &= ~(1_u64 << idx);
2363 aluInitEffectPanning(slot->mSlot, context);
2365 EffectState *state{slot->Effect.State.get()};
2366 state->mOutTarget = device->Dry.Buffer;
2367 state->deviceUpdate(device, GetEffectBuffer(slot->Buffer));
2368 slot->updateProps(context);
2371 slotlock.unlock();
2373 const uint num_sends{device->NumAuxSends};
2374 std::unique_lock<std::mutex> srclock{context->mSourceLock};
2375 for(auto &sublist : context->mSourceList)
2377 uint64_t usemask{~sublist.FreeMask};
2378 while(usemask)
2380 const int idx{al::countr_zero(usemask)};
2381 ALsource *source{sublist.Sources + idx};
2382 usemask &= ~(1_u64 << idx);
2384 auto clear_send = [](ALsource::SendData &send) -> void
2386 if(send.Slot)
2387 DecrementRef(send.Slot->ref);
2388 send.Slot = nullptr;
2389 send.Gain = 1.0f;
2390 send.GainHF = 1.0f;
2391 send.HFReference = LOWPASSFREQREF;
2392 send.GainLF = 1.0f;
2393 send.LFReference = HIGHPASSFREQREF;
2395 auto send_begin = source->Send.begin() + static_cast<ptrdiff_t>(num_sends);
2396 std::for_each(send_begin, source->Send.end(), clear_send);
2398 source->mPropsDirty = true;
2402 auto voicelist = context->getVoicesSpan();
2403 for(Voice *voice : voicelist)
2405 /* Clear extraneous property set sends. */
2406 std::fill(std::begin(voice->mProps.Send)+num_sends, std::end(voice->mProps.Send),
2407 VoiceProps::SendData{});
2409 std::fill(voice->mSend.begin()+num_sends, voice->mSend.end(), Voice::TargetData{});
2410 for(auto &chandata : voice->mChans)
2412 std::fill(chandata.mWetParams.begin()+num_sends, chandata.mWetParams.end(),
2413 SendParams{});
2416 if(VoicePropsItem *props{voice->mUpdate.exchange(nullptr, std::memory_order_relaxed)})
2417 AtomicReplaceHead(context->mFreeVoiceProps, props);
2419 /* Force the voice to stopped if it was stopping. */
2420 Voice::State vstate{Voice::Stopping};
2421 voice->mPlayState.compare_exchange_strong(vstate, Voice::Stopped,
2422 std::memory_order_acquire, std::memory_order_acquire);
2423 if(voice->mSourceID.load(std::memory_order_relaxed) == 0u)
2424 continue;
2426 voice->prepare(device);
2428 /* Clear all voice props to let them get allocated again. */
2429 context->mVoicePropClusters.clear();
2430 context->mFreeVoiceProps.store(nullptr, std::memory_order_relaxed);
2431 srclock.unlock();
2433 context->mPropsDirty = false;
2434 UpdateContextProps(context);
2435 UpdateAllSourceProps(context);
2437 mixer_mode.leave();
2439 if(!device->Flags.test(DevicePaused))
2441 try {
2442 auto backend = device->Backend.get();
2443 backend->start();
2444 device->Flags.set(DeviceRunning);
2446 catch(al::backend_exception& e) {
2447 ERR("%s\n", e.what());
2448 device->handleDisconnect("%s", e.what());
2449 return ALC_INVALID_DEVICE;
2451 TRACE("Post-start: %s, %s, %uhz, %u / %u buffer\n",
2452 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2453 device->Frequency, device->UpdateSize, device->BufferSize);
2456 return ALC_NO_ERROR;
2460 * Updates device parameters as above, and also first clears the disconnected
2461 * status, if set.
2463 bool ResetDeviceParams(ALCdevice *device, const int *attrList)
2465 /* If the device was disconnected, reset it since we're opened anew. */
2466 if(!device->Connected.load(std::memory_order_relaxed)) [[unlikely]]
2468 /* Make sure disconnection is finished before continuing on. */
2469 device->waitForMix();
2471 for(ContextBase *ctxbase : *device->mContexts.load(std::memory_order_acquire))
2473 auto *ctx = static_cast<ALCcontext*>(ctxbase);
2474 if(!ctx->mStopVoicesOnDisconnect.load(std::memory_order_acquire))
2475 continue;
2477 /* Clear any pending voice changes and reallocate voices to get a
2478 * clean restart.
2480 std::lock_guard<std::mutex> __{ctx->mSourceLock};
2481 auto *vchg = ctx->mCurrentVoiceChange.load(std::memory_order_acquire);
2482 while(auto *next = vchg->mNext.load(std::memory_order_acquire))
2483 vchg = next;
2484 ctx->mCurrentVoiceChange.store(vchg, std::memory_order_release);
2486 ctx->mVoicePropClusters.clear();
2487 ctx->mFreeVoiceProps.store(nullptr, std::memory_order_relaxed);
2489 ctx->mVoiceClusters.clear();
2490 ctx->allocVoices(std::max<size_t>(256,
2491 ctx->mActiveVoiceCount.load(std::memory_order_relaxed)));
2494 device->Connected.store(true);
2497 ALCenum err{UpdateDeviceParams(device, attrList)};
2498 if(err == ALC_NO_ERROR) [[likely]] return ALC_TRUE;
2500 alcSetError(device, err);
2501 return ALC_FALSE;
2505 /** Checks if the device handle is valid, and returns a new reference if so. */
2506 DeviceRef VerifyDevice(ALCdevice *device)
2508 std::lock_guard<std::recursive_mutex> _{ListLock};
2509 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
2510 if(iter != DeviceList.end() && *iter == device)
2512 (*iter)->add_ref();
2513 return DeviceRef{*iter};
2515 return nullptr;
2520 * Checks if the given context is valid, returning a new reference to it if so.
2522 ContextRef VerifyContext(ALCcontext *context)
2524 std::lock_guard<std::recursive_mutex> _{ListLock};
2525 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
2526 if(iter != ContextList.end() && *iter == context)
2528 (*iter)->add_ref();
2529 return ContextRef{*iter};
2531 return nullptr;
2534 } // namespace
2536 /** Returns a new reference to the currently active context for this thread. */
2537 ContextRef GetContextRef(void)
2539 ALCcontext *context{ALCcontext::getThreadContext()};
2540 if(context)
2541 context->add_ref();
2542 else
2544 while(ALCcontext::sGlobalContextLock.exchange(true, std::memory_order_acquire)) {
2545 /* Wait to make sure another thread isn't trying to change the
2546 * current context and bring its refcount to 0.
2549 context = ALCcontext::sGlobalContext.load(std::memory_order_acquire);
2550 if(context) [[likely]] context->add_ref();
2551 ALCcontext::sGlobalContextLock.store(false, std::memory_order_release);
2553 return ContextRef{context};
2557 /************************************************
2558 * Standard ALC functions
2559 ************************************************/
2561 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2562 START_API_FUNC
2564 DeviceRef dev{VerifyDevice(device)};
2565 if(dev) return dev->LastError.exchange(ALC_NO_ERROR);
2566 return LastNullDeviceError.exchange(ALC_NO_ERROR);
2568 END_API_FUNC
2571 ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2572 START_API_FUNC
2574 if(!SuspendDefers)
2575 return;
2577 ContextRef ctx{VerifyContext(context)};
2578 if(!ctx)
2579 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2580 else
2582 std::lock_guard<std::mutex> _{ctx->mPropLock};
2583 ctx->deferUpdates();
2586 END_API_FUNC
2588 ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context)
2589 START_API_FUNC
2591 if(!SuspendDefers)
2592 return;
2594 ContextRef ctx{VerifyContext(context)};
2595 if(!ctx)
2596 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2597 else
2599 std::lock_guard<std::mutex> _{ctx->mPropLock};
2600 ctx->processUpdates();
2603 END_API_FUNC
2606 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2607 START_API_FUNC
2609 const ALCchar *value{nullptr};
2611 switch(param)
2613 case ALC_NO_ERROR:
2614 value = alcNoError;
2615 break;
2617 case ALC_INVALID_ENUM:
2618 value = alcErrInvalidEnum;
2619 break;
2621 case ALC_INVALID_VALUE:
2622 value = alcErrInvalidValue;
2623 break;
2625 case ALC_INVALID_DEVICE:
2626 value = alcErrInvalidDevice;
2627 break;
2629 case ALC_INVALID_CONTEXT:
2630 value = alcErrInvalidContext;
2631 break;
2633 case ALC_OUT_OF_MEMORY:
2634 value = alcErrOutOfMemory;
2635 break;
2637 case ALC_DEVICE_SPECIFIER:
2638 value = alcDefaultName;
2639 break;
2641 case ALC_ALL_DEVICES_SPECIFIER:
2642 if(DeviceRef dev{VerifyDevice(Device)})
2644 if(dev->Type == DeviceType::Capture)
2645 alcSetError(dev.get(), ALC_INVALID_ENUM);
2646 else if(dev->Type == DeviceType::Loopback)
2647 value = alcDefaultName;
2648 else
2650 std::lock_guard<std::mutex> _{dev->StateLock};
2651 value = dev->DeviceName.c_str();
2654 else
2656 ProbeAllDevicesList();
2657 value = alcAllDevicesList.c_str();
2659 break;
2661 case ALC_CAPTURE_DEVICE_SPECIFIER:
2662 if(DeviceRef dev{VerifyDevice(Device)})
2664 if(dev->Type != DeviceType::Capture)
2665 alcSetError(dev.get(), ALC_INVALID_ENUM);
2666 else
2668 std::lock_guard<std::mutex> _{dev->StateLock};
2669 value = dev->DeviceName.c_str();
2672 else
2674 ProbeCaptureDeviceList();
2675 value = alcCaptureDeviceList.c_str();
2677 break;
2679 /* Default devices are always first in the list */
2680 case ALC_DEFAULT_DEVICE_SPECIFIER:
2681 value = alcDefaultName;
2682 break;
2684 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2685 if(alcAllDevicesList.empty())
2686 ProbeAllDevicesList();
2688 /* Copy first entry as default. */
2689 alcDefaultAllDevicesSpecifier = alcAllDevicesList.c_str();
2690 value = alcDefaultAllDevicesSpecifier.c_str();
2691 break;
2693 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2694 if(alcCaptureDeviceList.empty())
2695 ProbeCaptureDeviceList();
2697 /* Copy first entry as default. */
2698 alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList.c_str();
2699 value = alcCaptureDefaultDeviceSpecifier.c_str();
2700 break;
2702 case ALC_EXTENSIONS:
2703 if(VerifyDevice(Device))
2704 value = alcExtensionList;
2705 else
2706 value = alcNoDeviceExtList;
2707 break;
2709 case ALC_HRTF_SPECIFIER_SOFT:
2710 if(DeviceRef dev{VerifyDevice(Device)})
2712 std::lock_guard<std::mutex> _{dev->StateLock};
2713 value = (dev->mHrtf ? dev->mHrtfName.c_str() : "");
2715 else
2716 alcSetError(nullptr, ALC_INVALID_DEVICE);
2717 break;
2719 default:
2720 alcSetError(VerifyDevice(Device).get(), ALC_INVALID_ENUM);
2721 break;
2724 return value;
2726 END_API_FUNC
2729 static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span<int> values)
2731 size_t i;
2733 if(values.empty())
2735 alcSetError(device, ALC_INVALID_VALUE);
2736 return 0;
2739 if(!device)
2741 switch(param)
2743 case ALC_MAJOR_VERSION:
2744 values[0] = alcMajorVersion;
2745 return 1;
2746 case ALC_MINOR_VERSION:
2747 values[0] = alcMinorVersion;
2748 return 1;
2750 case ALC_EFX_MAJOR_VERSION:
2751 values[0] = alcEFXMajorVersion;
2752 return 1;
2753 case ALC_EFX_MINOR_VERSION:
2754 values[0] = alcEFXMinorVersion;
2755 return 1;
2756 case ALC_MAX_AUXILIARY_SENDS:
2757 values[0] = MAX_SENDS;
2758 return 1;
2760 case ALC_ATTRIBUTES_SIZE:
2761 case ALC_ALL_ATTRIBUTES:
2762 case ALC_FREQUENCY:
2763 case ALC_REFRESH:
2764 case ALC_SYNC:
2765 case ALC_MONO_SOURCES:
2766 case ALC_STEREO_SOURCES:
2767 case ALC_CAPTURE_SAMPLES:
2768 case ALC_FORMAT_CHANNELS_SOFT:
2769 case ALC_FORMAT_TYPE_SOFT:
2770 case ALC_AMBISONIC_LAYOUT_SOFT:
2771 case ALC_AMBISONIC_SCALING_SOFT:
2772 case ALC_AMBISONIC_ORDER_SOFT:
2773 case ALC_MAX_AMBISONIC_ORDER_SOFT:
2774 alcSetError(nullptr, ALC_INVALID_DEVICE);
2775 return 0;
2777 default:
2778 alcSetError(nullptr, ALC_INVALID_ENUM);
2780 return 0;
2783 std::lock_guard<std::mutex> _{device->StateLock};
2784 if(device->Type == DeviceType::Capture)
2786 static constexpr int MaxCaptureAttributes{9};
2787 switch(param)
2789 case ALC_ATTRIBUTES_SIZE:
2790 values[0] = MaxCaptureAttributes;
2791 return 1;
2792 case ALC_ALL_ATTRIBUTES:
2793 i = 0;
2794 if(values.size() < MaxCaptureAttributes)
2795 alcSetError(device, ALC_INVALID_VALUE);
2796 else
2798 values[i++] = ALC_MAJOR_VERSION;
2799 values[i++] = alcMajorVersion;
2800 values[i++] = ALC_MINOR_VERSION;
2801 values[i++] = alcMinorVersion;
2802 values[i++] = ALC_CAPTURE_SAMPLES;
2803 values[i++] = static_cast<int>(device->Backend->availableSamples());
2804 values[i++] = ALC_CONNECTED;
2805 values[i++] = device->Connected.load(std::memory_order_relaxed);
2806 values[i++] = 0;
2807 assert(i == MaxCaptureAttributes);
2809 return i;
2811 case ALC_MAJOR_VERSION:
2812 values[0] = alcMajorVersion;
2813 return 1;
2814 case ALC_MINOR_VERSION:
2815 values[0] = alcMinorVersion;
2816 return 1;
2818 case ALC_CAPTURE_SAMPLES:
2819 values[0] = static_cast<int>(device->Backend->availableSamples());
2820 return 1;
2822 case ALC_CONNECTED:
2823 values[0] = device->Connected.load(std::memory_order_acquire);
2824 return 1;
2826 default:
2827 alcSetError(device, ALC_INVALID_ENUM);
2829 return 0;
2832 /* render device */
2833 auto NumAttrsForDevice = [](ALCdevice *aldev) noexcept
2835 if(aldev->Type == DeviceType::Loopback && aldev->FmtChans == DevFmtAmbi3D)
2836 return 37;
2837 return 31;
2839 switch(param)
2841 case ALC_ATTRIBUTES_SIZE:
2842 values[0] = NumAttrsForDevice(device);
2843 return 1;
2845 case ALC_ALL_ATTRIBUTES:
2846 i = 0;
2847 if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2848 alcSetError(device, ALC_INVALID_VALUE);
2849 else
2851 values[i++] = ALC_MAJOR_VERSION;
2852 values[i++] = alcMajorVersion;
2853 values[i++] = ALC_MINOR_VERSION;
2854 values[i++] = alcMinorVersion;
2855 values[i++] = ALC_EFX_MAJOR_VERSION;
2856 values[i++] = alcEFXMajorVersion;
2857 values[i++] = ALC_EFX_MINOR_VERSION;
2858 values[i++] = alcEFXMinorVersion;
2860 values[i++] = ALC_FREQUENCY;
2861 values[i++] = static_cast<int>(device->Frequency);
2862 if(device->Type != DeviceType::Loopback)
2864 values[i++] = ALC_REFRESH;
2865 values[i++] = static_cast<int>(device->Frequency / device->UpdateSize);
2867 values[i++] = ALC_SYNC;
2868 values[i++] = ALC_FALSE;
2870 else
2872 if(device->FmtChans == DevFmtAmbi3D)
2874 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
2875 values[i++] = EnumFromDevAmbi(device->mAmbiLayout);
2877 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
2878 values[i++] = EnumFromDevAmbi(device->mAmbiScale);
2880 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
2881 values[i++] = static_cast<int>(device->mAmbiOrder);
2884 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2885 values[i++] = EnumFromDevFmt(device->FmtChans);
2887 values[i++] = ALC_FORMAT_TYPE_SOFT;
2888 values[i++] = EnumFromDevFmt(device->FmtType);
2891 values[i++] = ALC_MONO_SOURCES;
2892 values[i++] = static_cast<int>(device->NumMonoSources);
2894 values[i++] = ALC_STEREO_SOURCES;
2895 values[i++] = static_cast<int>(device->NumStereoSources);
2897 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2898 values[i++] = static_cast<int>(device->NumAuxSends);
2900 values[i++] = ALC_HRTF_SOFT;
2901 values[i++] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
2903 values[i++] = ALC_HRTF_STATUS_SOFT;
2904 values[i++] = device->mHrtfStatus;
2906 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
2907 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
2909 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
2910 values[i++] = MaxAmbiOrder;
2912 values[i++] = ALC_OUTPUT_MODE_SOFT;
2913 values[i++] = static_cast<ALCenum>(device->getOutputMode1());
2915 values[i++] = 0;
2917 return i;
2919 case ALC_MAJOR_VERSION:
2920 values[0] = alcMajorVersion;
2921 return 1;
2923 case ALC_MINOR_VERSION:
2924 values[0] = alcMinorVersion;
2925 return 1;
2927 case ALC_EFX_MAJOR_VERSION:
2928 values[0] = alcEFXMajorVersion;
2929 return 1;
2931 case ALC_EFX_MINOR_VERSION:
2932 values[0] = alcEFXMinorVersion;
2933 return 1;
2935 case ALC_FREQUENCY:
2936 values[0] = static_cast<int>(device->Frequency);
2937 return 1;
2939 case ALC_REFRESH:
2940 if(device->Type == DeviceType::Loopback)
2942 alcSetError(device, ALC_INVALID_DEVICE);
2943 return 0;
2945 values[0] = static_cast<int>(device->Frequency / device->UpdateSize);
2946 return 1;
2948 case ALC_SYNC:
2949 if(device->Type == DeviceType::Loopback)
2951 alcSetError(device, ALC_INVALID_DEVICE);
2952 return 0;
2954 values[0] = ALC_FALSE;
2955 return 1;
2957 case ALC_FORMAT_CHANNELS_SOFT:
2958 if(device->Type != DeviceType::Loopback)
2960 alcSetError(device, ALC_INVALID_DEVICE);
2961 return 0;
2963 values[0] = EnumFromDevFmt(device->FmtChans);
2964 return 1;
2966 case ALC_FORMAT_TYPE_SOFT:
2967 if(device->Type != DeviceType::Loopback)
2969 alcSetError(device, ALC_INVALID_DEVICE);
2970 return 0;
2972 values[0] = EnumFromDevFmt(device->FmtType);
2973 return 1;
2975 case ALC_AMBISONIC_LAYOUT_SOFT:
2976 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2978 alcSetError(device, ALC_INVALID_DEVICE);
2979 return 0;
2981 values[0] = EnumFromDevAmbi(device->mAmbiLayout);
2982 return 1;
2984 case ALC_AMBISONIC_SCALING_SOFT:
2985 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2987 alcSetError(device, ALC_INVALID_DEVICE);
2988 return 0;
2990 values[0] = EnumFromDevAmbi(device->mAmbiScale);
2991 return 1;
2993 case ALC_AMBISONIC_ORDER_SOFT:
2994 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2996 alcSetError(device, ALC_INVALID_DEVICE);
2997 return 0;
2999 values[0] = static_cast<int>(device->mAmbiOrder);
3000 return 1;
3002 case ALC_MONO_SOURCES:
3003 values[0] = static_cast<int>(device->NumMonoSources);
3004 return 1;
3006 case ALC_STEREO_SOURCES:
3007 values[0] = static_cast<int>(device->NumStereoSources);
3008 return 1;
3010 case ALC_MAX_AUXILIARY_SENDS:
3011 values[0] = static_cast<int>(device->NumAuxSends);
3012 return 1;
3014 case ALC_CONNECTED:
3015 values[0] = device->Connected.load(std::memory_order_acquire);
3016 return 1;
3018 case ALC_HRTF_SOFT:
3019 values[0] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
3020 return 1;
3022 case ALC_HRTF_STATUS_SOFT:
3023 values[0] = device->mHrtfStatus;
3024 return 1;
3026 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3027 device->enumerateHrtfs();
3028 values[0] = static_cast<int>(minz(device->mHrtfList.size(),
3029 std::numeric_limits<int>::max()));
3030 return 1;
3032 case ALC_OUTPUT_LIMITER_SOFT:
3033 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3034 return 1;
3036 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3037 values[0] = MaxAmbiOrder;
3038 return 1;
3040 case ALC_OUTPUT_MODE_SOFT:
3041 values[0] = static_cast<ALCenum>(device->getOutputMode1());
3042 return 1;
3044 default:
3045 alcSetError(device, ALC_INVALID_ENUM);
3047 return 0;
3050 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3051 START_API_FUNC
3053 DeviceRef dev{VerifyDevice(device)};
3054 if(size <= 0 || values == nullptr)
3055 alcSetError(dev.get(), ALC_INVALID_VALUE);
3056 else
3057 GetIntegerv(dev.get(), param, {values, static_cast<uint>(size)});
3059 END_API_FUNC
3061 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3062 START_API_FUNC
3064 DeviceRef dev{VerifyDevice(device)};
3065 if(size <= 0 || values == nullptr)
3067 alcSetError(dev.get(), ALC_INVALID_VALUE);
3068 return;
3070 if(!dev || dev->Type == DeviceType::Capture)
3072 auto ivals = al::vector<int>(static_cast<uint>(size));
3073 if(size_t got{GetIntegerv(dev.get(), pname, ivals)})
3074 std::copy_n(ivals.begin(), got, values);
3075 return;
3077 /* render device */
3078 auto NumAttrsForDevice = [](ALCdevice *aldev) noexcept
3080 if(aldev->Type == DeviceType::Loopback && aldev->FmtChans == DevFmtAmbi3D)
3081 return 41;
3082 return 35;
3084 std::lock_guard<std::mutex> _{dev->StateLock};
3085 switch(pname)
3087 case ALC_ATTRIBUTES_SIZE:
3088 *values = NumAttrsForDevice(dev.get());
3089 break;
3091 case ALC_ALL_ATTRIBUTES:
3092 if(size < NumAttrsForDevice(dev.get()))
3093 alcSetError(dev.get(), ALC_INVALID_VALUE);
3094 else
3096 size_t i{0};
3097 values[i++] = ALC_FREQUENCY;
3098 values[i++] = dev->Frequency;
3100 if(dev->Type != DeviceType::Loopback)
3102 values[i++] = ALC_REFRESH;
3103 values[i++] = dev->Frequency / dev->UpdateSize;
3105 values[i++] = ALC_SYNC;
3106 values[i++] = ALC_FALSE;
3108 else
3110 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3111 values[i++] = EnumFromDevFmt(dev->FmtChans);
3113 values[i++] = ALC_FORMAT_TYPE_SOFT;
3114 values[i++] = EnumFromDevFmt(dev->FmtType);
3116 if(dev->FmtChans == DevFmtAmbi3D)
3118 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3119 values[i++] = EnumFromDevAmbi(dev->mAmbiLayout);
3121 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3122 values[i++] = EnumFromDevAmbi(dev->mAmbiScale);
3124 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3125 values[i++] = dev->mAmbiOrder;
3129 values[i++] = ALC_MONO_SOURCES;
3130 values[i++] = dev->NumMonoSources;
3132 values[i++] = ALC_STEREO_SOURCES;
3133 values[i++] = dev->NumStereoSources;
3135 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3136 values[i++] = dev->NumAuxSends;
3138 values[i++] = ALC_HRTF_SOFT;
3139 values[i++] = (dev->mHrtf ? ALC_TRUE : ALC_FALSE);
3141 values[i++] = ALC_HRTF_STATUS_SOFT;
3142 values[i++] = dev->mHrtfStatus;
3144 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3145 values[i++] = dev->Limiter ? ALC_TRUE : ALC_FALSE;
3147 ClockLatency clock{GetClockLatency(dev.get(), dev->Backend.get())};
3148 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3149 values[i++] = clock.ClockTime.count();
3151 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3152 values[i++] = clock.Latency.count();
3154 values[i++] = ALC_OUTPUT_MODE_SOFT;
3155 values[i++] = static_cast<ALCenum>(device->getOutputMode1());
3157 values[i++] = 0;
3159 break;
3161 case ALC_DEVICE_CLOCK_SOFT:
3163 uint samplecount, refcount;
3164 nanoseconds basecount;
3165 do {
3166 refcount = dev->waitForMix();
3167 basecount = dev->ClockBase;
3168 samplecount = dev->SamplesDone;
3169 } while(refcount != ReadRef(dev->MixCount));
3170 basecount += nanoseconds{seconds{samplecount}} / dev->Frequency;
3171 *values = basecount.count();
3173 break;
3175 case ALC_DEVICE_LATENCY_SOFT:
3176 *values = GetClockLatency(dev.get(), dev->Backend.get()).Latency.count();
3177 break;
3179 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3180 if(size < 2)
3181 alcSetError(dev.get(), ALC_INVALID_VALUE);
3182 else
3184 ClockLatency clock{GetClockLatency(dev.get(), dev->Backend.get())};
3185 values[0] = clock.ClockTime.count();
3186 values[1] = clock.Latency.count();
3188 break;
3190 default:
3191 auto ivals = al::vector<int>(static_cast<uint>(size));
3192 if(size_t got{GetIntegerv(dev.get(), pname, ivals)})
3193 std::copy_n(ivals.begin(), got, values);
3194 break;
3197 END_API_FUNC
3200 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3201 START_API_FUNC
3203 DeviceRef dev{VerifyDevice(device)};
3204 if(!extName)
3205 alcSetError(dev.get(), ALC_INVALID_VALUE);
3206 else
3208 size_t len = strlen(extName);
3209 const char *ptr = (dev ? alcExtensionList : alcNoDeviceExtList);
3210 while(ptr && *ptr)
3212 if(al::strncasecmp(ptr, extName, len) == 0 && (ptr[len] == '\0' || isspace(ptr[len])))
3213 return ALC_TRUE;
3215 if((ptr=strchr(ptr, ' ')) != nullptr)
3217 do {
3218 ++ptr;
3219 } while(isspace(*ptr));
3223 return ALC_FALSE;
3225 END_API_FUNC
3228 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3229 START_API_FUNC
3231 if(!funcName)
3233 DeviceRef dev{VerifyDevice(device)};
3234 alcSetError(dev.get(), ALC_INVALID_VALUE);
3235 return nullptr;
3237 #ifdef ALSOFT_EAX
3238 if(eax_g_is_enabled)
3240 for(const auto &func : eaxFunctions)
3242 if(strcmp(func.funcName, funcName) == 0)
3243 return func.address;
3246 #endif
3247 for(const auto &func : alcFunctions)
3249 if(strcmp(func.funcName, funcName) == 0)
3250 return func.address;
3252 return nullptr;
3254 END_API_FUNC
3257 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3258 START_API_FUNC
3260 if(!enumName)
3262 DeviceRef dev{VerifyDevice(device)};
3263 alcSetError(dev.get(), ALC_INVALID_VALUE);
3264 return 0;
3266 #ifdef ALSOFT_EAX
3267 if(eax_g_is_enabled)
3269 for(const auto &enm : eaxEnumerations)
3271 if(strcmp(enm.enumName, enumName) == 0)
3272 return enm.value;
3275 #endif
3276 for(const auto &enm : alcEnumerations)
3278 if(strcmp(enm.enumName, enumName) == 0)
3279 return enm.value;
3282 return 0;
3284 END_API_FUNC
3287 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3288 START_API_FUNC
3290 /* Explicitly hold the list lock while taking the StateLock in case the
3291 * device is asynchronously destroyed, to ensure this new context is
3292 * properly cleaned up after being made.
3294 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3295 DeviceRef dev{VerifyDevice(device)};
3296 if(!dev || dev->Type == DeviceType::Capture || !dev->Connected.load(std::memory_order_relaxed))
3298 listlock.unlock();
3299 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3300 return nullptr;
3302 std::unique_lock<std::mutex> statelock{dev->StateLock};
3303 listlock.unlock();
3305 dev->LastError.store(ALC_NO_ERROR);
3307 ALCenum err{UpdateDeviceParams(dev.get(), attrList)};
3308 if(err != ALC_NO_ERROR)
3310 alcSetError(dev.get(), err);
3311 return nullptr;
3314 ContextRef context{new ALCcontext{dev}};
3315 context->init();
3317 if(auto volopt = dev->configValue<float>(nullptr, "volume-adjust"))
3319 const float valf{*volopt};
3320 if(!std::isfinite(valf))
3321 ERR("volume-adjust must be finite: %f\n", valf);
3322 else
3324 const float db{clampf(valf, -24.0f, 24.0f)};
3325 if(db != valf)
3326 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3327 context->mGainBoost = std::pow(10.0f, db/20.0f);
3328 TRACE("volume-adjust gain: %f\n", context->mGainBoost);
3333 using ContextArray = al::FlexArray<ContextBase*>;
3335 /* Allocate a new context array, which holds 1 more than the current/
3336 * old array.
3338 auto *oldarray = device->mContexts.load();
3339 const size_t newcount{oldarray->size()+1};
3340 std::unique_ptr<ContextArray> newarray{ContextArray::Create(newcount)};
3342 /* Copy the current/old context handles to the new array, appending the
3343 * new context.
3345 auto iter = std::copy(oldarray->begin(), oldarray->end(), newarray->begin());
3346 *iter = context.get();
3348 /* Store the new context array in the device. Wait for any current mix
3349 * to finish before deleting the old array.
3351 dev->mContexts.store(newarray.release());
3352 if(oldarray != &DeviceBase::sEmptyContextArray)
3354 dev->waitForMix();
3355 delete oldarray;
3358 statelock.unlock();
3361 std::lock_guard<std::recursive_mutex> _{ListLock};
3362 auto iter = std::lower_bound(ContextList.cbegin(), ContextList.cend(), context.get());
3363 ContextList.emplace(iter, context.get());
3366 if(ALeffectslot *slot{context->mDefaultSlot.get()})
3368 ALenum sloterr{slot->initEffect(ALCcontext::sDefaultEffect.type,
3369 ALCcontext::sDefaultEffect.Props, context.get())};
3370 if(sloterr == AL_NO_ERROR)
3371 slot->updateProps(context.get());
3372 else
3373 ERR("Failed to initialize the default effect\n");
3376 TRACE("Created context %p\n", voidp{context.get()});
3377 return context.release();
3379 END_API_FUNC
3381 ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3382 START_API_FUNC
3384 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3385 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
3386 if(iter == ContextList.end() || *iter != context)
3388 listlock.unlock();
3389 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3390 return;
3393 /* Hold a reference to this context so it remains valid until the ListLock
3394 * is released.
3396 ContextRef ctx{*iter};
3397 ContextList.erase(iter);
3399 ALCdevice *Device{ctx->mALDevice.get()};
3401 std::lock_guard<std::mutex> _{Device->StateLock};
3402 if(!ctx->deinit() && Device->Flags.test(DeviceRunning))
3404 Device->Backend->stop();
3405 Device->Flags.reset(DeviceRunning);
3408 END_API_FUNC
3411 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3412 START_API_FUNC
3414 ALCcontext *Context{ALCcontext::getThreadContext()};
3415 if(!Context) Context = ALCcontext::sGlobalContext.load();
3416 return Context;
3418 END_API_FUNC
3420 /** Returns the currently active thread-local context. */
3421 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3422 START_API_FUNC
3423 { return ALCcontext::getThreadContext(); }
3424 END_API_FUNC
3426 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3427 START_API_FUNC
3429 /* context must be valid or nullptr */
3430 ContextRef ctx;
3431 if(context)
3433 ctx = VerifyContext(context);
3434 if(!ctx)
3436 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3437 return ALC_FALSE;
3440 /* Release this reference (if any) to store it in the GlobalContext
3441 * pointer. Take ownership of the reference (if any) that was previously
3442 * stored there, and let the reference go.
3444 while(ALCcontext::sGlobalContextLock.exchange(true, std::memory_order_acquire)) {
3445 /* Wait to make sure another thread isn't getting or trying to change
3446 * the current context as its refcount is decremented.
3449 ContextRef{ALCcontext::sGlobalContext.exchange(ctx.release())};
3450 ALCcontext::sGlobalContextLock.store(false, std::memory_order_release);
3452 /* Take ownership of the thread-local context reference (if any), clearing
3453 * the storage to null.
3455 ctx = ContextRef{ALCcontext::getThreadContext()};
3456 if(ctx) ALCcontext::setThreadContext(nullptr);
3457 /* Reset (decrement) the previous thread-local reference. */
3459 return ALC_TRUE;
3461 END_API_FUNC
3463 /** Makes the given context the active context for the current thread. */
3464 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3465 START_API_FUNC
3467 /* context must be valid or nullptr */
3468 ContextRef ctx;
3469 if(context)
3471 ctx = VerifyContext(context);
3472 if(!ctx)
3474 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3475 return ALC_FALSE;
3478 /* context's reference count is already incremented */
3479 ContextRef old{ALCcontext::getThreadContext()};
3480 ALCcontext::setThreadContext(ctx.release());
3482 return ALC_TRUE;
3484 END_API_FUNC
3487 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3488 START_API_FUNC
3490 ContextRef ctx{VerifyContext(Context)};
3491 if(!ctx)
3493 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3494 return nullptr;
3496 return ctx->mALDevice.get();
3498 END_API_FUNC
3501 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3502 START_API_FUNC
3504 InitConfig();
3506 if(!PlaybackFactory)
3508 alcSetError(nullptr, ALC_INVALID_VALUE);
3509 return nullptr;
3512 if(deviceName)
3514 TRACE("Opening playback device \"%s\"\n", deviceName);
3515 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3516 #ifdef _WIN32
3517 /* Some old Windows apps hardcode these expecting OpenAL to use a
3518 * specific audio API, even when they're not enumerated. Creative's
3519 * router effectively ignores them too.
3521 || al::strcasecmp(deviceName, "DirectSound3D") == 0
3522 || al::strcasecmp(deviceName, "DirectSound") == 0
3523 || al::strcasecmp(deviceName, "MMSYSTEM") == 0
3524 #endif
3525 /* Some old Linux apps hardcode configuration strings that were
3526 * supported by the OpenAL SI. We can't really do anything useful
3527 * with them, so just ignore.
3529 || (deviceName[0] == '\'' && deviceName[1] == '(')
3530 || al::strcasecmp(deviceName, "openal-soft") == 0)
3531 deviceName = nullptr;
3533 else
3534 TRACE("Opening default playback device\n");
3536 const uint DefaultSends{
3537 #ifdef ALSOFT_EAX
3538 eax_g_is_enabled ? uint{EAX_MAX_FXSLOTS} :
3539 #endif // ALSOFT_EAX
3540 DEFAULT_SENDS
3543 DeviceRef device{new ALCdevice{DeviceType::Playback}};
3545 /* Set output format */
3546 device->FmtChans = DevFmtChannelsDefault;
3547 device->FmtType = DevFmtTypeDefault;
3548 device->Frequency = DEFAULT_OUTPUT_RATE;
3549 device->UpdateSize = DEFAULT_UPDATE_SIZE;
3550 device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
3552 device->SourcesMax = 256;
3553 device->NumStereoSources = 1;
3554 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3555 device->AuxiliaryEffectSlotMax = 64;
3556 device->NumAuxSends = DefaultSends;
3558 try {
3559 auto backend = PlaybackFactory->createBackend(device.get(), BackendType::Playback);
3560 std::lock_guard<std::recursive_mutex> _{ListLock};
3561 backend->open(deviceName);
3562 device->Backend = std::move(backend);
3564 catch(al::backend_exception &e) {
3565 WARN("Failed to open playback device: %s\n", e.what());
3566 alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory)
3567 ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
3568 return nullptr;
3572 std::lock_guard<std::recursive_mutex> _{ListLock};
3573 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3574 DeviceList.emplace(iter, device.get());
3577 TRACE("Created device %p, \"%s\"\n", voidp{device.get()}, device->DeviceName.c_str());
3578 return device.release();
3580 END_API_FUNC
3582 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3583 START_API_FUNC
3585 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3586 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3587 if(iter == DeviceList.end() || *iter != device)
3589 alcSetError(nullptr, ALC_INVALID_DEVICE);
3590 return ALC_FALSE;
3592 if((*iter)->Type == DeviceType::Capture)
3594 alcSetError(*iter, ALC_INVALID_DEVICE);
3595 return ALC_FALSE;
3598 /* Erase the device, and any remaining contexts left on it, from their
3599 * respective lists.
3601 DeviceRef dev{*iter};
3602 DeviceList.erase(iter);
3604 std::unique_lock<std::mutex> statelock{dev->StateLock};
3605 al::vector<ContextRef> orphanctxs;
3606 for(ContextBase *ctx : *dev->mContexts.load())
3608 auto ctxiter = std::lower_bound(ContextList.begin(), ContextList.end(), ctx);
3609 if(ctxiter != ContextList.end() && *ctxiter == ctx)
3611 orphanctxs.emplace_back(ContextRef{*ctxiter});
3612 ContextList.erase(ctxiter);
3615 listlock.unlock();
3617 for(ContextRef &context : orphanctxs)
3619 WARN("Releasing orphaned context %p\n", voidp{context.get()});
3620 context->deinit();
3622 orphanctxs.clear();
3624 if(dev->Flags.test(DeviceRunning))
3625 dev->Backend->stop();
3626 dev->Flags.reset(DeviceRunning);
3628 return ALC_TRUE;
3630 END_API_FUNC
3633 /************************************************
3634 * ALC capture functions
3635 ************************************************/
3636 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3637 START_API_FUNC
3639 InitConfig();
3641 if(!CaptureFactory)
3643 alcSetError(nullptr, ALC_INVALID_VALUE);
3644 return nullptr;
3647 if(samples <= 0)
3649 alcSetError(nullptr, ALC_INVALID_VALUE);
3650 return nullptr;
3653 if(deviceName)
3655 TRACE("Opening capture device \"%s\"\n", deviceName);
3656 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3657 || al::strcasecmp(deviceName, "openal-soft") == 0)
3658 deviceName = nullptr;
3660 else
3661 TRACE("Opening default capture device\n");
3663 DeviceRef device{new ALCdevice{DeviceType::Capture}};
3665 auto decompfmt = DecomposeDevFormat(format);
3666 if(!decompfmt)
3668 alcSetError(nullptr, ALC_INVALID_ENUM);
3669 return nullptr;
3672 device->Frequency = frequency;
3673 device->FmtChans = decompfmt->chans;
3674 device->FmtType = decompfmt->type;
3675 device->Flags.set(FrequencyRequest);
3676 device->Flags.set(ChannelsRequest);
3677 device->Flags.set(SampleTypeRequest);
3679 device->UpdateSize = static_cast<uint>(samples);
3680 device->BufferSize = static_cast<uint>(samples);
3682 try {
3683 TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n",
3684 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
3685 device->Frequency, device->UpdateSize, device->BufferSize);
3687 auto backend = CaptureFactory->createBackend(device.get(), BackendType::Capture);
3688 std::lock_guard<std::recursive_mutex> _{ListLock};
3689 backend->open(deviceName);
3690 device->Backend = std::move(backend);
3692 catch(al::backend_exception &e) {
3693 WARN("Failed to open capture device: %s\n", e.what());
3694 alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory)
3695 ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
3696 return nullptr;
3700 std::lock_guard<std::recursive_mutex> _{ListLock};
3701 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3702 DeviceList.emplace(iter, device.get());
3705 TRACE("Created capture device %p, \"%s\"\n", voidp{device.get()}, device->DeviceName.c_str());
3706 return device.release();
3708 END_API_FUNC
3710 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3711 START_API_FUNC
3713 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3714 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3715 if(iter == DeviceList.end() || *iter != device)
3717 alcSetError(nullptr, ALC_INVALID_DEVICE);
3718 return ALC_FALSE;
3720 if((*iter)->Type != DeviceType::Capture)
3722 alcSetError(*iter, ALC_INVALID_DEVICE);
3723 return ALC_FALSE;
3726 DeviceRef dev{*iter};
3727 DeviceList.erase(iter);
3728 listlock.unlock();
3730 std::lock_guard<std::mutex> _{dev->StateLock};
3731 if(dev->Flags.test(DeviceRunning))
3732 dev->Backend->stop();
3733 dev->Flags.reset(DeviceRunning);
3735 return ALC_TRUE;
3737 END_API_FUNC
3739 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3740 START_API_FUNC
3742 DeviceRef dev{VerifyDevice(device)};
3743 if(!dev || dev->Type != DeviceType::Capture)
3745 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3746 return;
3749 std::lock_guard<std::mutex> _{dev->StateLock};
3750 if(!dev->Connected.load(std::memory_order_acquire))
3751 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3752 else if(!dev->Flags.test(DeviceRunning))
3754 try {
3755 auto backend = dev->Backend.get();
3756 backend->start();
3757 dev->Flags.set(DeviceRunning);
3759 catch(al::backend_exception& e) {
3760 ERR("%s\n", e.what());
3761 dev->handleDisconnect("%s", e.what());
3762 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3766 END_API_FUNC
3768 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3769 START_API_FUNC
3771 DeviceRef dev{VerifyDevice(device)};
3772 if(!dev || dev->Type != DeviceType::Capture)
3773 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3774 else
3776 std::lock_guard<std::mutex> _{dev->StateLock};
3777 if(dev->Flags.test(DeviceRunning))
3778 dev->Backend->stop();
3779 dev->Flags.reset(DeviceRunning);
3782 END_API_FUNC
3784 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3785 START_API_FUNC
3787 DeviceRef dev{VerifyDevice(device)};
3788 if(!dev || dev->Type != DeviceType::Capture)
3790 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3791 return;
3794 if(samples < 0 || (samples > 0 && buffer == nullptr))
3796 alcSetError(dev.get(), ALC_INVALID_VALUE);
3797 return;
3799 if(samples < 1)
3800 return;
3802 std::lock_guard<std::mutex> _{dev->StateLock};
3803 BackendBase *backend{dev->Backend.get()};
3805 const auto usamples = static_cast<uint>(samples);
3806 if(usamples > backend->availableSamples())
3808 alcSetError(dev.get(), ALC_INVALID_VALUE);
3809 return;
3812 backend->captureSamples(static_cast<al::byte*>(buffer), usamples);
3814 END_API_FUNC
3817 /************************************************
3818 * ALC loopback functions
3819 ************************************************/
3821 /** Open a loopback device, for manual rendering. */
3822 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3823 START_API_FUNC
3825 InitConfig();
3827 /* Make sure the device name, if specified, is us. */
3828 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3830 alcSetError(nullptr, ALC_INVALID_VALUE);
3831 return nullptr;
3834 const uint DefaultSends{
3835 #ifdef ALSOFT_EAX
3836 eax_g_is_enabled ? uint{EAX_MAX_FXSLOTS} :
3837 #endif // ALSOFT_EAX
3838 DEFAULT_SENDS
3841 DeviceRef device{new ALCdevice{DeviceType::Loopback}};
3843 device->SourcesMax = 256;
3844 device->AuxiliaryEffectSlotMax = 64;
3845 device->NumAuxSends = DefaultSends;
3847 //Set output format
3848 device->BufferSize = 0;
3849 device->UpdateSize = 0;
3851 device->Frequency = DEFAULT_OUTPUT_RATE;
3852 device->FmtChans = DevFmtChannelsDefault;
3853 device->FmtType = DevFmtTypeDefault;
3855 device->NumStereoSources = 1;
3856 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3858 try {
3859 auto backend = LoopbackBackendFactory::getFactory().createBackend(device.get(),
3860 BackendType::Playback);
3861 backend->open("Loopback");
3862 device->Backend = std::move(backend);
3864 catch(al::backend_exception &e) {
3865 WARN("Failed to open loopback device: %s\n", e.what());
3866 alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory)
3867 ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
3868 return nullptr;
3872 std::lock_guard<std::recursive_mutex> _{ListLock};
3873 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3874 DeviceList.emplace(iter, device.get());
3877 TRACE("Created loopback device %p\n", voidp{device.get()});
3878 return device.release();
3880 END_API_FUNC
3883 * Determines if the loopback device supports the given format for rendering.
3885 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3886 START_API_FUNC
3888 DeviceRef dev{VerifyDevice(device)};
3889 if(!dev || dev->Type != DeviceType::Loopback)
3890 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3891 else if(freq <= 0)
3892 alcSetError(dev.get(), ALC_INVALID_VALUE);
3893 else
3895 if(DevFmtTypeFromEnum(type).has_value() && DevFmtChannelsFromEnum(channels).has_value()
3896 && freq >= MIN_OUTPUT_RATE && freq <= MAX_OUTPUT_RATE)
3897 return ALC_TRUE;
3900 return ALC_FALSE;
3902 END_API_FUNC
3905 * Renders some samples into a buffer, using the format last set by the
3906 * attributes given to alcCreateContext.
3908 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3909 START_API_FUNC
3911 if(!device || device->Type != DeviceType::Loopback)
3912 alcSetError(device, ALC_INVALID_DEVICE);
3913 else if(samples < 0 || (samples > 0 && buffer == nullptr))
3914 alcSetError(device, ALC_INVALID_VALUE);
3915 else
3916 device->renderSamples(buffer, static_cast<uint>(samples), device->channelsFromFmt());
3918 END_API_FUNC
3921 /************************************************
3922 * ALC DSP pause/resume functions
3923 ************************************************/
3925 /** Pause the DSP to stop audio processing. */
3926 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
3927 START_API_FUNC
3929 DeviceRef dev{VerifyDevice(device)};
3930 if(!dev || dev->Type != DeviceType::Playback)
3931 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3932 else
3934 std::lock_guard<std::mutex> _{dev->StateLock};
3935 if(dev->Flags.test(DeviceRunning))
3936 dev->Backend->stop();
3937 dev->Flags.reset(DeviceRunning);
3938 dev->Flags.set(DevicePaused);
3941 END_API_FUNC
3943 /** Resume the DSP to restart audio processing. */
3944 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
3945 START_API_FUNC
3947 DeviceRef dev{VerifyDevice(device)};
3948 if(!dev || dev->Type != DeviceType::Playback)
3950 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3951 return;
3954 std::lock_guard<std::mutex> _{dev->StateLock};
3955 if(!dev->Flags.test(DevicePaused))
3956 return;
3957 dev->Flags.reset(DevicePaused);
3958 if(dev->mContexts.load()->empty())
3959 return;
3961 try {
3962 auto backend = dev->Backend.get();
3963 backend->start();
3964 dev->Flags.set(DeviceRunning);
3966 catch(al::backend_exception& e) {
3967 ERR("%s\n", e.what());
3968 dev->handleDisconnect("%s", e.what());
3969 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3970 return;
3972 TRACE("Post-resume: %s, %s, %uhz, %u / %u buffer\n",
3973 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
3974 device->Frequency, device->UpdateSize, device->BufferSize);
3976 END_API_FUNC
3979 /************************************************
3980 * ALC HRTF functions
3981 ************************************************/
3983 /** Gets a string parameter at the given index. */
3984 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
3985 START_API_FUNC
3987 DeviceRef dev{VerifyDevice(device)};
3988 if(!dev || dev->Type == DeviceType::Capture)
3989 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3990 else switch(paramName)
3992 case ALC_HRTF_SPECIFIER_SOFT:
3993 if(index >= 0 && static_cast<uint>(index) < dev->mHrtfList.size())
3994 return dev->mHrtfList[static_cast<uint>(index)].c_str();
3995 alcSetError(dev.get(), ALC_INVALID_VALUE);
3996 break;
3998 default:
3999 alcSetError(dev.get(), ALC_INVALID_ENUM);
4000 break;
4003 return nullptr;
4005 END_API_FUNC
4007 /** Resets the given device output, using the specified attribute list. */
4008 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4009 START_API_FUNC
4011 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4012 DeviceRef dev{VerifyDevice(device)};
4013 if(!dev || dev->Type == DeviceType::Capture)
4015 listlock.unlock();
4016 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4017 return ALC_FALSE;
4019 std::lock_guard<std::mutex> _{dev->StateLock};
4020 listlock.unlock();
4022 /* Force the backend to stop mixing first since we're resetting. Also reset
4023 * the connected state so lost devices can attempt recover.
4025 if(dev->Flags.test(DeviceRunning))
4026 dev->Backend->stop();
4027 dev->Flags.reset(DeviceRunning);
4029 return ResetDeviceParams(dev.get(), attribs) ? ALC_TRUE : ALC_FALSE;
4031 END_API_FUNC
4034 /************************************************
4035 * ALC device reopen functions
4036 ************************************************/
4038 /** Reopens the given device output, using the specified name and attribute list. */
4039 FORCE_ALIGN ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device,
4040 const ALCchar *deviceName, const ALCint *attribs)
4041 START_API_FUNC
4043 if(deviceName)
4045 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0)
4046 deviceName = nullptr;
4049 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4050 DeviceRef dev{VerifyDevice(device)};
4051 if(!dev || dev->Type != DeviceType::Playback)
4053 listlock.unlock();
4054 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4055 return ALC_FALSE;
4057 std::lock_guard<std::mutex> _{dev->StateLock};
4059 /* Force the backend to stop mixing first since we're reopening. */
4060 if(dev->Flags.test(DeviceRunning))
4062 auto backend = dev->Backend.get();
4063 backend->stop();
4064 dev->Flags.reset(DeviceRunning);
4067 BackendPtr newbackend;
4068 try {
4069 newbackend = PlaybackFactory->createBackend(dev.get(), BackendType::Playback);
4070 newbackend->open(deviceName);
4072 catch(al::backend_exception &e) {
4073 listlock.unlock();
4074 newbackend = nullptr;
4076 WARN("Failed to reopen playback device: %s\n", e.what());
4077 alcSetError(dev.get(), (e.errorCode() == al::backend_error::OutOfMemory)
4078 ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
4080 /* If the device is connected, not paused, and has contexts, ensure it
4081 * continues playing.
4083 if(dev->Connected.load(std::memory_order_relaxed) && !dev->Flags.test(DevicePaused)
4084 && !dev->mContexts.load(std::memory_order_relaxed)->empty())
4086 try {
4087 auto backend = dev->Backend.get();
4088 backend->start();
4089 dev->Flags.set(DeviceRunning);
4091 catch(al::backend_exception &be) {
4092 ERR("%s\n", be.what());
4093 dev->handleDisconnect("%s", be.what());
4096 return ALC_FALSE;
4098 listlock.unlock();
4099 dev->Backend = std::move(newbackend);
4100 TRACE("Reopened device %p, \"%s\"\n", voidp{dev.get()}, dev->DeviceName.c_str());
4102 /* Always return true even if resetting fails. It shouldn't fail, but this
4103 * is primarily to avoid confusion by the app seeing the function return
4104 * false while the device is on the new output anyway. We could try to
4105 * restore the old backend if this fails, but the configuration would be
4106 * changed with the new backend and would need to be reset again with the
4107 * old one, and the provided attributes may not be appropriate or desirable
4108 * for the old device.
4110 * In this way, we essentially act as if the function succeeded, but
4111 * immediately disconnects following it.
4113 ResetDeviceParams(dev.get(), attribs);
4114 return ALC_TRUE;
4116 END_API_FUNC