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.
8 *
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.
13 *
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
19 */
20
21 #include "config.h"
22
23 #include "version.h"
24
25 #ifdef _WIN32
26 #define WIN32_LEAN_AND_MEAN
27 #include <windows.h>
28 #endif
29
30 #include <exception>
31 #include <algorithm>
32 #include <array>
33 #include <atomic>
34 #include <cctype>
35 #include <chrono>
36 #include <cinttypes>
37 #include <climits>
38 #include <cmath>
39 #include <csignal>
40 #include <cstdint>
41 #include <cstdio>
42 #include <cstdlib>
43 #include <cstring>
44 #include <functional>
45 #include <iterator>
46 #include <limits>
47 #include <memory>
48 #include <mutex>
49 #include <new>
50 #include <numeric>
51 #include <string>
52 #include <thread>
53 #include <utility>
54
55 #include "AL/al.h"
56 #include "AL/alc.h"
57 #include "AL/alext.h"
58 #include "AL/efx.h"
59
60 #include "al/auxeffectslot.h"
61 #include "al/buffer.h"
62 #include "al/effect.h"
63 #include "al/event.h"
64 #include "al/filter.h"
65 #include "al/listener.h"
66 #include "al/source.h"
67 #include "albit.h"
68 #include "alcmain.h"
69 #include "albyte.h"
70 #include "alconfig.h"
71 #include "alcontext.h"
72 #include "almalloc.h"
73 #include "alnumeric.h"
74 #include "aloptional.h"
75 #include "alspan.h"
76 #include "alstring.h"
77 #include "alu.h"
78 #include "async_event.h"
79 #include "atomic.h"
80 #include "bformatdec.h"
81 #include "compat.h"
82 #include "core/ambidefs.h"
83 #include "core/bs2b.h"
84 #include "core/cpu_caps.h"
85 #include "core/devformat.h"
86 #include "core/except.h"
87 #include "core/mastering.h"
88 #include "core/filters/nfc.h"
89 #include "core/filters/splitter.h"
90 #include "core/fpu_ctrl.h"
91 #include "core/logging.h"
92 #include "core/uhjfilter.h"
93 #include "effects/base.h"
94 #include "front_stablizer.h"
95 #include "hrtf.h"
96 #include "inprogext.h"
97 #include "intrusive_ptr.h"
98 #include "opthelpers.h"
99 #include "pragmadefs.h"
100 #include "ringbuffer.h"
101 #include "strutils.h"
102 #include "threads.h"
103 #include "vecmat.h"
104 #include "vector.h"
105 #include "voice_change.h"
106
107 #include "backends/base.h"
108 #include "backends/null.h"
109 #include "backends/loopback.h"
110 #ifdef HAVE_JACK
111 #include "backends/jack.h"
112 #endif
113 #ifdef HAVE_PULSEAUDIO
114 #include "backends/pulseaudio.h"
115 #endif
116 #ifdef HAVE_ALSA
117 #include "backends/alsa.h"
118 #endif
119 #ifdef HAVE_WASAPI
120 #include "backends/wasapi.h"
121 #endif
122 #ifdef HAVE_COREAUDIO
123 #include "backends/coreaudio.h"
124 #endif
125 #ifdef HAVE_OPENSL
126 #include "backends/opensl.h"
127 #endif
128 #ifdef HAVE_OBOE
129 #include "backends/oboe.h"
130 #endif
131 #ifdef HAVE_SOLARIS
132 #include "backends/solaris.h"
133 #endif
134 #ifdef HAVE_SNDIO
135 #include "backends/sndio.h"
136 #endif
137 #ifdef HAVE_OSS
138 #include "backends/oss.h"
139 #endif
140 #ifdef HAVE_DSOUND
141 #include "backends/dsound.h"
142 #endif
143 #ifdef HAVE_WINMM
144 #include "backends/winmm.h"
145 #endif
146 #ifdef HAVE_PORTAUDIO
147 #include "backends/portaudio.h"
148 #endif
149 #ifdef HAVE_SDL2
150 #include "backends/sdl2.h"
151 #endif
152 #ifdef HAVE_WAVE
153 #include "backends/wave.h"
154 #endif
155
156
157 namespace {
158
159 using namespace std::placeholders;
160 using std::chrono::seconds;
161 using std::chrono::nanoseconds;
162
163 using voidp = void*;
164
165
166 /************************************************
167 * Backends
168 ************************************************/
169 struct BackendInfo {
170 const char *name;
171 BackendFactory& (*getFactory)(void);
172 };
173
174 BackendInfo BackendList[] = {
175 #ifdef HAVE_JACK
176 { "jack", JackBackendFactory::getFactory },
177 #endif
178 #ifdef HAVE_PULSEAUDIO
179 { "pulse", PulseBackendFactory::getFactory },
180 #endif
181 #ifdef HAVE_ALSA
182 { "alsa", AlsaBackendFactory::getFactory },
183 #endif
184 #ifdef HAVE_WASAPI
185 { "wasapi", WasapiBackendFactory::getFactory },
186 #endif
187 #ifdef HAVE_COREAUDIO
188 { "core", CoreAudioBackendFactory::getFactory },
189 #endif
190 #ifdef HAVE_OBOE
191 { "oboe", OboeBackendFactory::getFactory },
192 #endif
193 #ifdef HAVE_OPENSL
194 { "opensl", OSLBackendFactory::getFactory },
195 #endif
196 #ifdef HAVE_SOLARIS
197 { "solaris", SolarisBackendFactory::getFactory },
198 #endif
199 #ifdef HAVE_SNDIO
200 { "sndio", SndIOBackendFactory::getFactory },
201 #endif
202 #ifdef HAVE_OSS
203 { "oss", OSSBackendFactory::getFactory },
204 #endif
205 #ifdef HAVE_DSOUND
206 { "dsound", DSoundBackendFactory::getFactory },
207 #endif
208 #ifdef HAVE_WINMM
209 { "winmm", WinMMBackendFactory::getFactory },
210 #endif
211 #ifdef HAVE_PORTAUDIO
212 { "port", PortBackendFactory::getFactory },
213 #endif
214 #ifdef HAVE_SDL2
215 { "sdl2", SDL2BackendFactory::getFactory },
216 #endif
217
218 { "null", NullBackendFactory::getFactory },
219 #ifdef HAVE_WAVE
220 { "wave", WaveBackendFactory::getFactory },
221 #endif
222 };
223
224 BackendFactory *PlaybackFactory{};
225 BackendFactory *CaptureFactory{};
226
227
228 /************************************************
229 * Functions, enums, and errors
230 ************************************************/
231 #define DECL(x) { #x, reinterpret_cast<void*>(x) }
232 const struct {
233 const char *funcName;
234 void *address;
235 } alcFunctions[] = {
236 DECL(alcCreateContext),
237 DECL(alcMakeContextCurrent),
238 DECL(alcProcessContext),
239 DECL(alcSuspendContext),
240 DECL(alcDestroyContext),
241 DECL(alcGetCurrentContext),
242 DECL(alcGetContextsDevice),
243 DECL(alcOpenDevice),
244 DECL(alcCloseDevice),
245 DECL(alcGetError),
246 DECL(alcIsExtensionPresent),
247 DECL(alcGetProcAddress),
248 DECL(alcGetEnumValue),
249 DECL(alcGetString),
250 DECL(alcGetIntegerv),
251 DECL(alcCaptureOpenDevice),
252 DECL(alcCaptureCloseDevice),
253 DECL(alcCaptureStart),
254 DECL(alcCaptureStop),
255 DECL(alcCaptureSamples),
256
257 DECL(alcSetThreadContext),
258 DECL(alcGetThreadContext),
259
260 DECL(alcLoopbackOpenDeviceSOFT),
261 DECL(alcIsRenderFormatSupportedSOFT),
262 DECL(alcRenderSamplesSOFT),
263
264 DECL(alcDevicePauseSOFT),
265 DECL(alcDeviceResumeSOFT),
266
267 DECL(alcGetStringiSOFT),
268 DECL(alcResetDeviceSOFT),
269
270 DECL(alcGetInteger64vSOFT),
271
272 DECL(alEnable),
273 DECL(alDisable),
274 DECL(alIsEnabled),
275 DECL(alGetString),
276 DECL(alGetBooleanv),
277 DECL(alGetIntegerv),
278 DECL(alGetFloatv),
279 DECL(alGetDoublev),
280 DECL(alGetBoolean),
281 DECL(alGetInteger),
282 DECL(alGetFloat),
283 DECL(alGetDouble),
284 DECL(alGetError),
285 DECL(alIsExtensionPresent),
286 DECL(alGetProcAddress),
287 DECL(alGetEnumValue),
288 DECL(alListenerf),
289 DECL(alListener3f),
290 DECL(alListenerfv),
291 DECL(alListeneri),
292 DECL(alListener3i),
293 DECL(alListeneriv),
294 DECL(alGetListenerf),
295 DECL(alGetListener3f),
296 DECL(alGetListenerfv),
297 DECL(alGetListeneri),
298 DECL(alGetListener3i),
299 DECL(alGetListeneriv),
300 DECL(alGenSources),
301 DECL(alDeleteSources),
302 DECL(alIsSource),
303 DECL(alSourcef),
304 DECL(alSource3f),
305 DECL(alSourcefv),
306 DECL(alSourcei),
307 DECL(alSource3i),
308 DECL(alSourceiv),
309 DECL(alGetSourcef),
310 DECL(alGetSource3f),
311 DECL(alGetSourcefv),
312 DECL(alGetSourcei),
313 DECL(alGetSource3i),
314 DECL(alGetSourceiv),
315 DECL(alSourcePlayv),
316 DECL(alSourceStopv),
317 DECL(alSourceRewindv),
318 DECL(alSourcePausev),
319 DECL(alSourcePlay),
320 DECL(alSourceStop),
321 DECL(alSourceRewind),
322 DECL(alSourcePause),
323 DECL(alSourceQueueBuffers),
324 DECL(alSourceUnqueueBuffers),
325 DECL(alGenBuffers),
326 DECL(alDeleteBuffers),
327 DECL(alIsBuffer),
328 DECL(alBufferData),
329 DECL(alBufferf),
330 DECL(alBuffer3f),
331 DECL(alBufferfv),
332 DECL(alBufferi),
333 DECL(alBuffer3i),
334 DECL(alBufferiv),
335 DECL(alGetBufferf),
336 DECL(alGetBuffer3f),
337 DECL(alGetBufferfv),
338 DECL(alGetBufferi),
339 DECL(alGetBuffer3i),
340 DECL(alGetBufferiv),
341 DECL(alDopplerFactor),
342 DECL(alDopplerVelocity),
343 DECL(alSpeedOfSound),
344 DECL(alDistanceModel),
345
346 DECL(alGenFilters),
347 DECL(alDeleteFilters),
348 DECL(alIsFilter),
349 DECL(alFilteri),
350 DECL(alFilteriv),
351 DECL(alFilterf),
352 DECL(alFilterfv),
353 DECL(alGetFilteri),
354 DECL(alGetFilteriv),
355 DECL(alGetFilterf),
356 DECL(alGetFilterfv),
357 DECL(alGenEffects),
358 DECL(alDeleteEffects),
359 DECL(alIsEffect),
360 DECL(alEffecti),
361 DECL(alEffectiv),
362 DECL(alEffectf),
363 DECL(alEffectfv),
364 DECL(alGetEffecti),
365 DECL(alGetEffectiv),
366 DECL(alGetEffectf),
367 DECL(alGetEffectfv),
368 DECL(alGenAuxiliaryEffectSlots),
369 DECL(alDeleteAuxiliaryEffectSlots),
370 DECL(alIsAuxiliaryEffectSlot),
371 DECL(alAuxiliaryEffectSloti),
372 DECL(alAuxiliaryEffectSlotiv),
373 DECL(alAuxiliaryEffectSlotf),
374 DECL(alAuxiliaryEffectSlotfv),
375 DECL(alGetAuxiliaryEffectSloti),
376 DECL(alGetAuxiliaryEffectSlotiv),
377 DECL(alGetAuxiliaryEffectSlotf),
378 DECL(alGetAuxiliaryEffectSlotfv),
379
380 DECL(alDeferUpdatesSOFT),
381 DECL(alProcessUpdatesSOFT),
382
383 DECL(alSourcedSOFT),
384 DECL(alSource3dSOFT),
385 DECL(alSourcedvSOFT),
386 DECL(alGetSourcedSOFT),
387 DECL(alGetSource3dSOFT),
388 DECL(alGetSourcedvSOFT),
389 DECL(alSourcei64SOFT),
390 DECL(alSource3i64SOFT),
391 DECL(alSourcei64vSOFT),
392 DECL(alGetSourcei64SOFT),
393 DECL(alGetSource3i64SOFT),
394 DECL(alGetSourcei64vSOFT),
395
396 DECL(alGetStringiSOFT),
397
398 DECL(alBufferStorageSOFT),
399 DECL(alMapBufferSOFT),
400 DECL(alUnmapBufferSOFT),
401 DECL(alFlushMappedBufferSOFT),
402
403 DECL(alEventControlSOFT),
404 DECL(alEventCallbackSOFT),
405 DECL(alGetPointerSOFT),
406 DECL(alGetPointervSOFT),
407
408 DECL(alBufferCallbackSOFT),
409 DECL(alGetBufferPtrSOFT),
410 DECL(alGetBuffer3PtrSOFT),
411 DECL(alGetBufferPtrvSOFT),
412
413 DECL(alAuxiliaryEffectSlotPlaySOFT),
414 DECL(alAuxiliaryEffectSlotPlayvSOFT),
415 DECL(alAuxiliaryEffectSlotStopSOFT),
416 DECL(alAuxiliaryEffectSlotStopvSOFT),
417 };
418 #undef DECL
419
420 #define DECL(x) { #x, (x) }
421 constexpr struct {
422 const ALCchar *enumName;
423 ALCenum value;
424 } alcEnumerations[] = {
425 DECL(ALC_INVALID),
426 DECL(ALC_FALSE),
427 DECL(ALC_TRUE),
428
429 DECL(ALC_MAJOR_VERSION),
430 DECL(ALC_MINOR_VERSION),
431 DECL(ALC_ATTRIBUTES_SIZE),
432 DECL(ALC_ALL_ATTRIBUTES),
433 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
434 DECL(ALC_DEVICE_SPECIFIER),
435 DECL(ALC_ALL_DEVICES_SPECIFIER),
436 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
437 DECL(ALC_EXTENSIONS),
438 DECL(ALC_FREQUENCY),
439 DECL(ALC_REFRESH),
440 DECL(ALC_SYNC),
441 DECL(ALC_MONO_SOURCES),
442 DECL(ALC_STEREO_SOURCES),
443 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
444 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
445 DECL(ALC_CAPTURE_SAMPLES),
446 DECL(ALC_CONNECTED),
447
448 DECL(ALC_EFX_MAJOR_VERSION),
449 DECL(ALC_EFX_MINOR_VERSION),
450 DECL(ALC_MAX_AUXILIARY_SENDS),
451
452 DECL(ALC_FORMAT_CHANNELS_SOFT),
453 DECL(ALC_FORMAT_TYPE_SOFT),
454
455 DECL(ALC_MONO_SOFT),
456 DECL(ALC_STEREO_SOFT),
457 DECL(ALC_QUAD_SOFT),
458 DECL(ALC_5POINT1_SOFT),
459 DECL(ALC_6POINT1_SOFT),
460 DECL(ALC_7POINT1_SOFT),
461 DECL(ALC_BFORMAT3D_SOFT),
462
463 DECL(ALC_BYTE_SOFT),
464 DECL(ALC_UNSIGNED_BYTE_SOFT),
465 DECL(ALC_SHORT_SOFT),
466 DECL(ALC_UNSIGNED_SHORT_SOFT),
467 DECL(ALC_INT_SOFT),
468 DECL(ALC_UNSIGNED_INT_SOFT),
469 DECL(ALC_FLOAT_SOFT),
470
471 DECL(ALC_HRTF_SOFT),
472 DECL(ALC_DONT_CARE_SOFT),
473 DECL(ALC_HRTF_STATUS_SOFT),
474 DECL(ALC_HRTF_DISABLED_SOFT),
475 DECL(ALC_HRTF_ENABLED_SOFT),
476 DECL(ALC_HRTF_DENIED_SOFT),
477 DECL(ALC_HRTF_REQUIRED_SOFT),
478 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
479 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
480 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
481 DECL(ALC_HRTF_SPECIFIER_SOFT),
482 DECL(ALC_HRTF_ID_SOFT),
483
484 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
485 DECL(ALC_AMBISONIC_SCALING_SOFT),
486 DECL(ALC_AMBISONIC_ORDER_SOFT),
487 DECL(ALC_ACN_SOFT),
488 DECL(ALC_FUMA_SOFT),
489 DECL(ALC_N3D_SOFT),
490 DECL(ALC_SN3D_SOFT),
491
492 DECL(ALC_OUTPUT_LIMITER_SOFT),
493
494 DECL(ALC_NO_ERROR),
495 DECL(ALC_INVALID_DEVICE),
496 DECL(ALC_INVALID_CONTEXT),
497 DECL(ALC_INVALID_ENUM),
498 DECL(ALC_INVALID_VALUE),
499 DECL(ALC_OUT_OF_MEMORY),
500
501
502 DECL(AL_INVALID),
503 DECL(AL_NONE),
504 DECL(AL_FALSE),
505 DECL(AL_TRUE),
506
507 DECL(AL_SOURCE_RELATIVE),
508 DECL(AL_CONE_INNER_ANGLE),
509 DECL(AL_CONE_OUTER_ANGLE),
510 DECL(AL_PITCH),
511 DECL(AL_POSITION),
512 DECL(AL_DIRECTION),
513 DECL(AL_VELOCITY),
514 DECL(AL_LOOPING),
515 DECL(AL_BUFFER),
516 DECL(AL_GAIN),
517 DECL(AL_MIN_GAIN),
518 DECL(AL_MAX_GAIN),
519 DECL(AL_ORIENTATION),
520 DECL(AL_REFERENCE_DISTANCE),
521 DECL(AL_ROLLOFF_FACTOR),
522 DECL(AL_CONE_OUTER_GAIN),
523 DECL(AL_MAX_DISTANCE),
524 DECL(AL_SEC_OFFSET),
525 DECL(AL_SAMPLE_OFFSET),
526 DECL(AL_BYTE_OFFSET),
527 DECL(AL_SOURCE_TYPE),
528 DECL(AL_STATIC),
529 DECL(AL_STREAMING),
530 DECL(AL_UNDETERMINED),
531 DECL(AL_METERS_PER_UNIT),
532 DECL(AL_LOOP_POINTS_SOFT),
533 DECL(AL_DIRECT_CHANNELS_SOFT),
534
535 DECL(AL_DIRECT_FILTER),
536 DECL(AL_AUXILIARY_SEND_FILTER),
537 DECL(AL_AIR_ABSORPTION_FACTOR),
538 DECL(AL_ROOM_ROLLOFF_FACTOR),
539 DECL(AL_CONE_OUTER_GAINHF),
540 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
541 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
542 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
543
544 DECL(AL_SOURCE_STATE),
545 DECL(AL_INITIAL),
546 DECL(AL_PLAYING),
547 DECL(AL_PAUSED),
548 DECL(AL_STOPPED),
549
550 DECL(AL_BUFFERS_QUEUED),
551 DECL(AL_BUFFERS_PROCESSED),
552
553 DECL(AL_FORMAT_MONO8),
554 DECL(AL_FORMAT_MONO16),
555 DECL(AL_FORMAT_MONO_FLOAT32),
556 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
557 DECL(AL_FORMAT_STEREO8),
558 DECL(AL_FORMAT_STEREO16),
559 DECL(AL_FORMAT_STEREO_FLOAT32),
560 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
561 DECL(AL_FORMAT_MONO_IMA4),
562 DECL(AL_FORMAT_STEREO_IMA4),
563 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
564 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
565 DECL(AL_FORMAT_QUAD8_LOKI),
566 DECL(AL_FORMAT_QUAD16_LOKI),
567 DECL(AL_FORMAT_QUAD8),
568 DECL(AL_FORMAT_QUAD16),
569 DECL(AL_FORMAT_QUAD32),
570 DECL(AL_FORMAT_51CHN8),
571 DECL(AL_FORMAT_51CHN16),
572 DECL(AL_FORMAT_51CHN32),
573 DECL(AL_FORMAT_61CHN8),
574 DECL(AL_FORMAT_61CHN16),
575 DECL(AL_FORMAT_61CHN32),
576 DECL(AL_FORMAT_71CHN8),
577 DECL(AL_FORMAT_71CHN16),
578 DECL(AL_FORMAT_71CHN32),
579 DECL(AL_FORMAT_REAR8),
580 DECL(AL_FORMAT_REAR16),
581 DECL(AL_FORMAT_REAR32),
582 DECL(AL_FORMAT_MONO_MULAW),
583 DECL(AL_FORMAT_MONO_MULAW_EXT),
584 DECL(AL_FORMAT_STEREO_MULAW),
585 DECL(AL_FORMAT_STEREO_MULAW_EXT),
586 DECL(AL_FORMAT_QUAD_MULAW),
587 DECL(AL_FORMAT_51CHN_MULAW),
588 DECL(AL_FORMAT_61CHN_MULAW),
589 DECL(AL_FORMAT_71CHN_MULAW),
590 DECL(AL_FORMAT_REAR_MULAW),
591 DECL(AL_FORMAT_MONO_ALAW_EXT),
592 DECL(AL_FORMAT_STEREO_ALAW_EXT),
593
594 DECL(AL_FORMAT_BFORMAT2D_8),
595 DECL(AL_FORMAT_BFORMAT2D_16),
596 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
597 DECL(AL_FORMAT_BFORMAT2D_MULAW),
598 DECL(AL_FORMAT_BFORMAT3D_8),
599 DECL(AL_FORMAT_BFORMAT3D_16),
600 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
601 DECL(AL_FORMAT_BFORMAT3D_MULAW),
602
603 DECL(AL_FREQUENCY),
604 DECL(AL_BITS),
605 DECL(AL_CHANNELS),
606 DECL(AL_SIZE),
607 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
608 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
609
610 DECL(AL_SOURCE_RADIUS),
611
612 DECL(AL_STEREO_ANGLES),
613
614 DECL(AL_UNUSED),
615 DECL(AL_PENDING),
616 DECL(AL_PROCESSED),
617
618 DECL(AL_NO_ERROR),
619 DECL(AL_INVALID_NAME),
620 DECL(AL_INVALID_ENUM),
621 DECL(AL_INVALID_VALUE),
622 DECL(AL_INVALID_OPERATION),
623 DECL(AL_OUT_OF_MEMORY),
624
625 DECL(AL_VENDOR),
626 DECL(AL_VERSION),
627 DECL(AL_RENDERER),
628 DECL(AL_EXTENSIONS),
629
630 DECL(AL_DOPPLER_FACTOR),
631 DECL(AL_DOPPLER_VELOCITY),
632 DECL(AL_DISTANCE_MODEL),
633 DECL(AL_SPEED_OF_SOUND),
634 DECL(AL_SOURCE_DISTANCE_MODEL),
635 DECL(AL_DEFERRED_UPDATES_SOFT),
636 DECL(AL_GAIN_LIMIT_SOFT),
637
638 DECL(AL_INVERSE_DISTANCE),
639 DECL(AL_INVERSE_DISTANCE_CLAMPED),
640 DECL(AL_LINEAR_DISTANCE),
641 DECL(AL_LINEAR_DISTANCE_CLAMPED),
642 DECL(AL_EXPONENT_DISTANCE),
643 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
644
645 DECL(AL_FILTER_TYPE),
646 DECL(AL_FILTER_NULL),
647 DECL(AL_FILTER_LOWPASS),
648 DECL(AL_FILTER_HIGHPASS),
649 DECL(AL_FILTER_BANDPASS),
650
651 DECL(AL_LOWPASS_GAIN),
652 DECL(AL_LOWPASS_GAINHF),
653
654 DECL(AL_HIGHPASS_GAIN),
655 DECL(AL_HIGHPASS_GAINLF),
656
657 DECL(AL_BANDPASS_GAIN),
658 DECL(AL_BANDPASS_GAINHF),
659 DECL(AL_BANDPASS_GAINLF),
660
661 DECL(AL_EFFECT_TYPE),
662 DECL(AL_EFFECT_NULL),
663 DECL(AL_EFFECT_REVERB),
664 DECL(AL_EFFECT_EAXREVERB),
665 DECL(AL_EFFECT_CHORUS),
666 DECL(AL_EFFECT_DISTORTION),
667 DECL(AL_EFFECT_ECHO),
668 DECL(AL_EFFECT_FLANGER),
669 DECL(AL_EFFECT_PITCH_SHIFTER),
670 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
671 DECL(AL_EFFECT_VOCAL_MORPHER),
672 DECL(AL_EFFECT_RING_MODULATOR),
673 DECL(AL_EFFECT_AUTOWAH),
674 DECL(AL_EFFECT_COMPRESSOR),
675 DECL(AL_EFFECT_EQUALIZER),
676 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
677 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
678
679 DECL(AL_EFFECTSLOT_EFFECT),
680 DECL(AL_EFFECTSLOT_GAIN),
681 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
682 DECL(AL_EFFECTSLOT_NULL),
683
684 DECL(AL_EAXREVERB_DENSITY),
685 DECL(AL_EAXREVERB_DIFFUSION),
686 DECL(AL_EAXREVERB_GAIN),
687 DECL(AL_EAXREVERB_GAINHF),
688 DECL(AL_EAXREVERB_GAINLF),
689 DECL(AL_EAXREVERB_DECAY_TIME),
690 DECL(AL_EAXREVERB_DECAY_HFRATIO),
691 DECL(AL_EAXREVERB_DECAY_LFRATIO),
692 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
693 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
694 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
695 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
696 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
697 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
698 DECL(AL_EAXREVERB_ECHO_TIME),
699 DECL(AL_EAXREVERB_ECHO_DEPTH),
700 DECL(AL_EAXREVERB_MODULATION_TIME),
701 DECL(AL_EAXREVERB_MODULATION_DEPTH),
702 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
703 DECL(AL_EAXREVERB_HFREFERENCE),
704 DECL(AL_EAXREVERB_LFREFERENCE),
705 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
706 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
707
708 DECL(AL_REVERB_DENSITY),
709 DECL(AL_REVERB_DIFFUSION),
710 DECL(AL_REVERB_GAIN),
711 DECL(AL_REVERB_GAINHF),
712 DECL(AL_REVERB_DECAY_TIME),
713 DECL(AL_REVERB_DECAY_HFRATIO),
714 DECL(AL_REVERB_REFLECTIONS_GAIN),
715 DECL(AL_REVERB_REFLECTIONS_DELAY),
716 DECL(AL_REVERB_LATE_REVERB_GAIN),
717 DECL(AL_REVERB_LATE_REVERB_DELAY),
718 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
719 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
720 DECL(AL_REVERB_DECAY_HFLIMIT),
721
722 DECL(AL_CHORUS_WAVEFORM),
723 DECL(AL_CHORUS_PHASE),
724 DECL(AL_CHORUS_RATE),
725 DECL(AL_CHORUS_DEPTH),
726 DECL(AL_CHORUS_FEEDBACK),
727 DECL(AL_CHORUS_DELAY),
728
729 DECL(AL_DISTORTION_EDGE),
730 DECL(AL_DISTORTION_GAIN),
731 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
732 DECL(AL_DISTORTION_EQCENTER),
733 DECL(AL_DISTORTION_EQBANDWIDTH),
734
735 DECL(AL_ECHO_DELAY),
736 DECL(AL_ECHO_LRDELAY),
737 DECL(AL_ECHO_DAMPING),
738 DECL(AL_ECHO_FEEDBACK),
739 DECL(AL_ECHO_SPREAD),
740
741 DECL(AL_FLANGER_WAVEFORM),
742 DECL(AL_FLANGER_PHASE),
743 DECL(AL_FLANGER_RATE),
744 DECL(AL_FLANGER_DEPTH),
745 DECL(AL_FLANGER_FEEDBACK),
746 DECL(AL_FLANGER_DELAY),
747
748 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY),
749 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION),
750 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION),
751
752 DECL(AL_RING_MODULATOR_FREQUENCY),
753 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
754 DECL(AL_RING_MODULATOR_WAVEFORM),
755
756 DECL(AL_PITCH_SHIFTER_COARSE_TUNE),
757 DECL(AL_PITCH_SHIFTER_FINE_TUNE),
758
759 DECL(AL_COMPRESSOR_ONOFF),
760
761 DECL(AL_EQUALIZER_LOW_GAIN),
762 DECL(AL_EQUALIZER_LOW_CUTOFF),
763 DECL(AL_EQUALIZER_MID1_GAIN),
764 DECL(AL_EQUALIZER_MID1_CENTER),
765 DECL(AL_EQUALIZER_MID1_WIDTH),
766 DECL(AL_EQUALIZER_MID2_GAIN),
767 DECL(AL_EQUALIZER_MID2_CENTER),
768 DECL(AL_EQUALIZER_MID2_WIDTH),
769 DECL(AL_EQUALIZER_HIGH_GAIN),
770 DECL(AL_EQUALIZER_HIGH_CUTOFF),
771
772 DECL(AL_DEDICATED_GAIN),
773
774 DECL(AL_AUTOWAH_ATTACK_TIME),
775 DECL(AL_AUTOWAH_RELEASE_TIME),
776 DECL(AL_AUTOWAH_RESONANCE),
777 DECL(AL_AUTOWAH_PEAK_GAIN),
778
779 DECL(AL_VOCAL_MORPHER_PHONEMEA),
780 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING),
781 DECL(AL_VOCAL_MORPHER_PHONEMEB),
782 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING),
783 DECL(AL_VOCAL_MORPHER_WAVEFORM),
784 DECL(AL_VOCAL_MORPHER_RATE),
785
786 DECL(AL_EFFECTSLOT_TARGET_SOFT),
787
788 DECL(AL_NUM_RESAMPLERS_SOFT),
789 DECL(AL_DEFAULT_RESAMPLER_SOFT),
790 DECL(AL_SOURCE_RESAMPLER_SOFT),
791 DECL(AL_RESAMPLER_NAME_SOFT),
792
793 DECL(AL_SOURCE_SPATIALIZE_SOFT),
794 DECL(AL_AUTO_SOFT),
795
796 DECL(AL_MAP_READ_BIT_SOFT),
797 DECL(AL_MAP_WRITE_BIT_SOFT),
798 DECL(AL_MAP_PERSISTENT_BIT_SOFT),
799 DECL(AL_PRESERVE_DATA_BIT_SOFT),
800
801 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT),
802 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT),
803 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT),
804 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT),
805 DECL(AL_EVENT_TYPE_DISCONNECTED_SOFT),
806
807 DECL(AL_DROP_UNMATCHED_SOFT),
808 DECL(AL_REMIX_UNMATCHED_SOFT),
809
810 DECL(AL_AMBISONIC_LAYOUT_SOFT),
811 DECL(AL_AMBISONIC_SCALING_SOFT),
812 DECL(AL_FUMA_SOFT),
813 DECL(AL_ACN_SOFT),
814 DECL(AL_SN3D_SOFT),
815 DECL(AL_N3D_SOFT),
816
817 DECL(AL_BUFFER_CALLBACK_FUNCTION_SOFT),
818 DECL(AL_BUFFER_CALLBACK_USER_PARAM_SOFT),
819
820 DECL(AL_UNPACK_AMBISONIC_ORDER_SOFT),
821
822 DECL(AL_EFFECT_CONVOLUTION_REVERB_SOFT),
823 DECL(AL_EFFECTSLOT_STATE_SOFT),
824 };
825 #undef DECL
826
827 constexpr ALCchar alcNoError[] = "No Error";
828 constexpr ALCchar alcErrInvalidDevice[] = "Invalid Device";
829 constexpr ALCchar alcErrInvalidContext[] = "Invalid Context";
830 constexpr ALCchar alcErrInvalidEnum[] = "Invalid Enum";
831 constexpr ALCchar alcErrInvalidValue[] = "Invalid Value";
832 constexpr ALCchar alcErrOutOfMemory[] = "Out of Memory";
833
834
835 /************************************************
836 * Global variables
837 ************************************************/
838
839 /* Enumerated device names */
840 constexpr ALCchar alcDefaultName[] = "OpenAL Soft\0";
841
842 std::string alcAllDevicesList;
843 std::string alcCaptureDeviceList;
844
845 /* Default is always the first in the list */
846 al::string alcDefaultAllDevicesSpecifier;
847 al::string alcCaptureDefaultDeviceSpecifier;
848
849 /* Default context extensions */
850 constexpr ALchar alExtList[] =
851 "AL_EXT_ALAW "
852 "AL_EXT_BFORMAT "
853 "AL_EXT_DOUBLE "
854 "AL_EXT_EXPONENT_DISTANCE "
855 "AL_EXT_FLOAT32 "
856 "AL_EXT_IMA4 "
857 "AL_EXT_LINEAR_DISTANCE "
858 "AL_EXT_MCFORMATS "
859 "AL_EXT_MULAW "
860 "AL_EXT_MULAW_BFORMAT "
861 "AL_EXT_MULAW_MCFORMATS "
862 "AL_EXT_OFFSET "
863 "AL_EXT_source_distance_model "
864 "AL_EXT_SOURCE_RADIUS "
865 "AL_EXT_STEREO_ANGLES "
866 "AL_LOKI_quadriphonic "
867 "AL_SOFT_bformat_ex "
868 "AL_SOFTX_bformat_hoa "
869 "AL_SOFT_block_alignment "
870 "AL_SOFTX_callback_buffer "
871 "AL_SOFTX_convolution_reverb "
872 "AL_SOFT_deferred_updates "
873 "AL_SOFT_direct_channels "
874 "AL_SOFT_direct_channels_remix "
875 "AL_SOFT_effect_target "
876 "AL_SOFT_events "
877 "AL_SOFTX_filter_gain_ex "
878 "AL_SOFT_gain_clamp_ex "
879 "AL_SOFT_loop_points "
880 "AL_SOFTX_map_buffer "
881 "AL_SOFT_MSADPCM "
882 "AL_SOFT_source_latency "
883 "AL_SOFT_source_length "
884 "AL_SOFT_source_resampler "
885 "AL_SOFT_source_spatialize";
886
887 std::atomic<ALCenum> LastNullDeviceError{ALC_NO_ERROR};
888
889 /* Thread-local current context. The handling may look a little obtuse, but
890 * it's designed this way to avoid a bug with 32-bit GCC/MinGW, which causes
891 * thread-local object destructors to get a junk 'this' pointer. This method
892 * has the benefit of making LocalContext access more efficient since it's a
893 * a plain pointer, with the ThreadContext object used to check it at thread
894 * exit (and given no data fields, 'this' being junk is inconsequential since
895 * it's never accessed).
896 */
897 thread_local ALCcontext *LocalContext{nullptr};
898 class ThreadCtx {
899 public:
~ThreadCtx()900 ~ThreadCtx()
901 {
902 if(ALCcontext *ctx{LocalContext})
903 {
904 const bool result{ctx->releaseIfNoDelete()};
905 ERR("Context %p current for thread being destroyed%s!\n", voidp{ctx},
906 result ? "" : ", leak detected");
907 }
908 }
909
set(ALCcontext * ctx) const910 void set(ALCcontext *ctx) const noexcept { LocalContext = ctx; }
911 };
912 thread_local ThreadCtx ThreadContext;
913
914 /* Process-wide current context */
915 std::atomic<ALCcontext*> GlobalContext{nullptr};
916
917 /* Flag to trap ALC device errors */
918 bool TrapALCError{false};
919
920 /* One-time configuration init control */
921 std::once_flag alc_config_once{};
922
923 /* Default effect that applies to sources that don't have an effect on send 0 */
924 ALeffect DefaultEffect;
925
926 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
927 * updates.
928 */
929 bool SuspendDefers{true};
930
931 /* Initial seed for dithering. */
932 constexpr uint DitherRNGSeed{22222u};
933
934
935 /************************************************
936 * ALC information
937 ************************************************/
938 constexpr ALCchar alcNoDeviceExtList[] =
939 "ALC_ENUMERATE_ALL_EXT "
940 "ALC_ENUMERATION_EXT "
941 "ALC_EXT_CAPTURE "
942 "ALC_EXT_EFX "
943 "ALC_EXT_thread_local_context "
944 "ALC_SOFT_loopback "
945 "ALC_SOFT_loopback_bformat";
946 constexpr ALCchar alcExtensionList[] =
947 "ALC_ENUMERATE_ALL_EXT "
948 "ALC_ENUMERATION_EXT "
949 "ALC_EXT_CAPTURE "
950 "ALC_EXT_DEDICATED "
951 "ALC_EXT_disconnect "
952 "ALC_EXT_EFX "
953 "ALC_EXT_thread_local_context "
954 "ALC_SOFT_device_clock "
955 "ALC_SOFT_HRTF "
956 "ALC_SOFT_loopback "
957 "ALC_SOFT_loopback_bformat "
958 "ALC_SOFT_output_limiter "
959 "ALC_SOFT_pause_device";
960 constexpr int alcMajorVersion{1};
961 constexpr int alcMinorVersion{1};
962
963 constexpr int alcEFXMajorVersion{1};
964 constexpr int alcEFXMinorVersion{0};
965
966
967 /* To avoid extraneous allocations, a 0-sized FlexArray<ALCcontext*> is defined
968 * globally as a sharable object.
969 */
970 al::FlexArray<ALCcontext*> EmptyContextArray{0u};
971
972
973 using DeviceRef = al::intrusive_ptr<ALCdevice>;
974
975
976 /************************************************
977 * Device lists
978 ************************************************/
979 al::vector<ALCdevice*> DeviceList;
980 al::vector<ALCcontext*> ContextList;
981
982 std::recursive_mutex ListLock;
983
984
alc_initconfig(void)985 void alc_initconfig(void)
986 {
987 if(auto loglevel = al::getenv("ALSOFT_LOGLEVEL"))
988 {
989 long lvl = strtol(loglevel->c_str(), nullptr, 0);
990 if(lvl >= static_cast<long>(LogLevel::Trace))
991 gLogLevel = LogLevel::Trace;
992 else if(lvl <= static_cast<long>(LogLevel::Disable))
993 gLogLevel = LogLevel::Disable;
994 else
995 gLogLevel = static_cast<LogLevel>(lvl);
996 }
997
998 #ifdef _WIN32
999 if(const auto logfile = al::getenv(L"ALSOFT_LOGFILE"))
1000 {
1001 FILE *logf{_wfopen(logfile->c_str(), L"wt")};
1002 if(logf) gLogFile = logf;
1003 else
1004 {
1005 auto u8name = wstr_to_utf8(logfile->c_str());
1006 ERR("Failed to open log file '%s'\n", u8name.c_str());
1007 }
1008 }
1009 #else
1010 if(const auto logfile = al::getenv("ALSOFT_LOGFILE"))
1011 {
1012 FILE *logf{fopen(logfile->c_str(), "wt")};
1013 if(logf) gLogFile = logf;
1014 else ERR("Failed to open log file '%s'\n", logfile->c_str());
1015 }
1016 #endif
1017
1018 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION, ALSOFT_GIT_COMMIT_HASH,
1019 ALSOFT_GIT_BRANCH);
1020 {
1021 al::string names;
1022 if(al::size(BackendList) < 1)
1023 names = "(none)";
1024 else
1025 {
1026 const al::span<const BackendInfo> infos{BackendList};
1027 names = infos[0].name;
1028 for(const auto &backend : infos.subspan<1>())
1029 {
1030 names += ", ";
1031 names += backend.name;
1032 }
1033 }
1034 TRACE("Supported backends: %s\n", names.c_str());
1035 }
1036 ReadALConfig();
1037
1038 if(auto suspendmode = al::getenv("__ALSOFT_SUSPEND_CONTEXT"))
1039 {
1040 if(al::strcasecmp(suspendmode->c_str(), "ignore") == 0)
1041 {
1042 SuspendDefers = false;
1043 TRACE("Selected context suspend behavior, \"ignore\"\n");
1044 }
1045 else
1046 ERR("Unhandled context suspend behavior setting: \"%s\"\n", suspendmode->c_str());
1047 }
1048
1049 int capfilter{0};
1050 #if defined(HAVE_SSE4_1)
1051 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
1052 #elif defined(HAVE_SSE3)
1053 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
1054 #elif defined(HAVE_SSE2)
1055 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
1056 #elif defined(HAVE_SSE)
1057 capfilter |= CPU_CAP_SSE;
1058 #endif
1059 #ifdef HAVE_NEON
1060 capfilter |= CPU_CAP_NEON;
1061 #endif
1062 if(auto cpuopt = ConfigValueStr(nullptr, nullptr, "disable-cpu-exts"))
1063 {
1064 const char *str{cpuopt->c_str()};
1065 if(al::strcasecmp(str, "all") == 0)
1066 capfilter = 0;
1067 else
1068 {
1069 const char *next = str;
1070 do {
1071 str = next;
1072 while(isspace(str[0]))
1073 str++;
1074 next = strchr(str, ',');
1075
1076 if(!str[0] || str[0] == ',')
1077 continue;
1078
1079 size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1080 while(len > 0 && isspace(str[len-1]))
1081 len--;
1082 if(len == 3 && al::strncasecmp(str, "sse", len) == 0)
1083 capfilter &= ~CPU_CAP_SSE;
1084 else if(len == 4 && al::strncasecmp(str, "sse2", len) == 0)
1085 capfilter &= ~CPU_CAP_SSE2;
1086 else if(len == 4 && al::strncasecmp(str, "sse3", len) == 0)
1087 capfilter &= ~CPU_CAP_SSE3;
1088 else if(len == 6 && al::strncasecmp(str, "sse4.1", len) == 0)
1089 capfilter &= ~CPU_CAP_SSE4_1;
1090 else if(len == 4 && al::strncasecmp(str, "neon", len) == 0)
1091 capfilter &= ~CPU_CAP_NEON;
1092 else
1093 WARN("Invalid CPU extension \"%s\"\n", str);
1094 } while(next++);
1095 }
1096 }
1097 if(auto cpuopt = GetCPUInfo())
1098 {
1099 if(!cpuopt->mVendor.empty() || !cpuopt->mName.empty())
1100 {
1101 TRACE("Vendor ID: \"%s\"\n", cpuopt->mVendor.c_str());
1102 TRACE("Name: \"%s\"\n", cpuopt->mName.c_str());
1103 }
1104 const int caps{cpuopt->mCaps};
1105 TRACE("Extensions:%s%s%s%s%s%s\n",
1106 ((capfilter&CPU_CAP_SSE) ? ((caps&CPU_CAP_SSE) ? " +SSE" : " -SSE") : ""),
1107 ((capfilter&CPU_CAP_SSE2) ? ((caps&CPU_CAP_SSE2) ? " +SSE2" : " -SSE2") : ""),
1108 ((capfilter&CPU_CAP_SSE3) ? ((caps&CPU_CAP_SSE3) ? " +SSE3" : " -SSE3") : ""),
1109 ((capfilter&CPU_CAP_SSE4_1) ? ((caps&CPU_CAP_SSE4_1) ? " +SSE4.1" : " -SSE4.1") : ""),
1110 ((capfilter&CPU_CAP_NEON) ? ((caps&CPU_CAP_NEON) ? " +NEON" : " -NEON") : ""),
1111 ((!capfilter) ? " -none-" : ""));
1112 CPUCapFlags = caps & capfilter;
1113 }
1114
1115 if(auto priopt = ConfigValueInt(nullptr, nullptr, "rt-prio"))
1116 RTPrioLevel = *priopt;
1117
1118 aluInit();
1119 aluInitMixer();
1120
1121 auto traperr = al::getenv("ALSOFT_TRAP_ERROR");
1122 if(traperr && (al::strcasecmp(traperr->c_str(), "true") == 0
1123 || std::strtol(traperr->c_str(), nullptr, 0) == 1))
1124 {
1125 TrapALError = true;
1126 TrapALCError = true;
1127 }
1128 else
1129 {
1130 traperr = al::getenv("ALSOFT_TRAP_AL_ERROR");
1131 if(traperr)
1132 TrapALError = al::strcasecmp(traperr->c_str(), "true") == 0
1133 || strtol(traperr->c_str(), nullptr, 0) == 1;
1134 else
1135 TrapALError = !!GetConfigValueBool(nullptr, nullptr, "trap-al-error", false);
1136
1137 traperr = al::getenv("ALSOFT_TRAP_ALC_ERROR");
1138 if(traperr)
1139 TrapALCError = al::strcasecmp(traperr->c_str(), "true") == 0
1140 || strtol(traperr->c_str(), nullptr, 0) == 1;
1141 else
1142 TrapALCError = !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", false);
1143 }
1144
1145 if(auto boostopt = ConfigValueFloat(nullptr, "reverb", "boost"))
1146 {
1147 const float valf{std::isfinite(*boostopt) ? clampf(*boostopt, -24.0f, 24.0f) : 0.0f};
1148 ReverbBoost *= std::pow(10.0f, valf / 20.0f);
1149 }
1150
1151 auto BackendListEnd = std::end(BackendList);
1152 auto devopt = al::getenv("ALSOFT_DRIVERS");
1153 if(devopt || (devopt=ConfigValueStr(nullptr, nullptr, "drivers")))
1154 {
1155 auto backendlist_cur = std::begin(BackendList);
1156
1157 bool endlist{true};
1158 const char *next{devopt->c_str()};
1159 do {
1160 const char *devs{next};
1161 while(isspace(devs[0]))
1162 devs++;
1163 next = strchr(devs, ',');
1164
1165 const bool delitem{devs[0] == '-'};
1166 if(devs[0] == '-') devs++;
1167
1168 if(!devs[0] || devs[0] == ',')
1169 {
1170 endlist = false;
1171 continue;
1172 }
1173 endlist = true;
1174
1175 size_t len{next ? (static_cast<size_t>(next-devs)) : strlen(devs)};
1176 while(len > 0 && isspace(devs[len-1])) --len;
1177 #ifdef HAVE_WASAPI
1178 /* HACK: For backwards compatibility, convert backend references of
1179 * mmdevapi to wasapi. This should eventually be removed.
1180 */
1181 if(len == 8 && strncmp(devs, "mmdevapi", len) == 0)
1182 {
1183 devs = "wasapi";
1184 len = 6;
1185 }
1186 #endif
1187
1188 auto find_backend = [devs,len](const BackendInfo &backend) -> bool
1189 { return len == strlen(backend.name) && strncmp(backend.name, devs, len) == 0; };
1190 auto this_backend = std::find_if(std::begin(BackendList), BackendListEnd,
1191 find_backend);
1192
1193 if(this_backend == BackendListEnd)
1194 continue;
1195
1196 if(delitem)
1197 BackendListEnd = std::move(this_backend+1, BackendListEnd, this_backend);
1198 else
1199 backendlist_cur = std::rotate(backendlist_cur, this_backend, this_backend+1);
1200 } while(next++);
1201
1202 if(endlist)
1203 BackendListEnd = backendlist_cur;
1204 }
1205
1206 auto init_backend = [](BackendInfo &backend) -> void
1207 {
1208 if(PlaybackFactory && CaptureFactory)
1209 return;
1210
1211 BackendFactory &factory = backend.getFactory();
1212 if(!factory.init())
1213 {
1214 WARN("Failed to initialize backend \"%s\"\n", backend.name);
1215 return;
1216 }
1217
1218 TRACE("Initialized backend \"%s\"\n", backend.name);
1219 if(!PlaybackFactory && factory.querySupport(BackendType::Playback))
1220 {
1221 PlaybackFactory = &factory;
1222 TRACE("Added \"%s\" for playback\n", backend.name);
1223 }
1224 if(!CaptureFactory && factory.querySupport(BackendType::Capture))
1225 {
1226 CaptureFactory = &factory;
1227 TRACE("Added \"%s\" for capture\n", backend.name);
1228 }
1229 };
1230 std::for_each(std::begin(BackendList), BackendListEnd, init_backend);
1231
1232 LoopbackBackendFactory::getFactory().init();
1233
1234 if(!PlaybackFactory)
1235 WARN("No playback backend available!\n");
1236 if(!CaptureFactory)
1237 WARN("No capture backend available!\n");
1238
1239 if(auto exclopt = ConfigValueStr(nullptr, nullptr, "excludefx"))
1240 {
1241 const char *next{exclopt->c_str()};
1242 do {
1243 const char *str{next};
1244 next = strchr(str, ',');
1245
1246 if(!str[0] || next == str)
1247 continue;
1248
1249 size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1250 for(const EffectList &effectitem : gEffectList)
1251 {
1252 if(len == strlen(effectitem.name) &&
1253 strncmp(effectitem.name, str, len) == 0)
1254 DisabledEffects[effectitem.type] = true;
1255 }
1256 } while(next++);
1257 }
1258
1259 InitEffect(&DefaultEffect);
1260 auto defrevopt = al::getenv("ALSOFT_DEFAULT_REVERB");
1261 if(defrevopt || (defrevopt=ConfigValueStr(nullptr, nullptr, "default-reverb")))
1262 LoadReverbPreset(defrevopt->c_str(), &DefaultEffect);
1263 }
1264 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1265
1266
1267 /************************************************
1268 * Device enumeration
1269 ************************************************/
ProbeAllDevicesList()1270 void ProbeAllDevicesList()
1271 {
1272 DO_INITCONFIG();
1273
1274 std::lock_guard<std::recursive_mutex> _{ListLock};
1275 if(!PlaybackFactory)
1276 decltype(alcAllDevicesList){}.swap(alcAllDevicesList);
1277 else
1278 {
1279 std::string names{PlaybackFactory->probe(BackendType::Playback)};
1280 if(names.empty()) names += '\0';
1281 names.swap(alcAllDevicesList);
1282 }
1283 }
ProbeCaptureDeviceList()1284 void ProbeCaptureDeviceList()
1285 {
1286 DO_INITCONFIG();
1287
1288 std::lock_guard<std::recursive_mutex> _{ListLock};
1289 if(!CaptureFactory)
1290 decltype(alcCaptureDeviceList){}.swap(alcCaptureDeviceList);
1291 else
1292 {
1293 std::string names{CaptureFactory->probe(BackendType::Capture)};
1294 if(names.empty()) names += '\0';
1295 names.swap(alcCaptureDeviceList);
1296 }
1297 }
1298
1299 } // namespace
1300
1301 /* Mixing thread piority level */
1302 int RTPrioLevel{1};
1303
1304 FILE *gLogFile{stderr};
1305 #ifdef _DEBUG
1306 LogLevel gLogLevel{LogLevel::Warning};
1307 #else
1308 LogLevel gLogLevel{LogLevel::Error};
1309 #endif
1310
1311 /************************************************
1312 * Library initialization
1313 ************************************************/
1314 #if defined(_WIN32) && !defined(AL_LIBTYPE_STATIC)
DllMain(HINSTANCE module,DWORD reason,LPVOID)1315 BOOL APIENTRY DllMain(HINSTANCE module, DWORD reason, LPVOID /*reserved*/)
1316 {
1317 switch(reason)
1318 {
1319 case DLL_PROCESS_ATTACH:
1320 /* Pin the DLL so we won't get unloaded until the process terminates */
1321 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
1322 reinterpret_cast<WCHAR*>(module), &module);
1323 break;
1324 }
1325 return TRUE;
1326 }
1327 #endif
1328
1329 /************************************************
1330 * Device format information
1331 ************************************************/
1332 namespace {
1333
1334 struct DevFmtPair { DevFmtChannels chans; DevFmtType type; };
DecomposeDevFormat(ALenum format)1335 al::optional<DevFmtPair> DecomposeDevFormat(ALenum format)
1336 {
1337 static const struct {
1338 ALenum format;
1339 DevFmtChannels channels;
1340 DevFmtType type;
1341 } list[] = {
1342 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1343 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1344 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1345
1346 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1347 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1348 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1349
1350 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1351 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1352 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1353
1354 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1355 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1356 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1357
1358 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1359 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1360 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1361
1362 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1363 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1364 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1365 };
1366
1367 for(const auto &item : list)
1368 {
1369 if(item.format == format)
1370 return al::make_optional(DevFmtPair{item.channels, item.type});
1371 }
1372
1373 return al::nullopt;
1374 }
1375
DevFmtTypeFromEnum(ALCenum type)1376 al::optional<DevFmtType> DevFmtTypeFromEnum(ALCenum type)
1377 {
1378 switch(type)
1379 {
1380 case ALC_BYTE_SOFT: return al::make_optional(DevFmtByte);
1381 case ALC_UNSIGNED_BYTE_SOFT: return al::make_optional(DevFmtUByte);
1382 case ALC_SHORT_SOFT: return al::make_optional(DevFmtShort);
1383 case ALC_UNSIGNED_SHORT_SOFT: return al::make_optional(DevFmtUShort);
1384 case ALC_INT_SOFT: return al::make_optional(DevFmtInt);
1385 case ALC_UNSIGNED_INT_SOFT: return al::make_optional(DevFmtUInt);
1386 case ALC_FLOAT_SOFT: return al::make_optional(DevFmtFloat);
1387 }
1388 WARN("Unsupported format type: 0x%04x\n", type);
1389 return al::nullopt;
1390 }
EnumFromDevFmt(DevFmtType type)1391 ALCenum EnumFromDevFmt(DevFmtType type)
1392 {
1393 switch(type)
1394 {
1395 case DevFmtByte: return ALC_BYTE_SOFT;
1396 case DevFmtUByte: return ALC_UNSIGNED_BYTE_SOFT;
1397 case DevFmtShort: return ALC_SHORT_SOFT;
1398 case DevFmtUShort: return ALC_UNSIGNED_SHORT_SOFT;
1399 case DevFmtInt: return ALC_INT_SOFT;
1400 case DevFmtUInt: return ALC_UNSIGNED_INT_SOFT;
1401 case DevFmtFloat: return ALC_FLOAT_SOFT;
1402 }
1403 throw std::runtime_error{"Invalid DevFmtType: "+std::to_string(int(type))};
1404 }
1405
DevFmtChannelsFromEnum(ALCenum channels)1406 al::optional<DevFmtChannels> DevFmtChannelsFromEnum(ALCenum channels)
1407 {
1408 switch(channels)
1409 {
1410 case ALC_MONO_SOFT: return al::make_optional(DevFmtMono);
1411 case ALC_STEREO_SOFT: return al::make_optional(DevFmtStereo);
1412 case ALC_QUAD_SOFT: return al::make_optional(DevFmtQuad);
1413 case ALC_5POINT1_SOFT: return al::make_optional(DevFmtX51);
1414 case ALC_6POINT1_SOFT: return al::make_optional(DevFmtX61);
1415 case ALC_7POINT1_SOFT: return al::make_optional(DevFmtX71);
1416 case ALC_BFORMAT3D_SOFT: return al::make_optional(DevFmtAmbi3D);
1417 }
1418 WARN("Unsupported format channels: 0x%04x\n", channels);
1419 return al::nullopt;
1420 }
EnumFromDevFmt(DevFmtChannels channels)1421 ALCenum EnumFromDevFmt(DevFmtChannels channels)
1422 {
1423 switch(channels)
1424 {
1425 case DevFmtMono: return ALC_MONO_SOFT;
1426 case DevFmtStereo: return ALC_STEREO_SOFT;
1427 case DevFmtQuad: return ALC_QUAD_SOFT;
1428 case DevFmtX51: /* fall-through */
1429 case DevFmtX51Rear: return ALC_5POINT1_SOFT;
1430 case DevFmtX61: return ALC_6POINT1_SOFT;
1431 case DevFmtX71: return ALC_7POINT1_SOFT;
1432 case DevFmtAmbi3D: return ALC_BFORMAT3D_SOFT;
1433 }
1434 throw std::runtime_error{"Invalid DevFmtChannels: "+std::to_string(int(channels))};
1435 }
1436
DevAmbiLayoutFromEnum(ALCenum layout)1437 al::optional<DevAmbiLayout> DevAmbiLayoutFromEnum(ALCenum layout)
1438 {
1439 switch(layout)
1440 {
1441 case ALC_FUMA_SOFT: return al::make_optional(DevAmbiLayout::FuMa);
1442 case ALC_ACN_SOFT: return al::make_optional(DevAmbiLayout::ACN);
1443 }
1444 WARN("Unsupported ambisonic layout: 0x%04x\n", layout);
1445 return al::nullopt;
1446 }
EnumFromDevAmbi(DevAmbiLayout layout)1447 ALCenum EnumFromDevAmbi(DevAmbiLayout layout)
1448 {
1449 switch(layout)
1450 {
1451 case DevAmbiLayout::FuMa: return ALC_FUMA_SOFT;
1452 case DevAmbiLayout::ACN: return ALC_ACN_SOFT;
1453 }
1454 throw std::runtime_error{"Invalid DevAmbiLayout: "+std::to_string(int(layout))};
1455 }
1456
DevAmbiScalingFromEnum(ALCenum scaling)1457 al::optional<DevAmbiScaling> DevAmbiScalingFromEnum(ALCenum scaling)
1458 {
1459 switch(scaling)
1460 {
1461 case ALC_FUMA_SOFT: return al::make_optional(DevAmbiScaling::FuMa);
1462 case ALC_SN3D_SOFT: return al::make_optional(DevAmbiScaling::SN3D);
1463 case ALC_N3D_SOFT: return al::make_optional(DevAmbiScaling::N3D);
1464 }
1465 WARN("Unsupported ambisonic scaling: 0x%04x\n", scaling);
1466 return al::nullopt;
1467 }
EnumFromDevAmbi(DevAmbiScaling scaling)1468 ALCenum EnumFromDevAmbi(DevAmbiScaling scaling)
1469 {
1470 switch(scaling)
1471 {
1472 case DevAmbiScaling::FuMa: return ALC_FUMA_SOFT;
1473 case DevAmbiScaling::SN3D: return ALC_SN3D_SOFT;
1474 case DevAmbiScaling::N3D: return ALC_N3D_SOFT;
1475 }
1476 throw std::runtime_error{"Invalid DevAmbiScaling: "+std::to_string(int(scaling))};
1477 }
1478
1479
1480 /* Downmixing channel arrays, to map the given format's missing channels to
1481 * existing ones. Based on Wine's DSound downmix values, which are based on
1482 * PulseAudio's.
1483 */
1484 const std::array<InputRemixMap,7> MonoDownmix{{
1485 { FrontLeft, {{{FrontCenter, 0.5f}, {LFE, 0.0f}}} },
1486 { FrontRight, {{{FrontCenter, 0.5f}, {LFE, 0.0f}}} },
1487 { SideLeft, {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1488 { SideRight, {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1489 { BackLeft, {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1490 { BackRight, {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1491 { BackCenter, {{{FrontCenter, 1.0f/9.0f}, {LFE, 0.0f}}} },
1492 }};
1493 const std::array<InputRemixMap,6> StereoDownmix{{
1494 { FrontCenter, {{{FrontLeft, 0.5f}, {FrontRight, 0.5f}}} },
1495 { SideLeft, {{{FrontLeft, 1.0f/9.0f}, {FrontRight, 0.0f}}} },
1496 { SideRight, {{{FrontLeft, 0.0f}, {FrontRight, 1.0f/9.0f}}} },
1497 { BackLeft, {{{FrontLeft, 1.0f/9.0f}, {FrontRight, 0.0f}}} },
1498 { BackRight, {{{FrontLeft, 0.0f}, {FrontRight, 1.0f/9.0f}}} },
1499 { BackCenter, {{{FrontLeft, 0.5f/9.0f}, {FrontRight, 0.5f/9.0f}}} },
1500 }};
1501 const std::array<InputRemixMap,4> QuadDownmix{{
1502 { FrontCenter, {{{FrontLeft, 0.5f}, {FrontRight, 0.5f}}} },
1503 { SideLeft, {{{FrontLeft, 0.5f}, {BackLeft, 0.5f}}} },
1504 { SideRight, {{{FrontRight, 0.5f}, {BackRight, 0.5f}}} },
1505 { BackCenter, {{{BackLeft, 0.5f}, {BackRight, 0.5f}}} },
1506 }};
1507 const std::array<InputRemixMap,3> X51Downmix{{
1508 { BackLeft, {{{SideLeft, 1.0f}, {SideRight, 0.0f}}} },
1509 { BackRight, {{{SideLeft, 0.0f}, {SideRight, 1.0f}}} },
1510 { BackCenter, {{{SideLeft, 0.5f}, {SideRight, 0.5f}}} },
1511 }};
1512 const std::array<InputRemixMap,3> X51RearDownmix{{
1513 { SideLeft, {{{BackLeft, 1.0f}, {BackRight, 0.0f}}} },
1514 { SideRight, {{{BackLeft, 0.0f}, {BackRight, 1.0f}}} },
1515 { BackCenter, {{{BackLeft, 0.5f}, {BackRight, 0.5f}}} },
1516 }};
1517 const std::array<InputRemixMap,2> X61Downmix{{
1518 { BackLeft, {{{BackCenter, 0.5f}, {SideLeft, 0.5f}}} },
1519 { BackRight, {{{BackCenter, 0.5f}, {SideRight, 0.5f}}} },
1520 }};
1521 const std::array<InputRemixMap,1> X71Downmix{{
1522 { BackCenter, {{{BackLeft, 0.5f}, {BackRight, 0.5f}}} },
1523 }};
1524
1525 } // namespace
1526
1527 /************************************************
1528 * Miscellaneous ALC helpers
1529 ************************************************/
1530
processUpdates()1531 void ALCcontext::processUpdates()
1532 {
1533 std::lock_guard<std::mutex> _{mPropLock};
1534 if(mDeferUpdates.exchange(false, std::memory_order_acq_rel))
1535 {
1536 /* Tell the mixer to stop applying updates, then wait for any active
1537 * updating to finish, before providing updates.
1538 */
1539 mHoldUpdates.store(true, std::memory_order_release);
1540 while((mUpdateCount.load(std::memory_order_acquire)&1) != 0) {
1541 /* busy-wait */
1542 }
1543
1544 if(!mPropsClean.test_and_set(std::memory_order_acq_rel))
1545 UpdateContextProps(this);
1546 if(!mListener.PropsClean.test_and_set(std::memory_order_acq_rel))
1547 UpdateListenerProps(this);
1548 UpdateAllEffectSlotProps(this);
1549 UpdateAllSourceProps(this);
1550
1551 /* Now with all updates declared, let the mixer continue applying them
1552 * so they all happen at once.
1553 */
1554 mHoldUpdates.store(false, std::memory_order_release);
1555 }
1556 }
1557
1558
allocVoiceChanges(size_t addcount)1559 void ALCcontext::allocVoiceChanges(size_t addcount)
1560 {
1561 constexpr size_t clustersize{128};
1562 /* Convert element count to cluster count. */
1563 addcount = (addcount+(clustersize-1)) / clustersize;
1564 while(addcount)
1565 {
1566 VoiceChangeCluster cluster{std::make_unique<VoiceChange[]>(clustersize)};
1567 for(size_t i{1};i < clustersize;++i)
1568 cluster[i-1].mNext.store(std::addressof(cluster[i]), std::memory_order_relaxed);
1569 cluster[clustersize-1].mNext.store(mVoiceChangeTail, std::memory_order_relaxed);
1570 mVoiceChangeClusters.emplace_back(std::move(cluster));
1571 mVoiceChangeTail = mVoiceChangeClusters.back().get();
1572 --addcount;
1573 }
1574 }
1575
allocVoices(size_t addcount)1576 void ALCcontext::allocVoices(size_t addcount)
1577 {
1578 constexpr size_t clustersize{32};
1579 /* Convert element count to cluster count. */
1580 addcount = (addcount+(clustersize-1)) / clustersize;
1581
1582 if(addcount >= std::numeric_limits<int>::max()/clustersize - mVoiceClusters.size())
1583 throw std::runtime_error{"Allocating too many voices"};
1584 const size_t totalcount{(mVoiceClusters.size()+addcount) * clustersize};
1585 TRACE("Increasing allocated voices to %zu\n", totalcount);
1586
1587 auto newarray = VoiceArray::Create(totalcount);
1588 while(addcount)
1589 {
1590 mVoiceClusters.emplace_back(std::make_unique<Voice[]>(clustersize));
1591 --addcount;
1592 }
1593
1594 auto voice_iter = newarray->begin();
1595 for(VoiceCluster &cluster : mVoiceClusters)
1596 {
1597 for(size_t i{0};i < clustersize;++i)
1598 *(voice_iter++) = &cluster[i];
1599 }
1600
1601 if(auto *oldvoices = mVoices.exchange(newarray.release(), std::memory_order_acq_rel))
1602 {
1603 mDevice->waitForMix();
1604 delete oldvoices;
1605 }
1606 }
1607
1608
1609 /** Stores the latest ALC device error. */
alcSetError(ALCdevice * device,ALCenum errorCode)1610 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1611 {
1612 WARN("Error generated on device %p, code 0x%04x\n", voidp{device}, errorCode);
1613 if(TrapALCError)
1614 {
1615 #ifdef _WIN32
1616 /* DebugBreak() will cause an exception if there is no debugger */
1617 if(IsDebuggerPresent())
1618 DebugBreak();
1619 #elif defined(SIGTRAP)
1620 raise(SIGTRAP);
1621 #endif
1622 }
1623
1624 if(device)
1625 device->LastError.store(errorCode);
1626 else
1627 LastNullDeviceError.store(errorCode);
1628 }
1629
1630
CreateDeviceLimiter(const ALCdevice * device,const float threshold)1631 static std::unique_ptr<Compressor> CreateDeviceLimiter(const ALCdevice *device, const float threshold)
1632 {
1633 constexpr bool AutoKnee{true};
1634 constexpr bool AutoAttack{true};
1635 constexpr bool AutoRelease{true};
1636 constexpr bool AutoPostGain{true};
1637 constexpr bool AutoDeclip{true};
1638 constexpr float LookAheadTime{0.001f};
1639 constexpr float HoldTime{0.002f};
1640 constexpr float PreGainDb{0.0f};
1641 constexpr float PostGainDb{0.0f};
1642 constexpr float Ratio{std::numeric_limits<float>::infinity()};
1643 constexpr float KneeDb{0.0f};
1644 constexpr float AttackTime{0.02f};
1645 constexpr float ReleaseTime{0.2f};
1646
1647 return Compressor::Create(device->RealOut.Buffer.size(), static_cast<float>(device->Frequency),
1648 AutoKnee, AutoAttack, AutoRelease, AutoPostGain, AutoDeclip, LookAheadTime, HoldTime,
1649 PreGainDb, PostGainDb, threshold, Ratio, KneeDb, AttackTime, ReleaseTime);
1650 }
1651
1652 /**
1653 * Updates the device's base clock time with however many samples have been
1654 * done. This is used so frequency changes on the device don't cause the time
1655 * to jump forward or back. Must not be called while the device is running/
1656 * mixing.
1657 */
UpdateClockBase(ALCdevice * device)1658 static inline void UpdateClockBase(ALCdevice *device)
1659 {
1660 IncrementRef(device->MixCount);
1661 device->ClockBase += nanoseconds{seconds{device->SamplesDone}} / device->Frequency;
1662 device->SamplesDone = 0;
1663 IncrementRef(device->MixCount);
1664 }
1665
1666 /**
1667 * Updates device parameters according to the attribute list (caller is
1668 * responsible for holding the list lock).
1669 */
UpdateDeviceParams(ALCdevice * device,const int * attrList)1670 static ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
1671 {
1672 HrtfRequestMode hrtf_userreq{Hrtf_Default};
1673 HrtfRequestMode hrtf_appreq{Hrtf_Default};
1674 ALCenum gainLimiter{device->LimiterState};
1675 uint new_sends{device->NumAuxSends};
1676 DevFmtChannels oldChans;
1677 DevFmtType oldType;
1678 int hrtf_id{-1};
1679 uint oldFreq;
1680
1681 if((!attrList || !attrList[0]) && device->Type == DeviceType::Loopback)
1682 {
1683 WARN("Missing attributes for loopback device\n");
1684 return ALC_INVALID_VALUE;
1685 }
1686
1687 // Check for attributes
1688 if(attrList && attrList[0])
1689 {
1690 uint numMono{device->NumMonoSources};
1691 uint numStereo{device->NumStereoSources};
1692 uint numSends{device->NumAuxSends};
1693
1694 al::optional<DevFmtChannels> optchans;
1695 al::optional<DevFmtType> opttype;
1696 al::optional<DevAmbiLayout> optlayout;
1697 al::optional<DevAmbiScaling> optscale;
1698
1699 uint aorder{0u};
1700 uint freq{0u};
1701
1702 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1703 size_t attrIdx{0};
1704 while(attrList[attrIdx])
1705 {
1706 switch(attrList[attrIdx])
1707 {
1708 case ALC_FORMAT_CHANNELS_SOFT:
1709 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, attrList[attrIdx + 1]);
1710 optchans = DevFmtChannelsFromEnum(attrList[attrIdx + 1]);
1711 break;
1712
1713 case ALC_FORMAT_TYPE_SOFT:
1714 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, attrList[attrIdx + 1]);
1715 opttype = DevFmtTypeFromEnum(attrList[attrIdx + 1]);
1716 break;
1717
1718 case ALC_FREQUENCY:
1719 freq = static_cast<uint>(attrList[attrIdx + 1]);
1720 TRACE_ATTR(ALC_FREQUENCY, freq);
1721 break;
1722
1723 case ALC_AMBISONIC_LAYOUT_SOFT:
1724 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, attrList[attrIdx + 1]);
1725 optlayout = DevAmbiLayoutFromEnum(attrList[attrIdx + 1]);
1726 break;
1727
1728 case ALC_AMBISONIC_SCALING_SOFT:
1729 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, attrList[attrIdx + 1]);
1730 optscale = DevAmbiScalingFromEnum(attrList[attrIdx + 1]);
1731 break;
1732
1733 case ALC_AMBISONIC_ORDER_SOFT:
1734 aorder = static_cast<uint>(attrList[attrIdx + 1]);
1735 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1736 break;
1737
1738 case ALC_MONO_SOURCES:
1739 numMono = static_cast<uint>(attrList[attrIdx + 1]);
1740 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1741 if(numMono > INT_MAX) numMono = 0;
1742 break;
1743
1744 case ALC_STEREO_SOURCES:
1745 numStereo = static_cast<uint>(attrList[attrIdx + 1]);
1746 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1747 if(numStereo > INT_MAX) numStereo = 0;
1748 break;
1749
1750 case ALC_MAX_AUXILIARY_SENDS:
1751 numSends = static_cast<uint>(attrList[attrIdx + 1]);
1752 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1753 if(numSends > INT_MAX) numSends = 0;
1754 else numSends = minu(numSends, MAX_SENDS);
1755 break;
1756
1757 case ALC_HRTF_SOFT:
1758 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1759 if(attrList[attrIdx + 1] == ALC_FALSE)
1760 hrtf_appreq = Hrtf_Disable;
1761 else if(attrList[attrIdx + 1] == ALC_TRUE)
1762 hrtf_appreq = Hrtf_Enable;
1763 else
1764 hrtf_appreq = Hrtf_Default;
1765 break;
1766
1767 case ALC_HRTF_ID_SOFT:
1768 hrtf_id = attrList[attrIdx + 1];
1769 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1770 break;
1771
1772 case ALC_OUTPUT_LIMITER_SOFT:
1773 gainLimiter = attrList[attrIdx + 1];
1774 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1775 break;
1776
1777 default:
1778 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1779 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1780 break;
1781 }
1782
1783 attrIdx += 2;
1784 }
1785 #undef TRACE_ATTR
1786
1787 const bool loopback{device->Type == DeviceType::Loopback};
1788 if(loopback)
1789 {
1790 if(!optchans || !opttype)
1791 return ALC_INVALID_VALUE;
1792 if(freq < MIN_OUTPUT_RATE || freq > MAX_OUTPUT_RATE)
1793 return ALC_INVALID_VALUE;
1794 if(*optchans == DevFmtAmbi3D)
1795 {
1796 if(!optlayout || !optscale)
1797 return ALC_INVALID_VALUE;
1798 if(aorder < 1 || aorder > MaxAmbiOrder)
1799 return ALC_INVALID_VALUE;
1800 if((*optlayout == DevAmbiLayout::FuMa || *optscale == DevAmbiScaling::FuMa)
1801 && aorder > 3)
1802 return ALC_INVALID_VALUE;
1803 }
1804 }
1805
1806 /* If a context is already running on the device, stop playback so the
1807 * device attributes can be updated.
1808 */
1809 if(device->Flags.test(DeviceRunning))
1810 device->Backend->stop();
1811 device->Flags.reset(DeviceRunning);
1812
1813 UpdateClockBase(device);
1814
1815 const char *devname{nullptr};
1816 if(loopback)
1817 {
1818 device->Frequency = freq;
1819 device->FmtChans = *optchans;
1820 device->FmtType = *opttype;
1821 if(device->FmtChans == DevFmtAmbi3D)
1822 {
1823 device->mAmbiOrder = aorder;
1824 device->mAmbiLayout = *optlayout;
1825 device->mAmbiScale = *optscale;
1826 }
1827 }
1828 else
1829 {
1830 devname = device->DeviceName.c_str();
1831
1832 device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
1833 device->UpdateSize = DEFAULT_UPDATE_SIZE;
1834 device->Frequency = DEFAULT_OUTPUT_RATE;
1835
1836 freq = ConfigValueUInt(devname, nullptr, "frequency").value_or(freq);
1837 if(freq < 1)
1838 device->Flags.reset(FrequencyRequest);
1839 else
1840 {
1841 freq = clampu(freq, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE);
1842
1843 const double scale{static_cast<double>(freq) / device->Frequency};
1844 device->UpdateSize = static_cast<uint>(device->UpdateSize*scale + 0.5);
1845 device->BufferSize = static_cast<uint>(device->BufferSize*scale + 0.5);
1846
1847 device->Frequency = freq;
1848 device->Flags.set(FrequencyRequest);
1849 }
1850
1851 if(auto persizeopt = ConfigValueUInt(devname, nullptr, "period_size"))
1852 device->UpdateSize = clampu(*persizeopt, 64, 8192);
1853
1854 if(auto peropt = ConfigValueUInt(devname, nullptr, "periods"))
1855 device->BufferSize = device->UpdateSize * clampu(*peropt, 2, 16);
1856 else
1857 device->BufferSize = maxu(device->BufferSize, device->UpdateSize*2);
1858 }
1859
1860 if(numMono > INT_MAX-numStereo)
1861 numMono = INT_MAX-numStereo;
1862 numMono += numStereo;
1863 if(auto srcsopt = ConfigValueUInt(devname, nullptr, "sources"))
1864 {
1865 if(*srcsopt <= 0) numMono = 256;
1866 else numMono = *srcsopt;
1867 }
1868 else
1869 numMono = maxu(numMono, 256);
1870 numStereo = minu(numStereo, numMono);
1871 numMono -= numStereo;
1872 device->SourcesMax = numMono + numStereo;
1873
1874 device->NumMonoSources = numMono;
1875 device->NumStereoSources = numStereo;
1876
1877 if(auto sendsopt = ConfigValueInt(devname, nullptr, "sends"))
1878 new_sends = minu(numSends, static_cast<uint>(clampi(*sendsopt, 0, MAX_SENDS)));
1879 else
1880 new_sends = numSends;
1881 }
1882
1883 if(device->Flags.test(DeviceRunning))
1884 return ALC_NO_ERROR;
1885
1886 device->AvgSpeakerDist = 0.0f;
1887 device->Uhj_Encoder = nullptr;
1888 device->AmbiDecoder = nullptr;
1889 device->Bs2b = nullptr;
1890 device->PostProcess = nullptr;
1891
1892 device->Limiter = nullptr;
1893 device->ChannelDelays = nullptr;
1894
1895 std::fill(std::begin(device->HrtfAccumData), std::end(device->HrtfAccumData), float2{});
1896
1897 device->Dry.AmbiMap.fill(BFChannelConfig{});
1898 device->Dry.Buffer = {};
1899 std::fill(std::begin(device->NumChannelsPerOrder), std::end(device->NumChannelsPerOrder), 0u);
1900 device->RealOut.RemixMap = {};
1901 device->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
1902 device->RealOut.Buffer = {};
1903 device->MixBuffer.clear();
1904 device->MixBuffer.shrink_to_fit();
1905
1906 UpdateClockBase(device);
1907 device->FixedLatency = nanoseconds::zero();
1908
1909 device->DitherDepth = 0.0f;
1910 device->DitherSeed = DitherRNGSeed;
1911
1912 /*************************************************************************
1913 * Update device format request if HRTF is requested
1914 */
1915 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
1916 if(device->Type != DeviceType::Loopback)
1917 {
1918 if(auto hrtfopt = ConfigValueStr(device->DeviceName.c_str(), nullptr, "hrtf"))
1919 {
1920 const char *hrtf{hrtfopt->c_str()};
1921 if(al::strcasecmp(hrtf, "true") == 0)
1922 hrtf_userreq = Hrtf_Enable;
1923 else if(al::strcasecmp(hrtf, "false") == 0)
1924 hrtf_userreq = Hrtf_Disable;
1925 else if(al::strcasecmp(hrtf, "auto") != 0)
1926 ERR("Unexpected hrtf value: %s\n", hrtf);
1927 }
1928
1929 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
1930 {
1931 device->FmtChans = DevFmtStereo;
1932 device->Flags.set(ChannelsRequest);
1933 }
1934 }
1935
1936 oldFreq = device->Frequency;
1937 oldChans = device->FmtChans;
1938 oldType = device->FmtType;
1939
1940 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u / %u buffer\n",
1941 device->Flags.test(ChannelsRequest)?"*":"", DevFmtChannelsString(device->FmtChans),
1942 device->Flags.test(SampleTypeRequest)?"*":"", DevFmtTypeString(device->FmtType),
1943 device->Flags.test(FrequencyRequest)?"*":"", device->Frequency,
1944 device->UpdateSize, device->BufferSize);
1945
1946 try {
1947 auto backend = device->Backend.get();
1948 if(!backend->reset())
1949 throw al::backend_exception{al::backend_error::DeviceError, "Device reset failure"};
1950 }
1951 catch(std::exception &e) {
1952 device->handleDisconnect("%s", e.what());
1953 return ALC_INVALID_DEVICE;
1954 }
1955
1956 if(device->FmtChans != oldChans && device->Flags.test(ChannelsRequest))
1957 {
1958 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1959 DevFmtChannelsString(device->FmtChans));
1960 device->Flags.reset(ChannelsRequest);
1961 }
1962 if(device->FmtType != oldType && device->Flags.test(SampleTypeRequest))
1963 {
1964 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1965 DevFmtTypeString(device->FmtType));
1966 device->Flags.reset(SampleTypeRequest);
1967 }
1968 if(device->Frequency != oldFreq && device->Flags.test(FrequencyRequest))
1969 {
1970 WARN("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1971 device->Flags.reset(FrequencyRequest);
1972 }
1973
1974 TRACE("Post-reset: %s, %s, %uhz, %u / %u buffer\n",
1975 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
1976 device->Frequency, device->UpdateSize, device->BufferSize);
1977
1978 switch(device->FmtChans)
1979 {
1980 case DevFmtMono: device->RealOut.RemixMap = MonoDownmix; break;
1981 case DevFmtStereo: device->RealOut.RemixMap = StereoDownmix; break;
1982 case DevFmtQuad: device->RealOut.RemixMap = QuadDownmix; break;
1983 case DevFmtX51: device->RealOut.RemixMap = X51Downmix; break;
1984 case DevFmtX51Rear: device->RealOut.RemixMap = X51RearDownmix; break;
1985 case DevFmtX61: device->RealOut.RemixMap = X61Downmix; break;
1986 case DevFmtX71: device->RealOut.RemixMap = X71Downmix; break;
1987 case DevFmtAmbi3D: break;
1988 }
1989
1990 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
1991
1992 device->NumAuxSends = new_sends;
1993 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
1994 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
1995 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
1996
1997 nanoseconds::rep sample_delay{0};
1998 if(device->Uhj_Encoder)
1999 sample_delay += Uhj2Encoder::sFilterSize;
2000 if(device->mHrtfState)
2001 sample_delay += HrtfDirectDelay;
2002 if(auto *ambidec = device->AmbiDecoder.get())
2003 {
2004 if(ambidec->hasStablizer())
2005 sample_delay += FrontStablizer::DelayLength;
2006 }
2007
2008 if(GetConfigValueBool(device->DeviceName.c_str(), nullptr, "dither", 1))
2009 {
2010 int depth{ConfigValueInt(device->DeviceName.c_str(), nullptr, "dither-depth").value_or(0)};
2011 if(depth <= 0)
2012 {
2013 switch(device->FmtType)
2014 {
2015 case DevFmtByte:
2016 case DevFmtUByte:
2017 depth = 8;
2018 break;
2019 case DevFmtShort:
2020 case DevFmtUShort:
2021 depth = 16;
2022 break;
2023 case DevFmtInt:
2024 case DevFmtUInt:
2025 case DevFmtFloat:
2026 break;
2027 }
2028 }
2029
2030 if(depth > 0)
2031 {
2032 depth = clampi(depth, 2, 24);
2033 device->DitherDepth = std::pow(2.0f, static_cast<float>(depth-1));
2034 }
2035 }
2036 if(!(device->DitherDepth > 0.0f))
2037 TRACE("Dithering disabled\n");
2038 else
2039 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device->DitherDepth)+0.5f)+1,
2040 device->DitherDepth);
2041
2042 device->LimiterState = gainLimiter;
2043 if(auto limopt = ConfigValueBool(device->DeviceName.c_str(), nullptr, "output-limiter"))
2044 gainLimiter = *limopt ? ALC_TRUE : ALC_FALSE;
2045
2046 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2047 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2048 * output (where samples must be clamped), and don't for floating-point
2049 * (which can take unclamped samples).
2050 */
2051 if(gainLimiter == ALC_DONT_CARE_SOFT)
2052 {
2053 switch(device->FmtType)
2054 {
2055 case DevFmtByte:
2056 case DevFmtUByte:
2057 case DevFmtShort:
2058 case DevFmtUShort:
2059 case DevFmtInt:
2060 case DevFmtUInt:
2061 gainLimiter = ALC_TRUE;
2062 break;
2063 case DevFmtFloat:
2064 gainLimiter = ALC_FALSE;
2065 break;
2066 }
2067 }
2068 if(gainLimiter == ALC_FALSE)
2069 TRACE("Output limiter disabled\n");
2070 else
2071 {
2072 float thrshld{1.0f};
2073 switch(device->FmtType)
2074 {
2075 case DevFmtByte:
2076 case DevFmtUByte:
2077 thrshld = 127.0f / 128.0f;
2078 break;
2079 case DevFmtShort:
2080 case DevFmtUShort:
2081 thrshld = 32767.0f / 32768.0f;
2082 break;
2083 case DevFmtInt:
2084 case DevFmtUInt:
2085 case DevFmtFloat:
2086 break;
2087 }
2088 if(device->DitherDepth > 0.0f)
2089 thrshld -= 1.0f / device->DitherDepth;
2090
2091 const float thrshld_dB{std::log10(thrshld) * 20.0f};
2092 auto limiter = CreateDeviceLimiter(device, thrshld_dB);
2093
2094 sample_delay += limiter->getLookAhead();
2095 device->Limiter = std::move(limiter);
2096 TRACE("Output limiter enabled, %.4fdB limit\n", thrshld_dB);
2097 }
2098
2099 /* Convert the sample delay from samples to nanosamples to nanoseconds. */
2100 device->FixedLatency += nanoseconds{seconds{sample_delay}} / device->Frequency;
2101 TRACE("Fixed device latency: %" PRId64 "ns\n", int64_t{device->FixedLatency.count()});
2102
2103 FPUCtl mixer_mode{};
2104 for(ALCcontext *context : *device->mContexts.load())
2105 {
2106 auto GetEffectBuffer = [](ALbuffer *buffer) noexcept -> EffectState::Buffer
2107 {
2108 if(!buffer) return EffectState::Buffer{};
2109 return EffectState::Buffer{buffer, buffer->mData};
2110 };
2111 std::unique_lock<std::mutex> proplock{context->mPropLock};
2112 std::unique_lock<std::mutex> slotlock{context->mEffectSlotLock};
2113
2114 /* Clear out unused wet buffers. */
2115 auto buffer_not_in_use = [](WetBufferPtr &wetbuffer) noexcept -> bool
2116 { return !wetbuffer->mInUse; };
2117 auto wetbuffer_iter = std::remove_if(context->mWetBuffers.begin(),
2118 context->mWetBuffers.end(), buffer_not_in_use);
2119 context->mWetBuffers.erase(wetbuffer_iter, context->mWetBuffers.end());
2120
2121 if(ALeffectslot *slot{context->mDefaultSlot.get()})
2122 {
2123 aluInitEffectPanning(&slot->mSlot, context);
2124
2125 EffectState *state{slot->Effect.State.get()};
2126 state->mOutTarget = device->Dry.Buffer;
2127 state->deviceUpdate(device, GetEffectBuffer(slot->Buffer));
2128 slot->updateProps(context);
2129 }
2130
2131 if(EffectSlotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_relaxed)})
2132 std::fill_n(curarray->end(), curarray->size(), nullptr);
2133 for(auto &sublist : context->mEffectSlotList)
2134 {
2135 uint64_t usemask{~sublist.FreeMask};
2136 while(usemask)
2137 {
2138 const int idx{al::countr_zero(usemask)};
2139 ALeffectslot *slot{sublist.EffectSlots + idx};
2140 usemask &= ~(1_u64 << idx);
2141
2142 aluInitEffectPanning(&slot->mSlot, context);
2143
2144 EffectState *state{slot->Effect.State.get()};
2145 state->mOutTarget = device->Dry.Buffer;
2146 state->deviceUpdate(device, GetEffectBuffer(slot->Buffer));
2147 slot->updateProps(context);
2148 }
2149 }
2150 slotlock.unlock();
2151
2152 const uint num_sends{device->NumAuxSends};
2153 std::unique_lock<std::mutex> srclock{context->mSourceLock};
2154 for(auto &sublist : context->mSourceList)
2155 {
2156 uint64_t usemask{~sublist.FreeMask};
2157 while(usemask)
2158 {
2159 const int idx{al::countr_zero(usemask)};
2160 ALsource *source{sublist.Sources + idx};
2161 usemask &= ~(1_u64 << idx);
2162
2163 auto clear_send = [](ALsource::SendData &send) -> void
2164 {
2165 if(send.Slot)
2166 DecrementRef(send.Slot->ref);
2167 send.Slot = nullptr;
2168 send.Gain = 1.0f;
2169 send.GainHF = 1.0f;
2170 send.HFReference = LOWPASSFREQREF;
2171 send.GainLF = 1.0f;
2172 send.LFReference = HIGHPASSFREQREF;
2173 };
2174 auto send_begin = source->Send.begin() + static_cast<ptrdiff_t>(num_sends);
2175 std::for_each(send_begin, source->Send.end(), clear_send);
2176
2177 source->PropsClean.clear(std::memory_order_release);
2178 }
2179 }
2180
2181 /* Clear any pre-existing voice property structs, in case the number of
2182 * auxiliary sends is changing. Active sources will have updates
2183 * respecified in UpdateAllSourceProps.
2184 */
2185 VoicePropsItem *vprops{context->mFreeVoiceProps.exchange(nullptr, std::memory_order_acq_rel)};
2186 while(vprops)
2187 {
2188 VoicePropsItem *next = vprops->next.load(std::memory_order_relaxed);
2189 delete vprops;
2190 vprops = next;
2191 }
2192
2193 auto voicelist = context->getVoicesSpan();
2194 for(Voice *voice : voicelist)
2195 {
2196 /* Clear extraneous property set sends. */
2197 std::fill(std::begin(voice->mProps.Send)+num_sends, std::end(voice->mProps.Send),
2198 VoiceProps::SendData{});
2199
2200 std::fill(voice->mSend.begin()+num_sends, voice->mSend.end(), Voice::TargetData{});
2201 for(auto &chandata : voice->mChans)
2202 {
2203 std::fill(chandata.mWetParams.begin()+num_sends, chandata.mWetParams.end(),
2204 SendParams{});
2205 }
2206
2207 delete voice->mUpdate.exchange(nullptr, std::memory_order_acq_rel);
2208
2209 /* Force the voice to stopped if it was stopping. */
2210 Voice::State vstate{Voice::Stopping};
2211 voice->mPlayState.compare_exchange_strong(vstate, Voice::Stopped,
2212 std::memory_order_acquire, std::memory_order_acquire);
2213 if(voice->mSourceID.load(std::memory_order_relaxed) == 0u)
2214 continue;
2215
2216 voice->mStep = 0;
2217 voice->mFlags |= VoiceIsFading;
2218
2219 if(voice->mAmbiOrder && device->mAmbiOrder > voice->mAmbiOrder)
2220 {
2221 const uint8_t *OrderFromChan{(voice->mFmtChannels == FmtBFormat2D) ?
2222 AmbiIndex::OrderFrom2DChannel().data() :
2223 AmbiIndex::OrderFromChannel().data()};
2224
2225 const BandSplitter splitter{device->mXOverFreq /
2226 static_cast<float>(device->Frequency)};
2227
2228 const auto scales = BFormatDec::GetHFOrderScales(voice->mAmbiOrder,
2229 device->mAmbiOrder);
2230 for(auto &chandata : voice->mChans)
2231 {
2232 chandata.mPrevSamples.fill(0.0f);
2233 chandata.mAmbiScale = scales[*(OrderFromChan++)];
2234 chandata.mAmbiSplitter = splitter;
2235 chandata.mDryParams = DirectParams{};
2236 std::fill_n(chandata.mWetParams.begin(), num_sends, SendParams{});
2237 }
2238
2239 voice->mFlags |= VoiceIsAmbisonic;
2240 }
2241 else
2242 {
2243 /* Clear previous samples. */
2244 for(auto &chandata : voice->mChans)
2245 {
2246 chandata.mPrevSamples.fill(0.0f);
2247 chandata.mDryParams = DirectParams{};
2248 std::fill_n(chandata.mWetParams.begin(), num_sends, SendParams{});
2249 }
2250
2251 voice->mFlags &= ~VoiceIsAmbisonic;
2252 }
2253
2254 if(device->AvgSpeakerDist > 0.0f)
2255 {
2256 /* Reinitialize the NFC filters for new parameters. */
2257 const float w1{SpeedOfSoundMetersPerSec /
2258 (device->AvgSpeakerDist * static_cast<float>(device->Frequency))};
2259 for(auto &chandata : voice->mChans)
2260 chandata.mDryParams.NFCtrlFilter.init(w1);
2261 }
2262 }
2263 srclock.unlock();
2264
2265 context->mPropsClean.test_and_set(std::memory_order_release);
2266 UpdateContextProps(context);
2267 context->mListener.PropsClean.test_and_set(std::memory_order_release);
2268 UpdateListenerProps(context);
2269 UpdateAllSourceProps(context);
2270 }
2271 mixer_mode.leave();
2272
2273 if(!device->Flags.test(DevicePaused))
2274 {
2275 try {
2276 auto backend = device->Backend.get();
2277 backend->start();
2278 device->Flags.set(DeviceRunning);
2279 }
2280 catch(al::backend_exception& e) {
2281 device->handleDisconnect("%s", e.what());
2282 return ALC_INVALID_DEVICE;
2283 }
2284 }
2285
2286 return ALC_NO_ERROR;
2287 }
2288
2289
ALCdevice(DeviceType type)2290 ALCdevice::ALCdevice(DeviceType type) : Type{type}, mContexts{&EmptyContextArray}
2291 {
2292 }
2293
~ALCdevice()2294 ALCdevice::~ALCdevice()
2295 {
2296 TRACE("Freeing device %p\n", voidp{this});
2297
2298 Backend = nullptr;
2299
2300 size_t count{std::accumulate(BufferList.cbegin(), BufferList.cend(), size_t{0u},
2301 [](size_t cur, const BufferSubList &sublist) noexcept -> size_t
2302 { return cur + static_cast<uint>(al::popcount(~sublist.FreeMask)); })};
2303 if(count > 0)
2304 WARN("%zu Buffer%s not deleted\n", count, (count==1)?"":"s");
2305
2306 count = std::accumulate(EffectList.cbegin(), EffectList.cend(), size_t{0u},
2307 [](size_t cur, const EffectSubList &sublist) noexcept -> size_t
2308 { return cur + static_cast<uint>(al::popcount(~sublist.FreeMask)); });
2309 if(count > 0)
2310 WARN("%zu Effect%s not deleted\n", count, (count==1)?"":"s");
2311
2312 count = std::accumulate(FilterList.cbegin(), FilterList.cend(), size_t{0u},
2313 [](size_t cur, const FilterSubList &sublist) noexcept -> size_t
2314 { return cur + static_cast<uint>(al::popcount(~sublist.FreeMask)); });
2315 if(count > 0)
2316 WARN("%zu Filter%s not deleted\n", count, (count==1)?"":"s");
2317
2318 mHrtf = nullptr;
2319
2320 auto *oldarray = mContexts.exchange(nullptr, std::memory_order_relaxed);
2321 if(oldarray != &EmptyContextArray) delete oldarray;
2322 }
2323
2324
2325 /** Checks if the device handle is valid, and returns a new reference if so. */
VerifyDevice(ALCdevice * device)2326 static DeviceRef VerifyDevice(ALCdevice *device)
2327 {
2328 std::lock_guard<std::recursive_mutex> _{ListLock};
2329 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
2330 if(iter != DeviceList.end() && *iter == device)
2331 {
2332 (*iter)->add_ref();
2333 return DeviceRef{*iter};
2334 }
2335 return nullptr;
2336 }
2337
2338
ALCcontext(al::intrusive_ptr<ALCdevice> device)2339 ALCcontext::ALCcontext(al::intrusive_ptr<ALCdevice> device) : mDevice{std::move(device)}
2340 {
2341 mPropsClean.test_and_set(std::memory_order_relaxed);
2342 }
2343
~ALCcontext()2344 ALCcontext::~ALCcontext()
2345 {
2346 TRACE("Freeing context %p\n", voidp{this});
2347
2348 size_t count{0};
2349 ContextProps *cprops{mParams.ContextUpdate.exchange(nullptr, std::memory_order_relaxed)};
2350 if(cprops)
2351 {
2352 ++count;
2353 delete cprops;
2354 }
2355 cprops = mFreeContextProps.exchange(nullptr, std::memory_order_acquire);
2356 while(cprops)
2357 {
2358 std::unique_ptr<ContextProps> old{cprops};
2359 cprops = old->next.load(std::memory_order_relaxed);
2360 ++count;
2361 }
2362 TRACE("Freed %zu context property object%s\n", count, (count==1)?"":"s");
2363
2364 count = std::accumulate(mSourceList.cbegin(), mSourceList.cend(), size_t{0u},
2365 [](size_t cur, const SourceSubList &sublist) noexcept -> size_t
2366 { return cur + static_cast<uint>(al::popcount(~sublist.FreeMask)); });
2367 if(count > 0)
2368 WARN("%zu Source%s not deleted\n", count, (count==1)?"":"s");
2369 mSourceList.clear();
2370 mNumSources = 0;
2371
2372 count = 0;
2373 EffectSlotProps *eprops{mFreeEffectslotProps.exchange(nullptr, std::memory_order_acquire)};
2374 while(eprops)
2375 {
2376 std::unique_ptr<EffectSlotProps> old{eprops};
2377 eprops = old->next.load(std::memory_order_relaxed);
2378 ++count;
2379 }
2380 TRACE("Freed %zu AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2381
2382 if(EffectSlotArray *curarray{mActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed)})
2383 {
2384 al::destroy_n(curarray->end(), curarray->size());
2385 delete curarray;
2386 }
2387 mDefaultSlot = nullptr;
2388
2389 count = std::accumulate(mEffectSlotList.cbegin(), mEffectSlotList.cend(), size_t{0u},
2390 [](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t
2391 { return cur + static_cast<uint>(al::popcount(~sublist.FreeMask)); });
2392 if(count > 0)
2393 WARN("%zu AuxiliaryEffectSlot%s not deleted\n", count, (count==1)?"":"s");
2394 mEffectSlotList.clear();
2395 mNumEffectSlots = 0;
2396
2397 count = 0;
2398 VoicePropsItem *vprops{mFreeVoiceProps.exchange(nullptr, std::memory_order_acquire)};
2399 while(vprops)
2400 {
2401 std::unique_ptr<VoicePropsItem> old{vprops};
2402 vprops = old->next.load(std::memory_order_relaxed);
2403 ++count;
2404 }
2405 TRACE("Freed %zu voice property object%s\n", count, (count==1)?"":"s");
2406
2407 delete mVoices.exchange(nullptr, std::memory_order_relaxed);
2408
2409 count = 0;
2410 ListenerProps *lprops{mParams.ListenerUpdate.exchange(nullptr, std::memory_order_relaxed)};
2411 if(lprops)
2412 {
2413 ++count;
2414 delete lprops;
2415 }
2416 lprops = mFreeListenerProps.exchange(nullptr, std::memory_order_acquire);
2417 while(lprops)
2418 {
2419 std::unique_ptr<ListenerProps> old{lprops};
2420 lprops = old->next.load(std::memory_order_relaxed);
2421 ++count;
2422 }
2423 TRACE("Freed %zu listener property object%s\n", count, (count==1)?"":"s");
2424
2425 if(mAsyncEvents)
2426 {
2427 count = 0;
2428 auto evt_vec = mAsyncEvents->getReadVector();
2429 if(evt_vec.first.len > 0)
2430 {
2431 al::destroy_n(reinterpret_cast<AsyncEvent*>(evt_vec.first.buf), evt_vec.first.len);
2432 count += evt_vec.first.len;
2433 }
2434 if(evt_vec.second.len > 0)
2435 {
2436 al::destroy_n(reinterpret_cast<AsyncEvent*>(evt_vec.second.buf), evt_vec.second.len);
2437 count += evt_vec.second.len;
2438 }
2439 if(count > 0)
2440 TRACE("Destructed %zu orphaned event%s\n", count, (count==1)?"":"s");
2441 mAsyncEvents->readAdvance(count);
2442 }
2443 }
2444
init()2445 void ALCcontext::init()
2446 {
2447 if(DefaultEffect.type != AL_EFFECT_NULL && mDevice->Type == DeviceType::Playback)
2448 {
2449 mDefaultSlot = std::make_unique<ALeffectslot>();
2450 aluInitEffectPanning(&mDefaultSlot->mSlot, this);
2451 }
2452
2453 EffectSlotArray *auxslots;
2454 if(!mDefaultSlot)
2455 auxslots = EffectSlot::CreatePtrArray(0);
2456 else
2457 {
2458 auxslots = EffectSlot::CreatePtrArray(1);
2459 (*auxslots)[0] = &mDefaultSlot->mSlot;
2460 mDefaultSlot->mState = SlotState::Playing;
2461 }
2462 mActiveAuxSlots.store(auxslots, std::memory_order_relaxed);
2463
2464 allocVoiceChanges(1);
2465 {
2466 VoiceChange *cur{mVoiceChangeTail};
2467 while(VoiceChange *next{cur->mNext.load(std::memory_order_relaxed)})
2468 cur = next;
2469 mCurrentVoiceChange.store(cur, std::memory_order_relaxed);
2470 }
2471
2472 mExtensionList = alExtList;
2473
2474
2475 mParams.Matrix = alu::Matrix::Identity();
2476 mParams.Velocity = alu::Vector{};
2477 mParams.Gain = mListener.Gain;
2478 mParams.MetersPerUnit = mListener.mMetersPerUnit;
2479 mParams.DopplerFactor = mDopplerFactor;
2480 mParams.SpeedOfSound = mSpeedOfSound * mDopplerVelocity;
2481 mParams.SourceDistanceModel = mSourceDistanceModel;
2482 mParams.mDistanceModel = mDistanceModel;
2483
2484
2485 mAsyncEvents = RingBuffer::Create(511, sizeof(AsyncEvent), false);
2486 StartEventThrd(this);
2487
2488
2489 allocVoices(256);
2490 mActiveVoiceCount.store(64, std::memory_order_relaxed);
2491 }
2492
deinit()2493 bool ALCcontext::deinit()
2494 {
2495 if(LocalContext == this)
2496 {
2497 WARN("%p released while current on thread\n", voidp{this});
2498 ThreadContext.set(nullptr);
2499 release();
2500 }
2501
2502 ALCcontext *origctx{this};
2503 if(GlobalContext.compare_exchange_strong(origctx, nullptr))
2504 release();
2505
2506 bool ret{};
2507 /* First make sure this context exists in the device's list. */
2508 auto *oldarray = mDevice->mContexts.load(std::memory_order_acquire);
2509 if(auto toremove = static_cast<size_t>(std::count(oldarray->begin(), oldarray->end(), this)))
2510 {
2511 using ContextArray = al::FlexArray<ALCcontext*>;
2512 auto alloc_ctx_array = [](const size_t count) -> ContextArray*
2513 {
2514 if(count == 0) return &EmptyContextArray;
2515 return ContextArray::Create(count).release();
2516 };
2517 auto *newarray = alloc_ctx_array(oldarray->size() - toremove);
2518
2519 /* Copy the current/old context handles to the new array, excluding the
2520 * given context.
2521 */
2522 std::copy_if(oldarray->begin(), oldarray->end(), newarray->begin(),
2523 std::bind(std::not_equal_to<ALCcontext*>{}, _1, this));
2524
2525 /* Store the new context array in the device. Wait for any current mix
2526 * to finish before deleting the old array.
2527 */
2528 mDevice->mContexts.store(newarray);
2529 if(oldarray != &EmptyContextArray)
2530 {
2531 mDevice->waitForMix();
2532 delete oldarray;
2533 }
2534
2535 ret = !newarray->empty();
2536 }
2537 else
2538 ret = !oldarray->empty();
2539
2540 StopEventThrd(this);
2541
2542 return ret;
2543 }
2544
2545
2546 /**
2547 * Checks if the given context is valid, returning a new reference to it if so.
2548 */
VerifyContext(ALCcontext * context)2549 static ContextRef VerifyContext(ALCcontext *context)
2550 {
2551 std::lock_guard<std::recursive_mutex> _{ListLock};
2552 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
2553 if(iter != ContextList.end() && *iter == context)
2554 {
2555 (*iter)->add_ref();
2556 return ContextRef{*iter};
2557 }
2558 return nullptr;
2559 }
2560
2561 /** Returns a new reference to the currently active context for this thread. */
GetContextRef(void)2562 ContextRef GetContextRef(void)
2563 {
2564 ALCcontext *context{LocalContext};
2565 if(context)
2566 context->add_ref();
2567 else
2568 {
2569 std::lock_guard<std::recursive_mutex> _{ListLock};
2570 context = GlobalContext.load(std::memory_order_acquire);
2571 if(context) context->add_ref();
2572 }
2573 return ContextRef{context};
2574 }
2575
2576
2577 /************************************************
2578 * Standard ALC functions
2579 ************************************************/
2580
alcGetError(ALCdevice * device)2581 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2582 START_API_FUNC
2583 {
2584 DeviceRef dev{VerifyDevice(device)};
2585 if(dev) return dev->LastError.exchange(ALC_NO_ERROR);
2586 return LastNullDeviceError.exchange(ALC_NO_ERROR);
2587 }
2588 END_API_FUNC
2589
2590
alcSuspendContext(ALCcontext * context)2591 ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2592 START_API_FUNC
2593 {
2594 if(!SuspendDefers)
2595 return;
2596
2597 ContextRef ctx{VerifyContext(context)};
2598 if(!ctx)
2599 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2600 else
2601 ctx->deferUpdates();
2602 }
2603 END_API_FUNC
2604
alcProcessContext(ALCcontext * context)2605 ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context)
2606 START_API_FUNC
2607 {
2608 if(!SuspendDefers)
2609 return;
2610
2611 ContextRef ctx{VerifyContext(context)};
2612 if(!ctx)
2613 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2614 else
2615 ctx->processUpdates();
2616 }
2617 END_API_FUNC
2618
2619
alcGetString(ALCdevice * Device,ALCenum param)2620 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2621 START_API_FUNC
2622 {
2623 const ALCchar *value{nullptr};
2624
2625 switch(param)
2626 {
2627 case ALC_NO_ERROR:
2628 value = alcNoError;
2629 break;
2630
2631 case ALC_INVALID_ENUM:
2632 value = alcErrInvalidEnum;
2633 break;
2634
2635 case ALC_INVALID_VALUE:
2636 value = alcErrInvalidValue;
2637 break;
2638
2639 case ALC_INVALID_DEVICE:
2640 value = alcErrInvalidDevice;
2641 break;
2642
2643 case ALC_INVALID_CONTEXT:
2644 value = alcErrInvalidContext;
2645 break;
2646
2647 case ALC_OUT_OF_MEMORY:
2648 value = alcErrOutOfMemory;
2649 break;
2650
2651 case ALC_DEVICE_SPECIFIER:
2652 value = alcDefaultName;
2653 break;
2654
2655 case ALC_ALL_DEVICES_SPECIFIER:
2656 if(DeviceRef dev{VerifyDevice(Device)})
2657 value = dev->DeviceName.c_str();
2658 else
2659 {
2660 ProbeAllDevicesList();
2661 value = alcAllDevicesList.c_str();
2662 }
2663 break;
2664
2665 case ALC_CAPTURE_DEVICE_SPECIFIER:
2666 if(DeviceRef dev{VerifyDevice(Device)})
2667 value = dev->DeviceName.c_str();
2668 else
2669 {
2670 ProbeCaptureDeviceList();
2671 value = alcCaptureDeviceList.c_str();
2672 }
2673 break;
2674
2675 /* Default devices are always first in the list */
2676 case ALC_DEFAULT_DEVICE_SPECIFIER:
2677 value = alcDefaultName;
2678 break;
2679
2680 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2681 if(alcAllDevicesList.empty())
2682 ProbeAllDevicesList();
2683
2684 /* Copy first entry as default. */
2685 alcDefaultAllDevicesSpecifier = alcAllDevicesList.c_str();
2686 value = alcDefaultAllDevicesSpecifier.c_str();
2687 break;
2688
2689 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2690 if(alcCaptureDeviceList.empty())
2691 ProbeCaptureDeviceList();
2692
2693 /* Copy first entry as default. */
2694 alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList.c_str();
2695 value = alcCaptureDefaultDeviceSpecifier.c_str();
2696 break;
2697
2698 case ALC_EXTENSIONS:
2699 if(VerifyDevice(Device))
2700 value = alcExtensionList;
2701 else
2702 value = alcNoDeviceExtList;
2703 break;
2704
2705 case ALC_HRTF_SPECIFIER_SOFT:
2706 if(DeviceRef dev{VerifyDevice(Device)})
2707 {
2708 std::lock_guard<std::mutex> _{dev->StateLock};
2709 value = (dev->mHrtf ? dev->HrtfName.c_str() : "");
2710 }
2711 else
2712 alcSetError(nullptr, ALC_INVALID_DEVICE);
2713 break;
2714
2715 default:
2716 alcSetError(VerifyDevice(Device).get(), ALC_INVALID_ENUM);
2717 break;
2718 }
2719
2720 return value;
2721 }
2722 END_API_FUNC
2723
2724
NumAttrsForDevice(ALCdevice * device)2725 static inline int NumAttrsForDevice(ALCdevice *device)
2726 {
2727 if(device->Type == DeviceType::Capture) return 9;
2728 if(device->Type != DeviceType::Loopback) return 29;
2729 if(device->FmtChans == DevFmtAmbi3D)
2730 return 35;
2731 return 29;
2732 }
2733
GetIntegerv(ALCdevice * device,ALCenum param,const al::span<int> values)2734 static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span<int> values)
2735 {
2736 size_t i;
2737
2738 if(values.empty())
2739 {
2740 alcSetError(device, ALC_INVALID_VALUE);
2741 return 0;
2742 }
2743
2744 if(!device)
2745 {
2746 switch(param)
2747 {
2748 case ALC_MAJOR_VERSION:
2749 values[0] = alcMajorVersion;
2750 return 1;
2751 case ALC_MINOR_VERSION:
2752 values[0] = alcMinorVersion;
2753 return 1;
2754
2755 case ALC_EFX_MAJOR_VERSION:
2756 values[0] = alcEFXMajorVersion;
2757 return 1;
2758 case ALC_EFX_MINOR_VERSION:
2759 values[0] = alcEFXMinorVersion;
2760 return 1;
2761 case ALC_MAX_AUXILIARY_SENDS:
2762 values[0] = MAX_SENDS;
2763 return 1;
2764
2765 case ALC_ATTRIBUTES_SIZE:
2766 case ALC_ALL_ATTRIBUTES:
2767 case ALC_FREQUENCY:
2768 case ALC_REFRESH:
2769 case ALC_SYNC:
2770 case ALC_MONO_SOURCES:
2771 case ALC_STEREO_SOURCES:
2772 case ALC_CAPTURE_SAMPLES:
2773 case ALC_FORMAT_CHANNELS_SOFT:
2774 case ALC_FORMAT_TYPE_SOFT:
2775 case ALC_AMBISONIC_LAYOUT_SOFT:
2776 case ALC_AMBISONIC_SCALING_SOFT:
2777 case ALC_AMBISONIC_ORDER_SOFT:
2778 case ALC_MAX_AMBISONIC_ORDER_SOFT:
2779 alcSetError(nullptr, ALC_INVALID_DEVICE);
2780 return 0;
2781
2782 default:
2783 alcSetError(nullptr, ALC_INVALID_ENUM);
2784 }
2785 return 0;
2786 }
2787
2788 if(device->Type == DeviceType::Capture)
2789 {
2790 switch(param)
2791 {
2792 case ALC_ATTRIBUTES_SIZE:
2793 values[0] = NumAttrsForDevice(device);
2794 return 1;
2795
2796 case ALC_ALL_ATTRIBUTES:
2797 i = 0;
2798 if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2799 alcSetError(device, ALC_INVALID_VALUE);
2800 else
2801 {
2802 std::lock_guard<std::mutex> _{device->StateLock};
2803 values[i++] = ALC_MAJOR_VERSION;
2804 values[i++] = alcMajorVersion;
2805 values[i++] = ALC_MINOR_VERSION;
2806 values[i++] = alcMinorVersion;
2807 values[i++] = ALC_CAPTURE_SAMPLES;
2808 values[i++] = static_cast<int>(device->Backend->availableSamples());
2809 values[i++] = ALC_CONNECTED;
2810 values[i++] = device->Connected.load(std::memory_order_relaxed);
2811 values[i++] = 0;
2812 }
2813 return i;
2814
2815 case ALC_MAJOR_VERSION:
2816 values[0] = alcMajorVersion;
2817 return 1;
2818 case ALC_MINOR_VERSION:
2819 values[0] = alcMinorVersion;
2820 return 1;
2821
2822 case ALC_CAPTURE_SAMPLES:
2823 {
2824 std::lock_guard<std::mutex> _{device->StateLock};
2825 values[0] = static_cast<int>(device->Backend->availableSamples());
2826 }
2827 return 1;
2828
2829 case ALC_CONNECTED:
2830 {
2831 std::lock_guard<std::mutex> _{device->StateLock};
2832 values[0] = device->Connected.load(std::memory_order_acquire);
2833 }
2834 return 1;
2835
2836 default:
2837 alcSetError(device, ALC_INVALID_ENUM);
2838 }
2839 return 0;
2840 }
2841
2842 /* render device */
2843 switch(param)
2844 {
2845 case ALC_ATTRIBUTES_SIZE:
2846 values[0] = NumAttrsForDevice(device);
2847 return 1;
2848
2849 case ALC_ALL_ATTRIBUTES:
2850 i = 0;
2851 if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2852 alcSetError(device, ALC_INVALID_VALUE);
2853 else
2854 {
2855 std::lock_guard<std::mutex> _{device->StateLock};
2856 values[i++] = ALC_MAJOR_VERSION;
2857 values[i++] = alcMajorVersion;
2858 values[i++] = ALC_MINOR_VERSION;
2859 values[i++] = alcMinorVersion;
2860 values[i++] = ALC_EFX_MAJOR_VERSION;
2861 values[i++] = alcEFXMajorVersion;
2862 values[i++] = ALC_EFX_MINOR_VERSION;
2863 values[i++] = alcEFXMinorVersion;
2864
2865 values[i++] = ALC_FREQUENCY;
2866 values[i++] = static_cast<int>(device->Frequency);
2867 if(device->Type != DeviceType::Loopback)
2868 {
2869 values[i++] = ALC_REFRESH;
2870 values[i++] = static_cast<int>(device->Frequency / device->UpdateSize);
2871
2872 values[i++] = ALC_SYNC;
2873 values[i++] = ALC_FALSE;
2874 }
2875 else
2876 {
2877 if(device->FmtChans == DevFmtAmbi3D)
2878 {
2879 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
2880 values[i++] = EnumFromDevAmbi(device->mAmbiLayout);
2881
2882 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
2883 values[i++] = EnumFromDevAmbi(device->mAmbiScale);
2884
2885 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
2886 values[i++] = static_cast<int>(device->mAmbiOrder);
2887 }
2888
2889 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2890 values[i++] = EnumFromDevFmt(device->FmtChans);
2891
2892 values[i++] = ALC_FORMAT_TYPE_SOFT;
2893 values[i++] = EnumFromDevFmt(device->FmtType);
2894 }
2895
2896 values[i++] = ALC_MONO_SOURCES;
2897 values[i++] = static_cast<int>(device->NumMonoSources);
2898
2899 values[i++] = ALC_STEREO_SOURCES;
2900 values[i++] = static_cast<int>(device->NumStereoSources);
2901
2902 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2903 values[i++] = static_cast<int>(device->NumAuxSends);
2904
2905 values[i++] = ALC_HRTF_SOFT;
2906 values[i++] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
2907
2908 values[i++] = ALC_HRTF_STATUS_SOFT;
2909 values[i++] = device->HrtfStatus;
2910
2911 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
2912 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
2913
2914 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
2915 values[i++] = MaxAmbiOrder;
2916
2917 values[i++] = 0;
2918 }
2919 return i;
2920
2921 case ALC_MAJOR_VERSION:
2922 values[0] = alcMajorVersion;
2923 return 1;
2924
2925 case ALC_MINOR_VERSION:
2926 values[0] = alcMinorVersion;
2927 return 1;
2928
2929 case ALC_EFX_MAJOR_VERSION:
2930 values[0] = alcEFXMajorVersion;
2931 return 1;
2932
2933 case ALC_EFX_MINOR_VERSION:
2934 values[0] = alcEFXMinorVersion;
2935 return 1;
2936
2937 case ALC_FREQUENCY:
2938 values[0] = static_cast<int>(device->Frequency);
2939 return 1;
2940
2941 case ALC_REFRESH:
2942 if(device->Type == DeviceType::Loopback)
2943 {
2944 alcSetError(device, ALC_INVALID_DEVICE);
2945 return 0;
2946 }
2947 {
2948 std::lock_guard<std::mutex> _{device->StateLock};
2949 values[0] = static_cast<int>(device->Frequency / device->UpdateSize);
2950 }
2951 return 1;
2952
2953 case ALC_SYNC:
2954 if(device->Type == DeviceType::Loopback)
2955 {
2956 alcSetError(device, ALC_INVALID_DEVICE);
2957 return 0;
2958 }
2959 values[0] = ALC_FALSE;
2960 return 1;
2961
2962 case ALC_FORMAT_CHANNELS_SOFT:
2963 if(device->Type != DeviceType::Loopback)
2964 {
2965 alcSetError(device, ALC_INVALID_DEVICE);
2966 return 0;
2967 }
2968 values[0] = EnumFromDevFmt(device->FmtChans);
2969 return 1;
2970
2971 case ALC_FORMAT_TYPE_SOFT:
2972 if(device->Type != DeviceType::Loopback)
2973 {
2974 alcSetError(device, ALC_INVALID_DEVICE);
2975 return 0;
2976 }
2977 values[0] = EnumFromDevFmt(device->FmtType);
2978 return 1;
2979
2980 case ALC_AMBISONIC_LAYOUT_SOFT:
2981 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2982 {
2983 alcSetError(device, ALC_INVALID_DEVICE);
2984 return 0;
2985 }
2986 values[0] = EnumFromDevAmbi(device->mAmbiLayout);
2987 return 1;
2988
2989 case ALC_AMBISONIC_SCALING_SOFT:
2990 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2991 {
2992 alcSetError(device, ALC_INVALID_DEVICE);
2993 return 0;
2994 }
2995 values[0] = EnumFromDevAmbi(device->mAmbiScale);
2996 return 1;
2997
2998 case ALC_AMBISONIC_ORDER_SOFT:
2999 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
3000 {
3001 alcSetError(device, ALC_INVALID_DEVICE);
3002 return 0;
3003 }
3004 values[0] = static_cast<int>(device->mAmbiOrder);
3005 return 1;
3006
3007 case ALC_MONO_SOURCES:
3008 values[0] = static_cast<int>(device->NumMonoSources);
3009 return 1;
3010
3011 case ALC_STEREO_SOURCES:
3012 values[0] = static_cast<int>(device->NumStereoSources);
3013 return 1;
3014
3015 case ALC_MAX_AUXILIARY_SENDS:
3016 values[0] = static_cast<int>(device->NumAuxSends);
3017 return 1;
3018
3019 case ALC_CONNECTED:
3020 {
3021 std::lock_guard<std::mutex> _{device->StateLock};
3022 values[0] = device->Connected.load(std::memory_order_acquire);
3023 }
3024 return 1;
3025
3026 case ALC_HRTF_SOFT:
3027 values[0] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
3028 return 1;
3029
3030 case ALC_HRTF_STATUS_SOFT:
3031 values[0] = device->HrtfStatus;
3032 return 1;
3033
3034 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3035 {
3036 std::lock_guard<std::mutex> _{device->StateLock};
3037 device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
3038 values[0] = static_cast<int>(minz(device->HrtfList.size(),
3039 std::numeric_limits<int>::max()));
3040 }
3041 return 1;
3042
3043 case ALC_OUTPUT_LIMITER_SOFT:
3044 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3045 return 1;
3046
3047 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3048 values[0] = MaxAmbiOrder;
3049 return 1;
3050
3051 default:
3052 alcSetError(device, ALC_INVALID_ENUM);
3053 }
3054 return 0;
3055 }
3056
alcGetIntegerv(ALCdevice * device,ALCenum param,ALCsizei size,ALCint * values)3057 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3058 START_API_FUNC
3059 {
3060 DeviceRef dev{VerifyDevice(device)};
3061 if(size <= 0 || values == nullptr)
3062 alcSetError(dev.get(), ALC_INVALID_VALUE);
3063 else
3064 GetIntegerv(dev.get(), param, {values, static_cast<uint>(size)});
3065 }
3066 END_API_FUNC
3067
alcGetInteger64vSOFT(ALCdevice * device,ALCenum pname,ALCsizei size,ALCint64SOFT * values)3068 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3069 START_API_FUNC
3070 {
3071 DeviceRef dev{VerifyDevice(device)};
3072 if(size <= 0 || values == nullptr)
3073 {
3074 alcSetError(dev.get(), ALC_INVALID_VALUE);
3075 return;
3076 }
3077 if(!dev || dev->Type == DeviceType::Capture)
3078 {
3079 auto ivals = al::vector<int>(static_cast<uint>(size));
3080 size_t got{GetIntegerv(dev.get(), pname, ivals)};
3081 std::copy_n(ivals.begin(), got, values);
3082 return;
3083 }
3084 /* render device */
3085 switch(pname)
3086 {
3087 case ALC_ATTRIBUTES_SIZE:
3088 *values = NumAttrsForDevice(dev.get())+4;
3089 break;
3090
3091 case ALC_ALL_ATTRIBUTES:
3092 if(size < NumAttrsForDevice(dev.get())+4)
3093 alcSetError(dev.get(), ALC_INVALID_VALUE);
3094 else
3095 {
3096 size_t i{0};
3097 std::lock_guard<std::mutex> _{dev->StateLock};
3098 values[i++] = ALC_FREQUENCY;
3099 values[i++] = dev->Frequency;
3100
3101 if(dev->Type != DeviceType::Loopback)
3102 {
3103 values[i++] = ALC_REFRESH;
3104 values[i++] = dev->Frequency / dev->UpdateSize;
3105
3106 values[i++] = ALC_SYNC;
3107 values[i++] = ALC_FALSE;
3108 }
3109 else
3110 {
3111 if(dev->FmtChans == DevFmtAmbi3D)
3112 {
3113 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3114 values[i++] = EnumFromDevAmbi(dev->mAmbiLayout);
3115
3116 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3117 values[i++] = EnumFromDevAmbi(dev->mAmbiScale);
3118
3119 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3120 values[i++] = dev->mAmbiOrder;
3121 }
3122
3123 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3124 values[i++] = EnumFromDevFmt(dev->FmtChans);
3125
3126 values[i++] = ALC_FORMAT_TYPE_SOFT;
3127 values[i++] = EnumFromDevFmt(dev->FmtType);
3128 }
3129
3130 values[i++] = ALC_MONO_SOURCES;
3131 values[i++] = dev->NumMonoSources;
3132
3133 values[i++] = ALC_STEREO_SOURCES;
3134 values[i++] = dev->NumStereoSources;
3135
3136 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3137 values[i++] = dev->NumAuxSends;
3138
3139 values[i++] = ALC_HRTF_SOFT;
3140 values[i++] = (dev->mHrtf ? ALC_TRUE : ALC_FALSE);
3141
3142 values[i++] = ALC_HRTF_STATUS_SOFT;
3143 values[i++] = dev->HrtfStatus;
3144
3145 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3146 values[i++] = dev->Limiter ? ALC_TRUE : ALC_FALSE;
3147
3148 ClockLatency clock{GetClockLatency(dev.get())};
3149 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3150 values[i++] = clock.ClockTime.count();
3151
3152 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3153 values[i++] = clock.Latency.count();
3154
3155 values[i++] = 0;
3156 }
3157 break;
3158
3159 case ALC_DEVICE_CLOCK_SOFT:
3160 {
3161 std::lock_guard<std::mutex> _{dev->StateLock};
3162 uint samplecount, refcount;
3163 nanoseconds basecount;
3164 do {
3165 refcount = dev->waitForMix();
3166 basecount = dev->ClockBase;
3167 samplecount = dev->SamplesDone;
3168 } while(refcount != ReadRef(dev->MixCount));
3169 basecount += nanoseconds{seconds{samplecount}} / dev->Frequency;
3170 *values = basecount.count();
3171 }
3172 break;
3173
3174 case ALC_DEVICE_LATENCY_SOFT:
3175 {
3176 std::lock_guard<std::mutex> _{dev->StateLock};
3177 ClockLatency clock{GetClockLatency(dev.get())};
3178 *values = clock.Latency.count();
3179 }
3180 break;
3181
3182 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3183 if(size < 2)
3184 alcSetError(dev.get(), ALC_INVALID_VALUE);
3185 else
3186 {
3187 std::lock_guard<std::mutex> _{dev->StateLock};
3188 ClockLatency clock{GetClockLatency(dev.get())};
3189 values[0] = clock.ClockTime.count();
3190 values[1] = clock.Latency.count();
3191 }
3192 break;
3193
3194 default:
3195 auto ivals = al::vector<int>(static_cast<uint>(size));
3196 size_t got{GetIntegerv(dev.get(), pname, ivals)};
3197 std::copy_n(ivals.begin(), got, values);
3198 break;
3199 }
3200 }
3201 END_API_FUNC
3202
3203
alcIsExtensionPresent(ALCdevice * device,const ALCchar * extName)3204 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3205 START_API_FUNC
3206 {
3207 DeviceRef dev{VerifyDevice(device)};
3208 if(!extName)
3209 alcSetError(dev.get(), ALC_INVALID_VALUE);
3210 else
3211 {
3212 size_t len = strlen(extName);
3213 const char *ptr = (dev ? alcExtensionList : alcNoDeviceExtList);
3214 while(ptr && *ptr)
3215 {
3216 if(al::strncasecmp(ptr, extName, len) == 0 && (ptr[len] == '\0' || isspace(ptr[len])))
3217 return ALC_TRUE;
3218
3219 if((ptr=strchr(ptr, ' ')) != nullptr)
3220 {
3221 do {
3222 ++ptr;
3223 } while(isspace(*ptr));
3224 }
3225 }
3226 }
3227 return ALC_FALSE;
3228 }
3229 END_API_FUNC
3230
3231
alcGetProcAddress(ALCdevice * device,const ALCchar * funcName)3232 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3233 START_API_FUNC
3234 {
3235 if(!funcName)
3236 {
3237 DeviceRef dev{VerifyDevice(device)};
3238 alcSetError(dev.get(), ALC_INVALID_VALUE);
3239 }
3240 else
3241 {
3242 for(const auto &func : alcFunctions)
3243 {
3244 if(strcmp(func.funcName, funcName) == 0)
3245 return func.address;
3246 }
3247 }
3248 return nullptr;
3249 }
3250 END_API_FUNC
3251
3252
alcGetEnumValue(ALCdevice * device,const ALCchar * enumName)3253 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3254 START_API_FUNC
3255 {
3256 if(!enumName)
3257 {
3258 DeviceRef dev{VerifyDevice(device)};
3259 alcSetError(dev.get(), ALC_INVALID_VALUE);
3260 }
3261 else
3262 {
3263 for(const auto &enm : alcEnumerations)
3264 {
3265 if(strcmp(enm.enumName, enumName) == 0)
3266 return enm.value;
3267 }
3268 }
3269 return 0;
3270 }
3271 END_API_FUNC
3272
3273
alcCreateContext(ALCdevice * device,const ALCint * attrList)3274 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3275 START_API_FUNC
3276 {
3277 /* Explicitly hold the list lock while taking the StateLock in case the
3278 * device is asynchronously destroyed, to ensure this new context is
3279 * properly cleaned up after being made.
3280 */
3281 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3282 DeviceRef dev{VerifyDevice(device)};
3283 if(!dev || dev->Type == DeviceType::Capture || !dev->Connected.load(std::memory_order_relaxed))
3284 {
3285 listlock.unlock();
3286 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3287 return nullptr;
3288 }
3289 std::unique_lock<std::mutex> statelock{dev->StateLock};
3290 listlock.unlock();
3291
3292 dev->LastError.store(ALC_NO_ERROR);
3293
3294 ALCenum err{UpdateDeviceParams(dev.get(), attrList)};
3295 if(err != ALC_NO_ERROR)
3296 {
3297 alcSetError(dev.get(), err);
3298 return nullptr;
3299 }
3300
3301 ContextRef context{new ALCcontext{dev}};
3302 context->init();
3303
3304 if(auto volopt = ConfigValueFloat(dev->DeviceName.c_str(), nullptr, "volume-adjust"))
3305 {
3306 const float valf{*volopt};
3307 if(!std::isfinite(valf))
3308 ERR("volume-adjust must be finite: %f\n", valf);
3309 else
3310 {
3311 const float db{clampf(valf, -24.0f, 24.0f)};
3312 if(db != valf)
3313 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3314 context->mGainBoost = std::pow(10.0f, db/20.0f);
3315 TRACE("volume-adjust gain: %f\n", context->mGainBoost);
3316 }
3317 }
3318 UpdateListenerProps(context.get());
3319
3320 {
3321 using ContextArray = al::FlexArray<ALCcontext*>;
3322
3323 /* Allocate a new context array, which holds 1 more than the current/
3324 * old array.
3325 */
3326 auto *oldarray = device->mContexts.load();
3327 const size_t newcount{oldarray->size()+1};
3328 std::unique_ptr<ContextArray> newarray{ContextArray::Create(newcount)};
3329
3330 /* Copy the current/old context handles to the new array, appending the
3331 * new context.
3332 */
3333 auto iter = std::copy(oldarray->begin(), oldarray->end(), newarray->begin());
3334 *iter = context.get();
3335
3336 /* Store the new context array in the device. Wait for any current mix
3337 * to finish before deleting the old array.
3338 */
3339 dev->mContexts.store(newarray.release());
3340 if(oldarray != &EmptyContextArray)
3341 {
3342 dev->waitForMix();
3343 delete oldarray;
3344 }
3345 }
3346 statelock.unlock();
3347
3348 {
3349 std::lock_guard<std::recursive_mutex> _{ListLock};
3350 auto iter = std::lower_bound(ContextList.cbegin(), ContextList.cend(), context.get());
3351 ContextList.emplace(iter, context.get());
3352 }
3353
3354 if(ALeffectslot *slot{context->mDefaultSlot.get()})
3355 {
3356 if(slot->initEffect(&DefaultEffect, context.get()) == AL_NO_ERROR)
3357 slot->updateProps(context.get());
3358 else
3359 ERR("Failed to initialize the default effect\n");
3360 }
3361
3362 TRACE("Created context %p\n", voidp{context.get()});
3363 return context.release();
3364 }
3365 END_API_FUNC
3366
alcDestroyContext(ALCcontext * context)3367 ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3368 START_API_FUNC
3369 {
3370 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3371 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
3372 if(iter == ContextList.end() || *iter != context)
3373 {
3374 listlock.unlock();
3375 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3376 return;
3377 }
3378 /* Hold a reference to this context so it remains valid until the ListLock
3379 * is released.
3380 */
3381 ContextRef ctx{*iter};
3382 ContextList.erase(iter);
3383
3384 ALCdevice *Device{ctx->mDevice.get()};
3385
3386 std::lock_guard<std::mutex> _{Device->StateLock};
3387 if(!ctx->deinit() && Device->Flags.test(DeviceRunning))
3388 {
3389 Device->Backend->stop();
3390 Device->Flags.reset(DeviceRunning);
3391 }
3392 }
3393 END_API_FUNC
3394
3395
alcGetCurrentContext(void)3396 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3397 START_API_FUNC
3398 {
3399 ALCcontext *Context{LocalContext};
3400 if(!Context) Context = GlobalContext.load();
3401 return Context;
3402 }
3403 END_API_FUNC
3404
3405 /** Returns the currently active thread-local context. */
alcGetThreadContext(void)3406 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3407 START_API_FUNC
3408 { return LocalContext; }
3409 END_API_FUNC
3410
alcMakeContextCurrent(ALCcontext * context)3411 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3412 START_API_FUNC
3413 {
3414 /* context must be valid or nullptr */
3415 ContextRef ctx;
3416 if(context)
3417 {
3418 ctx = VerifyContext(context);
3419 if(!ctx)
3420 {
3421 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3422 return ALC_FALSE;
3423 }
3424 }
3425 /* Release this reference (if any) to store it in the GlobalContext
3426 * pointer. Take ownership of the reference (if any) that was previously
3427 * stored there.
3428 */
3429 ctx = ContextRef{GlobalContext.exchange(ctx.release())};
3430
3431 /* Reset (decrement) the previous global reference by replacing it with the
3432 * thread-local context. Take ownership of the thread-local context
3433 * reference (if any), clearing the storage to null.
3434 */
3435 ctx = ContextRef{LocalContext};
3436 if(ctx) ThreadContext.set(nullptr);
3437 /* Reset (decrement) the previous thread-local reference. */
3438
3439 return ALC_TRUE;
3440 }
3441 END_API_FUNC
3442
3443 /** Makes the given context the active context for the current thread. */
alcSetThreadContext(ALCcontext * context)3444 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3445 START_API_FUNC
3446 {
3447 /* context must be valid or nullptr */
3448 ContextRef ctx;
3449 if(context)
3450 {
3451 ctx = VerifyContext(context);
3452 if(!ctx)
3453 {
3454 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3455 return ALC_FALSE;
3456 }
3457 }
3458 /* context's reference count is already incremented */
3459 ContextRef old{LocalContext};
3460 ThreadContext.set(ctx.release());
3461
3462 return ALC_TRUE;
3463 }
3464 END_API_FUNC
3465
3466
alcGetContextsDevice(ALCcontext * Context)3467 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3468 START_API_FUNC
3469 {
3470 ContextRef ctx{VerifyContext(Context)};
3471 if(!ctx)
3472 {
3473 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3474 return nullptr;
3475 }
3476 return ctx->mDevice.get();
3477 }
3478 END_API_FUNC
3479
3480
alcOpenDevice(const ALCchar * deviceName)3481 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3482 START_API_FUNC
3483 {
3484 DO_INITCONFIG();
3485
3486 if(!PlaybackFactory)
3487 {
3488 alcSetError(nullptr, ALC_INVALID_VALUE);
3489 return nullptr;
3490 }
3491
3492 if(deviceName)
3493 {
3494 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3495 #ifdef _WIN32
3496 /* Some old Windows apps hardcode these expecting OpenAL to use a
3497 * specific audio API, even when they're not enumerated. Creative's
3498 * router effectively ignores them too.
3499 */
3500 || al::strcasecmp(deviceName, "DirectSound3D") == 0
3501 || al::strcasecmp(deviceName, "DirectSound") == 0
3502 || al::strcasecmp(deviceName, "MMSYSTEM") == 0
3503 #endif
3504 /* Some old Linux apps hardcode configuration strings that were
3505 * supported by the OpenAL SI. We can't really do anything useful
3506 * with them, so just ignore.
3507 */
3508 || (deviceName[0] == '\'' && deviceName[1] == '(')
3509 || al::strcasecmp(deviceName, "openal-soft") == 0)
3510 deviceName = nullptr;
3511 }
3512
3513 DeviceRef device{new ALCdevice{DeviceType::Playback}};
3514
3515 /* Set output format */
3516 device->FmtChans = DevFmtChannelsDefault;
3517 device->FmtType = DevFmtTypeDefault;
3518 device->Frequency = DEFAULT_OUTPUT_RATE;
3519 device->UpdateSize = DEFAULT_UPDATE_SIZE;
3520 device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
3521
3522 device->SourcesMax = 256;
3523 device->AuxiliaryEffectSlotMax = 64;
3524 device->NumAuxSends = DEFAULT_SENDS;
3525
3526 try {
3527 auto backend = PlaybackFactory->createBackend(device.get(), BackendType::Playback);
3528 std::lock_guard<std::recursive_mutex> _{ListLock};
3529 backend->open(deviceName);
3530 device->Backend = std::move(backend);
3531 }
3532 catch(al::backend_exception &e) {
3533 WARN("Failed to open playback device: %s\n", e.what());
3534 alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory)
3535 ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
3536 return nullptr;
3537 }
3538
3539 deviceName = device->DeviceName.c_str();
3540 if(auto chanopt = ConfigValueStr(deviceName, nullptr, "channels"))
3541 {
3542 static const struct ChannelMap {
3543 const char name[16];
3544 DevFmtChannels chans;
3545 uint order;
3546 } chanlist[] = {
3547 { "mono", DevFmtMono, 0 },
3548 { "stereo", DevFmtStereo, 0 },
3549 { "quad", DevFmtQuad, 0 },
3550 { "surround51", DevFmtX51, 0 },
3551 { "surround61", DevFmtX61, 0 },
3552 { "surround71", DevFmtX71, 0 },
3553 { "surround51rear", DevFmtX51Rear, 0 },
3554 { "ambi1", DevFmtAmbi3D, 1 },
3555 { "ambi2", DevFmtAmbi3D, 2 },
3556 { "ambi3", DevFmtAmbi3D, 3 },
3557 };
3558
3559 const ALCchar *fmt{chanopt->c_str()};
3560 auto iter = std::find_if(std::begin(chanlist), std::end(chanlist),
3561 [fmt](const ChannelMap &entry) -> bool
3562 { return al::strcasecmp(entry.name, fmt) == 0; }
3563 );
3564 if(iter == std::end(chanlist))
3565 ERR("Unsupported channels: %s\n", fmt);
3566 else
3567 {
3568 device->FmtChans = iter->chans;
3569 device->mAmbiOrder = iter->order;
3570 device->Flags.set(ChannelsRequest);
3571 }
3572 }
3573 if(auto typeopt = ConfigValueStr(deviceName, nullptr, "sample-type"))
3574 {
3575 static const struct TypeMap {
3576 const char name[16];
3577 DevFmtType type;
3578 } typelist[] = {
3579 { "int8", DevFmtByte },
3580 { "uint8", DevFmtUByte },
3581 { "int16", DevFmtShort },
3582 { "uint16", DevFmtUShort },
3583 { "int32", DevFmtInt },
3584 { "uint32", DevFmtUInt },
3585 { "float32", DevFmtFloat },
3586 };
3587
3588 const ALCchar *fmt{typeopt->c_str()};
3589 auto iter = std::find_if(std::begin(typelist), std::end(typelist),
3590 [fmt](const TypeMap &entry) -> bool
3591 { return al::strcasecmp(entry.name, fmt) == 0; }
3592 );
3593 if(iter == std::end(typelist))
3594 ERR("Unsupported sample-type: %s\n", fmt);
3595 else
3596 {
3597 device->FmtType = iter->type;
3598 device->Flags.set(SampleTypeRequest);
3599 }
3600 }
3601
3602 if(uint freq{ConfigValueUInt(deviceName, nullptr, "frequency").value_or(0u)})
3603 {
3604 if(freq < MIN_OUTPUT_RATE || freq > MAX_OUTPUT_RATE)
3605 {
3606 const uint newfreq{clampu(freq, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE)};
3607 ERR("%uhz request clamped to %uhz\n", freq, newfreq);
3608 freq = newfreq;
3609 }
3610 const double scale{static_cast<double>(freq) / device->Frequency};
3611 device->UpdateSize = static_cast<uint>(device->UpdateSize*scale + 0.5);
3612 device->BufferSize = static_cast<uint>(device->BufferSize*scale + 0.5);
3613 device->Frequency = freq;
3614 device->Flags.set(FrequencyRequest);
3615 }
3616
3617 if(auto persizeopt = ConfigValueUInt(deviceName, nullptr, "period_size"))
3618 device->UpdateSize = clampu(*persizeopt, 64, 8192);
3619
3620 if(auto peropt = ConfigValueUInt(deviceName, nullptr, "periods"))
3621 device->BufferSize = device->UpdateSize * clampu(*peropt, 2, 16);
3622 else
3623 device->BufferSize = maxu(device->BufferSize, device->UpdateSize*2);
3624
3625 if(auto srcsmax = ConfigValueUInt(deviceName, nullptr, "sources").value_or(0))
3626 device->SourcesMax = srcsmax;
3627
3628 if(auto slotsmax = ConfigValueUInt(deviceName, nullptr, "slots").value_or(0))
3629 device->AuxiliaryEffectSlotMax = minu(slotsmax, INT_MAX);
3630
3631 if(auto sendsopt = ConfigValueInt(deviceName, nullptr, "sends"))
3632 device->NumAuxSends = minu(DEFAULT_SENDS,
3633 static_cast<uint>(clampi(*sendsopt, 0, MAX_SENDS)));
3634
3635 device->NumStereoSources = 1;
3636 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3637
3638 if(auto ambiopt = ConfigValueStr(deviceName, nullptr, "ambi-format"))
3639 {
3640 const ALCchar *fmt{ambiopt->c_str()};
3641 if(al::strcasecmp(fmt, "fuma") == 0)
3642 {
3643 if(device->mAmbiOrder > 3)
3644 ERR("FuMa is incompatible with %d%s order ambisonics (up to third-order only)\n",
3645 device->mAmbiOrder,
3646 (((device->mAmbiOrder%100)/10) == 1) ? "th" :
3647 ((device->mAmbiOrder%10) == 1) ? "st" :
3648 ((device->mAmbiOrder%10) == 2) ? "nd" :
3649 ((device->mAmbiOrder%10) == 3) ? "rd" : "th");
3650 else
3651 {
3652 device->mAmbiLayout = DevAmbiLayout::FuMa;
3653 device->mAmbiScale = DevAmbiScaling::FuMa;
3654 }
3655 }
3656 else if(al::strcasecmp(fmt, "ambix") == 0 || al::strcasecmp(fmt, "acn+sn3d") == 0)
3657 {
3658 device->mAmbiLayout = DevAmbiLayout::ACN;
3659 device->mAmbiScale = DevAmbiScaling::SN3D;
3660 }
3661 else if(al::strcasecmp(fmt, "acn+n3d") == 0)
3662 {
3663 device->mAmbiLayout = DevAmbiLayout::ACN;
3664 device->mAmbiScale = DevAmbiScaling::N3D;
3665 }
3666 else
3667 ERR("Unsupported ambi-format: %s\n", fmt);
3668 }
3669
3670 {
3671 std::lock_guard<std::recursive_mutex> _{ListLock};
3672 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3673 DeviceList.emplace(iter, device.get());
3674 }
3675
3676 TRACE("Created device %p, \"%s\"\n", voidp{device.get()}, device->DeviceName.c_str());
3677 return device.release();
3678 }
3679 END_API_FUNC
3680
alcCloseDevice(ALCdevice * device)3681 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3682 START_API_FUNC
3683 {
3684 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3685 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3686 if(iter == DeviceList.end() || *iter != device)
3687 {
3688 alcSetError(nullptr, ALC_INVALID_DEVICE);
3689 return ALC_FALSE;
3690 }
3691 if((*iter)->Type == DeviceType::Capture)
3692 {
3693 alcSetError(*iter, ALC_INVALID_DEVICE);
3694 return ALC_FALSE;
3695 }
3696
3697 /* Erase the device, and any remaining contexts left on it, from their
3698 * respective lists.
3699 */
3700 DeviceRef dev{*iter};
3701 DeviceList.erase(iter);
3702
3703 std::unique_lock<std::mutex> statelock{dev->StateLock};
3704 al::vector<ContextRef> orphanctxs;
3705 for(ALCcontext *ctx : *dev->mContexts.load())
3706 {
3707 auto ctxiter = std::lower_bound(ContextList.begin(), ContextList.end(), ctx);
3708 if(ctxiter != ContextList.end() && *ctxiter == ctx)
3709 {
3710 orphanctxs.emplace_back(ContextRef{*ctxiter});
3711 ContextList.erase(ctxiter);
3712 }
3713 }
3714 listlock.unlock();
3715
3716 for(ContextRef &context : orphanctxs)
3717 {
3718 WARN("Releasing orphaned context %p\n", voidp{context.get()});
3719 context->deinit();
3720 }
3721 orphanctxs.clear();
3722
3723 if(dev->Flags.test(DeviceRunning))
3724 dev->Backend->stop();
3725 dev->Flags.reset(DeviceRunning);
3726
3727 return ALC_TRUE;
3728 }
3729 END_API_FUNC
3730
3731
3732 /************************************************
3733 * ALC capture functions
3734 ************************************************/
alcCaptureOpenDevice(const ALCchar * deviceName,ALCuint frequency,ALCenum format,ALCsizei samples)3735 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3736 START_API_FUNC
3737 {
3738 DO_INITCONFIG();
3739
3740 if(!CaptureFactory)
3741 {
3742 alcSetError(nullptr, ALC_INVALID_VALUE);
3743 return nullptr;
3744 }
3745
3746 if(samples <= 0)
3747 {
3748 alcSetError(nullptr, ALC_INVALID_VALUE);
3749 return nullptr;
3750 }
3751
3752 if(deviceName)
3753 {
3754 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3755 || al::strcasecmp(deviceName, "openal-soft") == 0)
3756 deviceName = nullptr;
3757 }
3758
3759 DeviceRef device{new ALCdevice{DeviceType::Capture}};
3760
3761 auto decompfmt = DecomposeDevFormat(format);
3762 if(!decompfmt)
3763 {
3764 alcSetError(nullptr, ALC_INVALID_ENUM);
3765 return nullptr;
3766 }
3767
3768 device->Frequency = frequency;
3769 device->FmtChans = decompfmt->chans;
3770 device->FmtType = decompfmt->type;
3771 device->Flags.set(FrequencyRequest);
3772 device->Flags.set(ChannelsRequest);
3773 device->Flags.set(SampleTypeRequest);
3774
3775 device->UpdateSize = static_cast<uint>(samples);
3776 device->BufferSize = static_cast<uint>(samples);
3777
3778 try {
3779 TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n",
3780 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
3781 device->Frequency, device->UpdateSize, device->BufferSize);
3782
3783 auto backend = CaptureFactory->createBackend(device.get(), BackendType::Capture);
3784 std::lock_guard<std::recursive_mutex> _{ListLock};
3785 backend->open(deviceName);
3786 device->Backend = std::move(backend);
3787 }
3788 catch(al::backend_exception &e) {
3789 WARN("Failed to open capture device: %s\n", e.what());
3790 alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory)
3791 ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
3792 return nullptr;
3793 }
3794
3795 {
3796 std::lock_guard<std::recursive_mutex> _{ListLock};
3797 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3798 DeviceList.emplace(iter, device.get());
3799 }
3800
3801 TRACE("Created capture device %p, \"%s\"\n", voidp{device.get()}, device->DeviceName.c_str());
3802 return device.release();
3803 }
3804 END_API_FUNC
3805
alcCaptureCloseDevice(ALCdevice * device)3806 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3807 START_API_FUNC
3808 {
3809 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3810 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3811 if(iter == DeviceList.end() || *iter != device)
3812 {
3813 alcSetError(nullptr, ALC_INVALID_DEVICE);
3814 return ALC_FALSE;
3815 }
3816 if((*iter)->Type != DeviceType::Capture)
3817 {
3818 alcSetError(*iter, ALC_INVALID_DEVICE);
3819 return ALC_FALSE;
3820 }
3821
3822 DeviceRef dev{*iter};
3823 DeviceList.erase(iter);
3824 listlock.unlock();
3825
3826 std::lock_guard<std::mutex> _{dev->StateLock};
3827 if(dev->Flags.test(DeviceRunning))
3828 dev->Backend->stop();
3829 dev->Flags.reset(DeviceRunning);
3830
3831 return ALC_TRUE;
3832 }
3833 END_API_FUNC
3834
alcCaptureStart(ALCdevice * device)3835 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3836 START_API_FUNC
3837 {
3838 DeviceRef dev{VerifyDevice(device)};
3839 if(!dev || dev->Type != DeviceType::Capture)
3840 {
3841 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3842 return;
3843 }
3844
3845 std::lock_guard<std::mutex> _{dev->StateLock};
3846 if(!dev->Connected.load(std::memory_order_acquire))
3847 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3848 else if(!dev->Flags.test(DeviceRunning))
3849 {
3850 try {
3851 auto backend = dev->Backend.get();
3852 backend->start();
3853 dev->Flags.set(DeviceRunning);
3854 }
3855 catch(al::backend_exception& e) {
3856 dev->handleDisconnect("%s", e.what());
3857 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3858 }
3859 }
3860 }
3861 END_API_FUNC
3862
alcCaptureStop(ALCdevice * device)3863 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3864 START_API_FUNC
3865 {
3866 DeviceRef dev{VerifyDevice(device)};
3867 if(!dev || dev->Type != DeviceType::Capture)
3868 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3869 else
3870 {
3871 std::lock_guard<std::mutex> _{dev->StateLock};
3872 if(dev->Flags.test(DeviceRunning))
3873 dev->Backend->stop();
3874 dev->Flags.reset(DeviceRunning);
3875 }
3876 }
3877 END_API_FUNC
3878
alcCaptureSamples(ALCdevice * device,ALCvoid * buffer,ALCsizei samples)3879 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3880 START_API_FUNC
3881 {
3882 DeviceRef dev{VerifyDevice(device)};
3883 if(!dev || dev->Type != DeviceType::Capture)
3884 {
3885 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3886 return;
3887 }
3888
3889 if(samples < 0 || (samples > 0 && buffer == nullptr))
3890 {
3891 alcSetError(dev.get(), ALC_INVALID_VALUE);
3892 return;
3893 }
3894 if(samples < 1)
3895 return;
3896
3897 std::lock_guard<std::mutex> _{dev->StateLock};
3898 BackendBase *backend{dev->Backend.get()};
3899
3900 const auto usamples = static_cast<uint>(samples);
3901 if(usamples > backend->availableSamples())
3902 {
3903 alcSetError(dev.get(), ALC_INVALID_VALUE);
3904 return;
3905 }
3906
3907 backend->captureSamples(static_cast<al::byte*>(buffer), usamples);
3908 }
3909 END_API_FUNC
3910
3911
3912 /************************************************
3913 * ALC loopback functions
3914 ************************************************/
3915
3916 /** Open a loopback device, for manual rendering. */
alcLoopbackOpenDeviceSOFT(const ALCchar * deviceName)3917 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3918 START_API_FUNC
3919 {
3920 DO_INITCONFIG();
3921
3922 /* Make sure the device name, if specified, is us. */
3923 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3924 {
3925 alcSetError(nullptr, ALC_INVALID_VALUE);
3926 return nullptr;
3927 }
3928
3929 DeviceRef device{new ALCdevice{DeviceType::Loopback}};
3930
3931 device->SourcesMax = 256;
3932 device->AuxiliaryEffectSlotMax = 64;
3933 device->NumAuxSends = DEFAULT_SENDS;
3934
3935 //Set output format
3936 device->BufferSize = 0;
3937 device->UpdateSize = 0;
3938
3939 device->Frequency = DEFAULT_OUTPUT_RATE;
3940 device->FmtChans = DevFmtChannelsDefault;
3941 device->FmtType = DevFmtTypeDefault;
3942
3943 if(auto srcsmax = ConfigValueUInt(nullptr, nullptr, "sources").value_or(0))
3944 device->SourcesMax = srcsmax;
3945
3946 if(auto slotsmax = ConfigValueUInt(nullptr, nullptr, "slots").value_or(0))
3947 device->AuxiliaryEffectSlotMax = minu(slotsmax, INT_MAX);
3948
3949 if(auto sendsopt = ConfigValueInt(nullptr, nullptr, "sends"))
3950 device->NumAuxSends = minu(DEFAULT_SENDS,
3951 static_cast<uint>(clampi(*sendsopt, 0, MAX_SENDS)));
3952
3953 device->NumStereoSources = 1;
3954 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3955
3956 try {
3957 auto backend = LoopbackBackendFactory::getFactory().createBackend(device.get(),
3958 BackendType::Playback);
3959 backend->open("Loopback");
3960 device->Backend = std::move(backend);
3961 }
3962 catch(al::backend_exception &e) {
3963 WARN("Failed to open loopback device: %s\n", e.what());
3964 alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory)
3965 ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
3966 return nullptr;
3967 }
3968
3969 {
3970 std::lock_guard<std::recursive_mutex> _{ListLock};
3971 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3972 DeviceList.emplace(iter, device.get());
3973 }
3974
3975 TRACE("Created loopback device %p\n", voidp{device.get()});
3976 return device.release();
3977 }
3978 END_API_FUNC
3979
3980 /**
3981 * Determines if the loopback device supports the given format for rendering.
3982 */
alcIsRenderFormatSupportedSOFT(ALCdevice * device,ALCsizei freq,ALCenum channels,ALCenum type)3983 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3984 START_API_FUNC
3985 {
3986 DeviceRef dev{VerifyDevice(device)};
3987 if(!dev || dev->Type != DeviceType::Loopback)
3988 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3989 else if(freq <= 0)
3990 alcSetError(dev.get(), ALC_INVALID_VALUE);
3991 else
3992 {
3993 if(DevFmtTypeFromEnum(type).has_value() && DevFmtChannelsFromEnum(channels).has_value()
3994 && freq >= MIN_OUTPUT_RATE && freq <= MAX_OUTPUT_RATE)
3995 return ALC_TRUE;
3996 }
3997
3998 return ALC_FALSE;
3999 }
4000 END_API_FUNC
4001
4002 /**
4003 * Renders some samples into a buffer, using the format last set by the
4004 * attributes given to alcCreateContext.
4005 */
alcRenderSamplesSOFT(ALCdevice * device,ALCvoid * buffer,ALCsizei samples)4006 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4007 START_API_FUNC
4008 {
4009 DeviceRef dev{VerifyDevice(device)};
4010 if(!dev || dev->Type != DeviceType::Loopback)
4011 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4012 else if(samples < 0 || (samples > 0 && buffer == nullptr))
4013 alcSetError(dev.get(), ALC_INVALID_VALUE);
4014 else
4015 dev->renderSamples(buffer, static_cast<uint>(samples), dev->channelsFromFmt());
4016 }
4017 END_API_FUNC
4018
4019
4020 /************************************************
4021 * ALC DSP pause/resume functions
4022 ************************************************/
4023
4024 /** Pause the DSP to stop audio processing. */
alcDevicePauseSOFT(ALCdevice * device)4025 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4026 START_API_FUNC
4027 {
4028 DeviceRef dev{VerifyDevice(device)};
4029 if(!dev || dev->Type != DeviceType::Playback)
4030 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4031 else
4032 {
4033 std::lock_guard<std::mutex> _{dev->StateLock};
4034 if(dev->Flags.test(DeviceRunning))
4035 dev->Backend->stop();
4036 dev->Flags.reset(DeviceRunning);
4037 dev->Flags.set(DevicePaused);
4038 }
4039 }
4040 END_API_FUNC
4041
4042 /** Resume the DSP to restart audio processing. */
alcDeviceResumeSOFT(ALCdevice * device)4043 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4044 START_API_FUNC
4045 {
4046 DeviceRef dev{VerifyDevice(device)};
4047 if(!dev || dev->Type != DeviceType::Playback)
4048 {
4049 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4050 return;
4051 }
4052
4053 std::lock_guard<std::mutex> _{dev->StateLock};
4054 if(!dev->Flags.test(DevicePaused))
4055 return;
4056 dev->Flags.reset(DevicePaused);
4057 if(dev->mContexts.load()->empty())
4058 return;
4059
4060 try {
4061 auto backend = dev->Backend.get();
4062 backend->start();
4063 dev->Flags.set(DeviceRunning);
4064 }
4065 catch(al::backend_exception& e) {
4066 dev->handleDisconnect("%s", e.what());
4067 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4068 }
4069 }
4070 END_API_FUNC
4071
4072
4073 /************************************************
4074 * ALC HRTF functions
4075 ************************************************/
4076
4077 /** Gets a string parameter at the given index. */
alcGetStringiSOFT(ALCdevice * device,ALCenum paramName,ALCsizei index)4078 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4079 START_API_FUNC
4080 {
4081 DeviceRef dev{VerifyDevice(device)};
4082 if(!dev || dev->Type == DeviceType::Capture)
4083 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4084 else switch(paramName)
4085 {
4086 case ALC_HRTF_SPECIFIER_SOFT:
4087 if(index >= 0 && static_cast<uint>(index) < dev->HrtfList.size())
4088 return dev->HrtfList[static_cast<uint>(index)].c_str();
4089 alcSetError(dev.get(), ALC_INVALID_VALUE);
4090 break;
4091
4092 default:
4093 alcSetError(dev.get(), ALC_INVALID_ENUM);
4094 break;
4095 }
4096
4097 return nullptr;
4098 }
4099 END_API_FUNC
4100
4101 /** Resets the given device output, using the specified attribute list. */
alcResetDeviceSOFT(ALCdevice * device,const ALCint * attribs)4102 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4103 START_API_FUNC
4104 {
4105 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4106 DeviceRef dev{VerifyDevice(device)};
4107 if(!dev || dev->Type == DeviceType::Capture)
4108 {
4109 listlock.unlock();
4110 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4111 return ALC_FALSE;
4112 }
4113 std::lock_guard<std::mutex> _{dev->StateLock};
4114 listlock.unlock();
4115
4116 /* Force the backend to stop mixing first since we're resetting. Also reset
4117 * the connected state so lost devices can attempt recover.
4118 */
4119 if(dev->Flags.test(DeviceRunning))
4120 dev->Backend->stop();
4121 dev->Flags.reset(DeviceRunning);
4122 if(!dev->Connected.load(std::memory_order_relaxed))
4123 {
4124 /* Make sure disconnection is finished before continuing on. */
4125 dev->waitForMix();
4126
4127 for(ALCcontext *ctx : *dev->mContexts.load(std::memory_order_acquire))
4128 {
4129 /* Clear any pending voice changes and reallocate voices to get a
4130 * clean restart.
4131 */
4132 std::lock_guard<std::mutex> __{ctx->mSourceLock};
4133 auto *vchg = ctx->mCurrentVoiceChange.load(std::memory_order_acquire);
4134 while(auto *next = vchg->mNext.load(std::memory_order_acquire))
4135 vchg = next;
4136 ctx->mCurrentVoiceChange.store(vchg, std::memory_order_release);
4137
4138 ctx->mVoiceClusters.clear();
4139 ctx->allocVoices(std::max<size_t>(256,
4140 ctx->mActiveVoiceCount.load(std::memory_order_relaxed)));
4141 }
4142
4143 dev->Connected.store(true);
4144 }
4145
4146 ALCenum err{UpdateDeviceParams(dev.get(), attribs)};
4147 if LIKELY(err == ALC_NO_ERROR) return ALC_TRUE;
4148
4149 alcSetError(dev.get(), err);
4150 return ALC_FALSE;
4151 }
4152 END_API_FUNC
4153