Remove the FFT'd resampler from makemhr
[openal-soft.git] / alc / alc.cpp
blob37b85255402ef6f9819480929d6603dfb3f68c5a
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 al::make_optional(DevFmtByte);
1442 case ALC_UNSIGNED_BYTE_SOFT: return al::make_optional(DevFmtUByte);
1443 case ALC_SHORT_SOFT: return al::make_optional(DevFmtShort);
1444 case ALC_UNSIGNED_SHORT_SOFT: return al::make_optional(DevFmtUShort);
1445 case ALC_INT_SOFT: return al::make_optional(DevFmtInt);
1446 case ALC_UNSIGNED_INT_SOFT: return al::make_optional(DevFmtUInt);
1447 case ALC_FLOAT_SOFT: return al::make_optional(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 al::make_optional(DevFmtMono);
1472 case ALC_STEREO_SOFT: return al::make_optional(DevFmtStereo);
1473 case ALC_QUAD_SOFT: return al::make_optional(DevFmtQuad);
1474 case ALC_5POINT1_SOFT: return al::make_optional(DevFmtX51);
1475 case ALC_6POINT1_SOFT: return al::make_optional(DevFmtX61);
1476 case ALC_7POINT1_SOFT: return al::make_optional(DevFmtX71);
1477 case ALC_BFORMAT3D_SOFT: return al::make_optional(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 al::make_optional(DevAmbiLayout::FuMa);
1505 case ALC_ACN_SOFT: return al::make_optional(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 al::make_optional(DevAmbiScaling::FuMa);
1525 case ALC_SN3D_SOFT: return al::make_optional(DevAmbiScaling::SN3D);
1526 case ALC_N3D_SOFT: return al::make_optional(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 const std::array<InputRemixMap,6> StereoDownmix{{
1548 { FrontCenter, {{{FrontLeft, 0.5f}, {FrontRight, 0.5f}}} },
1549 { SideLeft, {{{FrontLeft, 1.0f/9.0f}}} },
1550 { SideRight, {{{FrontRight, 1.0f/9.0f}}} },
1551 { BackLeft, {{{FrontLeft, 1.0f/9.0f}}} },
1552 { BackRight, {{{FrontRight, 1.0f/9.0f}}} },
1553 { BackCenter, {{{FrontLeft, 0.5f/9.0f}, {FrontRight, 0.5f/9.0f}}} },
1555 const std::array<InputRemixMap,4> QuadDownmix{{
1556 { FrontCenter, {{{FrontLeft, 0.5f}, {FrontRight, 0.5f}}} },
1557 { SideLeft, {{{FrontLeft, 0.5f}, {BackLeft, 0.5f}}} },
1558 { SideRight, {{{FrontRight, 0.5f}, {BackRight, 0.5f}}} },
1559 { BackCenter, {{{BackLeft, 0.5f}, {BackRight, 0.5f}}} },
1561 const std::array<InputRemixMap,3> X51Downmix{{
1562 { BackLeft, {{{SideLeft, 1.0f}}} },
1563 { BackRight, {{{SideRight, 1.0f}}} },
1564 { BackCenter, {{{SideLeft, 0.5f}, {SideRight, 0.5f}}} },
1566 const std::array<InputRemixMap,2> X61Downmix{{
1567 { BackLeft, {{{BackCenter, 0.5f}, {SideLeft, 0.5f}}} },
1568 { BackRight, {{{BackCenter, 0.5f}, {SideRight, 0.5f}}} },
1570 const std::array<InputRemixMap,1> X71Downmix{{
1571 { BackCenter, {{{BackLeft, 0.5f}, {BackRight, 0.5f}}} },
1575 /** Stores the latest ALC device error. */
1576 void alcSetError(ALCdevice *device, ALCenum errorCode)
1578 WARN("Error generated on device %p, code 0x%04x\n", voidp{device}, errorCode);
1579 if(TrapALCError)
1581 #ifdef _WIN32
1582 /* DebugBreak() will cause an exception if there is no debugger */
1583 if(IsDebuggerPresent())
1584 DebugBreak();
1585 #elif defined(SIGTRAP)
1586 raise(SIGTRAP);
1587 #endif
1590 if(device)
1591 device->LastError.store(errorCode);
1592 else
1593 LastNullDeviceError.store(errorCode);
1597 std::unique_ptr<Compressor> CreateDeviceLimiter(const ALCdevice *device, const float threshold)
1599 static constexpr bool AutoKnee{true};
1600 static constexpr bool AutoAttack{true};
1601 static constexpr bool AutoRelease{true};
1602 static constexpr bool AutoPostGain{true};
1603 static constexpr bool AutoDeclip{true};
1604 static constexpr float LookAheadTime{0.001f};
1605 static constexpr float HoldTime{0.002f};
1606 static constexpr float PreGainDb{0.0f};
1607 static constexpr float PostGainDb{0.0f};
1608 static constexpr float Ratio{std::numeric_limits<float>::infinity()};
1609 static constexpr float KneeDb{0.0f};
1610 static constexpr float AttackTime{0.02f};
1611 static constexpr float ReleaseTime{0.2f};
1613 return Compressor::Create(device->RealOut.Buffer.size(), static_cast<float>(device->Frequency),
1614 AutoKnee, AutoAttack, AutoRelease, AutoPostGain, AutoDeclip, LookAheadTime, HoldTime,
1615 PreGainDb, PostGainDb, threshold, Ratio, KneeDb, AttackTime, ReleaseTime);
1619 * Updates the device's base clock time with however many samples have been
1620 * done. This is used so frequency changes on the device don't cause the time
1621 * to jump forward or back. Must not be called while the device is running/
1622 * mixing.
1624 static inline void UpdateClockBase(ALCdevice *device)
1626 IncrementRef(device->MixCount);
1627 device->ClockBase += nanoseconds{seconds{device->SamplesDone}} / device->Frequency;
1628 device->SamplesDone = 0;
1629 IncrementRef(device->MixCount);
1633 * Updates device parameters according to the attribute list (caller is
1634 * responsible for holding the list lock).
1636 ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
1638 if((!attrList || !attrList[0]) && device->Type == DeviceType::Loopback)
1640 WARN("Missing attributes for loopback device\n");
1641 return ALC_INVALID_VALUE;
1644 uint numMono{device->NumMonoSources};
1645 uint numStereo{device->NumStereoSources};
1646 uint numSends{device->NumAuxSends};
1647 al::optional<StereoEncoding> stereomode;
1648 al::optional<bool> optlimit;
1649 al::optional<uint> optsrate;
1650 al::optional<DevFmtChannels> optchans;
1651 al::optional<DevFmtType> opttype;
1652 al::optional<DevAmbiLayout> optlayout;
1653 al::optional<DevAmbiScaling> optscale;
1654 uint period_size{DEFAULT_UPDATE_SIZE};
1655 uint buffer_size{DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES};
1656 int hrtf_id{-1};
1657 uint aorder{0u};
1659 if(device->Type != DeviceType::Loopback)
1661 /* Get default settings from the user configuration */
1663 if(auto freqopt = device->configValue<uint>(nullptr, "frequency"))
1665 optsrate = clampu(*freqopt, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE);
1667 const double scale{static_cast<double>(*optsrate) / DEFAULT_OUTPUT_RATE};
1668 period_size = static_cast<uint>(period_size*scale + 0.5);
1669 buffer_size = static_cast<uint>(buffer_size*scale + 0.5);
1672 if(auto persizeopt = device->configValue<uint>(nullptr, "period_size"))
1673 period_size = clampu(*persizeopt, 64, 8192);
1674 if(auto numperopt = device->configValue<uint>(nullptr, "periods"))
1675 buffer_size = clampu(*numperopt, 2, 16) * period_size;
1676 else
1677 buffer_size = period_size * DEFAULT_NUM_UPDATES;
1679 if(auto typeopt = device->configValue<std::string>(nullptr, "sample-type"))
1681 static constexpr struct TypeMap {
1682 const char name[8];
1683 DevFmtType type;
1684 } typelist[] = {
1685 { "int8", DevFmtByte },
1686 { "uint8", DevFmtUByte },
1687 { "int16", DevFmtShort },
1688 { "uint16", DevFmtUShort },
1689 { "int32", DevFmtInt },
1690 { "uint32", DevFmtUInt },
1691 { "float32", DevFmtFloat },
1694 const ALCchar *fmt{typeopt->c_str()};
1695 auto iter = std::find_if(std::begin(typelist), std::end(typelist),
1696 [fmt](const TypeMap &entry) -> bool
1697 { return al::strcasecmp(entry.name, fmt) == 0; });
1698 if(iter == std::end(typelist))
1699 ERR("Unsupported sample-type: %s\n", fmt);
1700 else
1701 opttype = iter->type;
1703 if(auto chanopt = device->configValue<std::string>(nullptr, "channels"))
1705 static constexpr struct ChannelMap {
1706 const char name[16];
1707 DevFmtChannels chans;
1708 uint8_t order;
1709 } chanlist[] = {
1710 { "mono", DevFmtMono, 0 },
1711 { "stereo", DevFmtStereo, 0 },
1712 { "quad", DevFmtQuad, 0 },
1713 { "surround51", DevFmtX51, 0 },
1714 { "surround61", DevFmtX61, 0 },
1715 { "surround71", DevFmtX71, 0 },
1716 { "surround714", DevFmtX714, 0 },
1717 { "surround3d71", DevFmtX3D71, 0 },
1718 { "surround51rear", DevFmtX51, 0 },
1719 { "ambi1", DevFmtAmbi3D, 1 },
1720 { "ambi2", DevFmtAmbi3D, 2 },
1721 { "ambi3", DevFmtAmbi3D, 3 },
1724 const ALCchar *fmt{chanopt->c_str()};
1725 auto iter = std::find_if(std::begin(chanlist), std::end(chanlist),
1726 [fmt](const ChannelMap &entry) -> bool
1727 { return al::strcasecmp(entry.name, fmt) == 0; });
1728 if(iter == std::end(chanlist))
1729 ERR("Unsupported channels: %s\n", fmt);
1730 else
1732 optchans = iter->chans;
1733 aorder = iter->order;
1736 if(auto ambiopt = device->configValue<std::string>(nullptr, "ambi-format"))
1738 const ALCchar *fmt{ambiopt->c_str()};
1739 if(al::strcasecmp(fmt, "fuma") == 0)
1741 optlayout = DevAmbiLayout::FuMa;
1742 optscale = DevAmbiScaling::FuMa;
1744 else if(al::strcasecmp(fmt, "acn+fuma") == 0)
1746 optlayout = DevAmbiLayout::ACN;
1747 optscale = DevAmbiScaling::FuMa;
1749 else if(al::strcasecmp(fmt, "ambix") == 0 || al::strcasecmp(fmt, "acn+sn3d") == 0)
1751 optlayout = DevAmbiLayout::ACN;
1752 optscale = DevAmbiScaling::SN3D;
1754 else if(al::strcasecmp(fmt, "acn+n3d") == 0)
1756 optlayout = DevAmbiLayout::ACN;
1757 optscale = DevAmbiScaling::N3D;
1759 else
1760 ERR("Unsupported ambi-format: %s\n", fmt);
1763 if(auto hrtfopt = device->configValue<std::string>(nullptr, "hrtf"))
1765 WARN("general/hrtf is deprecated, please use stereo-encoding instead\n");
1767 const char *hrtf{hrtfopt->c_str()};
1768 if(al::strcasecmp(hrtf, "true") == 0)
1769 stereomode = StereoEncoding::Hrtf;
1770 else if(al::strcasecmp(hrtf, "false") == 0)
1772 if(!stereomode || *stereomode == StereoEncoding::Hrtf)
1773 stereomode = StereoEncoding::Default;
1775 else if(al::strcasecmp(hrtf, "auto") != 0)
1776 ERR("Unexpected hrtf value: %s\n", hrtf);
1780 if(auto encopt = device->configValue<std::string>(nullptr, "stereo-encoding"))
1782 const char *mode{encopt->c_str()};
1783 if(al::strcasecmp(mode, "basic") == 0 || al::strcasecmp(mode, "panpot") == 0)
1784 stereomode = StereoEncoding::Basic;
1785 else if(al::strcasecmp(mode, "uhj") == 0)
1786 stereomode = StereoEncoding::Uhj;
1787 else if(al::strcasecmp(mode, "hrtf") == 0)
1788 stereomode = StereoEncoding::Hrtf;
1789 else
1790 ERR("Unexpected stereo-encoding: %s\n", mode);
1793 // Check for app-specified attributes
1794 if(attrList && attrList[0])
1796 ALenum outmode{ALC_ANY_SOFT};
1797 al::optional<bool> opthrtf;
1798 int freqAttr{};
1800 #define ATTRIBUTE(a) a: TRACE("%s = %d\n", #a, attrList[attrIdx + 1]);
1801 size_t attrIdx{0};
1802 while(attrList[attrIdx])
1804 switch(attrList[attrIdx])
1806 case ATTRIBUTE(ALC_FORMAT_CHANNELS_SOFT)
1807 if(device->Type == DeviceType::Loopback)
1808 optchans = DevFmtChannelsFromEnum(attrList[attrIdx + 1]);
1809 break;
1811 case ATTRIBUTE(ALC_FORMAT_TYPE_SOFT)
1812 if(device->Type == DeviceType::Loopback)
1813 opttype = DevFmtTypeFromEnum(attrList[attrIdx + 1]);
1814 break;
1816 case ATTRIBUTE(ALC_FREQUENCY)
1817 freqAttr = attrList[attrIdx + 1];
1818 break;
1820 case ATTRIBUTE(ALC_AMBISONIC_LAYOUT_SOFT)
1821 if(device->Type == DeviceType::Loopback)
1822 optlayout = DevAmbiLayoutFromEnum(attrList[attrIdx + 1]);
1823 break;
1825 case ATTRIBUTE(ALC_AMBISONIC_SCALING_SOFT)
1826 if(device->Type == DeviceType::Loopback)
1827 optscale = DevAmbiScalingFromEnum(attrList[attrIdx + 1]);
1828 break;
1830 case ATTRIBUTE(ALC_AMBISONIC_ORDER_SOFT)
1831 if(device->Type == DeviceType::Loopback)
1832 aorder = static_cast<uint>(attrList[attrIdx + 1]);
1833 break;
1835 case ATTRIBUTE(ALC_MONO_SOURCES)
1836 numMono = static_cast<uint>(attrList[attrIdx + 1]);
1837 if(numMono > INT_MAX) numMono = 0;
1838 break;
1840 case ATTRIBUTE(ALC_STEREO_SOURCES)
1841 numStereo = static_cast<uint>(attrList[attrIdx + 1]);
1842 if(numStereo > INT_MAX) numStereo = 0;
1843 break;
1845 case ATTRIBUTE(ALC_MAX_AUXILIARY_SENDS)
1846 numSends = static_cast<uint>(attrList[attrIdx + 1]);
1847 if(numSends > INT_MAX) numSends = 0;
1848 else numSends = minu(numSends, MAX_SENDS);
1849 break;
1851 case ATTRIBUTE(ALC_HRTF_SOFT)
1852 if(attrList[attrIdx + 1] == ALC_FALSE)
1853 opthrtf = false;
1854 else if(attrList[attrIdx + 1] == ALC_TRUE)
1855 opthrtf = true;
1856 else if(attrList[attrIdx + 1] == ALC_DONT_CARE_SOFT)
1857 opthrtf = al::nullopt;
1858 break;
1860 case ATTRIBUTE(ALC_HRTF_ID_SOFT)
1861 hrtf_id = attrList[attrIdx + 1];
1862 break;
1864 case ATTRIBUTE(ALC_OUTPUT_LIMITER_SOFT)
1865 if(attrList[attrIdx + 1] == ALC_FALSE)
1866 optlimit = false;
1867 else if(attrList[attrIdx + 1] == ALC_TRUE)
1868 optlimit = true;
1869 else if(attrList[attrIdx + 1] == ALC_DONT_CARE_SOFT)
1870 optlimit = al::nullopt;
1871 break;
1873 case ATTRIBUTE(ALC_OUTPUT_MODE_SOFT)
1874 outmode = attrList[attrIdx + 1];
1875 break;
1877 default:
1878 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1879 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1880 break;
1883 attrIdx += 2;
1885 #undef ATTRIBUTE
1887 if(device->Type == DeviceType::Loopback)
1889 if(!optchans || !opttype)
1890 return ALC_INVALID_VALUE;
1891 if(freqAttr < MIN_OUTPUT_RATE || freqAttr > MAX_OUTPUT_RATE)
1892 return ALC_INVALID_VALUE;
1893 if(*optchans == DevFmtAmbi3D)
1895 if(!optlayout || !optscale)
1896 return ALC_INVALID_VALUE;
1897 if(aorder < 1 || aorder > MaxAmbiOrder)
1898 return ALC_INVALID_VALUE;
1899 if((*optlayout == DevAmbiLayout::FuMa || *optscale == DevAmbiScaling::FuMa)
1900 && aorder > 3)
1901 return ALC_INVALID_VALUE;
1903 else if(*optchans == DevFmtStereo)
1905 if(opthrtf)
1907 if(*opthrtf)
1908 stereomode = StereoEncoding::Hrtf;
1909 else
1911 if(stereomode.value_or(StereoEncoding::Hrtf) == StereoEncoding::Hrtf)
1912 stereomode = StereoEncoding::Default;
1916 if(outmode == ALC_STEREO_BASIC_SOFT)
1917 stereomode = StereoEncoding::Basic;
1918 else if(outmode == ALC_STEREO_UHJ_SOFT)
1919 stereomode = StereoEncoding::Uhj;
1920 else if(outmode == ALC_STEREO_HRTF_SOFT)
1921 stereomode = StereoEncoding::Hrtf;
1924 optsrate = static_cast<uint>(freqAttr);
1926 else
1928 if(opthrtf)
1930 if(*opthrtf)
1931 stereomode = StereoEncoding::Hrtf;
1932 else
1934 if(stereomode.value_or(StereoEncoding::Hrtf) == StereoEncoding::Hrtf)
1935 stereomode = StereoEncoding::Default;
1939 if(outmode != ALC_ANY_SOFT)
1941 using OutputMode = ALCdevice::OutputMode;
1942 switch(OutputMode(outmode))
1944 case OutputMode::Any: break;
1945 case OutputMode::Mono: optchans = DevFmtMono; break;
1946 case OutputMode::Stereo: optchans = DevFmtStereo; break;
1947 case OutputMode::StereoBasic:
1948 optchans = DevFmtStereo;
1949 stereomode = StereoEncoding::Basic;
1950 break;
1951 case OutputMode::Uhj2:
1952 optchans = DevFmtStereo;
1953 stereomode = StereoEncoding::Uhj;
1954 break;
1955 case OutputMode::Hrtf:
1956 optchans = DevFmtStereo;
1957 stereomode = StereoEncoding::Hrtf;
1958 break;
1959 case OutputMode::Quad: optchans = DevFmtQuad; break;
1960 case OutputMode::X51: optchans = DevFmtX51; break;
1961 case OutputMode::X61: optchans = DevFmtX61; break;
1962 case OutputMode::X71: optchans = DevFmtX71; break;
1966 if(freqAttr)
1968 uint oldrate = optsrate.value_or(DEFAULT_OUTPUT_RATE);
1969 freqAttr = clampi(freqAttr, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE);
1971 const double scale{static_cast<double>(freqAttr) / oldrate};
1972 period_size = static_cast<uint>(period_size*scale + 0.5);
1973 buffer_size = static_cast<uint>(buffer_size*scale + 0.5);
1974 optsrate = static_cast<uint>(freqAttr);
1978 /* If a context is already running on the device, stop playback so the
1979 * device attributes can be updated.
1981 if(device->Flags.test(DeviceRunning))
1982 device->Backend->stop();
1983 device->Flags.reset(DeviceRunning);
1985 UpdateClockBase(device);
1988 if(device->Flags.test(DeviceRunning))
1989 return ALC_NO_ERROR;
1991 device->AvgSpeakerDist = 0.0f;
1992 device->mNFCtrlFilter = NfcFilter{};
1993 device->mUhjEncoder = nullptr;
1994 device->AmbiDecoder = nullptr;
1995 device->Bs2b = nullptr;
1996 device->PostProcess = nullptr;
1998 device->Limiter = nullptr;
1999 device->ChannelDelays = nullptr;
2001 std::fill(std::begin(device->HrtfAccumData), std::end(device->HrtfAccumData), float2{});
2003 device->Dry.AmbiMap.fill(BFChannelConfig{});
2004 device->Dry.Buffer = {};
2005 std::fill(std::begin(device->NumChannelsPerOrder), std::end(device->NumChannelsPerOrder), 0u);
2006 device->RealOut.RemixMap = {};
2007 device->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
2008 device->RealOut.Buffer = {};
2009 device->MixBuffer.clear();
2010 device->MixBuffer.shrink_to_fit();
2012 UpdateClockBase(device);
2013 device->FixedLatency = nanoseconds::zero();
2015 device->DitherDepth = 0.0f;
2016 device->DitherSeed = DitherRNGSeed;
2018 device->mHrtfStatus = ALC_HRTF_DISABLED_SOFT;
2020 /*************************************************************************
2021 * Update device format request
2024 if(device->Type == DeviceType::Loopback)
2026 device->Frequency = *optsrate;
2027 device->FmtChans = *optchans;
2028 device->FmtType = *opttype;
2029 if(device->FmtChans == DevFmtAmbi3D)
2031 device->mAmbiOrder = aorder;
2032 device->mAmbiLayout = *optlayout;
2033 device->mAmbiScale = *optscale;
2035 device->Flags.set(FrequencyRequest).set(ChannelsRequest).set(SampleTypeRequest);
2037 else
2039 device->FmtType = opttype.value_or(DevFmtTypeDefault);
2040 device->FmtChans = optchans.value_or(DevFmtChannelsDefault);
2041 device->mAmbiOrder = 0;
2042 device->BufferSize = buffer_size;
2043 device->UpdateSize = period_size;
2044 device->Frequency = optsrate.value_or(DEFAULT_OUTPUT_RATE);
2045 device->Flags.set(FrequencyRequest, optsrate.has_value())
2046 .set(ChannelsRequest, optchans.has_value())
2047 .set(SampleTypeRequest, opttype.has_value());
2049 if(device->FmtChans == DevFmtAmbi3D)
2051 device->mAmbiOrder = clampu(aorder, 1, MaxAmbiOrder);
2052 device->mAmbiLayout = optlayout.value_or(DevAmbiLayout::Default);
2053 device->mAmbiScale = optscale.value_or(DevAmbiScaling::Default);
2054 if(device->mAmbiOrder > 3
2055 && (device->mAmbiLayout == DevAmbiLayout::FuMa
2056 || device->mAmbiScale == DevAmbiScaling::FuMa))
2058 ERR("FuMa is incompatible with %d%s order ambisonics (up to 3rd order only)\n",
2059 device->mAmbiOrder,
2060 (((device->mAmbiOrder%100)/10) == 1) ? "th" :
2061 ((device->mAmbiOrder%10) == 1) ? "st" :
2062 ((device->mAmbiOrder%10) == 2) ? "nd" :
2063 ((device->mAmbiOrder%10) == 3) ? "rd" : "th");
2064 device->mAmbiOrder = 3;
2069 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u / %u buffer\n",
2070 device->Flags.test(ChannelsRequest)?"*":"", DevFmtChannelsString(device->FmtChans),
2071 device->Flags.test(SampleTypeRequest)?"*":"", DevFmtTypeString(device->FmtType),
2072 device->Flags.test(FrequencyRequest)?"*":"", device->Frequency,
2073 device->UpdateSize, device->BufferSize);
2075 const uint oldFreq{device->Frequency};
2076 const DevFmtChannels oldChans{device->FmtChans};
2077 const DevFmtType oldType{device->FmtType};
2078 try {
2079 auto backend = device->Backend.get();
2080 if(!backend->reset())
2081 throw al::backend_exception{al::backend_error::DeviceError, "Device reset failure"};
2083 catch(std::exception &e) {
2084 ERR("Device error: %s\n", e.what());
2085 device->handleDisconnect("%s", e.what());
2086 return ALC_INVALID_DEVICE;
2089 if(device->FmtChans != oldChans && device->Flags.test(ChannelsRequest))
2091 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2092 DevFmtChannelsString(device->FmtChans));
2093 device->Flags.reset(ChannelsRequest);
2095 if(device->FmtType != oldType && device->Flags.test(SampleTypeRequest))
2097 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2098 DevFmtTypeString(device->FmtType));
2099 device->Flags.reset(SampleTypeRequest);
2101 if(device->Frequency != oldFreq && device->Flags.test(FrequencyRequest))
2103 WARN("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2104 device->Flags.reset(FrequencyRequest);
2107 TRACE("Post-reset: %s, %s, %uhz, %u / %u buffer\n",
2108 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2109 device->Frequency, device->UpdateSize, device->BufferSize);
2111 if(device->Type != DeviceType::Loopback)
2113 if(auto modeopt = device->configValue<std::string>(nullptr, "stereo-mode"))
2115 const char *mode{modeopt->c_str()};
2116 if(al::strcasecmp(mode, "headphones") == 0)
2117 device->Flags.set(DirectEar);
2118 else if(al::strcasecmp(mode, "speakers") == 0)
2119 device->Flags.reset(DirectEar);
2120 else if(al::strcasecmp(mode, "auto") != 0)
2121 ERR("Unexpected stereo-mode: %s\n", mode);
2125 aluInitRenderer(device, hrtf_id, stereomode);
2127 /* Calculate the max number of sources, and split them between the mono and
2128 * stereo count given the requested number of stereo sources.
2130 if(auto srcsopt = device->configValue<uint>(nullptr, "sources"))
2132 if(*srcsopt <= 0) numMono = 256;
2133 else numMono = maxu(*srcsopt, 16);
2135 else
2137 numMono = minu(numMono, INT_MAX-numStereo);
2138 numMono = maxu(numMono+numStereo, 256);
2140 numStereo = minu(numStereo, numMono);
2141 numMono -= numStereo;
2142 device->SourcesMax = numMono + numStereo;
2143 device->NumMonoSources = numMono;
2144 device->NumStereoSources = numStereo;
2146 if(auto sendsopt = device->configValue<int>(nullptr, "sends"))
2147 numSends = minu(numSends, static_cast<uint>(clampi(*sendsopt, 0, MAX_SENDS)));
2148 device->NumAuxSends = numSends;
2150 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2151 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
2152 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
2154 switch(device->FmtChans)
2156 case DevFmtMono: break;
2157 case DevFmtStereo:
2158 if(!device->mUhjEncoder)
2159 device->RealOut.RemixMap = StereoDownmix;
2160 break;
2161 case DevFmtQuad: device->RealOut.RemixMap = QuadDownmix; break;
2162 case DevFmtX51: device->RealOut.RemixMap = X51Downmix; break;
2163 case DevFmtX61: device->RealOut.RemixMap = X61Downmix; break;
2164 case DevFmtX71: device->RealOut.RemixMap = X71Downmix; break;
2165 case DevFmtX714: device->RealOut.RemixMap = X71Downmix; break;
2166 case DevFmtX3D71: device->RealOut.RemixMap = X51Downmix; break;
2167 case DevFmtAmbi3D: break;
2170 nanoseconds::rep sample_delay{0};
2171 if(auto *encoder{device->mUhjEncoder.get()})
2172 sample_delay += encoder->getDelay();
2174 if(device->getConfigValueBool(nullptr, "dither", true))
2176 int depth{device->configValue<int>(nullptr, "dither-depth").value_or(0)};
2177 if(depth <= 0)
2179 switch(device->FmtType)
2181 case DevFmtByte:
2182 case DevFmtUByte:
2183 depth = 8;
2184 break;
2185 case DevFmtShort:
2186 case DevFmtUShort:
2187 depth = 16;
2188 break;
2189 case DevFmtInt:
2190 case DevFmtUInt:
2191 case DevFmtFloat:
2192 break;
2196 if(depth > 0)
2198 depth = clampi(depth, 2, 24);
2199 device->DitherDepth = std::pow(2.0f, static_cast<float>(depth-1));
2202 if(!(device->DitherDepth > 0.0f))
2203 TRACE("Dithering disabled\n");
2204 else
2205 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device->DitherDepth)+0.5f)+1,
2206 device->DitherDepth);
2208 if(!optlimit)
2209 optlimit = device->configValue<bool>(nullptr, "output-limiter");
2211 /* If the gain limiter is unset, use the limiter for integer-based output
2212 * (where samples must be clamped), and don't for floating-point (which can
2213 * take unclamped samples).
2215 if(!optlimit)
2217 switch(device->FmtType)
2219 case DevFmtByte:
2220 case DevFmtUByte:
2221 case DevFmtShort:
2222 case DevFmtUShort:
2223 case DevFmtInt:
2224 case DevFmtUInt:
2225 optlimit = true;
2226 break;
2227 case DevFmtFloat:
2228 break;
2231 if(optlimit.value_or(false) == false)
2232 TRACE("Output limiter disabled\n");
2233 else
2235 float thrshld{1.0f};
2236 switch(device->FmtType)
2238 case DevFmtByte:
2239 case DevFmtUByte:
2240 thrshld = 127.0f / 128.0f;
2241 break;
2242 case DevFmtShort:
2243 case DevFmtUShort:
2244 thrshld = 32767.0f / 32768.0f;
2245 break;
2246 case DevFmtInt:
2247 case DevFmtUInt:
2248 case DevFmtFloat:
2249 break;
2251 if(device->DitherDepth > 0.0f)
2252 thrshld -= 1.0f / device->DitherDepth;
2254 const float thrshld_dB{std::log10(thrshld) * 20.0f};
2255 auto limiter = CreateDeviceLimiter(device, thrshld_dB);
2257 sample_delay += limiter->getLookAhead();
2258 device->Limiter = std::move(limiter);
2259 TRACE("Output limiter enabled, %.4fdB limit\n", thrshld_dB);
2262 /* Convert the sample delay from samples to nanosamples to nanoseconds. */
2263 device->FixedLatency += nanoseconds{seconds{sample_delay}} / device->Frequency;
2264 TRACE("Fixed device latency: %" PRId64 "ns\n", int64_t{device->FixedLatency.count()});
2266 FPUCtl mixer_mode{};
2267 for(ContextBase *ctxbase : *device->mContexts.load())
2269 auto *context = static_cast<ALCcontext*>(ctxbase);
2271 auto GetEffectBuffer = [](ALbuffer *buffer) noexcept -> EffectState::Buffer
2273 if(!buffer) return EffectState::Buffer{};
2274 return EffectState::Buffer{buffer, buffer->mData};
2276 std::unique_lock<std::mutex> proplock{context->mPropLock};
2277 std::unique_lock<std::mutex> slotlock{context->mEffectSlotLock};
2279 /* Clear out unused effect slot clusters. */
2280 auto slot_cluster_not_in_use = [](ContextBase::EffectSlotCluster &cluster)
2282 for(size_t i{0};i < ContextBase::EffectSlotClusterSize;++i)
2284 if(cluster[i].InUse)
2285 return false;
2287 return true;
2289 auto slotcluster_iter = std::remove_if(context->mEffectSlotClusters.begin(),
2290 context->mEffectSlotClusters.end(), slot_cluster_not_in_use);
2291 context->mEffectSlotClusters.erase(slotcluster_iter, context->mEffectSlotClusters.end());
2293 /* Free all wet buffers. Any in use will be reallocated with an updated
2294 * configuration in aluInitEffectPanning.
2296 for(auto&& slots : context->mEffectSlotClusters)
2298 for(size_t i{0};i < ContextBase::EffectSlotClusterSize;++i)
2300 slots[i].mWetBuffer.clear();
2301 slots[i].mWetBuffer.shrink_to_fit();
2302 slots[i].Wet.Buffer = {};
2306 if(ALeffectslot *slot{context->mDefaultSlot.get()})
2308 aluInitEffectPanning(slot->mSlot, context);
2310 EffectState *state{slot->Effect.State.get()};
2311 state->mOutTarget = device->Dry.Buffer;
2312 state->deviceUpdate(device, GetEffectBuffer(slot->Buffer));
2313 slot->updateProps(context);
2316 if(EffectSlotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_relaxed)})
2317 std::fill_n(curarray->end(), curarray->size(), nullptr);
2318 for(auto &sublist : context->mEffectSlotList)
2320 uint64_t usemask{~sublist.FreeMask};
2321 while(usemask)
2323 const int idx{al::countr_zero(usemask)};
2324 ALeffectslot *slot{sublist.EffectSlots + idx};
2325 usemask &= ~(1_u64 << idx);
2327 aluInitEffectPanning(slot->mSlot, context);
2329 EffectState *state{slot->Effect.State.get()};
2330 state->mOutTarget = device->Dry.Buffer;
2331 state->deviceUpdate(device, GetEffectBuffer(slot->Buffer));
2332 slot->updateProps(context);
2335 slotlock.unlock();
2337 const uint num_sends{device->NumAuxSends};
2338 std::unique_lock<std::mutex> srclock{context->mSourceLock};
2339 for(auto &sublist : context->mSourceList)
2341 uint64_t usemask{~sublist.FreeMask};
2342 while(usemask)
2344 const int idx{al::countr_zero(usemask)};
2345 ALsource *source{sublist.Sources + idx};
2346 usemask &= ~(1_u64 << idx);
2348 auto clear_send = [](ALsource::SendData &send) -> void
2350 if(send.Slot)
2351 DecrementRef(send.Slot->ref);
2352 send.Slot = nullptr;
2353 send.Gain = 1.0f;
2354 send.GainHF = 1.0f;
2355 send.HFReference = LOWPASSFREQREF;
2356 send.GainLF = 1.0f;
2357 send.LFReference = HIGHPASSFREQREF;
2359 auto send_begin = source->Send.begin() + static_cast<ptrdiff_t>(num_sends);
2360 std::for_each(send_begin, source->Send.end(), clear_send);
2362 source->mPropsDirty = true;
2366 auto voicelist = context->getVoicesSpan();
2367 for(Voice *voice : voicelist)
2369 /* Clear extraneous property set sends. */
2370 std::fill(std::begin(voice->mProps.Send)+num_sends, std::end(voice->mProps.Send),
2371 VoiceProps::SendData{});
2373 std::fill(voice->mSend.begin()+num_sends, voice->mSend.end(), Voice::TargetData{});
2374 for(auto &chandata : voice->mChans)
2376 std::fill(chandata.mWetParams.begin()+num_sends, chandata.mWetParams.end(),
2377 SendParams{});
2380 if(VoicePropsItem *props{voice->mUpdate.exchange(nullptr, std::memory_order_relaxed)})
2381 AtomicReplaceHead(context->mFreeVoiceProps, props);
2383 /* Force the voice to stopped if it was stopping. */
2384 Voice::State vstate{Voice::Stopping};
2385 voice->mPlayState.compare_exchange_strong(vstate, Voice::Stopped,
2386 std::memory_order_acquire, std::memory_order_acquire);
2387 if(voice->mSourceID.load(std::memory_order_relaxed) == 0u)
2388 continue;
2390 voice->prepare(device);
2392 /* Clear all voice props to let them get allocated again. */
2393 context->mVoicePropClusters.clear();
2394 context->mFreeVoiceProps.store(nullptr, std::memory_order_relaxed);
2395 srclock.unlock();
2397 context->mPropsDirty = false;
2398 UpdateContextProps(context);
2399 UpdateAllSourceProps(context);
2401 mixer_mode.leave();
2403 if(!device->Flags.test(DevicePaused))
2405 try {
2406 auto backend = device->Backend.get();
2407 backend->start();
2408 device->Flags.set(DeviceRunning);
2410 catch(al::backend_exception& e) {
2411 ERR("%s\n", e.what());
2412 device->handleDisconnect("%s", e.what());
2413 return ALC_INVALID_DEVICE;
2415 TRACE("Post-start: %s, %s, %uhz, %u / %u buffer\n",
2416 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2417 device->Frequency, device->UpdateSize, device->BufferSize);
2420 return ALC_NO_ERROR;
2424 * Updates device parameters as above, and also first clears the disconnected
2425 * status, if set.
2427 bool ResetDeviceParams(ALCdevice *device, const int *attrList)
2429 /* If the device was disconnected, reset it since we're opened anew. */
2430 if(!device->Connected.load(std::memory_order_relaxed)) [[unlikely]]
2432 /* Make sure disconnection is finished before continuing on. */
2433 device->waitForMix();
2435 for(ContextBase *ctxbase : *device->mContexts.load(std::memory_order_acquire))
2437 auto *ctx = static_cast<ALCcontext*>(ctxbase);
2438 if(!ctx->mStopVoicesOnDisconnect.load(std::memory_order_acquire))
2439 continue;
2441 /* Clear any pending voice changes and reallocate voices to get a
2442 * clean restart.
2444 std::lock_guard<std::mutex> __{ctx->mSourceLock};
2445 auto *vchg = ctx->mCurrentVoiceChange.load(std::memory_order_acquire);
2446 while(auto *next = vchg->mNext.load(std::memory_order_acquire))
2447 vchg = next;
2448 ctx->mCurrentVoiceChange.store(vchg, std::memory_order_release);
2450 ctx->mVoicePropClusters.clear();
2451 ctx->mFreeVoiceProps.store(nullptr, std::memory_order_relaxed);
2453 ctx->mVoiceClusters.clear();
2454 ctx->allocVoices(std::max<size_t>(256,
2455 ctx->mActiveVoiceCount.load(std::memory_order_relaxed)));
2458 device->Connected.store(true);
2461 ALCenum err{UpdateDeviceParams(device, attrList)};
2462 if(err == ALC_NO_ERROR) [[likely]] return ALC_TRUE;
2464 alcSetError(device, err);
2465 return ALC_FALSE;
2469 /** Checks if the device handle is valid, and returns a new reference if so. */
2470 DeviceRef VerifyDevice(ALCdevice *device)
2472 std::lock_guard<std::recursive_mutex> _{ListLock};
2473 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
2474 if(iter != DeviceList.end() && *iter == device)
2476 (*iter)->add_ref();
2477 return DeviceRef{*iter};
2479 return nullptr;
2484 * Checks if the given context is valid, returning a new reference to it if so.
2486 ContextRef VerifyContext(ALCcontext *context)
2488 std::lock_guard<std::recursive_mutex> _{ListLock};
2489 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
2490 if(iter != ContextList.end() && *iter == context)
2492 (*iter)->add_ref();
2493 return ContextRef{*iter};
2495 return nullptr;
2498 } // namespace
2500 /** Returns a new reference to the currently active context for this thread. */
2501 ContextRef GetContextRef(void)
2503 ALCcontext *context{ALCcontext::getThreadContext()};
2504 if(context)
2505 context->add_ref();
2506 else
2508 while(ALCcontext::sGlobalContextLock.exchange(true, std::memory_order_acquire)) {
2509 /* Wait to make sure another thread isn't trying to change the
2510 * current context and bring its refcount to 0.
2513 context = ALCcontext::sGlobalContext.load(std::memory_order_acquire);
2514 if(context) [[likely]] context->add_ref();
2515 ALCcontext::sGlobalContextLock.store(false, std::memory_order_release);
2517 return ContextRef{context};
2521 /************************************************
2522 * Standard ALC functions
2523 ************************************************/
2525 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2526 START_API_FUNC
2528 DeviceRef dev{VerifyDevice(device)};
2529 if(dev) return dev->LastError.exchange(ALC_NO_ERROR);
2530 return LastNullDeviceError.exchange(ALC_NO_ERROR);
2532 END_API_FUNC
2535 ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2536 START_API_FUNC
2538 if(!SuspendDefers)
2539 return;
2541 ContextRef ctx{VerifyContext(context)};
2542 if(!ctx)
2543 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2544 else
2546 std::lock_guard<std::mutex> _{ctx->mPropLock};
2547 ctx->deferUpdates();
2550 END_API_FUNC
2552 ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context)
2553 START_API_FUNC
2555 if(!SuspendDefers)
2556 return;
2558 ContextRef ctx{VerifyContext(context)};
2559 if(!ctx)
2560 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2561 else
2563 std::lock_guard<std::mutex> _{ctx->mPropLock};
2564 ctx->processUpdates();
2567 END_API_FUNC
2570 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2571 START_API_FUNC
2573 const ALCchar *value{nullptr};
2575 switch(param)
2577 case ALC_NO_ERROR:
2578 value = alcNoError;
2579 break;
2581 case ALC_INVALID_ENUM:
2582 value = alcErrInvalidEnum;
2583 break;
2585 case ALC_INVALID_VALUE:
2586 value = alcErrInvalidValue;
2587 break;
2589 case ALC_INVALID_DEVICE:
2590 value = alcErrInvalidDevice;
2591 break;
2593 case ALC_INVALID_CONTEXT:
2594 value = alcErrInvalidContext;
2595 break;
2597 case ALC_OUT_OF_MEMORY:
2598 value = alcErrOutOfMemory;
2599 break;
2601 case ALC_DEVICE_SPECIFIER:
2602 value = alcDefaultName;
2603 break;
2605 case ALC_ALL_DEVICES_SPECIFIER:
2606 if(DeviceRef dev{VerifyDevice(Device)})
2608 if(dev->Type == DeviceType::Capture)
2609 alcSetError(dev.get(), ALC_INVALID_ENUM);
2610 else if(dev->Type == DeviceType::Loopback)
2611 value = alcDefaultName;
2612 else
2614 std::lock_guard<std::mutex> _{dev->StateLock};
2615 value = dev->DeviceName.c_str();
2618 else
2620 ProbeAllDevicesList();
2621 value = alcAllDevicesList.c_str();
2623 break;
2625 case ALC_CAPTURE_DEVICE_SPECIFIER:
2626 if(DeviceRef dev{VerifyDevice(Device)})
2628 if(dev->Type != DeviceType::Capture)
2629 alcSetError(dev.get(), ALC_INVALID_ENUM);
2630 else
2632 std::lock_guard<std::mutex> _{dev->StateLock};
2633 value = dev->DeviceName.c_str();
2636 else
2638 ProbeCaptureDeviceList();
2639 value = alcCaptureDeviceList.c_str();
2641 break;
2643 /* Default devices are always first in the list */
2644 case ALC_DEFAULT_DEVICE_SPECIFIER:
2645 value = alcDefaultName;
2646 break;
2648 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2649 if(alcAllDevicesList.empty())
2650 ProbeAllDevicesList();
2652 /* Copy first entry as default. */
2653 alcDefaultAllDevicesSpecifier = alcAllDevicesList.c_str();
2654 value = alcDefaultAllDevicesSpecifier.c_str();
2655 break;
2657 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2658 if(alcCaptureDeviceList.empty())
2659 ProbeCaptureDeviceList();
2661 /* Copy first entry as default. */
2662 alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList.c_str();
2663 value = alcCaptureDefaultDeviceSpecifier.c_str();
2664 break;
2666 case ALC_EXTENSIONS:
2667 if(VerifyDevice(Device))
2668 value = alcExtensionList;
2669 else
2670 value = alcNoDeviceExtList;
2671 break;
2673 case ALC_HRTF_SPECIFIER_SOFT:
2674 if(DeviceRef dev{VerifyDevice(Device)})
2676 std::lock_guard<std::mutex> _{dev->StateLock};
2677 value = (dev->mHrtf ? dev->mHrtfName.c_str() : "");
2679 else
2680 alcSetError(nullptr, ALC_INVALID_DEVICE);
2681 break;
2683 default:
2684 alcSetError(VerifyDevice(Device).get(), ALC_INVALID_ENUM);
2685 break;
2688 return value;
2690 END_API_FUNC
2693 static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span<int> values)
2695 size_t i;
2697 if(values.empty())
2699 alcSetError(device, ALC_INVALID_VALUE);
2700 return 0;
2703 if(!device)
2705 switch(param)
2707 case ALC_MAJOR_VERSION:
2708 values[0] = alcMajorVersion;
2709 return 1;
2710 case ALC_MINOR_VERSION:
2711 values[0] = alcMinorVersion;
2712 return 1;
2714 case ALC_EFX_MAJOR_VERSION:
2715 values[0] = alcEFXMajorVersion;
2716 return 1;
2717 case ALC_EFX_MINOR_VERSION:
2718 values[0] = alcEFXMinorVersion;
2719 return 1;
2720 case ALC_MAX_AUXILIARY_SENDS:
2721 values[0] = MAX_SENDS;
2722 return 1;
2724 case ALC_ATTRIBUTES_SIZE:
2725 case ALC_ALL_ATTRIBUTES:
2726 case ALC_FREQUENCY:
2727 case ALC_REFRESH:
2728 case ALC_SYNC:
2729 case ALC_MONO_SOURCES:
2730 case ALC_STEREO_SOURCES:
2731 case ALC_CAPTURE_SAMPLES:
2732 case ALC_FORMAT_CHANNELS_SOFT:
2733 case ALC_FORMAT_TYPE_SOFT:
2734 case ALC_AMBISONIC_LAYOUT_SOFT:
2735 case ALC_AMBISONIC_SCALING_SOFT:
2736 case ALC_AMBISONIC_ORDER_SOFT:
2737 case ALC_MAX_AMBISONIC_ORDER_SOFT:
2738 alcSetError(nullptr, ALC_INVALID_DEVICE);
2739 return 0;
2741 default:
2742 alcSetError(nullptr, ALC_INVALID_ENUM);
2744 return 0;
2747 std::lock_guard<std::mutex> _{device->StateLock};
2748 if(device->Type == DeviceType::Capture)
2750 static constexpr int MaxCaptureAttributes{9};
2751 switch(param)
2753 case ALC_ATTRIBUTES_SIZE:
2754 values[0] = MaxCaptureAttributes;
2755 return 1;
2756 case ALC_ALL_ATTRIBUTES:
2757 i = 0;
2758 if(values.size() < MaxCaptureAttributes)
2759 alcSetError(device, ALC_INVALID_VALUE);
2760 else
2762 values[i++] = ALC_MAJOR_VERSION;
2763 values[i++] = alcMajorVersion;
2764 values[i++] = ALC_MINOR_VERSION;
2765 values[i++] = alcMinorVersion;
2766 values[i++] = ALC_CAPTURE_SAMPLES;
2767 values[i++] = static_cast<int>(device->Backend->availableSamples());
2768 values[i++] = ALC_CONNECTED;
2769 values[i++] = device->Connected.load(std::memory_order_relaxed);
2770 values[i++] = 0;
2771 assert(i == MaxCaptureAttributes);
2773 return i;
2775 case ALC_MAJOR_VERSION:
2776 values[0] = alcMajorVersion;
2777 return 1;
2778 case ALC_MINOR_VERSION:
2779 values[0] = alcMinorVersion;
2780 return 1;
2782 case ALC_CAPTURE_SAMPLES:
2783 values[0] = static_cast<int>(device->Backend->availableSamples());
2784 return 1;
2786 case ALC_CONNECTED:
2787 values[0] = device->Connected.load(std::memory_order_acquire);
2788 return 1;
2790 default:
2791 alcSetError(device, ALC_INVALID_ENUM);
2793 return 0;
2796 /* render device */
2797 auto NumAttrsForDevice = [](ALCdevice *aldev) noexcept
2799 if(aldev->Type == DeviceType::Loopback && aldev->FmtChans == DevFmtAmbi3D)
2800 return 37;
2801 return 31;
2803 switch(param)
2805 case ALC_ATTRIBUTES_SIZE:
2806 values[0] = NumAttrsForDevice(device);
2807 return 1;
2809 case ALC_ALL_ATTRIBUTES:
2810 i = 0;
2811 if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2812 alcSetError(device, ALC_INVALID_VALUE);
2813 else
2815 values[i++] = ALC_MAJOR_VERSION;
2816 values[i++] = alcMajorVersion;
2817 values[i++] = ALC_MINOR_VERSION;
2818 values[i++] = alcMinorVersion;
2819 values[i++] = ALC_EFX_MAJOR_VERSION;
2820 values[i++] = alcEFXMajorVersion;
2821 values[i++] = ALC_EFX_MINOR_VERSION;
2822 values[i++] = alcEFXMinorVersion;
2824 values[i++] = ALC_FREQUENCY;
2825 values[i++] = static_cast<int>(device->Frequency);
2826 if(device->Type != DeviceType::Loopback)
2828 values[i++] = ALC_REFRESH;
2829 values[i++] = static_cast<int>(device->Frequency / device->UpdateSize);
2831 values[i++] = ALC_SYNC;
2832 values[i++] = ALC_FALSE;
2834 else
2836 if(device->FmtChans == DevFmtAmbi3D)
2838 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
2839 values[i++] = EnumFromDevAmbi(device->mAmbiLayout);
2841 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
2842 values[i++] = EnumFromDevAmbi(device->mAmbiScale);
2844 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
2845 values[i++] = static_cast<int>(device->mAmbiOrder);
2848 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2849 values[i++] = EnumFromDevFmt(device->FmtChans);
2851 values[i++] = ALC_FORMAT_TYPE_SOFT;
2852 values[i++] = EnumFromDevFmt(device->FmtType);
2855 values[i++] = ALC_MONO_SOURCES;
2856 values[i++] = static_cast<int>(device->NumMonoSources);
2858 values[i++] = ALC_STEREO_SOURCES;
2859 values[i++] = static_cast<int>(device->NumStereoSources);
2861 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2862 values[i++] = static_cast<int>(device->NumAuxSends);
2864 values[i++] = ALC_HRTF_SOFT;
2865 values[i++] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
2867 values[i++] = ALC_HRTF_STATUS_SOFT;
2868 values[i++] = device->mHrtfStatus;
2870 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
2871 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
2873 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
2874 values[i++] = MaxAmbiOrder;
2876 values[i++] = ALC_OUTPUT_MODE_SOFT;
2877 values[i++] = static_cast<ALCenum>(device->getOutputMode1());
2879 values[i++] = 0;
2881 return i;
2883 case ALC_MAJOR_VERSION:
2884 values[0] = alcMajorVersion;
2885 return 1;
2887 case ALC_MINOR_VERSION:
2888 values[0] = alcMinorVersion;
2889 return 1;
2891 case ALC_EFX_MAJOR_VERSION:
2892 values[0] = alcEFXMajorVersion;
2893 return 1;
2895 case ALC_EFX_MINOR_VERSION:
2896 values[0] = alcEFXMinorVersion;
2897 return 1;
2899 case ALC_FREQUENCY:
2900 values[0] = static_cast<int>(device->Frequency);
2901 return 1;
2903 case ALC_REFRESH:
2904 if(device->Type == DeviceType::Loopback)
2906 alcSetError(device, ALC_INVALID_DEVICE);
2907 return 0;
2909 values[0] = static_cast<int>(device->Frequency / device->UpdateSize);
2910 return 1;
2912 case ALC_SYNC:
2913 if(device->Type == DeviceType::Loopback)
2915 alcSetError(device, ALC_INVALID_DEVICE);
2916 return 0;
2918 values[0] = ALC_FALSE;
2919 return 1;
2921 case ALC_FORMAT_CHANNELS_SOFT:
2922 if(device->Type != DeviceType::Loopback)
2924 alcSetError(device, ALC_INVALID_DEVICE);
2925 return 0;
2927 values[0] = EnumFromDevFmt(device->FmtChans);
2928 return 1;
2930 case ALC_FORMAT_TYPE_SOFT:
2931 if(device->Type != DeviceType::Loopback)
2933 alcSetError(device, ALC_INVALID_DEVICE);
2934 return 0;
2936 values[0] = EnumFromDevFmt(device->FmtType);
2937 return 1;
2939 case ALC_AMBISONIC_LAYOUT_SOFT:
2940 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2942 alcSetError(device, ALC_INVALID_DEVICE);
2943 return 0;
2945 values[0] = EnumFromDevAmbi(device->mAmbiLayout);
2946 return 1;
2948 case ALC_AMBISONIC_SCALING_SOFT:
2949 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2951 alcSetError(device, ALC_INVALID_DEVICE);
2952 return 0;
2954 values[0] = EnumFromDevAmbi(device->mAmbiScale);
2955 return 1;
2957 case ALC_AMBISONIC_ORDER_SOFT:
2958 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2960 alcSetError(device, ALC_INVALID_DEVICE);
2961 return 0;
2963 values[0] = static_cast<int>(device->mAmbiOrder);
2964 return 1;
2966 case ALC_MONO_SOURCES:
2967 values[0] = static_cast<int>(device->NumMonoSources);
2968 return 1;
2970 case ALC_STEREO_SOURCES:
2971 values[0] = static_cast<int>(device->NumStereoSources);
2972 return 1;
2974 case ALC_MAX_AUXILIARY_SENDS:
2975 values[0] = static_cast<int>(device->NumAuxSends);
2976 return 1;
2978 case ALC_CONNECTED:
2979 values[0] = device->Connected.load(std::memory_order_acquire);
2980 return 1;
2982 case ALC_HRTF_SOFT:
2983 values[0] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
2984 return 1;
2986 case ALC_HRTF_STATUS_SOFT:
2987 values[0] = device->mHrtfStatus;
2988 return 1;
2990 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
2991 device->enumerateHrtfs();
2992 values[0] = static_cast<int>(minz(device->mHrtfList.size(),
2993 std::numeric_limits<int>::max()));
2994 return 1;
2996 case ALC_OUTPUT_LIMITER_SOFT:
2997 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
2998 return 1;
3000 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3001 values[0] = MaxAmbiOrder;
3002 return 1;
3004 case ALC_OUTPUT_MODE_SOFT:
3005 values[0] = static_cast<ALCenum>(device->getOutputMode1());
3006 return 1;
3008 default:
3009 alcSetError(device, ALC_INVALID_ENUM);
3011 return 0;
3014 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3015 START_API_FUNC
3017 DeviceRef dev{VerifyDevice(device)};
3018 if(size <= 0 || values == nullptr)
3019 alcSetError(dev.get(), ALC_INVALID_VALUE);
3020 else
3021 GetIntegerv(dev.get(), param, {values, static_cast<uint>(size)});
3023 END_API_FUNC
3025 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3026 START_API_FUNC
3028 DeviceRef dev{VerifyDevice(device)};
3029 if(size <= 0 || values == nullptr)
3031 alcSetError(dev.get(), ALC_INVALID_VALUE);
3032 return;
3034 if(!dev || dev->Type == DeviceType::Capture)
3036 auto ivals = al::vector<int>(static_cast<uint>(size));
3037 if(size_t got{GetIntegerv(dev.get(), pname, ivals)})
3038 std::copy_n(ivals.begin(), got, values);
3039 return;
3041 /* render device */
3042 auto NumAttrsForDevice = [](ALCdevice *aldev) noexcept
3044 if(aldev->Type == DeviceType::Loopback && aldev->FmtChans == DevFmtAmbi3D)
3045 return 41;
3046 return 35;
3048 std::lock_guard<std::mutex> _{dev->StateLock};
3049 switch(pname)
3051 case ALC_ATTRIBUTES_SIZE:
3052 *values = NumAttrsForDevice(dev.get());
3053 break;
3055 case ALC_ALL_ATTRIBUTES:
3056 if(size < NumAttrsForDevice(dev.get()))
3057 alcSetError(dev.get(), ALC_INVALID_VALUE);
3058 else
3060 size_t i{0};
3061 values[i++] = ALC_FREQUENCY;
3062 values[i++] = dev->Frequency;
3064 if(dev->Type != DeviceType::Loopback)
3066 values[i++] = ALC_REFRESH;
3067 values[i++] = dev->Frequency / dev->UpdateSize;
3069 values[i++] = ALC_SYNC;
3070 values[i++] = ALC_FALSE;
3072 else
3074 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3075 values[i++] = EnumFromDevFmt(dev->FmtChans);
3077 values[i++] = ALC_FORMAT_TYPE_SOFT;
3078 values[i++] = EnumFromDevFmt(dev->FmtType);
3080 if(dev->FmtChans == DevFmtAmbi3D)
3082 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3083 values[i++] = EnumFromDevAmbi(dev->mAmbiLayout);
3085 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3086 values[i++] = EnumFromDevAmbi(dev->mAmbiScale);
3088 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3089 values[i++] = dev->mAmbiOrder;
3093 values[i++] = ALC_MONO_SOURCES;
3094 values[i++] = dev->NumMonoSources;
3096 values[i++] = ALC_STEREO_SOURCES;
3097 values[i++] = dev->NumStereoSources;
3099 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3100 values[i++] = dev->NumAuxSends;
3102 values[i++] = ALC_HRTF_SOFT;
3103 values[i++] = (dev->mHrtf ? ALC_TRUE : ALC_FALSE);
3105 values[i++] = ALC_HRTF_STATUS_SOFT;
3106 values[i++] = dev->mHrtfStatus;
3108 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3109 values[i++] = dev->Limiter ? ALC_TRUE : ALC_FALSE;
3111 ClockLatency clock{GetClockLatency(dev.get(), dev->Backend.get())};
3112 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3113 values[i++] = clock.ClockTime.count();
3115 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3116 values[i++] = clock.Latency.count();
3118 values[i++] = ALC_OUTPUT_MODE_SOFT;
3119 values[i++] = static_cast<ALCenum>(device->getOutputMode1());
3121 values[i++] = 0;
3123 break;
3125 case ALC_DEVICE_CLOCK_SOFT:
3127 uint samplecount, refcount;
3128 nanoseconds basecount;
3129 do {
3130 refcount = dev->waitForMix();
3131 basecount = dev->ClockBase;
3132 samplecount = dev->SamplesDone;
3133 } while(refcount != ReadRef(dev->MixCount));
3134 basecount += nanoseconds{seconds{samplecount}} / dev->Frequency;
3135 *values = basecount.count();
3137 break;
3139 case ALC_DEVICE_LATENCY_SOFT:
3140 *values = GetClockLatency(dev.get(), dev->Backend.get()).Latency.count();
3141 break;
3143 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3144 if(size < 2)
3145 alcSetError(dev.get(), ALC_INVALID_VALUE);
3146 else
3148 ClockLatency clock{GetClockLatency(dev.get(), dev->Backend.get())};
3149 values[0] = clock.ClockTime.count();
3150 values[1] = clock.Latency.count();
3152 break;
3154 default:
3155 auto ivals = al::vector<int>(static_cast<uint>(size));
3156 if(size_t got{GetIntegerv(dev.get(), pname, ivals)})
3157 std::copy_n(ivals.begin(), got, values);
3158 break;
3161 END_API_FUNC
3164 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3165 START_API_FUNC
3167 DeviceRef dev{VerifyDevice(device)};
3168 if(!extName)
3169 alcSetError(dev.get(), ALC_INVALID_VALUE);
3170 else
3172 size_t len = strlen(extName);
3173 const char *ptr = (dev ? alcExtensionList : alcNoDeviceExtList);
3174 while(ptr && *ptr)
3176 if(al::strncasecmp(ptr, extName, len) == 0 && (ptr[len] == '\0' || isspace(ptr[len])))
3177 return ALC_TRUE;
3179 if((ptr=strchr(ptr, ' ')) != nullptr)
3181 do {
3182 ++ptr;
3183 } while(isspace(*ptr));
3187 return ALC_FALSE;
3189 END_API_FUNC
3192 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3193 START_API_FUNC
3195 if(!funcName)
3197 DeviceRef dev{VerifyDevice(device)};
3198 alcSetError(dev.get(), ALC_INVALID_VALUE);
3199 return nullptr;
3201 #ifdef ALSOFT_EAX
3202 if(eax_g_is_enabled)
3204 for(const auto &func : eaxFunctions)
3206 if(strcmp(func.funcName, funcName) == 0)
3207 return func.address;
3210 #endif
3211 for(const auto &func : alcFunctions)
3213 if(strcmp(func.funcName, funcName) == 0)
3214 return func.address;
3216 return nullptr;
3218 END_API_FUNC
3221 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3222 START_API_FUNC
3224 if(!enumName)
3226 DeviceRef dev{VerifyDevice(device)};
3227 alcSetError(dev.get(), ALC_INVALID_VALUE);
3228 return 0;
3230 #ifdef ALSOFT_EAX
3231 if(eax_g_is_enabled)
3233 for(const auto &enm : eaxEnumerations)
3235 if(strcmp(enm.enumName, enumName) == 0)
3236 return enm.value;
3239 #endif
3240 for(const auto &enm : alcEnumerations)
3242 if(strcmp(enm.enumName, enumName) == 0)
3243 return enm.value;
3246 return 0;
3248 END_API_FUNC
3251 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3252 START_API_FUNC
3254 /* Explicitly hold the list lock while taking the StateLock in case the
3255 * device is asynchronously destroyed, to ensure this new context is
3256 * properly cleaned up after being made.
3258 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3259 DeviceRef dev{VerifyDevice(device)};
3260 if(!dev || dev->Type == DeviceType::Capture || !dev->Connected.load(std::memory_order_relaxed))
3262 listlock.unlock();
3263 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3264 return nullptr;
3266 std::unique_lock<std::mutex> statelock{dev->StateLock};
3267 listlock.unlock();
3269 dev->LastError.store(ALC_NO_ERROR);
3271 ALCenum err{UpdateDeviceParams(dev.get(), attrList)};
3272 if(err != ALC_NO_ERROR)
3274 alcSetError(dev.get(), err);
3275 return nullptr;
3278 ContextRef context{new ALCcontext{dev}};
3279 context->init();
3281 if(auto volopt = dev->configValue<float>(nullptr, "volume-adjust"))
3283 const float valf{*volopt};
3284 if(!std::isfinite(valf))
3285 ERR("volume-adjust must be finite: %f\n", valf);
3286 else
3288 const float db{clampf(valf, -24.0f, 24.0f)};
3289 if(db != valf)
3290 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3291 context->mGainBoost = std::pow(10.0f, db/20.0f);
3292 TRACE("volume-adjust gain: %f\n", context->mGainBoost);
3297 using ContextArray = al::FlexArray<ContextBase*>;
3299 /* Allocate a new context array, which holds 1 more than the current/
3300 * old array.
3302 auto *oldarray = device->mContexts.load();
3303 const size_t newcount{oldarray->size()+1};
3304 std::unique_ptr<ContextArray> newarray{ContextArray::Create(newcount)};
3306 /* Copy the current/old context handles to the new array, appending the
3307 * new context.
3309 auto iter = std::copy(oldarray->begin(), oldarray->end(), newarray->begin());
3310 *iter = context.get();
3312 /* Store the new context array in the device. Wait for any current mix
3313 * to finish before deleting the old array.
3315 dev->mContexts.store(newarray.release());
3316 if(oldarray != &DeviceBase::sEmptyContextArray)
3318 dev->waitForMix();
3319 delete oldarray;
3322 statelock.unlock();
3325 std::lock_guard<std::recursive_mutex> _{ListLock};
3326 auto iter = std::lower_bound(ContextList.cbegin(), ContextList.cend(), context.get());
3327 ContextList.emplace(iter, context.get());
3330 if(ALeffectslot *slot{context->mDefaultSlot.get()})
3332 ALenum sloterr{slot->initEffect(ALCcontext::sDefaultEffect.type,
3333 ALCcontext::sDefaultEffect.Props, context.get())};
3334 if(sloterr == AL_NO_ERROR)
3335 slot->updateProps(context.get());
3336 else
3337 ERR("Failed to initialize the default effect\n");
3340 TRACE("Created context %p\n", voidp{context.get()});
3341 return context.release();
3343 END_API_FUNC
3345 ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3346 START_API_FUNC
3348 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3349 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
3350 if(iter == ContextList.end() || *iter != context)
3352 listlock.unlock();
3353 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3354 return;
3357 /* Hold a reference to this context so it remains valid until the ListLock
3358 * is released.
3360 ContextRef ctx{*iter};
3361 ContextList.erase(iter);
3363 ALCdevice *Device{ctx->mALDevice.get()};
3365 std::lock_guard<std::mutex> _{Device->StateLock};
3366 if(!ctx->deinit() && Device->Flags.test(DeviceRunning))
3368 Device->Backend->stop();
3369 Device->Flags.reset(DeviceRunning);
3372 END_API_FUNC
3375 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3376 START_API_FUNC
3378 ALCcontext *Context{ALCcontext::getThreadContext()};
3379 if(!Context) Context = ALCcontext::sGlobalContext.load();
3380 return Context;
3382 END_API_FUNC
3384 /** Returns the currently active thread-local context. */
3385 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3386 START_API_FUNC
3387 { return ALCcontext::getThreadContext(); }
3388 END_API_FUNC
3390 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3391 START_API_FUNC
3393 /* context must be valid or nullptr */
3394 ContextRef ctx;
3395 if(context)
3397 ctx = VerifyContext(context);
3398 if(!ctx)
3400 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3401 return ALC_FALSE;
3404 /* Release this reference (if any) to store it in the GlobalContext
3405 * pointer. Take ownership of the reference (if any) that was previously
3406 * stored there, and let the reference go.
3408 while(ALCcontext::sGlobalContextLock.exchange(true, std::memory_order_acquire)) {
3409 /* Wait to make sure another thread isn't getting or trying to change
3410 * the current context as its refcount is decremented.
3413 ContextRef{ALCcontext::sGlobalContext.exchange(ctx.release())};
3414 ALCcontext::sGlobalContextLock.store(false, std::memory_order_release);
3416 /* Take ownership of the thread-local context reference (if any), clearing
3417 * the storage to null.
3419 ctx = ContextRef{ALCcontext::getThreadContext()};
3420 if(ctx) ALCcontext::setThreadContext(nullptr);
3421 /* Reset (decrement) the previous thread-local reference. */
3423 return ALC_TRUE;
3425 END_API_FUNC
3427 /** Makes the given context the active context for the current thread. */
3428 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3429 START_API_FUNC
3431 /* context must be valid or nullptr */
3432 ContextRef ctx;
3433 if(context)
3435 ctx = VerifyContext(context);
3436 if(!ctx)
3438 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3439 return ALC_FALSE;
3442 /* context's reference count is already incremented */
3443 ContextRef old{ALCcontext::getThreadContext()};
3444 ALCcontext::setThreadContext(ctx.release());
3446 return ALC_TRUE;
3448 END_API_FUNC
3451 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3452 START_API_FUNC
3454 ContextRef ctx{VerifyContext(Context)};
3455 if(!ctx)
3457 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3458 return nullptr;
3460 return ctx->mALDevice.get();
3462 END_API_FUNC
3465 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3466 START_API_FUNC
3468 InitConfig();
3470 if(!PlaybackFactory)
3472 alcSetError(nullptr, ALC_INVALID_VALUE);
3473 return nullptr;
3476 if(deviceName)
3478 TRACE("Opening playback device \"%s\"\n", deviceName);
3479 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3480 #ifdef _WIN32
3481 /* Some old Windows apps hardcode these expecting OpenAL to use a
3482 * specific audio API, even when they're not enumerated. Creative's
3483 * router effectively ignores them too.
3485 || al::strcasecmp(deviceName, "DirectSound3D") == 0
3486 || al::strcasecmp(deviceName, "DirectSound") == 0
3487 || al::strcasecmp(deviceName, "MMSYSTEM") == 0
3488 #endif
3489 /* Some old Linux apps hardcode configuration strings that were
3490 * supported by the OpenAL SI. We can't really do anything useful
3491 * with them, so just ignore.
3493 || (deviceName[0] == '\'' && deviceName[1] == '(')
3494 || al::strcasecmp(deviceName, "openal-soft") == 0)
3495 deviceName = nullptr;
3497 else
3498 TRACE("Opening default playback device\n");
3500 const uint DefaultSends{
3501 #ifdef ALSOFT_EAX
3502 eax_g_is_enabled ? uint{EAX_MAX_FXSLOTS} :
3503 #endif // ALSOFT_EAX
3504 DEFAULT_SENDS
3507 DeviceRef device{new ALCdevice{DeviceType::Playback}};
3509 /* Set output format */
3510 device->FmtChans = DevFmtChannelsDefault;
3511 device->FmtType = DevFmtTypeDefault;
3512 device->Frequency = DEFAULT_OUTPUT_RATE;
3513 device->UpdateSize = DEFAULT_UPDATE_SIZE;
3514 device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
3516 device->SourcesMax = 256;
3517 device->NumStereoSources = 1;
3518 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3519 device->AuxiliaryEffectSlotMax = 64;
3520 device->NumAuxSends = DefaultSends;
3522 try {
3523 auto backend = PlaybackFactory->createBackend(device.get(), BackendType::Playback);
3524 std::lock_guard<std::recursive_mutex> _{ListLock};
3525 backend->open(deviceName);
3526 device->Backend = std::move(backend);
3528 catch(al::backend_exception &e) {
3529 WARN("Failed to open playback device: %s\n", e.what());
3530 alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory)
3531 ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
3532 return nullptr;
3536 std::lock_guard<std::recursive_mutex> _{ListLock};
3537 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3538 DeviceList.emplace(iter, device.get());
3541 TRACE("Created device %p, \"%s\"\n", voidp{device.get()}, device->DeviceName.c_str());
3542 return device.release();
3544 END_API_FUNC
3546 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3547 START_API_FUNC
3549 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3550 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3551 if(iter == DeviceList.end() || *iter != device)
3553 alcSetError(nullptr, ALC_INVALID_DEVICE);
3554 return ALC_FALSE;
3556 if((*iter)->Type == DeviceType::Capture)
3558 alcSetError(*iter, ALC_INVALID_DEVICE);
3559 return ALC_FALSE;
3562 /* Erase the device, and any remaining contexts left on it, from their
3563 * respective lists.
3565 DeviceRef dev{*iter};
3566 DeviceList.erase(iter);
3568 std::unique_lock<std::mutex> statelock{dev->StateLock};
3569 al::vector<ContextRef> orphanctxs;
3570 for(ContextBase *ctx : *dev->mContexts.load())
3572 auto ctxiter = std::lower_bound(ContextList.begin(), ContextList.end(), ctx);
3573 if(ctxiter != ContextList.end() && *ctxiter == ctx)
3575 orphanctxs.emplace_back(ContextRef{*ctxiter});
3576 ContextList.erase(ctxiter);
3579 listlock.unlock();
3581 for(ContextRef &context : orphanctxs)
3583 WARN("Releasing orphaned context %p\n", voidp{context.get()});
3584 context->deinit();
3586 orphanctxs.clear();
3588 if(dev->Flags.test(DeviceRunning))
3589 dev->Backend->stop();
3590 dev->Flags.reset(DeviceRunning);
3592 return ALC_TRUE;
3594 END_API_FUNC
3597 /************************************************
3598 * ALC capture functions
3599 ************************************************/
3600 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3601 START_API_FUNC
3603 InitConfig();
3605 if(!CaptureFactory)
3607 alcSetError(nullptr, ALC_INVALID_VALUE);
3608 return nullptr;
3611 if(samples <= 0)
3613 alcSetError(nullptr, ALC_INVALID_VALUE);
3614 return nullptr;
3617 if(deviceName)
3619 TRACE("Opening capture device \"%s\"\n", deviceName);
3620 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3621 || al::strcasecmp(deviceName, "openal-soft") == 0)
3622 deviceName = nullptr;
3624 else
3625 TRACE("Opening default capture device\n");
3627 DeviceRef device{new ALCdevice{DeviceType::Capture}};
3629 auto decompfmt = DecomposeDevFormat(format);
3630 if(!decompfmt)
3632 alcSetError(nullptr, ALC_INVALID_ENUM);
3633 return nullptr;
3636 device->Frequency = frequency;
3637 device->FmtChans = decompfmt->chans;
3638 device->FmtType = decompfmt->type;
3639 device->Flags.set(FrequencyRequest);
3640 device->Flags.set(ChannelsRequest);
3641 device->Flags.set(SampleTypeRequest);
3643 device->UpdateSize = static_cast<uint>(samples);
3644 device->BufferSize = static_cast<uint>(samples);
3646 try {
3647 TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n",
3648 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
3649 device->Frequency, device->UpdateSize, device->BufferSize);
3651 auto backend = CaptureFactory->createBackend(device.get(), BackendType::Capture);
3652 std::lock_guard<std::recursive_mutex> _{ListLock};
3653 backend->open(deviceName);
3654 device->Backend = std::move(backend);
3656 catch(al::backend_exception &e) {
3657 WARN("Failed to open capture device: %s\n", e.what());
3658 alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory)
3659 ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
3660 return nullptr;
3664 std::lock_guard<std::recursive_mutex> _{ListLock};
3665 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3666 DeviceList.emplace(iter, device.get());
3669 TRACE("Created capture device %p, \"%s\"\n", voidp{device.get()}, device->DeviceName.c_str());
3670 return device.release();
3672 END_API_FUNC
3674 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3675 START_API_FUNC
3677 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3678 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3679 if(iter == DeviceList.end() || *iter != device)
3681 alcSetError(nullptr, ALC_INVALID_DEVICE);
3682 return ALC_FALSE;
3684 if((*iter)->Type != DeviceType::Capture)
3686 alcSetError(*iter, ALC_INVALID_DEVICE);
3687 return ALC_FALSE;
3690 DeviceRef dev{*iter};
3691 DeviceList.erase(iter);
3692 listlock.unlock();
3694 std::lock_guard<std::mutex> _{dev->StateLock};
3695 if(dev->Flags.test(DeviceRunning))
3696 dev->Backend->stop();
3697 dev->Flags.reset(DeviceRunning);
3699 return ALC_TRUE;
3701 END_API_FUNC
3703 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3704 START_API_FUNC
3706 DeviceRef dev{VerifyDevice(device)};
3707 if(!dev || dev->Type != DeviceType::Capture)
3709 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3710 return;
3713 std::lock_guard<std::mutex> _{dev->StateLock};
3714 if(!dev->Connected.load(std::memory_order_acquire))
3715 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3716 else if(!dev->Flags.test(DeviceRunning))
3718 try {
3719 auto backend = dev->Backend.get();
3720 backend->start();
3721 dev->Flags.set(DeviceRunning);
3723 catch(al::backend_exception& e) {
3724 ERR("%s\n", e.what());
3725 dev->handleDisconnect("%s", e.what());
3726 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3730 END_API_FUNC
3732 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3733 START_API_FUNC
3735 DeviceRef dev{VerifyDevice(device)};
3736 if(!dev || dev->Type != DeviceType::Capture)
3737 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3738 else
3740 std::lock_guard<std::mutex> _{dev->StateLock};
3741 if(dev->Flags.test(DeviceRunning))
3742 dev->Backend->stop();
3743 dev->Flags.reset(DeviceRunning);
3746 END_API_FUNC
3748 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3749 START_API_FUNC
3751 DeviceRef dev{VerifyDevice(device)};
3752 if(!dev || dev->Type != DeviceType::Capture)
3754 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3755 return;
3758 if(samples < 0 || (samples > 0 && buffer == nullptr))
3760 alcSetError(dev.get(), ALC_INVALID_VALUE);
3761 return;
3763 if(samples < 1)
3764 return;
3766 std::lock_guard<std::mutex> _{dev->StateLock};
3767 BackendBase *backend{dev->Backend.get()};
3769 const auto usamples = static_cast<uint>(samples);
3770 if(usamples > backend->availableSamples())
3772 alcSetError(dev.get(), ALC_INVALID_VALUE);
3773 return;
3776 backend->captureSamples(static_cast<al::byte*>(buffer), usamples);
3778 END_API_FUNC
3781 /************************************************
3782 * ALC loopback functions
3783 ************************************************/
3785 /** Open a loopback device, for manual rendering. */
3786 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3787 START_API_FUNC
3789 InitConfig();
3791 /* Make sure the device name, if specified, is us. */
3792 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3794 alcSetError(nullptr, ALC_INVALID_VALUE);
3795 return nullptr;
3798 const uint DefaultSends{
3799 #ifdef ALSOFT_EAX
3800 eax_g_is_enabled ? uint{EAX_MAX_FXSLOTS} :
3801 #endif // ALSOFT_EAX
3802 DEFAULT_SENDS
3805 DeviceRef device{new ALCdevice{DeviceType::Loopback}};
3807 device->SourcesMax = 256;
3808 device->AuxiliaryEffectSlotMax = 64;
3809 device->NumAuxSends = DefaultSends;
3811 //Set output format
3812 device->BufferSize = 0;
3813 device->UpdateSize = 0;
3815 device->Frequency = DEFAULT_OUTPUT_RATE;
3816 device->FmtChans = DevFmtChannelsDefault;
3817 device->FmtType = DevFmtTypeDefault;
3819 device->NumStereoSources = 1;
3820 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3822 try {
3823 auto backend = LoopbackBackendFactory::getFactory().createBackend(device.get(),
3824 BackendType::Playback);
3825 backend->open("Loopback");
3826 device->Backend = std::move(backend);
3828 catch(al::backend_exception &e) {
3829 WARN("Failed to open loopback device: %s\n", e.what());
3830 alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory)
3831 ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
3832 return nullptr;
3836 std::lock_guard<std::recursive_mutex> _{ListLock};
3837 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3838 DeviceList.emplace(iter, device.get());
3841 TRACE("Created loopback device %p\n", voidp{device.get()});
3842 return device.release();
3844 END_API_FUNC
3847 * Determines if the loopback device supports the given format for rendering.
3849 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3850 START_API_FUNC
3852 DeviceRef dev{VerifyDevice(device)};
3853 if(!dev || dev->Type != DeviceType::Loopback)
3854 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3855 else if(freq <= 0)
3856 alcSetError(dev.get(), ALC_INVALID_VALUE);
3857 else
3859 if(DevFmtTypeFromEnum(type).has_value() && DevFmtChannelsFromEnum(channels).has_value()
3860 && freq >= MIN_OUTPUT_RATE && freq <= MAX_OUTPUT_RATE)
3861 return ALC_TRUE;
3864 return ALC_FALSE;
3866 END_API_FUNC
3869 * Renders some samples into a buffer, using the format last set by the
3870 * attributes given to alcCreateContext.
3872 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3873 START_API_FUNC
3875 if(!device || device->Type != DeviceType::Loopback)
3876 alcSetError(device, ALC_INVALID_DEVICE);
3877 else if(samples < 0 || (samples > 0 && buffer == nullptr))
3878 alcSetError(device, ALC_INVALID_VALUE);
3879 else
3880 device->renderSamples(buffer, static_cast<uint>(samples), device->channelsFromFmt());
3882 END_API_FUNC
3885 /************************************************
3886 * ALC DSP pause/resume functions
3887 ************************************************/
3889 /** Pause the DSP to stop audio processing. */
3890 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
3891 START_API_FUNC
3893 DeviceRef dev{VerifyDevice(device)};
3894 if(!dev || dev->Type != DeviceType::Playback)
3895 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3896 else
3898 std::lock_guard<std::mutex> _{dev->StateLock};
3899 if(dev->Flags.test(DeviceRunning))
3900 dev->Backend->stop();
3901 dev->Flags.reset(DeviceRunning);
3902 dev->Flags.set(DevicePaused);
3905 END_API_FUNC
3907 /** Resume the DSP to restart audio processing. */
3908 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
3909 START_API_FUNC
3911 DeviceRef dev{VerifyDevice(device)};
3912 if(!dev || dev->Type != DeviceType::Playback)
3914 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3915 return;
3918 std::lock_guard<std::mutex> _{dev->StateLock};
3919 if(!dev->Flags.test(DevicePaused))
3920 return;
3921 dev->Flags.reset(DevicePaused);
3922 if(dev->mContexts.load()->empty())
3923 return;
3925 try {
3926 auto backend = dev->Backend.get();
3927 backend->start();
3928 dev->Flags.set(DeviceRunning);
3930 catch(al::backend_exception& e) {
3931 ERR("%s\n", e.what());
3932 dev->handleDisconnect("%s", e.what());
3933 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3934 return;
3936 TRACE("Post-resume: %s, %s, %uhz, %u / %u buffer\n",
3937 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
3938 device->Frequency, device->UpdateSize, device->BufferSize);
3940 END_API_FUNC
3943 /************************************************
3944 * ALC HRTF functions
3945 ************************************************/
3947 /** Gets a string parameter at the given index. */
3948 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
3949 START_API_FUNC
3951 DeviceRef dev{VerifyDevice(device)};
3952 if(!dev || dev->Type == DeviceType::Capture)
3953 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3954 else switch(paramName)
3956 case ALC_HRTF_SPECIFIER_SOFT:
3957 if(index >= 0 && static_cast<uint>(index) < dev->mHrtfList.size())
3958 return dev->mHrtfList[static_cast<uint>(index)].c_str();
3959 alcSetError(dev.get(), ALC_INVALID_VALUE);
3960 break;
3962 default:
3963 alcSetError(dev.get(), ALC_INVALID_ENUM);
3964 break;
3967 return nullptr;
3969 END_API_FUNC
3971 /** Resets the given device output, using the specified attribute list. */
3972 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
3973 START_API_FUNC
3975 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3976 DeviceRef dev{VerifyDevice(device)};
3977 if(!dev || dev->Type == DeviceType::Capture)
3979 listlock.unlock();
3980 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3981 return ALC_FALSE;
3983 std::lock_guard<std::mutex> _{dev->StateLock};
3984 listlock.unlock();
3986 /* Force the backend to stop mixing first since we're resetting. Also reset
3987 * the connected state so lost devices can attempt recover.
3989 if(dev->Flags.test(DeviceRunning))
3990 dev->Backend->stop();
3991 dev->Flags.reset(DeviceRunning);
3993 return ResetDeviceParams(dev.get(), attribs) ? ALC_TRUE : ALC_FALSE;
3995 END_API_FUNC
3998 /************************************************
3999 * ALC device reopen functions
4000 ************************************************/
4002 /** Reopens the given device output, using the specified name and attribute list. */
4003 FORCE_ALIGN ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device,
4004 const ALCchar *deviceName, const ALCint *attribs)
4005 START_API_FUNC
4007 if(deviceName)
4009 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0)
4010 deviceName = nullptr;
4013 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4014 DeviceRef dev{VerifyDevice(device)};
4015 if(!dev || dev->Type != DeviceType::Playback)
4017 listlock.unlock();
4018 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4019 return ALC_FALSE;
4021 std::lock_guard<std::mutex> _{dev->StateLock};
4023 /* Force the backend to stop mixing first since we're reopening. */
4024 if(dev->Flags.test(DeviceRunning))
4026 auto backend = dev->Backend.get();
4027 backend->stop();
4028 dev->Flags.reset(DeviceRunning);
4031 BackendPtr newbackend;
4032 try {
4033 newbackend = PlaybackFactory->createBackend(dev.get(), BackendType::Playback);
4034 newbackend->open(deviceName);
4036 catch(al::backend_exception &e) {
4037 listlock.unlock();
4038 newbackend = nullptr;
4040 WARN("Failed to reopen playback device: %s\n", e.what());
4041 alcSetError(dev.get(), (e.errorCode() == al::backend_error::OutOfMemory)
4042 ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
4044 /* If the device is connected, not paused, and has contexts, ensure it
4045 * continues playing.
4047 if(dev->Connected.load(std::memory_order_relaxed) && !dev->Flags.test(DevicePaused)
4048 && !dev->mContexts.load(std::memory_order_relaxed)->empty())
4050 try {
4051 auto backend = dev->Backend.get();
4052 backend->start();
4053 dev->Flags.set(DeviceRunning);
4055 catch(al::backend_exception &be) {
4056 ERR("%s\n", be.what());
4057 dev->handleDisconnect("%s", be.what());
4060 return ALC_FALSE;
4062 listlock.unlock();
4063 dev->Backend = std::move(newbackend);
4064 TRACE("Reopened device %p, \"%s\"\n", voidp{dev.get()}, dev->DeviceName.c_str());
4066 /* Always return true even if resetting fails. It shouldn't fail, but this
4067 * is primarily to avoid confusion by the app seeing the function return
4068 * false while the device is on the new output anyway. We could try to
4069 * restore the old backend if this fails, but the configuration would be
4070 * changed with the new backend and would need to be reset again with the
4071 * old one, and the provided attributes may not be appropriate or desirable
4072 * for the old device.
4074 * In this way, we essentially act as if the function succeeded, but
4075 * immediately disconnects following it.
4077 ResetDeviceParams(dev.get(), attribs);
4078 return ALC_TRUE;
4080 END_API_FUNC