Better handle negative sample rate values
[openal-soft.git] / alc / alc.cpp
blobcf510ab47b318dfcb98077994a3b89bc4915fbfa
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);
1779 if(auto encopt = device->configValue<std::string>(nullptr, "stereo-encoding"))
1781 const char *mode{encopt->c_str()};
1782 if(al::strcasecmp(mode, "basic") == 0 || al::strcasecmp(mode, "panpot") == 0)
1783 stereomode = StereoEncoding::Basic;
1784 else if(al::strcasecmp(mode, "uhj") == 0)
1785 stereomode = StereoEncoding::Uhj;
1786 else if(al::strcasecmp(mode, "hrtf") == 0)
1787 stereomode = StereoEncoding::Hrtf;
1788 else
1789 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)
1906 stereomode = *opthrtf ? StereoEncoding::Hrtf : StereoEncoding::Default;
1908 if(outmode == ALC_STEREO_BASIC_SOFT)
1909 stereomode = StereoEncoding::Basic;
1910 else if(outmode == ALC_STEREO_UHJ_SOFT)
1911 stereomode = StereoEncoding::Uhj;
1912 else if(outmode == ALC_STEREO_HRTF_SOFT)
1913 stereomode = StereoEncoding::Hrtf;
1916 optsrate = static_cast<uint>(freqAttr);
1918 else
1920 if(outmode != ALC_ANY_SOFT)
1922 using OutputMode = ALCdevice::OutputMode;
1923 switch(OutputMode(outmode))
1925 case OutputMode::Any: break;
1926 case OutputMode::Mono: optchans = DevFmtMono; break;
1927 case OutputMode::Stereo: optchans = DevFmtStereo; break;
1928 case OutputMode::StereoBasic:
1929 optchans = DevFmtStereo;
1930 stereomode = StereoEncoding::Basic;
1931 break;
1932 case OutputMode::Uhj2:
1933 optchans = DevFmtStereo;
1934 stereomode = StereoEncoding::Uhj;
1935 break;
1936 case OutputMode::Hrtf:
1937 optchans = DevFmtStereo;
1938 stereomode = StereoEncoding::Hrtf;
1939 break;
1940 case OutputMode::Quad: optchans = DevFmtQuad; break;
1941 case OutputMode::X51: optchans = DevFmtX51; break;
1942 case OutputMode::X61: optchans = DevFmtX61; break;
1943 case OutputMode::X71: optchans = DevFmtX71; break;
1947 if(freqAttr)
1949 uint oldrate = optsrate.value_or(DEFAULT_OUTPUT_RATE);
1950 freqAttr = clampi(freqAttr, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE);
1952 const double scale{static_cast<double>(freqAttr) / oldrate};
1953 period_size = static_cast<uint>(period_size*scale + 0.5);
1954 buffer_size = static_cast<uint>(buffer_size*scale + 0.5);
1955 optsrate = static_cast<uint>(freqAttr);
1959 /* If a context is already running on the device, stop playback so the
1960 * device attributes can be updated.
1962 if(device->Flags.test(DeviceRunning))
1963 device->Backend->stop();
1964 device->Flags.reset(DeviceRunning);
1966 UpdateClockBase(device);
1969 if(device->Flags.test(DeviceRunning))
1970 return ALC_NO_ERROR;
1972 device->AvgSpeakerDist = 0.0f;
1973 device->mNFCtrlFilter = NfcFilter{};
1974 device->mUhjEncoder = nullptr;
1975 device->AmbiDecoder = nullptr;
1976 device->Bs2b = nullptr;
1977 device->PostProcess = nullptr;
1979 device->Limiter = nullptr;
1980 device->ChannelDelays = nullptr;
1982 std::fill(std::begin(device->HrtfAccumData), std::end(device->HrtfAccumData), float2{});
1984 device->Dry.AmbiMap.fill(BFChannelConfig{});
1985 device->Dry.Buffer = {};
1986 std::fill(std::begin(device->NumChannelsPerOrder), std::end(device->NumChannelsPerOrder), 0u);
1987 device->RealOut.RemixMap = {};
1988 device->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
1989 device->RealOut.Buffer = {};
1990 device->MixBuffer.clear();
1991 device->MixBuffer.shrink_to_fit();
1993 UpdateClockBase(device);
1994 device->FixedLatency = nanoseconds::zero();
1996 device->DitherDepth = 0.0f;
1997 device->DitherSeed = DitherRNGSeed;
1999 device->mHrtfStatus = ALC_HRTF_DISABLED_SOFT;
2001 /*************************************************************************
2002 * Update device format request
2005 if(device->Type == DeviceType::Loopback)
2007 device->Frequency = *optsrate;
2008 device->FmtChans = *optchans;
2009 device->FmtType = *opttype;
2010 if(device->FmtChans == DevFmtAmbi3D)
2012 device->mAmbiOrder = aorder;
2013 device->mAmbiLayout = *optlayout;
2014 device->mAmbiScale = *optscale;
2016 device->Flags.set(FrequencyRequest).set(ChannelsRequest).set(SampleTypeRequest);
2018 else
2020 device->FmtType = opttype.value_or(DevFmtTypeDefault);
2021 device->FmtChans = optchans.value_or(DevFmtChannelsDefault);
2022 device->mAmbiOrder = 0;
2023 device->BufferSize = buffer_size;
2024 device->UpdateSize = period_size;
2025 device->Frequency = optsrate.value_or(DEFAULT_OUTPUT_RATE);
2026 device->Flags.set(FrequencyRequest, optsrate.has_value())
2027 .set(ChannelsRequest, optchans.has_value())
2028 .set(SampleTypeRequest, opttype.has_value());
2030 if(device->FmtChans == DevFmtAmbi3D)
2032 device->mAmbiOrder = clampu(aorder, 1, MaxAmbiOrder);
2033 device->mAmbiLayout = optlayout.value_or(DevAmbiLayout::Default);
2034 device->mAmbiScale = optscale.value_or(DevAmbiScaling::Default);
2035 if(device->mAmbiOrder > 3
2036 && (device->mAmbiLayout == DevAmbiLayout::FuMa
2037 || device->mAmbiScale == DevAmbiScaling::FuMa))
2039 ERR("FuMa is incompatible with %d%s order ambisonics (up to 3rd order only)\n",
2040 device->mAmbiOrder,
2041 (((device->mAmbiOrder%100)/10) == 1) ? "th" :
2042 ((device->mAmbiOrder%10) == 1) ? "st" :
2043 ((device->mAmbiOrder%10) == 2) ? "nd" :
2044 ((device->mAmbiOrder%10) == 3) ? "rd" : "th");
2045 device->mAmbiOrder = 3;
2050 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u / %u buffer\n",
2051 device->Flags.test(ChannelsRequest)?"*":"", DevFmtChannelsString(device->FmtChans),
2052 device->Flags.test(SampleTypeRequest)?"*":"", DevFmtTypeString(device->FmtType),
2053 device->Flags.test(FrequencyRequest)?"*":"", device->Frequency,
2054 device->UpdateSize, device->BufferSize);
2056 const uint oldFreq{device->Frequency};
2057 const DevFmtChannels oldChans{device->FmtChans};
2058 const DevFmtType oldType{device->FmtType};
2059 try {
2060 auto backend = device->Backend.get();
2061 if(!backend->reset())
2062 throw al::backend_exception{al::backend_error::DeviceError, "Device reset failure"};
2064 catch(std::exception &e) {
2065 ERR("Device error: %s\n", e.what());
2066 device->handleDisconnect("%s", e.what());
2067 return ALC_INVALID_DEVICE;
2070 if(device->FmtChans != oldChans && device->Flags.test(ChannelsRequest))
2072 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2073 DevFmtChannelsString(device->FmtChans));
2074 device->Flags.reset(ChannelsRequest);
2076 if(device->FmtType != oldType && device->Flags.test(SampleTypeRequest))
2078 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2079 DevFmtTypeString(device->FmtType));
2080 device->Flags.reset(SampleTypeRequest);
2082 if(device->Frequency != oldFreq && device->Flags.test(FrequencyRequest))
2084 WARN("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2085 device->Flags.reset(FrequencyRequest);
2088 TRACE("Post-reset: %s, %s, %uhz, %u / %u buffer\n",
2089 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2090 device->Frequency, device->UpdateSize, device->BufferSize);
2092 if(device->Type != DeviceType::Loopback)
2094 if(auto modeopt = device->configValue<std::string>(nullptr, "stereo-mode"))
2096 const char *mode{modeopt->c_str()};
2097 if(al::strcasecmp(mode, "headphones") == 0)
2098 device->Flags.set(DirectEar);
2099 else if(al::strcasecmp(mode, "speakers") == 0)
2100 device->Flags.reset(DirectEar);
2101 else if(al::strcasecmp(mode, "auto") != 0)
2102 ERR("Unexpected stereo-mode: %s\n", mode);
2106 aluInitRenderer(device, hrtf_id, stereomode);
2108 /* Calculate the max number of sources, and split them between the mono and
2109 * stereo count given the requested number of stereo sources.
2111 if(auto srcsopt = device->configValue<uint>(nullptr, "sources"))
2113 if(*srcsopt <= 0) numMono = 256;
2114 else numMono = maxu(*srcsopt, 16);
2116 else
2118 numMono = minu(numMono, INT_MAX-numStereo);
2119 numMono = maxu(numMono+numStereo, 256);
2121 numStereo = minu(numStereo, numMono);
2122 numMono -= numStereo;
2123 device->SourcesMax = numMono + numStereo;
2124 device->NumMonoSources = numMono;
2125 device->NumStereoSources = numStereo;
2127 if(auto sendsopt = device->configValue<int>(nullptr, "sends"))
2128 numSends = minu(numSends, static_cast<uint>(clampi(*sendsopt, 0, MAX_SENDS)));
2129 device->NumAuxSends = numSends;
2131 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2132 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
2133 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
2135 switch(device->FmtChans)
2137 case DevFmtMono: break;
2138 case DevFmtStereo:
2139 if(!device->mUhjEncoder)
2140 device->RealOut.RemixMap = StereoDownmix;
2141 break;
2142 case DevFmtQuad: device->RealOut.RemixMap = QuadDownmix; break;
2143 case DevFmtX51: device->RealOut.RemixMap = X51Downmix; break;
2144 case DevFmtX61: device->RealOut.RemixMap = X61Downmix; break;
2145 case DevFmtX71: device->RealOut.RemixMap = X71Downmix; break;
2146 case DevFmtX714: device->RealOut.RemixMap = X71Downmix; break;
2147 case DevFmtX3D71: device->RealOut.RemixMap = X51Downmix; break;
2148 case DevFmtAmbi3D: break;
2151 nanoseconds::rep sample_delay{0};
2152 if(auto *encoder{device->mUhjEncoder.get()})
2153 sample_delay += encoder->getDelay();
2155 if(device->getConfigValueBool(nullptr, "dither", true))
2157 int depth{device->configValue<int>(nullptr, "dither-depth").value_or(0)};
2158 if(depth <= 0)
2160 switch(device->FmtType)
2162 case DevFmtByte:
2163 case DevFmtUByte:
2164 depth = 8;
2165 break;
2166 case DevFmtShort:
2167 case DevFmtUShort:
2168 depth = 16;
2169 break;
2170 case DevFmtInt:
2171 case DevFmtUInt:
2172 case DevFmtFloat:
2173 break;
2177 if(depth > 0)
2179 depth = clampi(depth, 2, 24);
2180 device->DitherDepth = std::pow(2.0f, static_cast<float>(depth-1));
2183 if(!(device->DitherDepth > 0.0f))
2184 TRACE("Dithering disabled\n");
2185 else
2186 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device->DitherDepth)+0.5f)+1,
2187 device->DitherDepth);
2189 if(!optlimit)
2190 optlimit = device->configValue<bool>(nullptr, "output-limiter");
2192 /* If the gain limiter is unset, use the limiter for integer-based output
2193 * (where samples must be clamped), and don't for floating-point (which can
2194 * take unclamped samples).
2196 if(!optlimit)
2198 switch(device->FmtType)
2200 case DevFmtByte:
2201 case DevFmtUByte:
2202 case DevFmtShort:
2203 case DevFmtUShort:
2204 case DevFmtInt:
2205 case DevFmtUInt:
2206 optlimit = true;
2207 break;
2208 case DevFmtFloat:
2209 break;
2212 if(optlimit.value_or(false) == false)
2213 TRACE("Output limiter disabled\n");
2214 else
2216 float thrshld{1.0f};
2217 switch(device->FmtType)
2219 case DevFmtByte:
2220 case DevFmtUByte:
2221 thrshld = 127.0f / 128.0f;
2222 break;
2223 case DevFmtShort:
2224 case DevFmtUShort:
2225 thrshld = 32767.0f / 32768.0f;
2226 break;
2227 case DevFmtInt:
2228 case DevFmtUInt:
2229 case DevFmtFloat:
2230 break;
2232 if(device->DitherDepth > 0.0f)
2233 thrshld -= 1.0f / device->DitherDepth;
2235 const float thrshld_dB{std::log10(thrshld) * 20.0f};
2236 auto limiter = CreateDeviceLimiter(device, thrshld_dB);
2238 sample_delay += limiter->getLookAhead();
2239 device->Limiter = std::move(limiter);
2240 TRACE("Output limiter enabled, %.4fdB limit\n", thrshld_dB);
2243 /* Convert the sample delay from samples to nanosamples to nanoseconds. */
2244 device->FixedLatency += nanoseconds{seconds{sample_delay}} / device->Frequency;
2245 TRACE("Fixed device latency: %" PRId64 "ns\n", int64_t{device->FixedLatency.count()});
2247 FPUCtl mixer_mode{};
2248 for(ContextBase *ctxbase : *device->mContexts.load())
2250 auto *context = static_cast<ALCcontext*>(ctxbase);
2252 auto GetEffectBuffer = [](ALbuffer *buffer) noexcept -> EffectState::Buffer
2254 if(!buffer) return EffectState::Buffer{};
2255 return EffectState::Buffer{buffer, buffer->mData};
2257 std::unique_lock<std::mutex> proplock{context->mPropLock};
2258 std::unique_lock<std::mutex> slotlock{context->mEffectSlotLock};
2260 /* Clear out unused effect slot clusters. */
2261 auto slot_cluster_not_in_use = [](ContextBase::EffectSlotCluster &cluster)
2263 for(size_t i{0};i < ContextBase::EffectSlotClusterSize;++i)
2265 if(cluster[i].InUse)
2266 return false;
2268 return true;
2270 auto slotcluster_iter = std::remove_if(context->mEffectSlotClusters.begin(),
2271 context->mEffectSlotClusters.end(), slot_cluster_not_in_use);
2272 context->mEffectSlotClusters.erase(slotcluster_iter, context->mEffectSlotClusters.end());
2274 /* Free all wet buffers. Any in use will be reallocated with an updated
2275 * configuration in aluInitEffectPanning.
2277 for(auto&& slots : context->mEffectSlotClusters)
2279 for(size_t i{0};i < ContextBase::EffectSlotClusterSize;++i)
2281 slots[i].mWetBuffer.clear();
2282 slots[i].mWetBuffer.shrink_to_fit();
2283 slots[i].Wet.Buffer = {};
2287 if(ALeffectslot *slot{context->mDefaultSlot.get()})
2289 aluInitEffectPanning(slot->mSlot, context);
2291 EffectState *state{slot->Effect.State.get()};
2292 state->mOutTarget = device->Dry.Buffer;
2293 state->deviceUpdate(device, GetEffectBuffer(slot->Buffer));
2294 slot->updateProps(context);
2297 if(EffectSlotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_relaxed)})
2298 std::fill_n(curarray->end(), curarray->size(), nullptr);
2299 for(auto &sublist : context->mEffectSlotList)
2301 uint64_t usemask{~sublist.FreeMask};
2302 while(usemask)
2304 const int idx{al::countr_zero(usemask)};
2305 ALeffectslot *slot{sublist.EffectSlots + idx};
2306 usemask &= ~(1_u64 << idx);
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 slotlock.unlock();
2318 const uint num_sends{device->NumAuxSends};
2319 std::unique_lock<std::mutex> srclock{context->mSourceLock};
2320 for(auto &sublist : context->mSourceList)
2322 uint64_t usemask{~sublist.FreeMask};
2323 while(usemask)
2325 const int idx{al::countr_zero(usemask)};
2326 ALsource *source{sublist.Sources + idx};
2327 usemask &= ~(1_u64 << idx);
2329 auto clear_send = [](ALsource::SendData &send) -> void
2331 if(send.Slot)
2332 DecrementRef(send.Slot->ref);
2333 send.Slot = nullptr;
2334 send.Gain = 1.0f;
2335 send.GainHF = 1.0f;
2336 send.HFReference = LOWPASSFREQREF;
2337 send.GainLF = 1.0f;
2338 send.LFReference = HIGHPASSFREQREF;
2340 auto send_begin = source->Send.begin() + static_cast<ptrdiff_t>(num_sends);
2341 std::for_each(send_begin, source->Send.end(), clear_send);
2343 source->mPropsDirty = true;
2347 auto voicelist = context->getVoicesSpan();
2348 for(Voice *voice : voicelist)
2350 /* Clear extraneous property set sends. */
2351 std::fill(std::begin(voice->mProps.Send)+num_sends, std::end(voice->mProps.Send),
2352 VoiceProps::SendData{});
2354 std::fill(voice->mSend.begin()+num_sends, voice->mSend.end(), Voice::TargetData{});
2355 for(auto &chandata : voice->mChans)
2357 std::fill(chandata.mWetParams.begin()+num_sends, chandata.mWetParams.end(),
2358 SendParams{});
2361 if(VoicePropsItem *props{voice->mUpdate.exchange(nullptr, std::memory_order_relaxed)})
2362 AtomicReplaceHead(context->mFreeVoiceProps, props);
2364 /* Force the voice to stopped if it was stopping. */
2365 Voice::State vstate{Voice::Stopping};
2366 voice->mPlayState.compare_exchange_strong(vstate, Voice::Stopped,
2367 std::memory_order_acquire, std::memory_order_acquire);
2368 if(voice->mSourceID.load(std::memory_order_relaxed) == 0u)
2369 continue;
2371 voice->prepare(device);
2373 /* Clear all voice props to let them get allocated again. */
2374 context->mVoicePropClusters.clear();
2375 context->mFreeVoiceProps.store(nullptr, std::memory_order_relaxed);
2376 srclock.unlock();
2378 context->mPropsDirty = false;
2379 UpdateContextProps(context);
2380 UpdateAllSourceProps(context);
2382 mixer_mode.leave();
2384 if(!device->Flags.test(DevicePaused))
2386 try {
2387 auto backend = device->Backend.get();
2388 backend->start();
2389 device->Flags.set(DeviceRunning);
2391 catch(al::backend_exception& e) {
2392 ERR("%s\n", e.what());
2393 device->handleDisconnect("%s", e.what());
2394 return ALC_INVALID_DEVICE;
2396 TRACE("Post-start: %s, %s, %uhz, %u / %u buffer\n",
2397 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2398 device->Frequency, device->UpdateSize, device->BufferSize);
2401 return ALC_NO_ERROR;
2405 * Updates device parameters as above, and also first clears the disconnected
2406 * status, if set.
2408 bool ResetDeviceParams(ALCdevice *device, const int *attrList)
2410 /* If the device was disconnected, reset it since we're opened anew. */
2411 if(!device->Connected.load(std::memory_order_relaxed)) [[unlikely]]
2413 /* Make sure disconnection is finished before continuing on. */
2414 device->waitForMix();
2416 for(ContextBase *ctxbase : *device->mContexts.load(std::memory_order_acquire))
2418 auto *ctx = static_cast<ALCcontext*>(ctxbase);
2419 if(!ctx->mStopVoicesOnDisconnect.load(std::memory_order_acquire))
2420 continue;
2422 /* Clear any pending voice changes and reallocate voices to get a
2423 * clean restart.
2425 std::lock_guard<std::mutex> __{ctx->mSourceLock};
2426 auto *vchg = ctx->mCurrentVoiceChange.load(std::memory_order_acquire);
2427 while(auto *next = vchg->mNext.load(std::memory_order_acquire))
2428 vchg = next;
2429 ctx->mCurrentVoiceChange.store(vchg, std::memory_order_release);
2431 ctx->mVoicePropClusters.clear();
2432 ctx->mFreeVoiceProps.store(nullptr, std::memory_order_relaxed);
2434 ctx->mVoiceClusters.clear();
2435 ctx->allocVoices(std::max<size_t>(256,
2436 ctx->mActiveVoiceCount.load(std::memory_order_relaxed)));
2439 device->Connected.store(true);
2442 ALCenum err{UpdateDeviceParams(device, attrList)};
2443 if(err == ALC_NO_ERROR) [[likely]] return ALC_TRUE;
2445 alcSetError(device, err);
2446 return ALC_FALSE;
2450 /** Checks if the device handle is valid, and returns a new reference if so. */
2451 DeviceRef VerifyDevice(ALCdevice *device)
2453 std::lock_guard<std::recursive_mutex> _{ListLock};
2454 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
2455 if(iter != DeviceList.end() && *iter == device)
2457 (*iter)->add_ref();
2458 return DeviceRef{*iter};
2460 return nullptr;
2465 * Checks if the given context is valid, returning a new reference to it if so.
2467 ContextRef VerifyContext(ALCcontext *context)
2469 std::lock_guard<std::recursive_mutex> _{ListLock};
2470 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
2471 if(iter != ContextList.end() && *iter == context)
2473 (*iter)->add_ref();
2474 return ContextRef{*iter};
2476 return nullptr;
2479 } // namespace
2481 /** Returns a new reference to the currently active context for this thread. */
2482 ContextRef GetContextRef(void)
2484 ALCcontext *context{ALCcontext::getThreadContext()};
2485 if(context)
2486 context->add_ref();
2487 else
2489 while(ALCcontext::sGlobalContextLock.exchange(true, std::memory_order_acquire)) {
2490 /* Wait to make sure another thread isn't trying to change the
2491 * current context and bring its refcount to 0.
2494 context = ALCcontext::sGlobalContext.load(std::memory_order_acquire);
2495 if(context) [[likely]] context->add_ref();
2496 ALCcontext::sGlobalContextLock.store(false, std::memory_order_release);
2498 return ContextRef{context};
2502 /************************************************
2503 * Standard ALC functions
2504 ************************************************/
2506 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2507 START_API_FUNC
2509 DeviceRef dev{VerifyDevice(device)};
2510 if(dev) return dev->LastError.exchange(ALC_NO_ERROR);
2511 return LastNullDeviceError.exchange(ALC_NO_ERROR);
2513 END_API_FUNC
2516 ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2517 START_API_FUNC
2519 if(!SuspendDefers)
2520 return;
2522 ContextRef ctx{VerifyContext(context)};
2523 if(!ctx)
2524 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2525 else
2527 std::lock_guard<std::mutex> _{ctx->mPropLock};
2528 ctx->deferUpdates();
2531 END_API_FUNC
2533 ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context)
2534 START_API_FUNC
2536 if(!SuspendDefers)
2537 return;
2539 ContextRef ctx{VerifyContext(context)};
2540 if(!ctx)
2541 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2542 else
2544 std::lock_guard<std::mutex> _{ctx->mPropLock};
2545 ctx->processUpdates();
2548 END_API_FUNC
2551 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2552 START_API_FUNC
2554 const ALCchar *value{nullptr};
2556 switch(param)
2558 case ALC_NO_ERROR:
2559 value = alcNoError;
2560 break;
2562 case ALC_INVALID_ENUM:
2563 value = alcErrInvalidEnum;
2564 break;
2566 case ALC_INVALID_VALUE:
2567 value = alcErrInvalidValue;
2568 break;
2570 case ALC_INVALID_DEVICE:
2571 value = alcErrInvalidDevice;
2572 break;
2574 case ALC_INVALID_CONTEXT:
2575 value = alcErrInvalidContext;
2576 break;
2578 case ALC_OUT_OF_MEMORY:
2579 value = alcErrOutOfMemory;
2580 break;
2582 case ALC_DEVICE_SPECIFIER:
2583 value = alcDefaultName;
2584 break;
2586 case ALC_ALL_DEVICES_SPECIFIER:
2587 if(DeviceRef dev{VerifyDevice(Device)})
2589 if(dev->Type == DeviceType::Capture)
2590 alcSetError(dev.get(), ALC_INVALID_ENUM);
2591 else if(dev->Type == DeviceType::Loopback)
2592 value = alcDefaultName;
2593 else
2595 std::lock_guard<std::mutex> _{dev->StateLock};
2596 value = dev->DeviceName.c_str();
2599 else
2601 ProbeAllDevicesList();
2602 value = alcAllDevicesList.c_str();
2604 break;
2606 case ALC_CAPTURE_DEVICE_SPECIFIER:
2607 if(DeviceRef dev{VerifyDevice(Device)})
2609 if(dev->Type != DeviceType::Capture)
2610 alcSetError(dev.get(), ALC_INVALID_ENUM);
2611 else
2613 std::lock_guard<std::mutex> _{dev->StateLock};
2614 value = dev->DeviceName.c_str();
2617 else
2619 ProbeCaptureDeviceList();
2620 value = alcCaptureDeviceList.c_str();
2622 break;
2624 /* Default devices are always first in the list */
2625 case ALC_DEFAULT_DEVICE_SPECIFIER:
2626 value = alcDefaultName;
2627 break;
2629 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2630 if(alcAllDevicesList.empty())
2631 ProbeAllDevicesList();
2633 /* Copy first entry as default. */
2634 alcDefaultAllDevicesSpecifier = alcAllDevicesList.c_str();
2635 value = alcDefaultAllDevicesSpecifier.c_str();
2636 break;
2638 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2639 if(alcCaptureDeviceList.empty())
2640 ProbeCaptureDeviceList();
2642 /* Copy first entry as default. */
2643 alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList.c_str();
2644 value = alcCaptureDefaultDeviceSpecifier.c_str();
2645 break;
2647 case ALC_EXTENSIONS:
2648 if(VerifyDevice(Device))
2649 value = alcExtensionList;
2650 else
2651 value = alcNoDeviceExtList;
2652 break;
2654 case ALC_HRTF_SPECIFIER_SOFT:
2655 if(DeviceRef dev{VerifyDevice(Device)})
2657 std::lock_guard<std::mutex> _{dev->StateLock};
2658 value = (dev->mHrtf ? dev->mHrtfName.c_str() : "");
2660 else
2661 alcSetError(nullptr, ALC_INVALID_DEVICE);
2662 break;
2664 default:
2665 alcSetError(VerifyDevice(Device).get(), ALC_INVALID_ENUM);
2666 break;
2669 return value;
2671 END_API_FUNC
2674 static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span<int> values)
2676 size_t i;
2678 if(values.empty())
2680 alcSetError(device, ALC_INVALID_VALUE);
2681 return 0;
2684 if(!device)
2686 switch(param)
2688 case ALC_MAJOR_VERSION:
2689 values[0] = alcMajorVersion;
2690 return 1;
2691 case ALC_MINOR_VERSION:
2692 values[0] = alcMinorVersion;
2693 return 1;
2695 case ALC_EFX_MAJOR_VERSION:
2696 values[0] = alcEFXMajorVersion;
2697 return 1;
2698 case ALC_EFX_MINOR_VERSION:
2699 values[0] = alcEFXMinorVersion;
2700 return 1;
2701 case ALC_MAX_AUXILIARY_SENDS:
2702 values[0] = MAX_SENDS;
2703 return 1;
2705 case ALC_ATTRIBUTES_SIZE:
2706 case ALC_ALL_ATTRIBUTES:
2707 case ALC_FREQUENCY:
2708 case ALC_REFRESH:
2709 case ALC_SYNC:
2710 case ALC_MONO_SOURCES:
2711 case ALC_STEREO_SOURCES:
2712 case ALC_CAPTURE_SAMPLES:
2713 case ALC_FORMAT_CHANNELS_SOFT:
2714 case ALC_FORMAT_TYPE_SOFT:
2715 case ALC_AMBISONIC_LAYOUT_SOFT:
2716 case ALC_AMBISONIC_SCALING_SOFT:
2717 case ALC_AMBISONIC_ORDER_SOFT:
2718 case ALC_MAX_AMBISONIC_ORDER_SOFT:
2719 alcSetError(nullptr, ALC_INVALID_DEVICE);
2720 return 0;
2722 default:
2723 alcSetError(nullptr, ALC_INVALID_ENUM);
2725 return 0;
2728 std::lock_guard<std::mutex> _{device->StateLock};
2729 if(device->Type == DeviceType::Capture)
2731 static constexpr int MaxCaptureAttributes{9};
2732 switch(param)
2734 case ALC_ATTRIBUTES_SIZE:
2735 values[0] = MaxCaptureAttributes;
2736 return 1;
2737 case ALC_ALL_ATTRIBUTES:
2738 i = 0;
2739 if(values.size() < MaxCaptureAttributes)
2740 alcSetError(device, ALC_INVALID_VALUE);
2741 else
2743 values[i++] = ALC_MAJOR_VERSION;
2744 values[i++] = alcMajorVersion;
2745 values[i++] = ALC_MINOR_VERSION;
2746 values[i++] = alcMinorVersion;
2747 values[i++] = ALC_CAPTURE_SAMPLES;
2748 values[i++] = static_cast<int>(device->Backend->availableSamples());
2749 values[i++] = ALC_CONNECTED;
2750 values[i++] = device->Connected.load(std::memory_order_relaxed);
2751 values[i++] = 0;
2752 assert(i == MaxCaptureAttributes);
2754 return i;
2756 case ALC_MAJOR_VERSION:
2757 values[0] = alcMajorVersion;
2758 return 1;
2759 case ALC_MINOR_VERSION:
2760 values[0] = alcMinorVersion;
2761 return 1;
2763 case ALC_CAPTURE_SAMPLES:
2764 values[0] = static_cast<int>(device->Backend->availableSamples());
2765 return 1;
2767 case ALC_CONNECTED:
2768 values[0] = device->Connected.load(std::memory_order_acquire);
2769 return 1;
2771 default:
2772 alcSetError(device, ALC_INVALID_ENUM);
2774 return 0;
2777 /* render device */
2778 auto NumAttrsForDevice = [](ALCdevice *aldev) noexcept
2780 if(aldev->Type == DeviceType::Loopback && aldev->FmtChans == DevFmtAmbi3D)
2781 return 37;
2782 return 31;
2784 switch(param)
2786 case ALC_ATTRIBUTES_SIZE:
2787 values[0] = NumAttrsForDevice(device);
2788 return 1;
2790 case ALC_ALL_ATTRIBUTES:
2791 i = 0;
2792 if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2793 alcSetError(device, ALC_INVALID_VALUE);
2794 else
2796 values[i++] = ALC_MAJOR_VERSION;
2797 values[i++] = alcMajorVersion;
2798 values[i++] = ALC_MINOR_VERSION;
2799 values[i++] = alcMinorVersion;
2800 values[i++] = ALC_EFX_MAJOR_VERSION;
2801 values[i++] = alcEFXMajorVersion;
2802 values[i++] = ALC_EFX_MINOR_VERSION;
2803 values[i++] = alcEFXMinorVersion;
2805 values[i++] = ALC_FREQUENCY;
2806 values[i++] = static_cast<int>(device->Frequency);
2807 if(device->Type != DeviceType::Loopback)
2809 values[i++] = ALC_REFRESH;
2810 values[i++] = static_cast<int>(device->Frequency / device->UpdateSize);
2812 values[i++] = ALC_SYNC;
2813 values[i++] = ALC_FALSE;
2815 else
2817 if(device->FmtChans == DevFmtAmbi3D)
2819 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
2820 values[i++] = EnumFromDevAmbi(device->mAmbiLayout);
2822 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
2823 values[i++] = EnumFromDevAmbi(device->mAmbiScale);
2825 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
2826 values[i++] = static_cast<int>(device->mAmbiOrder);
2829 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2830 values[i++] = EnumFromDevFmt(device->FmtChans);
2832 values[i++] = ALC_FORMAT_TYPE_SOFT;
2833 values[i++] = EnumFromDevFmt(device->FmtType);
2836 values[i++] = ALC_MONO_SOURCES;
2837 values[i++] = static_cast<int>(device->NumMonoSources);
2839 values[i++] = ALC_STEREO_SOURCES;
2840 values[i++] = static_cast<int>(device->NumStereoSources);
2842 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2843 values[i++] = static_cast<int>(device->NumAuxSends);
2845 values[i++] = ALC_HRTF_SOFT;
2846 values[i++] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
2848 values[i++] = ALC_HRTF_STATUS_SOFT;
2849 values[i++] = device->mHrtfStatus;
2851 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
2852 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
2854 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
2855 values[i++] = MaxAmbiOrder;
2857 values[i++] = ALC_OUTPUT_MODE_SOFT;
2858 values[i++] = static_cast<ALCenum>(device->getOutputMode1());
2860 values[i++] = 0;
2862 return i;
2864 case ALC_MAJOR_VERSION:
2865 values[0] = alcMajorVersion;
2866 return 1;
2868 case ALC_MINOR_VERSION:
2869 values[0] = alcMinorVersion;
2870 return 1;
2872 case ALC_EFX_MAJOR_VERSION:
2873 values[0] = alcEFXMajorVersion;
2874 return 1;
2876 case ALC_EFX_MINOR_VERSION:
2877 values[0] = alcEFXMinorVersion;
2878 return 1;
2880 case ALC_FREQUENCY:
2881 values[0] = static_cast<int>(device->Frequency);
2882 return 1;
2884 case ALC_REFRESH:
2885 if(device->Type == DeviceType::Loopback)
2887 alcSetError(device, ALC_INVALID_DEVICE);
2888 return 0;
2890 values[0] = static_cast<int>(device->Frequency / device->UpdateSize);
2891 return 1;
2893 case ALC_SYNC:
2894 if(device->Type == DeviceType::Loopback)
2896 alcSetError(device, ALC_INVALID_DEVICE);
2897 return 0;
2899 values[0] = ALC_FALSE;
2900 return 1;
2902 case ALC_FORMAT_CHANNELS_SOFT:
2903 if(device->Type != DeviceType::Loopback)
2905 alcSetError(device, ALC_INVALID_DEVICE);
2906 return 0;
2908 values[0] = EnumFromDevFmt(device->FmtChans);
2909 return 1;
2911 case ALC_FORMAT_TYPE_SOFT:
2912 if(device->Type != DeviceType::Loopback)
2914 alcSetError(device, ALC_INVALID_DEVICE);
2915 return 0;
2917 values[0] = EnumFromDevFmt(device->FmtType);
2918 return 1;
2920 case ALC_AMBISONIC_LAYOUT_SOFT:
2921 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2923 alcSetError(device, ALC_INVALID_DEVICE);
2924 return 0;
2926 values[0] = EnumFromDevAmbi(device->mAmbiLayout);
2927 return 1;
2929 case ALC_AMBISONIC_SCALING_SOFT:
2930 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2932 alcSetError(device, ALC_INVALID_DEVICE);
2933 return 0;
2935 values[0] = EnumFromDevAmbi(device->mAmbiScale);
2936 return 1;
2938 case ALC_AMBISONIC_ORDER_SOFT:
2939 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2941 alcSetError(device, ALC_INVALID_DEVICE);
2942 return 0;
2944 values[0] = static_cast<int>(device->mAmbiOrder);
2945 return 1;
2947 case ALC_MONO_SOURCES:
2948 values[0] = static_cast<int>(device->NumMonoSources);
2949 return 1;
2951 case ALC_STEREO_SOURCES:
2952 values[0] = static_cast<int>(device->NumStereoSources);
2953 return 1;
2955 case ALC_MAX_AUXILIARY_SENDS:
2956 values[0] = static_cast<int>(device->NumAuxSends);
2957 return 1;
2959 case ALC_CONNECTED:
2960 values[0] = device->Connected.load(std::memory_order_acquire);
2961 return 1;
2963 case ALC_HRTF_SOFT:
2964 values[0] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
2965 return 1;
2967 case ALC_HRTF_STATUS_SOFT:
2968 values[0] = device->mHrtfStatus;
2969 return 1;
2971 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
2972 device->enumerateHrtfs();
2973 values[0] = static_cast<int>(minz(device->mHrtfList.size(),
2974 std::numeric_limits<int>::max()));
2975 return 1;
2977 case ALC_OUTPUT_LIMITER_SOFT:
2978 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
2979 return 1;
2981 case ALC_MAX_AMBISONIC_ORDER_SOFT:
2982 values[0] = MaxAmbiOrder;
2983 return 1;
2985 case ALC_OUTPUT_MODE_SOFT:
2986 values[0] = static_cast<ALCenum>(device->getOutputMode1());
2987 return 1;
2989 default:
2990 alcSetError(device, ALC_INVALID_ENUM);
2992 return 0;
2995 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2996 START_API_FUNC
2998 DeviceRef dev{VerifyDevice(device)};
2999 if(size <= 0 || values == nullptr)
3000 alcSetError(dev.get(), ALC_INVALID_VALUE);
3001 else
3002 GetIntegerv(dev.get(), param, {values, static_cast<uint>(size)});
3004 END_API_FUNC
3006 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3007 START_API_FUNC
3009 DeviceRef dev{VerifyDevice(device)};
3010 if(size <= 0 || values == nullptr)
3012 alcSetError(dev.get(), ALC_INVALID_VALUE);
3013 return;
3015 if(!dev || dev->Type == DeviceType::Capture)
3017 auto ivals = al::vector<int>(static_cast<uint>(size));
3018 if(size_t got{GetIntegerv(dev.get(), pname, ivals)})
3019 std::copy_n(ivals.begin(), got, values);
3020 return;
3022 /* render device */
3023 auto NumAttrsForDevice = [](ALCdevice *aldev) noexcept
3025 if(aldev->Type == DeviceType::Loopback && aldev->FmtChans == DevFmtAmbi3D)
3026 return 41;
3027 return 35;
3029 std::lock_guard<std::mutex> _{dev->StateLock};
3030 switch(pname)
3032 case ALC_ATTRIBUTES_SIZE:
3033 *values = NumAttrsForDevice(dev.get());
3034 break;
3036 case ALC_ALL_ATTRIBUTES:
3037 if(size < NumAttrsForDevice(dev.get()))
3038 alcSetError(dev.get(), ALC_INVALID_VALUE);
3039 else
3041 size_t i{0};
3042 values[i++] = ALC_FREQUENCY;
3043 values[i++] = dev->Frequency;
3045 if(dev->Type != DeviceType::Loopback)
3047 values[i++] = ALC_REFRESH;
3048 values[i++] = dev->Frequency / dev->UpdateSize;
3050 values[i++] = ALC_SYNC;
3051 values[i++] = ALC_FALSE;
3053 else
3055 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3056 values[i++] = EnumFromDevFmt(dev->FmtChans);
3058 values[i++] = ALC_FORMAT_TYPE_SOFT;
3059 values[i++] = EnumFromDevFmt(dev->FmtType);
3061 if(dev->FmtChans == DevFmtAmbi3D)
3063 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3064 values[i++] = EnumFromDevAmbi(dev->mAmbiLayout);
3066 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3067 values[i++] = EnumFromDevAmbi(dev->mAmbiScale);
3069 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3070 values[i++] = dev->mAmbiOrder;
3074 values[i++] = ALC_MONO_SOURCES;
3075 values[i++] = dev->NumMonoSources;
3077 values[i++] = ALC_STEREO_SOURCES;
3078 values[i++] = dev->NumStereoSources;
3080 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3081 values[i++] = dev->NumAuxSends;
3083 values[i++] = ALC_HRTF_SOFT;
3084 values[i++] = (dev->mHrtf ? ALC_TRUE : ALC_FALSE);
3086 values[i++] = ALC_HRTF_STATUS_SOFT;
3087 values[i++] = dev->mHrtfStatus;
3089 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3090 values[i++] = dev->Limiter ? ALC_TRUE : ALC_FALSE;
3092 ClockLatency clock{GetClockLatency(dev.get(), dev->Backend.get())};
3093 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3094 values[i++] = clock.ClockTime.count();
3096 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3097 values[i++] = clock.Latency.count();
3099 values[i++] = ALC_OUTPUT_MODE_SOFT;
3100 values[i++] = static_cast<ALCenum>(device->getOutputMode1());
3102 values[i++] = 0;
3104 break;
3106 case ALC_DEVICE_CLOCK_SOFT:
3108 uint samplecount, refcount;
3109 nanoseconds basecount;
3110 do {
3111 refcount = dev->waitForMix();
3112 basecount = dev->ClockBase;
3113 samplecount = dev->SamplesDone;
3114 } while(refcount != ReadRef(dev->MixCount));
3115 basecount += nanoseconds{seconds{samplecount}} / dev->Frequency;
3116 *values = basecount.count();
3118 break;
3120 case ALC_DEVICE_LATENCY_SOFT:
3121 *values = GetClockLatency(dev.get(), dev->Backend.get()).Latency.count();
3122 break;
3124 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3125 if(size < 2)
3126 alcSetError(dev.get(), ALC_INVALID_VALUE);
3127 else
3129 ClockLatency clock{GetClockLatency(dev.get(), dev->Backend.get())};
3130 values[0] = clock.ClockTime.count();
3131 values[1] = clock.Latency.count();
3133 break;
3135 default:
3136 auto ivals = al::vector<int>(static_cast<uint>(size));
3137 if(size_t got{GetIntegerv(dev.get(), pname, ivals)})
3138 std::copy_n(ivals.begin(), got, values);
3139 break;
3142 END_API_FUNC
3145 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3146 START_API_FUNC
3148 DeviceRef dev{VerifyDevice(device)};
3149 if(!extName)
3150 alcSetError(dev.get(), ALC_INVALID_VALUE);
3151 else
3153 size_t len = strlen(extName);
3154 const char *ptr = (dev ? alcExtensionList : alcNoDeviceExtList);
3155 while(ptr && *ptr)
3157 if(al::strncasecmp(ptr, extName, len) == 0 && (ptr[len] == '\0' || isspace(ptr[len])))
3158 return ALC_TRUE;
3160 if((ptr=strchr(ptr, ' ')) != nullptr)
3162 do {
3163 ++ptr;
3164 } while(isspace(*ptr));
3168 return ALC_FALSE;
3170 END_API_FUNC
3173 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3174 START_API_FUNC
3176 if(!funcName)
3178 DeviceRef dev{VerifyDevice(device)};
3179 alcSetError(dev.get(), ALC_INVALID_VALUE);
3180 return nullptr;
3182 #ifdef ALSOFT_EAX
3183 if(eax_g_is_enabled)
3185 for(const auto &func : eaxFunctions)
3187 if(strcmp(func.funcName, funcName) == 0)
3188 return func.address;
3191 #endif
3192 for(const auto &func : alcFunctions)
3194 if(strcmp(func.funcName, funcName) == 0)
3195 return func.address;
3197 return nullptr;
3199 END_API_FUNC
3202 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3203 START_API_FUNC
3205 if(!enumName)
3207 DeviceRef dev{VerifyDevice(device)};
3208 alcSetError(dev.get(), ALC_INVALID_VALUE);
3209 return 0;
3211 #ifdef ALSOFT_EAX
3212 if(eax_g_is_enabled)
3214 for(const auto &enm : eaxEnumerations)
3216 if(strcmp(enm.enumName, enumName) == 0)
3217 return enm.value;
3220 #endif
3221 for(const auto &enm : alcEnumerations)
3223 if(strcmp(enm.enumName, enumName) == 0)
3224 return enm.value;
3227 return 0;
3229 END_API_FUNC
3232 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3233 START_API_FUNC
3235 /* Explicitly hold the list lock while taking the StateLock in case the
3236 * device is asynchronously destroyed, to ensure this new context is
3237 * properly cleaned up after being made.
3239 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3240 DeviceRef dev{VerifyDevice(device)};
3241 if(!dev || dev->Type == DeviceType::Capture || !dev->Connected.load(std::memory_order_relaxed))
3243 listlock.unlock();
3244 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3245 return nullptr;
3247 std::unique_lock<std::mutex> statelock{dev->StateLock};
3248 listlock.unlock();
3250 dev->LastError.store(ALC_NO_ERROR);
3252 ALCenum err{UpdateDeviceParams(dev.get(), attrList)};
3253 if(err != ALC_NO_ERROR)
3255 alcSetError(dev.get(), err);
3256 return nullptr;
3259 ContextRef context{new ALCcontext{dev}};
3260 context->init();
3262 if(auto volopt = dev->configValue<float>(nullptr, "volume-adjust"))
3264 const float valf{*volopt};
3265 if(!std::isfinite(valf))
3266 ERR("volume-adjust must be finite: %f\n", valf);
3267 else
3269 const float db{clampf(valf, -24.0f, 24.0f)};
3270 if(db != valf)
3271 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3272 context->mGainBoost = std::pow(10.0f, db/20.0f);
3273 TRACE("volume-adjust gain: %f\n", context->mGainBoost);
3278 using ContextArray = al::FlexArray<ContextBase*>;
3280 /* Allocate a new context array, which holds 1 more than the current/
3281 * old array.
3283 auto *oldarray = device->mContexts.load();
3284 const size_t newcount{oldarray->size()+1};
3285 std::unique_ptr<ContextArray> newarray{ContextArray::Create(newcount)};
3287 /* Copy the current/old context handles to the new array, appending the
3288 * new context.
3290 auto iter = std::copy(oldarray->begin(), oldarray->end(), newarray->begin());
3291 *iter = context.get();
3293 /* Store the new context array in the device. Wait for any current mix
3294 * to finish before deleting the old array.
3296 dev->mContexts.store(newarray.release());
3297 if(oldarray != &DeviceBase::sEmptyContextArray)
3299 dev->waitForMix();
3300 delete oldarray;
3303 statelock.unlock();
3306 std::lock_guard<std::recursive_mutex> _{ListLock};
3307 auto iter = std::lower_bound(ContextList.cbegin(), ContextList.cend(), context.get());
3308 ContextList.emplace(iter, context.get());
3311 if(ALeffectslot *slot{context->mDefaultSlot.get()})
3313 ALenum sloterr{slot->initEffect(ALCcontext::sDefaultEffect.type,
3314 ALCcontext::sDefaultEffect.Props, context.get())};
3315 if(sloterr == AL_NO_ERROR)
3316 slot->updateProps(context.get());
3317 else
3318 ERR("Failed to initialize the default effect\n");
3321 TRACE("Created context %p\n", voidp{context.get()});
3322 return context.release();
3324 END_API_FUNC
3326 ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3327 START_API_FUNC
3329 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3330 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
3331 if(iter == ContextList.end() || *iter != context)
3333 listlock.unlock();
3334 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3335 return;
3338 /* Hold a reference to this context so it remains valid until the ListLock
3339 * is released.
3341 ContextRef ctx{*iter};
3342 ContextList.erase(iter);
3344 ALCdevice *Device{ctx->mALDevice.get()};
3346 std::lock_guard<std::mutex> _{Device->StateLock};
3347 if(!ctx->deinit() && Device->Flags.test(DeviceRunning))
3349 Device->Backend->stop();
3350 Device->Flags.reset(DeviceRunning);
3353 END_API_FUNC
3356 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3357 START_API_FUNC
3359 ALCcontext *Context{ALCcontext::getThreadContext()};
3360 if(!Context) Context = ALCcontext::sGlobalContext.load();
3361 return Context;
3363 END_API_FUNC
3365 /** Returns the currently active thread-local context. */
3366 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3367 START_API_FUNC
3368 { return ALCcontext::getThreadContext(); }
3369 END_API_FUNC
3371 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3372 START_API_FUNC
3374 /* context must be valid or nullptr */
3375 ContextRef ctx;
3376 if(context)
3378 ctx = VerifyContext(context);
3379 if(!ctx)
3381 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3382 return ALC_FALSE;
3385 /* Release this reference (if any) to store it in the GlobalContext
3386 * pointer. Take ownership of the reference (if any) that was previously
3387 * stored there, and let the reference go.
3389 while(ALCcontext::sGlobalContextLock.exchange(true, std::memory_order_acquire)) {
3390 /* Wait to make sure another thread isn't getting or trying to change
3391 * the current context as its refcount is decremented.
3394 ContextRef{ALCcontext::sGlobalContext.exchange(ctx.release())};
3395 ALCcontext::sGlobalContextLock.store(false, std::memory_order_release);
3397 /* Take ownership of the thread-local context reference (if any), clearing
3398 * the storage to null.
3400 ctx = ContextRef{ALCcontext::getThreadContext()};
3401 if(ctx) ALCcontext::setThreadContext(nullptr);
3402 /* Reset (decrement) the previous thread-local reference. */
3404 return ALC_TRUE;
3406 END_API_FUNC
3408 /** Makes the given context the active context for the current thread. */
3409 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3410 START_API_FUNC
3412 /* context must be valid or nullptr */
3413 ContextRef ctx;
3414 if(context)
3416 ctx = VerifyContext(context);
3417 if(!ctx)
3419 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3420 return ALC_FALSE;
3423 /* context's reference count is already incremented */
3424 ContextRef old{ALCcontext::getThreadContext()};
3425 ALCcontext::setThreadContext(ctx.release());
3427 return ALC_TRUE;
3429 END_API_FUNC
3432 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3433 START_API_FUNC
3435 ContextRef ctx{VerifyContext(Context)};
3436 if(!ctx)
3438 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3439 return nullptr;
3441 return ctx->mALDevice.get();
3443 END_API_FUNC
3446 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3447 START_API_FUNC
3449 InitConfig();
3451 if(!PlaybackFactory)
3453 alcSetError(nullptr, ALC_INVALID_VALUE);
3454 return nullptr;
3457 if(deviceName)
3459 TRACE("Opening playback device \"%s\"\n", deviceName);
3460 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3461 #ifdef _WIN32
3462 /* Some old Windows apps hardcode these expecting OpenAL to use a
3463 * specific audio API, even when they're not enumerated. Creative's
3464 * router effectively ignores them too.
3466 || al::strcasecmp(deviceName, "DirectSound3D") == 0
3467 || al::strcasecmp(deviceName, "DirectSound") == 0
3468 || al::strcasecmp(deviceName, "MMSYSTEM") == 0
3469 #endif
3470 /* Some old Linux apps hardcode configuration strings that were
3471 * supported by the OpenAL SI. We can't really do anything useful
3472 * with them, so just ignore.
3474 || (deviceName[0] == '\'' && deviceName[1] == '(')
3475 || al::strcasecmp(deviceName, "openal-soft") == 0)
3476 deviceName = nullptr;
3478 else
3479 TRACE("Opening default playback device\n");
3481 const uint DefaultSends{
3482 #ifdef ALSOFT_EAX
3483 eax_g_is_enabled ? uint{EAX_MAX_FXSLOTS} :
3484 #endif // ALSOFT_EAX
3485 DEFAULT_SENDS
3488 DeviceRef device{new ALCdevice{DeviceType::Playback}};
3490 /* Set output format */
3491 device->FmtChans = DevFmtChannelsDefault;
3492 device->FmtType = DevFmtTypeDefault;
3493 device->Frequency = DEFAULT_OUTPUT_RATE;
3494 device->UpdateSize = DEFAULT_UPDATE_SIZE;
3495 device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
3497 device->SourcesMax = 256;
3498 device->NumStereoSources = 1;
3499 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3500 device->AuxiliaryEffectSlotMax = 64;
3501 device->NumAuxSends = DefaultSends;
3503 try {
3504 auto backend = PlaybackFactory->createBackend(device.get(), BackendType::Playback);
3505 std::lock_guard<std::recursive_mutex> _{ListLock};
3506 backend->open(deviceName);
3507 device->Backend = std::move(backend);
3509 catch(al::backend_exception &e) {
3510 WARN("Failed to open playback device: %s\n", e.what());
3511 alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory)
3512 ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
3513 return nullptr;
3517 std::lock_guard<std::recursive_mutex> _{ListLock};
3518 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3519 DeviceList.emplace(iter, device.get());
3522 TRACE("Created device %p, \"%s\"\n", voidp{device.get()}, device->DeviceName.c_str());
3523 return device.release();
3525 END_API_FUNC
3527 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3528 START_API_FUNC
3530 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3531 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3532 if(iter == DeviceList.end() || *iter != device)
3534 alcSetError(nullptr, ALC_INVALID_DEVICE);
3535 return ALC_FALSE;
3537 if((*iter)->Type == DeviceType::Capture)
3539 alcSetError(*iter, ALC_INVALID_DEVICE);
3540 return ALC_FALSE;
3543 /* Erase the device, and any remaining contexts left on it, from their
3544 * respective lists.
3546 DeviceRef dev{*iter};
3547 DeviceList.erase(iter);
3549 std::unique_lock<std::mutex> statelock{dev->StateLock};
3550 al::vector<ContextRef> orphanctxs;
3551 for(ContextBase *ctx : *dev->mContexts.load())
3553 auto ctxiter = std::lower_bound(ContextList.begin(), ContextList.end(), ctx);
3554 if(ctxiter != ContextList.end() && *ctxiter == ctx)
3556 orphanctxs.emplace_back(ContextRef{*ctxiter});
3557 ContextList.erase(ctxiter);
3560 listlock.unlock();
3562 for(ContextRef &context : orphanctxs)
3564 WARN("Releasing orphaned context %p\n", voidp{context.get()});
3565 context->deinit();
3567 orphanctxs.clear();
3569 if(dev->Flags.test(DeviceRunning))
3570 dev->Backend->stop();
3571 dev->Flags.reset(DeviceRunning);
3573 return ALC_TRUE;
3575 END_API_FUNC
3578 /************************************************
3579 * ALC capture functions
3580 ************************************************/
3581 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3582 START_API_FUNC
3584 InitConfig();
3586 if(!CaptureFactory)
3588 alcSetError(nullptr, ALC_INVALID_VALUE);
3589 return nullptr;
3592 if(samples <= 0)
3594 alcSetError(nullptr, ALC_INVALID_VALUE);
3595 return nullptr;
3598 if(deviceName)
3600 TRACE("Opening capture device \"%s\"\n", deviceName);
3601 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3602 || al::strcasecmp(deviceName, "openal-soft") == 0)
3603 deviceName = nullptr;
3605 else
3606 TRACE("Opening default capture device\n");
3608 DeviceRef device{new ALCdevice{DeviceType::Capture}};
3610 auto decompfmt = DecomposeDevFormat(format);
3611 if(!decompfmt)
3613 alcSetError(nullptr, ALC_INVALID_ENUM);
3614 return nullptr;
3617 device->Frequency = frequency;
3618 device->FmtChans = decompfmt->chans;
3619 device->FmtType = decompfmt->type;
3620 device->Flags.set(FrequencyRequest);
3621 device->Flags.set(ChannelsRequest);
3622 device->Flags.set(SampleTypeRequest);
3624 device->UpdateSize = static_cast<uint>(samples);
3625 device->BufferSize = static_cast<uint>(samples);
3627 try {
3628 TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n",
3629 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
3630 device->Frequency, device->UpdateSize, device->BufferSize);
3632 auto backend = CaptureFactory->createBackend(device.get(), BackendType::Capture);
3633 std::lock_guard<std::recursive_mutex> _{ListLock};
3634 backend->open(deviceName);
3635 device->Backend = std::move(backend);
3637 catch(al::backend_exception &e) {
3638 WARN("Failed to open capture device: %s\n", e.what());
3639 alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory)
3640 ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
3641 return nullptr;
3645 std::lock_guard<std::recursive_mutex> _{ListLock};
3646 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3647 DeviceList.emplace(iter, device.get());
3650 TRACE("Created capture device %p, \"%s\"\n", voidp{device.get()}, device->DeviceName.c_str());
3651 return device.release();
3653 END_API_FUNC
3655 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3656 START_API_FUNC
3658 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3659 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3660 if(iter == DeviceList.end() || *iter != device)
3662 alcSetError(nullptr, ALC_INVALID_DEVICE);
3663 return ALC_FALSE;
3665 if((*iter)->Type != DeviceType::Capture)
3667 alcSetError(*iter, ALC_INVALID_DEVICE);
3668 return ALC_FALSE;
3671 DeviceRef dev{*iter};
3672 DeviceList.erase(iter);
3673 listlock.unlock();
3675 std::lock_guard<std::mutex> _{dev->StateLock};
3676 if(dev->Flags.test(DeviceRunning))
3677 dev->Backend->stop();
3678 dev->Flags.reset(DeviceRunning);
3680 return ALC_TRUE;
3682 END_API_FUNC
3684 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3685 START_API_FUNC
3687 DeviceRef dev{VerifyDevice(device)};
3688 if(!dev || dev->Type != DeviceType::Capture)
3690 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3691 return;
3694 std::lock_guard<std::mutex> _{dev->StateLock};
3695 if(!dev->Connected.load(std::memory_order_acquire))
3696 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3697 else if(!dev->Flags.test(DeviceRunning))
3699 try {
3700 auto backend = dev->Backend.get();
3701 backend->start();
3702 dev->Flags.set(DeviceRunning);
3704 catch(al::backend_exception& e) {
3705 ERR("%s\n", e.what());
3706 dev->handleDisconnect("%s", e.what());
3707 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3711 END_API_FUNC
3713 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3714 START_API_FUNC
3716 DeviceRef dev{VerifyDevice(device)};
3717 if(!dev || dev->Type != DeviceType::Capture)
3718 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3719 else
3721 std::lock_guard<std::mutex> _{dev->StateLock};
3722 if(dev->Flags.test(DeviceRunning))
3723 dev->Backend->stop();
3724 dev->Flags.reset(DeviceRunning);
3727 END_API_FUNC
3729 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3730 START_API_FUNC
3732 DeviceRef dev{VerifyDevice(device)};
3733 if(!dev || dev->Type != DeviceType::Capture)
3735 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3736 return;
3739 if(samples < 0 || (samples > 0 && buffer == nullptr))
3741 alcSetError(dev.get(), ALC_INVALID_VALUE);
3742 return;
3744 if(samples < 1)
3745 return;
3747 std::lock_guard<std::mutex> _{dev->StateLock};
3748 BackendBase *backend{dev->Backend.get()};
3750 const auto usamples = static_cast<uint>(samples);
3751 if(usamples > backend->availableSamples())
3753 alcSetError(dev.get(), ALC_INVALID_VALUE);
3754 return;
3757 backend->captureSamples(static_cast<al::byte*>(buffer), usamples);
3759 END_API_FUNC
3762 /************************************************
3763 * ALC loopback functions
3764 ************************************************/
3766 /** Open a loopback device, for manual rendering. */
3767 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3768 START_API_FUNC
3770 InitConfig();
3772 /* Make sure the device name, if specified, is us. */
3773 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3775 alcSetError(nullptr, ALC_INVALID_VALUE);
3776 return nullptr;
3779 const uint DefaultSends{
3780 #ifdef ALSOFT_EAX
3781 eax_g_is_enabled ? uint{EAX_MAX_FXSLOTS} :
3782 #endif // ALSOFT_EAX
3783 DEFAULT_SENDS
3786 DeviceRef device{new ALCdevice{DeviceType::Loopback}};
3788 device->SourcesMax = 256;
3789 device->AuxiliaryEffectSlotMax = 64;
3790 device->NumAuxSends = DefaultSends;
3792 //Set output format
3793 device->BufferSize = 0;
3794 device->UpdateSize = 0;
3796 device->Frequency = DEFAULT_OUTPUT_RATE;
3797 device->FmtChans = DevFmtChannelsDefault;
3798 device->FmtType = DevFmtTypeDefault;
3800 device->NumStereoSources = 1;
3801 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3803 try {
3804 auto backend = LoopbackBackendFactory::getFactory().createBackend(device.get(),
3805 BackendType::Playback);
3806 backend->open("Loopback");
3807 device->Backend = std::move(backend);
3809 catch(al::backend_exception &e) {
3810 WARN("Failed to open loopback device: %s\n", e.what());
3811 alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory)
3812 ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
3813 return nullptr;
3817 std::lock_guard<std::recursive_mutex> _{ListLock};
3818 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3819 DeviceList.emplace(iter, device.get());
3822 TRACE("Created loopback device %p\n", voidp{device.get()});
3823 return device.release();
3825 END_API_FUNC
3828 * Determines if the loopback device supports the given format for rendering.
3830 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3831 START_API_FUNC
3833 DeviceRef dev{VerifyDevice(device)};
3834 if(!dev || dev->Type != DeviceType::Loopback)
3835 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3836 else if(freq <= 0)
3837 alcSetError(dev.get(), ALC_INVALID_VALUE);
3838 else
3840 if(DevFmtTypeFromEnum(type).has_value() && DevFmtChannelsFromEnum(channels).has_value()
3841 && freq >= MIN_OUTPUT_RATE && freq <= MAX_OUTPUT_RATE)
3842 return ALC_TRUE;
3845 return ALC_FALSE;
3847 END_API_FUNC
3850 * Renders some samples into a buffer, using the format last set by the
3851 * attributes given to alcCreateContext.
3853 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3854 START_API_FUNC
3856 if(!device || device->Type != DeviceType::Loopback)
3857 alcSetError(device, ALC_INVALID_DEVICE);
3858 else if(samples < 0 || (samples > 0 && buffer == nullptr))
3859 alcSetError(device, ALC_INVALID_VALUE);
3860 else
3861 device->renderSamples(buffer, static_cast<uint>(samples), device->channelsFromFmt());
3863 END_API_FUNC
3866 /************************************************
3867 * ALC DSP pause/resume functions
3868 ************************************************/
3870 /** Pause the DSP to stop audio processing. */
3871 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
3872 START_API_FUNC
3874 DeviceRef dev{VerifyDevice(device)};
3875 if(!dev || dev->Type != DeviceType::Playback)
3876 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3877 else
3879 std::lock_guard<std::mutex> _{dev->StateLock};
3880 if(dev->Flags.test(DeviceRunning))
3881 dev->Backend->stop();
3882 dev->Flags.reset(DeviceRunning);
3883 dev->Flags.set(DevicePaused);
3886 END_API_FUNC
3888 /** Resume the DSP to restart audio processing. */
3889 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
3890 START_API_FUNC
3892 DeviceRef dev{VerifyDevice(device)};
3893 if(!dev || dev->Type != DeviceType::Playback)
3895 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3896 return;
3899 std::lock_guard<std::mutex> _{dev->StateLock};
3900 if(!dev->Flags.test(DevicePaused))
3901 return;
3902 dev->Flags.reset(DevicePaused);
3903 if(dev->mContexts.load()->empty())
3904 return;
3906 try {
3907 auto backend = dev->Backend.get();
3908 backend->start();
3909 dev->Flags.set(DeviceRunning);
3911 catch(al::backend_exception& e) {
3912 ERR("%s\n", e.what());
3913 dev->handleDisconnect("%s", e.what());
3914 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3915 return;
3917 TRACE("Post-resume: %s, %s, %uhz, %u / %u buffer\n",
3918 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
3919 device->Frequency, device->UpdateSize, device->BufferSize);
3921 END_API_FUNC
3924 /************************************************
3925 * ALC HRTF functions
3926 ************************************************/
3928 /** Gets a string parameter at the given index. */
3929 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
3930 START_API_FUNC
3932 DeviceRef dev{VerifyDevice(device)};
3933 if(!dev || dev->Type == DeviceType::Capture)
3934 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3935 else switch(paramName)
3937 case ALC_HRTF_SPECIFIER_SOFT:
3938 if(index >= 0 && static_cast<uint>(index) < dev->mHrtfList.size())
3939 return dev->mHrtfList[static_cast<uint>(index)].c_str();
3940 alcSetError(dev.get(), ALC_INVALID_VALUE);
3941 break;
3943 default:
3944 alcSetError(dev.get(), ALC_INVALID_ENUM);
3945 break;
3948 return nullptr;
3950 END_API_FUNC
3952 /** Resets the given device output, using the specified attribute list. */
3953 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
3954 START_API_FUNC
3956 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3957 DeviceRef dev{VerifyDevice(device)};
3958 if(!dev || dev->Type == DeviceType::Capture)
3960 listlock.unlock();
3961 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3962 return ALC_FALSE;
3964 std::lock_guard<std::mutex> _{dev->StateLock};
3965 listlock.unlock();
3967 /* Force the backend to stop mixing first since we're resetting. Also reset
3968 * the connected state so lost devices can attempt recover.
3970 if(dev->Flags.test(DeviceRunning))
3971 dev->Backend->stop();
3972 dev->Flags.reset(DeviceRunning);
3974 return ResetDeviceParams(dev.get(), attribs) ? ALC_TRUE : ALC_FALSE;
3976 END_API_FUNC
3979 /************************************************
3980 * ALC device reopen functions
3981 ************************************************/
3983 /** Reopens the given device output, using the specified name and attribute list. */
3984 FORCE_ALIGN ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device,
3985 const ALCchar *deviceName, const ALCint *attribs)
3986 START_API_FUNC
3988 if(deviceName)
3990 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0)
3991 deviceName = nullptr;
3994 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3995 DeviceRef dev{VerifyDevice(device)};
3996 if(!dev || dev->Type != DeviceType::Playback)
3998 listlock.unlock();
3999 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4000 return ALC_FALSE;
4002 std::lock_guard<std::mutex> _{dev->StateLock};
4004 /* Force the backend to stop mixing first since we're reopening. */
4005 if(dev->Flags.test(DeviceRunning))
4007 auto backend = dev->Backend.get();
4008 backend->stop();
4009 dev->Flags.reset(DeviceRunning);
4012 BackendPtr newbackend;
4013 try {
4014 newbackend = PlaybackFactory->createBackend(dev.get(), BackendType::Playback);
4015 newbackend->open(deviceName);
4017 catch(al::backend_exception &e) {
4018 listlock.unlock();
4019 newbackend = nullptr;
4021 WARN("Failed to reopen playback device: %s\n", e.what());
4022 alcSetError(dev.get(), (e.errorCode() == al::backend_error::OutOfMemory)
4023 ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
4025 /* If the device is connected, not paused, and has contexts, ensure it
4026 * continues playing.
4028 if(dev->Connected.load(std::memory_order_relaxed) && !dev->Flags.test(DevicePaused)
4029 && !dev->mContexts.load(std::memory_order_relaxed)->empty())
4031 try {
4032 auto backend = dev->Backend.get();
4033 backend->start();
4034 dev->Flags.set(DeviceRunning);
4036 catch(al::backend_exception &be) {
4037 ERR("%s\n", be.what());
4038 dev->handleDisconnect("%s", be.what());
4041 return ALC_FALSE;
4043 listlock.unlock();
4044 dev->Backend = std::move(newbackend);
4045 TRACE("Reopened device %p, \"%s\"\n", voidp{dev.get()}, dev->DeviceName.c_str());
4047 /* Always return true even if resetting fails. It shouldn't fail, but this
4048 * is primarily to avoid confusion by the app seeing the function return
4049 * false while the device is on the new output anyway. We could try to
4050 * restore the old backend if this fails, but the configuration would be
4051 * changed with the new backend and would need to be reset again with the
4052 * old one, and the provided attributes may not be appropriate or desirable
4053 * for the old device.
4055 * In this way, we essentially act as if the function succeeded, but
4056 * immediately disconnects following it.
4058 ResetDeviceParams(dev.get(), attribs);
4059 return ALC_TRUE;
4061 END_API_FUNC