Avoid a full wipe and reallocation of wet buffers
[openal-soft.git] / alc / alc.cpp
blobc94a9d53be4c676ff12f8337057cd7877d80b7db
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include "version.h"
25 #ifdef _WIN32
26 #define WIN32_LEAN_AND_MEAN
27 #include <windows.h>
28 #endif
30 #include <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>
55 #include "AL/al.h"
56 #include "AL/alc.h"
57 #include "AL/alext.h"
58 #include "AL/efx.h"
60 #include "al/auxeffectslot.h"
61 #include "al/effect.h"
62 #include "al/event.h"
63 #include "al/filter.h"
64 #include "al/listener.h"
65 #include "al/source.h"
66 #include "alcmain.h"
67 #include "albyte.h"
68 #include "alconfig.h"
69 #include "alcontext.h"
70 #include "alexcpt.h"
71 #include "almalloc.h"
72 #include "alnumeric.h"
73 #include "aloptional.h"
74 #include "alspan.h"
75 #include "alstring.h"
76 #include "alu.h"
77 #include "ambidefs.h"
78 #include "atomic.h"
79 #include "bformatdec.h"
80 #include "bs2b.h"
81 #include "compat.h"
82 #include "cpu_caps.h"
83 #include "devformat.h"
84 #include "effects/base.h"
85 #include "filters/nfc.h"
86 #include "filters/splitter.h"
87 #include "fpu_ctrl.h"
88 #include "front_stablizer.h"
89 #include "hrtf.h"
90 #include "inprogext.h"
91 #include "intrusive_ptr.h"
92 #include "logging.h"
93 #include "mastering.h"
94 #include "opthelpers.h"
95 #include "pragmadefs.h"
96 #include "ringbuffer.h"
97 #include "strutils.h"
98 #include "threads.h"
99 #include "uhjfilter.h"
100 #include "vecmat.h"
101 #include "vector.h"
103 #include "backends/base.h"
104 #include "backends/null.h"
105 #include "backends/loopback.h"
106 #ifdef HAVE_JACK
107 #include "backends/jack.h"
108 #endif
109 #ifdef HAVE_PULSEAUDIO
110 #include "backends/pulseaudio.h"
111 #endif
112 #ifdef HAVE_ALSA
113 #include "backends/alsa.h"
114 #endif
115 #ifdef HAVE_WASAPI
116 #include "backends/wasapi.h"
117 #endif
118 #ifdef HAVE_COREAUDIO
119 #include "backends/coreaudio.h"
120 #endif
121 #ifdef HAVE_OPENSL
122 #include "backends/opensl.h"
123 #endif
124 #ifdef HAVE_OBOE
125 #include "backends/oboe.h"
126 #endif
127 #ifdef HAVE_SOLARIS
128 #include "backends/solaris.h"
129 #endif
130 #ifdef HAVE_SNDIO
131 #include "backends/sndio.h"
132 #endif
133 #ifdef HAVE_OSS
134 #include "backends/oss.h"
135 #endif
136 #ifdef HAVE_DSOUND
137 #include "backends/dsound.h"
138 #endif
139 #ifdef HAVE_WINMM
140 #include "backends/winmm.h"
141 #endif
142 #ifdef HAVE_PORTAUDIO
143 #include "backends/portaudio.h"
144 #endif
145 #ifdef HAVE_SDL2
146 #include "backends/sdl2.h"
147 #endif
148 #ifdef HAVE_WAVE
149 #include "backends/wave.h"
150 #endif
153 namespace {
155 using namespace std::placeholders;
156 using std::chrono::seconds;
157 using std::chrono::nanoseconds;
160 /************************************************
161 * Backends
162 ************************************************/
163 struct BackendInfo {
164 const char *name;
165 BackendFactory& (*getFactory)(void);
168 BackendInfo BackendList[] = {
169 #ifdef HAVE_JACK
170 { "jack", JackBackendFactory::getFactory },
171 #endif
172 #ifdef HAVE_PULSEAUDIO
173 { "pulse", PulseBackendFactory::getFactory },
174 #endif
175 #ifdef HAVE_ALSA
176 { "alsa", AlsaBackendFactory::getFactory },
177 #endif
178 #ifdef HAVE_WASAPI
179 { "wasapi", WasapiBackendFactory::getFactory },
180 #endif
181 #ifdef HAVE_COREAUDIO
182 { "core", CoreAudioBackendFactory::getFactory },
183 #endif
184 #ifdef HAVE_OBOE
185 { "oboe", OboeBackendFactory::getFactory },
186 #endif
187 #ifdef HAVE_OPENSL
188 { "opensl", OSLBackendFactory::getFactory },
189 #endif
190 #ifdef HAVE_SOLARIS
191 { "solaris", SolarisBackendFactory::getFactory },
192 #endif
193 #ifdef HAVE_SNDIO
194 { "sndio", SndIOBackendFactory::getFactory },
195 #endif
196 #ifdef HAVE_OSS
197 { "oss", OSSBackendFactory::getFactory },
198 #endif
199 #ifdef HAVE_DSOUND
200 { "dsound", DSoundBackendFactory::getFactory },
201 #endif
202 #ifdef HAVE_WINMM
203 { "winmm", WinMMBackendFactory::getFactory },
204 #endif
205 #ifdef HAVE_PORTAUDIO
206 { "port", PortBackendFactory::getFactory },
207 #endif
208 #ifdef HAVE_SDL2
209 { "sdl2", SDL2BackendFactory::getFactory },
210 #endif
212 { "null", NullBackendFactory::getFactory },
213 #ifdef HAVE_WAVE
214 { "wave", WaveBackendFactory::getFactory },
215 #endif
218 BackendFactory *PlaybackFactory{};
219 BackendFactory *CaptureFactory{};
222 /************************************************
223 * Functions, enums, and errors
224 ************************************************/
225 #define DECL(x) { #x, reinterpret_cast<void*>(x) }
226 const struct {
227 const char *funcName;
228 void *address;
229 } alcFunctions[] = {
230 DECL(alcCreateContext),
231 DECL(alcMakeContextCurrent),
232 DECL(alcProcessContext),
233 DECL(alcSuspendContext),
234 DECL(alcDestroyContext),
235 DECL(alcGetCurrentContext),
236 DECL(alcGetContextsDevice),
237 DECL(alcOpenDevice),
238 DECL(alcCloseDevice),
239 DECL(alcGetError),
240 DECL(alcIsExtensionPresent),
241 DECL(alcGetProcAddress),
242 DECL(alcGetEnumValue),
243 DECL(alcGetString),
244 DECL(alcGetIntegerv),
245 DECL(alcCaptureOpenDevice),
246 DECL(alcCaptureCloseDevice),
247 DECL(alcCaptureStart),
248 DECL(alcCaptureStop),
249 DECL(alcCaptureSamples),
251 DECL(alcSetThreadContext),
252 DECL(alcGetThreadContext),
254 DECL(alcLoopbackOpenDeviceSOFT),
255 DECL(alcIsRenderFormatSupportedSOFT),
256 DECL(alcRenderSamplesSOFT),
258 DECL(alcDevicePauseSOFT),
259 DECL(alcDeviceResumeSOFT),
261 DECL(alcGetStringiSOFT),
262 DECL(alcResetDeviceSOFT),
264 DECL(alcGetInteger64vSOFT),
266 DECL(alEnable),
267 DECL(alDisable),
268 DECL(alIsEnabled),
269 DECL(alGetString),
270 DECL(alGetBooleanv),
271 DECL(alGetIntegerv),
272 DECL(alGetFloatv),
273 DECL(alGetDoublev),
274 DECL(alGetBoolean),
275 DECL(alGetInteger),
276 DECL(alGetFloat),
277 DECL(alGetDouble),
278 DECL(alGetError),
279 DECL(alIsExtensionPresent),
280 DECL(alGetProcAddress),
281 DECL(alGetEnumValue),
282 DECL(alListenerf),
283 DECL(alListener3f),
284 DECL(alListenerfv),
285 DECL(alListeneri),
286 DECL(alListener3i),
287 DECL(alListeneriv),
288 DECL(alGetListenerf),
289 DECL(alGetListener3f),
290 DECL(alGetListenerfv),
291 DECL(alGetListeneri),
292 DECL(alGetListener3i),
293 DECL(alGetListeneriv),
294 DECL(alGenSources),
295 DECL(alDeleteSources),
296 DECL(alIsSource),
297 DECL(alSourcef),
298 DECL(alSource3f),
299 DECL(alSourcefv),
300 DECL(alSourcei),
301 DECL(alSource3i),
302 DECL(alSourceiv),
303 DECL(alGetSourcef),
304 DECL(alGetSource3f),
305 DECL(alGetSourcefv),
306 DECL(alGetSourcei),
307 DECL(alGetSource3i),
308 DECL(alGetSourceiv),
309 DECL(alSourcePlayv),
310 DECL(alSourceStopv),
311 DECL(alSourceRewindv),
312 DECL(alSourcePausev),
313 DECL(alSourcePlay),
314 DECL(alSourceStop),
315 DECL(alSourceRewind),
316 DECL(alSourcePause),
317 DECL(alSourceQueueBuffers),
318 DECL(alSourceUnqueueBuffers),
319 DECL(alGenBuffers),
320 DECL(alDeleteBuffers),
321 DECL(alIsBuffer),
322 DECL(alBufferData),
323 DECL(alBufferf),
324 DECL(alBuffer3f),
325 DECL(alBufferfv),
326 DECL(alBufferi),
327 DECL(alBuffer3i),
328 DECL(alBufferiv),
329 DECL(alGetBufferf),
330 DECL(alGetBuffer3f),
331 DECL(alGetBufferfv),
332 DECL(alGetBufferi),
333 DECL(alGetBuffer3i),
334 DECL(alGetBufferiv),
335 DECL(alDopplerFactor),
336 DECL(alDopplerVelocity),
337 DECL(alSpeedOfSound),
338 DECL(alDistanceModel),
340 DECL(alGenFilters),
341 DECL(alDeleteFilters),
342 DECL(alIsFilter),
343 DECL(alFilteri),
344 DECL(alFilteriv),
345 DECL(alFilterf),
346 DECL(alFilterfv),
347 DECL(alGetFilteri),
348 DECL(alGetFilteriv),
349 DECL(alGetFilterf),
350 DECL(alGetFilterfv),
351 DECL(alGenEffects),
352 DECL(alDeleteEffects),
353 DECL(alIsEffect),
354 DECL(alEffecti),
355 DECL(alEffectiv),
356 DECL(alEffectf),
357 DECL(alEffectfv),
358 DECL(alGetEffecti),
359 DECL(alGetEffectiv),
360 DECL(alGetEffectf),
361 DECL(alGetEffectfv),
362 DECL(alGenAuxiliaryEffectSlots),
363 DECL(alDeleteAuxiliaryEffectSlots),
364 DECL(alIsAuxiliaryEffectSlot),
365 DECL(alAuxiliaryEffectSloti),
366 DECL(alAuxiliaryEffectSlotiv),
367 DECL(alAuxiliaryEffectSlotf),
368 DECL(alAuxiliaryEffectSlotfv),
369 DECL(alGetAuxiliaryEffectSloti),
370 DECL(alGetAuxiliaryEffectSlotiv),
371 DECL(alGetAuxiliaryEffectSlotf),
372 DECL(alGetAuxiliaryEffectSlotfv),
374 DECL(alDeferUpdatesSOFT),
375 DECL(alProcessUpdatesSOFT),
377 DECL(alSourcedSOFT),
378 DECL(alSource3dSOFT),
379 DECL(alSourcedvSOFT),
380 DECL(alGetSourcedSOFT),
381 DECL(alGetSource3dSOFT),
382 DECL(alGetSourcedvSOFT),
383 DECL(alSourcei64SOFT),
384 DECL(alSource3i64SOFT),
385 DECL(alSourcei64vSOFT),
386 DECL(alGetSourcei64SOFT),
387 DECL(alGetSource3i64SOFT),
388 DECL(alGetSourcei64vSOFT),
390 DECL(alGetStringiSOFT),
392 DECL(alBufferStorageSOFT),
393 DECL(alMapBufferSOFT),
394 DECL(alUnmapBufferSOFT),
395 DECL(alFlushMappedBufferSOFT),
397 DECL(alEventControlSOFT),
398 DECL(alEventCallbackSOFT),
399 DECL(alGetPointerSOFT),
400 DECL(alGetPointervSOFT),
402 DECL(alBufferCallbackSOFT),
403 DECL(alGetBufferPtrSOFT),
404 DECL(alGetBuffer3PtrSOFT),
405 DECL(alGetBufferPtrvSOFT),
407 DECL(alAuxiliaryEffectSlotPlaySOFT),
408 DECL(alAuxiliaryEffectSlotPlayvSOFT),
409 DECL(alAuxiliaryEffectSlotStopSOFT),
410 DECL(alAuxiliaryEffectSlotStopvSOFT),
412 #undef DECL
414 #define DECL(x) { #x, (x) }
415 constexpr struct {
416 const ALCchar *enumName;
417 ALCenum value;
418 } alcEnumerations[] = {
419 DECL(ALC_INVALID),
420 DECL(ALC_FALSE),
421 DECL(ALC_TRUE),
423 DECL(ALC_MAJOR_VERSION),
424 DECL(ALC_MINOR_VERSION),
425 DECL(ALC_ATTRIBUTES_SIZE),
426 DECL(ALC_ALL_ATTRIBUTES),
427 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
428 DECL(ALC_DEVICE_SPECIFIER),
429 DECL(ALC_ALL_DEVICES_SPECIFIER),
430 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
431 DECL(ALC_EXTENSIONS),
432 DECL(ALC_FREQUENCY),
433 DECL(ALC_REFRESH),
434 DECL(ALC_SYNC),
435 DECL(ALC_MONO_SOURCES),
436 DECL(ALC_STEREO_SOURCES),
437 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
438 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
439 DECL(ALC_CAPTURE_SAMPLES),
440 DECL(ALC_CONNECTED),
442 DECL(ALC_EFX_MAJOR_VERSION),
443 DECL(ALC_EFX_MINOR_VERSION),
444 DECL(ALC_MAX_AUXILIARY_SENDS),
446 DECL(ALC_FORMAT_CHANNELS_SOFT),
447 DECL(ALC_FORMAT_TYPE_SOFT),
449 DECL(ALC_MONO_SOFT),
450 DECL(ALC_STEREO_SOFT),
451 DECL(ALC_QUAD_SOFT),
452 DECL(ALC_5POINT1_SOFT),
453 DECL(ALC_6POINT1_SOFT),
454 DECL(ALC_7POINT1_SOFT),
455 DECL(ALC_BFORMAT3D_SOFT),
457 DECL(ALC_BYTE_SOFT),
458 DECL(ALC_UNSIGNED_BYTE_SOFT),
459 DECL(ALC_SHORT_SOFT),
460 DECL(ALC_UNSIGNED_SHORT_SOFT),
461 DECL(ALC_INT_SOFT),
462 DECL(ALC_UNSIGNED_INT_SOFT),
463 DECL(ALC_FLOAT_SOFT),
465 DECL(ALC_HRTF_SOFT),
466 DECL(ALC_DONT_CARE_SOFT),
467 DECL(ALC_HRTF_STATUS_SOFT),
468 DECL(ALC_HRTF_DISABLED_SOFT),
469 DECL(ALC_HRTF_ENABLED_SOFT),
470 DECL(ALC_HRTF_DENIED_SOFT),
471 DECL(ALC_HRTF_REQUIRED_SOFT),
472 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
473 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
474 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
475 DECL(ALC_HRTF_SPECIFIER_SOFT),
476 DECL(ALC_HRTF_ID_SOFT),
478 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
479 DECL(ALC_AMBISONIC_SCALING_SOFT),
480 DECL(ALC_AMBISONIC_ORDER_SOFT),
481 DECL(ALC_ACN_SOFT),
482 DECL(ALC_FUMA_SOFT),
483 DECL(ALC_N3D_SOFT),
484 DECL(ALC_SN3D_SOFT),
486 DECL(ALC_OUTPUT_LIMITER_SOFT),
488 DECL(ALC_NO_ERROR),
489 DECL(ALC_INVALID_DEVICE),
490 DECL(ALC_INVALID_CONTEXT),
491 DECL(ALC_INVALID_ENUM),
492 DECL(ALC_INVALID_VALUE),
493 DECL(ALC_OUT_OF_MEMORY),
496 DECL(AL_INVALID),
497 DECL(AL_NONE),
498 DECL(AL_FALSE),
499 DECL(AL_TRUE),
501 DECL(AL_SOURCE_RELATIVE),
502 DECL(AL_CONE_INNER_ANGLE),
503 DECL(AL_CONE_OUTER_ANGLE),
504 DECL(AL_PITCH),
505 DECL(AL_POSITION),
506 DECL(AL_DIRECTION),
507 DECL(AL_VELOCITY),
508 DECL(AL_LOOPING),
509 DECL(AL_BUFFER),
510 DECL(AL_GAIN),
511 DECL(AL_MIN_GAIN),
512 DECL(AL_MAX_GAIN),
513 DECL(AL_ORIENTATION),
514 DECL(AL_REFERENCE_DISTANCE),
515 DECL(AL_ROLLOFF_FACTOR),
516 DECL(AL_CONE_OUTER_GAIN),
517 DECL(AL_MAX_DISTANCE),
518 DECL(AL_SEC_OFFSET),
519 DECL(AL_SAMPLE_OFFSET),
520 DECL(AL_BYTE_OFFSET),
521 DECL(AL_SOURCE_TYPE),
522 DECL(AL_STATIC),
523 DECL(AL_STREAMING),
524 DECL(AL_UNDETERMINED),
525 DECL(AL_METERS_PER_UNIT),
526 DECL(AL_LOOP_POINTS_SOFT),
527 DECL(AL_DIRECT_CHANNELS_SOFT),
529 DECL(AL_DIRECT_FILTER),
530 DECL(AL_AUXILIARY_SEND_FILTER),
531 DECL(AL_AIR_ABSORPTION_FACTOR),
532 DECL(AL_ROOM_ROLLOFF_FACTOR),
533 DECL(AL_CONE_OUTER_GAINHF),
534 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
535 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
536 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
538 DECL(AL_SOURCE_STATE),
539 DECL(AL_INITIAL),
540 DECL(AL_PLAYING),
541 DECL(AL_PAUSED),
542 DECL(AL_STOPPED),
544 DECL(AL_BUFFERS_QUEUED),
545 DECL(AL_BUFFERS_PROCESSED),
547 DECL(AL_FORMAT_MONO8),
548 DECL(AL_FORMAT_MONO16),
549 DECL(AL_FORMAT_MONO_FLOAT32),
550 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
551 DECL(AL_FORMAT_STEREO8),
552 DECL(AL_FORMAT_STEREO16),
553 DECL(AL_FORMAT_STEREO_FLOAT32),
554 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
555 DECL(AL_FORMAT_MONO_IMA4),
556 DECL(AL_FORMAT_STEREO_IMA4),
557 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
558 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
559 DECL(AL_FORMAT_QUAD8_LOKI),
560 DECL(AL_FORMAT_QUAD16_LOKI),
561 DECL(AL_FORMAT_QUAD8),
562 DECL(AL_FORMAT_QUAD16),
563 DECL(AL_FORMAT_QUAD32),
564 DECL(AL_FORMAT_51CHN8),
565 DECL(AL_FORMAT_51CHN16),
566 DECL(AL_FORMAT_51CHN32),
567 DECL(AL_FORMAT_61CHN8),
568 DECL(AL_FORMAT_61CHN16),
569 DECL(AL_FORMAT_61CHN32),
570 DECL(AL_FORMAT_71CHN8),
571 DECL(AL_FORMAT_71CHN16),
572 DECL(AL_FORMAT_71CHN32),
573 DECL(AL_FORMAT_REAR8),
574 DECL(AL_FORMAT_REAR16),
575 DECL(AL_FORMAT_REAR32),
576 DECL(AL_FORMAT_MONO_MULAW),
577 DECL(AL_FORMAT_MONO_MULAW_EXT),
578 DECL(AL_FORMAT_STEREO_MULAW),
579 DECL(AL_FORMAT_STEREO_MULAW_EXT),
580 DECL(AL_FORMAT_QUAD_MULAW),
581 DECL(AL_FORMAT_51CHN_MULAW),
582 DECL(AL_FORMAT_61CHN_MULAW),
583 DECL(AL_FORMAT_71CHN_MULAW),
584 DECL(AL_FORMAT_REAR_MULAW),
585 DECL(AL_FORMAT_MONO_ALAW_EXT),
586 DECL(AL_FORMAT_STEREO_ALAW_EXT),
588 DECL(AL_FORMAT_BFORMAT2D_8),
589 DECL(AL_FORMAT_BFORMAT2D_16),
590 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
591 DECL(AL_FORMAT_BFORMAT2D_MULAW),
592 DECL(AL_FORMAT_BFORMAT3D_8),
593 DECL(AL_FORMAT_BFORMAT3D_16),
594 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
595 DECL(AL_FORMAT_BFORMAT3D_MULAW),
597 DECL(AL_FREQUENCY),
598 DECL(AL_BITS),
599 DECL(AL_CHANNELS),
600 DECL(AL_SIZE),
601 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
602 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
604 DECL(AL_SOURCE_RADIUS),
606 DECL(AL_STEREO_ANGLES),
608 DECL(AL_UNUSED),
609 DECL(AL_PENDING),
610 DECL(AL_PROCESSED),
612 DECL(AL_NO_ERROR),
613 DECL(AL_INVALID_NAME),
614 DECL(AL_INVALID_ENUM),
615 DECL(AL_INVALID_VALUE),
616 DECL(AL_INVALID_OPERATION),
617 DECL(AL_OUT_OF_MEMORY),
619 DECL(AL_VENDOR),
620 DECL(AL_VERSION),
621 DECL(AL_RENDERER),
622 DECL(AL_EXTENSIONS),
624 DECL(AL_DOPPLER_FACTOR),
625 DECL(AL_DOPPLER_VELOCITY),
626 DECL(AL_DISTANCE_MODEL),
627 DECL(AL_SPEED_OF_SOUND),
628 DECL(AL_SOURCE_DISTANCE_MODEL),
629 DECL(AL_DEFERRED_UPDATES_SOFT),
630 DECL(AL_GAIN_LIMIT_SOFT),
632 DECL(AL_INVERSE_DISTANCE),
633 DECL(AL_INVERSE_DISTANCE_CLAMPED),
634 DECL(AL_LINEAR_DISTANCE),
635 DECL(AL_LINEAR_DISTANCE_CLAMPED),
636 DECL(AL_EXPONENT_DISTANCE),
637 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
639 DECL(AL_FILTER_TYPE),
640 DECL(AL_FILTER_NULL),
641 DECL(AL_FILTER_LOWPASS),
642 DECL(AL_FILTER_HIGHPASS),
643 DECL(AL_FILTER_BANDPASS),
645 DECL(AL_LOWPASS_GAIN),
646 DECL(AL_LOWPASS_GAINHF),
648 DECL(AL_HIGHPASS_GAIN),
649 DECL(AL_HIGHPASS_GAINLF),
651 DECL(AL_BANDPASS_GAIN),
652 DECL(AL_BANDPASS_GAINHF),
653 DECL(AL_BANDPASS_GAINLF),
655 DECL(AL_EFFECT_TYPE),
656 DECL(AL_EFFECT_NULL),
657 DECL(AL_EFFECT_REVERB),
658 DECL(AL_EFFECT_EAXREVERB),
659 DECL(AL_EFFECT_CHORUS),
660 DECL(AL_EFFECT_DISTORTION),
661 DECL(AL_EFFECT_ECHO),
662 DECL(AL_EFFECT_FLANGER),
663 DECL(AL_EFFECT_PITCH_SHIFTER),
664 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
665 DECL(AL_EFFECT_VOCAL_MORPHER),
666 DECL(AL_EFFECT_RING_MODULATOR),
667 DECL(AL_EFFECT_AUTOWAH),
668 DECL(AL_EFFECT_COMPRESSOR),
669 DECL(AL_EFFECT_EQUALIZER),
670 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
671 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
673 DECL(AL_EFFECTSLOT_EFFECT),
674 DECL(AL_EFFECTSLOT_GAIN),
675 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
676 DECL(AL_EFFECTSLOT_NULL),
678 DECL(AL_EAXREVERB_DENSITY),
679 DECL(AL_EAXREVERB_DIFFUSION),
680 DECL(AL_EAXREVERB_GAIN),
681 DECL(AL_EAXREVERB_GAINHF),
682 DECL(AL_EAXREVERB_GAINLF),
683 DECL(AL_EAXREVERB_DECAY_TIME),
684 DECL(AL_EAXREVERB_DECAY_HFRATIO),
685 DECL(AL_EAXREVERB_DECAY_LFRATIO),
686 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
687 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
688 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
689 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
690 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
691 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
692 DECL(AL_EAXREVERB_ECHO_TIME),
693 DECL(AL_EAXREVERB_ECHO_DEPTH),
694 DECL(AL_EAXREVERB_MODULATION_TIME),
695 DECL(AL_EAXREVERB_MODULATION_DEPTH),
696 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
697 DECL(AL_EAXREVERB_HFREFERENCE),
698 DECL(AL_EAXREVERB_LFREFERENCE),
699 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
700 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
702 DECL(AL_REVERB_DENSITY),
703 DECL(AL_REVERB_DIFFUSION),
704 DECL(AL_REVERB_GAIN),
705 DECL(AL_REVERB_GAINHF),
706 DECL(AL_REVERB_DECAY_TIME),
707 DECL(AL_REVERB_DECAY_HFRATIO),
708 DECL(AL_REVERB_REFLECTIONS_GAIN),
709 DECL(AL_REVERB_REFLECTIONS_DELAY),
710 DECL(AL_REVERB_LATE_REVERB_GAIN),
711 DECL(AL_REVERB_LATE_REVERB_DELAY),
712 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
713 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
714 DECL(AL_REVERB_DECAY_HFLIMIT),
716 DECL(AL_CHORUS_WAVEFORM),
717 DECL(AL_CHORUS_PHASE),
718 DECL(AL_CHORUS_RATE),
719 DECL(AL_CHORUS_DEPTH),
720 DECL(AL_CHORUS_FEEDBACK),
721 DECL(AL_CHORUS_DELAY),
723 DECL(AL_DISTORTION_EDGE),
724 DECL(AL_DISTORTION_GAIN),
725 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
726 DECL(AL_DISTORTION_EQCENTER),
727 DECL(AL_DISTORTION_EQBANDWIDTH),
729 DECL(AL_ECHO_DELAY),
730 DECL(AL_ECHO_LRDELAY),
731 DECL(AL_ECHO_DAMPING),
732 DECL(AL_ECHO_FEEDBACK),
733 DECL(AL_ECHO_SPREAD),
735 DECL(AL_FLANGER_WAVEFORM),
736 DECL(AL_FLANGER_PHASE),
737 DECL(AL_FLANGER_RATE),
738 DECL(AL_FLANGER_DEPTH),
739 DECL(AL_FLANGER_FEEDBACK),
740 DECL(AL_FLANGER_DELAY),
742 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY),
743 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION),
744 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION),
746 DECL(AL_RING_MODULATOR_FREQUENCY),
747 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
748 DECL(AL_RING_MODULATOR_WAVEFORM),
750 DECL(AL_PITCH_SHIFTER_COARSE_TUNE),
751 DECL(AL_PITCH_SHIFTER_FINE_TUNE),
753 DECL(AL_COMPRESSOR_ONOFF),
755 DECL(AL_EQUALIZER_LOW_GAIN),
756 DECL(AL_EQUALIZER_LOW_CUTOFF),
757 DECL(AL_EQUALIZER_MID1_GAIN),
758 DECL(AL_EQUALIZER_MID1_CENTER),
759 DECL(AL_EQUALIZER_MID1_WIDTH),
760 DECL(AL_EQUALIZER_MID2_GAIN),
761 DECL(AL_EQUALIZER_MID2_CENTER),
762 DECL(AL_EQUALIZER_MID2_WIDTH),
763 DECL(AL_EQUALIZER_HIGH_GAIN),
764 DECL(AL_EQUALIZER_HIGH_CUTOFF),
766 DECL(AL_DEDICATED_GAIN),
768 DECL(AL_AUTOWAH_ATTACK_TIME),
769 DECL(AL_AUTOWAH_RELEASE_TIME),
770 DECL(AL_AUTOWAH_RESONANCE),
771 DECL(AL_AUTOWAH_PEAK_GAIN),
773 DECL(AL_VOCAL_MORPHER_PHONEMEA),
774 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING),
775 DECL(AL_VOCAL_MORPHER_PHONEMEB),
776 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING),
777 DECL(AL_VOCAL_MORPHER_WAVEFORM),
778 DECL(AL_VOCAL_MORPHER_RATE),
780 DECL(AL_EFFECTSLOT_TARGET_SOFT),
782 DECL(AL_NUM_RESAMPLERS_SOFT),
783 DECL(AL_DEFAULT_RESAMPLER_SOFT),
784 DECL(AL_SOURCE_RESAMPLER_SOFT),
785 DECL(AL_RESAMPLER_NAME_SOFT),
787 DECL(AL_SOURCE_SPATIALIZE_SOFT),
788 DECL(AL_AUTO_SOFT),
790 DECL(AL_MAP_READ_BIT_SOFT),
791 DECL(AL_MAP_WRITE_BIT_SOFT),
792 DECL(AL_MAP_PERSISTENT_BIT_SOFT),
793 DECL(AL_PRESERVE_DATA_BIT_SOFT),
795 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT),
796 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT),
797 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT),
798 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT),
799 DECL(AL_EVENT_TYPE_DISCONNECTED_SOFT),
801 DECL(AL_DROP_UNMATCHED_SOFT),
802 DECL(AL_REMIX_UNMATCHED_SOFT),
804 DECL(AL_AMBISONIC_LAYOUT_SOFT),
805 DECL(AL_AMBISONIC_SCALING_SOFT),
806 DECL(AL_FUMA_SOFT),
807 DECL(AL_ACN_SOFT),
808 DECL(AL_SN3D_SOFT),
809 DECL(AL_N3D_SOFT),
811 DECL(AL_BUFFER_CALLBACK_FUNCTION_SOFT),
812 DECL(AL_BUFFER_CALLBACK_USER_PARAM_SOFT),
814 DECL(AL_UNPACK_AMBISONIC_ORDER_SOFT),
816 DECL(AL_EFFECT_CONVOLUTION_REVERB_SOFT),
817 DECL(AL_EFFECTSLOT_STATE_SOFT),
819 #undef DECL
821 constexpr ALCchar alcNoError[] = "No Error";
822 constexpr ALCchar alcErrInvalidDevice[] = "Invalid Device";
823 constexpr ALCchar alcErrInvalidContext[] = "Invalid Context";
824 constexpr ALCchar alcErrInvalidEnum[] = "Invalid Enum";
825 constexpr ALCchar alcErrInvalidValue[] = "Invalid Value";
826 constexpr ALCchar alcErrOutOfMemory[] = "Out of Memory";
829 /************************************************
830 * Global variables
831 ************************************************/
833 /* Enumerated device names */
834 constexpr ALCchar alcDefaultName[] = "OpenAL Soft\0";
836 std::string alcAllDevicesList;
837 std::string alcCaptureDeviceList;
839 /* Default is always the first in the list */
840 al::string alcDefaultAllDevicesSpecifier;
841 al::string alcCaptureDefaultDeviceSpecifier;
843 /* Default context extensions */
844 constexpr ALchar alExtList[] =
845 "AL_EXT_ALAW "
846 "AL_EXT_BFORMAT "
847 "AL_EXT_DOUBLE "
848 "AL_EXT_EXPONENT_DISTANCE "
849 "AL_EXT_FLOAT32 "
850 "AL_EXT_IMA4 "
851 "AL_EXT_LINEAR_DISTANCE "
852 "AL_EXT_MCFORMATS "
853 "AL_EXT_MULAW "
854 "AL_EXT_MULAW_BFORMAT "
855 "AL_EXT_MULAW_MCFORMATS "
856 "AL_EXT_OFFSET "
857 "AL_EXT_source_distance_model "
858 "AL_EXT_SOURCE_RADIUS "
859 "AL_EXT_STEREO_ANGLES "
860 "AL_LOKI_quadriphonic "
861 "AL_SOFT_bformat_ex "
862 "AL_SOFTX_bformat_hoa "
863 "AL_SOFT_block_alignment "
864 "AL_SOFTX_callback_buffer "
865 "AL_SOFTX_convolution_reverb "
866 "AL_SOFT_deferred_updates "
867 "AL_SOFT_direct_channels "
868 "AL_SOFT_direct_channels_remix "
869 "AL_SOFT_effect_target "
870 "AL_SOFT_events "
871 "AL_SOFTX_filter_gain_ex "
872 "AL_SOFT_gain_clamp_ex "
873 "AL_SOFT_loop_points "
874 "AL_SOFTX_map_buffer "
875 "AL_SOFT_MSADPCM "
876 "AL_SOFT_source_latency "
877 "AL_SOFT_source_length "
878 "AL_SOFT_source_resampler "
879 "AL_SOFT_source_spatialize";
881 std::atomic<ALCenum> LastNullDeviceError{ALC_NO_ERROR};
883 /* Thread-local current context. The handling may look a little obtuse, but
884 * it's designed this way to avoid a bug with 32-bit GCC/MinGW, which causes
885 * thread-local object destructors to get a junk 'this' pointer. This method
886 * has the benefit of making LocalContext access more efficient since it's a
887 * a plain pointer, with the ThreadContext object used to check it at thread
888 * exit (and given no data fields, 'this' being junk is inconsequential since
889 * it's never accessed).
891 thread_local ALCcontext *LocalContext{nullptr};
892 class ThreadCtx {
893 public:
894 ~ThreadCtx()
896 if(ALCcontext *ctx{LocalContext})
898 const bool result{ctx->releaseIfNoDelete()};
899 ERR("Context %p current for thread being destroyed%s!\n",
900 decltype(std::declval<void*>()){ctx}, result ? "" : ", leak detected");
904 void set(ALCcontext *ctx) const noexcept { LocalContext = ctx; }
906 thread_local ThreadCtx ThreadContext;
908 /* Process-wide current context */
909 std::atomic<ALCcontext*> GlobalContext{nullptr};
911 /* Flag to trap ALC device errors */
912 bool TrapALCError{false};
914 /* One-time configuration init control */
915 std::once_flag alc_config_once{};
917 /* Default effect that applies to sources that don't have an effect on send 0 */
918 ALeffect DefaultEffect;
920 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
921 * updates.
923 bool SuspendDefers{true};
925 /* Initial seed for dithering. */
926 constexpr ALuint DitherRNGSeed{22222u};
929 /************************************************
930 * ALC information
931 ************************************************/
932 constexpr ALCchar alcNoDeviceExtList[] =
933 "ALC_ENUMERATE_ALL_EXT "
934 "ALC_ENUMERATION_EXT "
935 "ALC_EXT_CAPTURE "
936 "ALC_EXT_thread_local_context "
937 "ALC_SOFT_loopback "
938 "ALC_SOFT_loopback_bformat";
939 constexpr ALCchar alcExtensionList[] =
940 "ALC_ENUMERATE_ALL_EXT "
941 "ALC_ENUMERATION_EXT "
942 "ALC_EXT_CAPTURE "
943 "ALC_EXT_DEDICATED "
944 "ALC_EXT_disconnect "
945 "ALC_EXT_EFX "
946 "ALC_EXT_thread_local_context "
947 "ALC_SOFT_device_clock "
948 "ALC_SOFT_HRTF "
949 "ALC_SOFT_loopback "
950 "ALC_SOFT_loopback_bformat "
951 "ALC_SOFT_output_limiter "
952 "ALC_SOFT_pause_device";
953 constexpr int alcMajorVersion{1};
954 constexpr int alcMinorVersion{1};
956 constexpr int alcEFXMajorVersion{1};
957 constexpr int alcEFXMinorVersion{0};
960 /* To avoid extraneous allocations, a 0-sized FlexArray<ALCcontext*> is defined
961 * globally as a sharable object.
963 al::FlexArray<ALCcontext*> EmptyContextArray{0u};
966 using DeviceRef = al::intrusive_ptr<ALCdevice>;
969 /************************************************
970 * Device lists
971 ************************************************/
972 al::vector<ALCdevice*> DeviceList;
973 al::vector<ALCcontext*> ContextList;
975 std::recursive_mutex ListLock;
978 void alc_initconfig(void)
980 if(auto loglevel = al::getenv("ALSOFT_LOGLEVEL"))
982 long lvl = strtol(loglevel->c_str(), nullptr, 0);
983 if(lvl >= static_cast<long>(LogLevel::Trace))
984 gLogLevel = LogLevel::Trace;
985 else if(lvl <= static_cast<long>(LogLevel::Disable))
986 gLogLevel = LogLevel::Disable;
987 else
988 gLogLevel = static_cast<LogLevel>(lvl);
991 #ifdef _WIN32
992 if(const auto logfile = al::getenv(L"ALSOFT_LOGFILE"))
994 FILE *logf{_wfopen(logfile->c_str(), L"wt")};
995 if(logf) gLogFile = logf;
996 else
998 auto u8name = wstr_to_utf8(logfile->c_str());
999 ERR("Failed to open log file '%s'\n", u8name.c_str());
1002 #else
1003 if(const auto logfile = al::getenv("ALSOFT_LOGFILE"))
1005 FILE *logf{fopen(logfile->c_str(), "wt")};
1006 if(logf) gLogFile = logf;
1007 else ERR("Failed to open log file '%s'\n", logfile->c_str());
1009 #endif
1011 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION, ALSOFT_GIT_COMMIT_HASH,
1012 ALSOFT_GIT_BRANCH);
1014 al::string names;
1015 if(al::size(BackendList) < 1)
1016 names = "(none)";
1017 else
1019 const al::span<const BackendInfo> infos{BackendList};
1020 names = infos[0].name;
1021 for(const auto &backend : infos.subspan<1>())
1023 names += ", ";
1024 names += backend.name;
1027 TRACE("Supported backends: %s\n", names.c_str());
1029 ReadALConfig();
1031 if(auto suspendmode = al::getenv("__ALSOFT_SUSPEND_CONTEXT"))
1033 if(al::strcasecmp(suspendmode->c_str(), "ignore") == 0)
1035 SuspendDefers = false;
1036 TRACE("Selected context suspend behavior, \"ignore\"\n");
1038 else
1039 ERR("Unhandled context suspend behavior setting: \"%s\"\n", suspendmode->c_str());
1042 int capfilter{0};
1043 #if defined(HAVE_SSE4_1)
1044 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
1045 #elif defined(HAVE_SSE3)
1046 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
1047 #elif defined(HAVE_SSE2)
1048 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
1049 #elif defined(HAVE_SSE)
1050 capfilter |= CPU_CAP_SSE;
1051 #endif
1052 #ifdef HAVE_NEON
1053 capfilter |= CPU_CAP_NEON;
1054 #endif
1055 if(auto cpuopt = ConfigValueStr(nullptr, nullptr, "disable-cpu-exts"))
1057 const char *str{cpuopt->c_str()};
1058 if(al::strcasecmp(str, "all") == 0)
1059 capfilter = 0;
1060 else
1062 const char *next = str;
1063 do {
1064 str = next;
1065 while(isspace(str[0]))
1066 str++;
1067 next = strchr(str, ',');
1069 if(!str[0] || str[0] == ',')
1070 continue;
1072 size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1073 while(len > 0 && isspace(str[len-1]))
1074 len--;
1075 if(len == 3 && al::strncasecmp(str, "sse", len) == 0)
1076 capfilter &= ~CPU_CAP_SSE;
1077 else if(len == 4 && al::strncasecmp(str, "sse2", len) == 0)
1078 capfilter &= ~CPU_CAP_SSE2;
1079 else if(len == 4 && al::strncasecmp(str, "sse3", len) == 0)
1080 capfilter &= ~CPU_CAP_SSE3;
1081 else if(len == 6 && al::strncasecmp(str, "sse4.1", len) == 0)
1082 capfilter &= ~CPU_CAP_SSE4_1;
1083 else if(len == 4 && al::strncasecmp(str, "neon", len) == 0)
1084 capfilter &= ~CPU_CAP_NEON;
1085 else
1086 WARN("Invalid CPU extension \"%s\"\n", str);
1087 } while(next++);
1090 FillCPUCaps(capfilter);
1092 if(auto priopt = ConfigValueInt(nullptr, nullptr, "rt-prio"))
1093 RTPrioLevel = *priopt;
1095 aluInit();
1096 aluInitMixer();
1098 auto traperr = al::getenv("ALSOFT_TRAP_ERROR");
1099 if(traperr && (al::strcasecmp(traperr->c_str(), "true") == 0
1100 || std::strtol(traperr->c_str(), nullptr, 0) == 1))
1102 TrapALError = true;
1103 TrapALCError = true;
1105 else
1107 traperr = al::getenv("ALSOFT_TRAP_AL_ERROR");
1108 if(traperr)
1109 TrapALError = al::strcasecmp(traperr->c_str(), "true") == 0
1110 || strtol(traperr->c_str(), nullptr, 0) == 1;
1111 else
1112 TrapALError = !!GetConfigValueBool(nullptr, nullptr, "trap-al-error", false);
1114 traperr = al::getenv("ALSOFT_TRAP_ALC_ERROR");
1115 if(traperr)
1116 TrapALCError = al::strcasecmp(traperr->c_str(), "true") == 0
1117 || strtol(traperr->c_str(), nullptr, 0) == 1;
1118 else
1119 TrapALCError = !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", false);
1122 if(auto boostopt = ConfigValueFloat(nullptr, "reverb", "boost"))
1124 const float valf{std::isfinite(*boostopt) ? clampf(*boostopt, -24.0f, 24.0f) : 0.0f};
1125 ReverbBoost *= std::pow(10.0f, valf / 20.0f);
1128 auto BackendListEnd = std::end(BackendList);
1129 auto devopt = al::getenv("ALSOFT_DRIVERS");
1130 if(devopt || (devopt=ConfigValueStr(nullptr, nullptr, "drivers")))
1132 auto backendlist_cur = std::begin(BackendList);
1134 bool endlist{true};
1135 const char *next{devopt->c_str()};
1136 do {
1137 const char *devs{next};
1138 while(isspace(devs[0]))
1139 devs++;
1140 next = strchr(devs, ',');
1142 const bool delitem{devs[0] == '-'};
1143 if(devs[0] == '-') devs++;
1145 if(!devs[0] || devs[0] == ',')
1147 endlist = false;
1148 continue;
1150 endlist = true;
1152 size_t len{next ? (static_cast<size_t>(next-devs)) : strlen(devs)};
1153 while(len > 0 && isspace(devs[len-1])) --len;
1154 #ifdef HAVE_WASAPI
1155 /* HACK: For backwards compatibility, convert backend references of
1156 * mmdevapi to wasapi. This should eventually be removed.
1158 if(len == 8 && strncmp(devs, "mmdevapi", len) == 0)
1160 devs = "wasapi";
1161 len = 6;
1163 #endif
1165 auto find_backend = [devs,len](const BackendInfo &backend) -> bool
1166 { return len == strlen(backend.name) && strncmp(backend.name, devs, len) == 0; };
1167 auto this_backend = std::find_if(std::begin(BackendList), BackendListEnd,
1168 find_backend);
1170 if(this_backend == BackendListEnd)
1171 continue;
1173 if(delitem)
1174 BackendListEnd = std::move(this_backend+1, BackendListEnd, this_backend);
1175 else
1176 backendlist_cur = std::rotate(backendlist_cur, this_backend, this_backend+1);
1177 } while(next++);
1179 if(endlist)
1180 BackendListEnd = backendlist_cur;
1183 auto init_backend = [](BackendInfo &backend) -> void
1185 if(PlaybackFactory && CaptureFactory)
1186 return;
1188 BackendFactory &factory = backend.getFactory();
1189 if(!factory.init())
1191 WARN("Failed to initialize backend \"%s\"\n", backend.name);
1192 return;
1195 TRACE("Initialized backend \"%s\"\n", backend.name);
1196 if(!PlaybackFactory && factory.querySupport(BackendType::Playback))
1198 PlaybackFactory = &factory;
1199 TRACE("Added \"%s\" for playback\n", backend.name);
1201 if(!CaptureFactory && factory.querySupport(BackendType::Capture))
1203 CaptureFactory = &factory;
1204 TRACE("Added \"%s\" for capture\n", backend.name);
1207 std::for_each(std::begin(BackendList), BackendListEnd, init_backend);
1209 LoopbackBackendFactory::getFactory().init();
1211 if(!PlaybackFactory)
1212 WARN("No playback backend available!\n");
1213 if(!CaptureFactory)
1214 WARN("No capture backend available!\n");
1216 if(auto exclopt = ConfigValueStr(nullptr, nullptr, "excludefx"))
1218 const char *next{exclopt->c_str()};
1219 do {
1220 const char *str{next};
1221 next = strchr(str, ',');
1223 if(!str[0] || next == str)
1224 continue;
1226 size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1227 for(const EffectList &effectitem : gEffectList)
1229 if(len == strlen(effectitem.name) &&
1230 strncmp(effectitem.name, str, len) == 0)
1231 DisabledEffects[effectitem.type] = true;
1233 } while(next++);
1236 InitEffect(&DefaultEffect);
1237 auto defrevopt = al::getenv("ALSOFT_DEFAULT_REVERB");
1238 if(defrevopt || (defrevopt=ConfigValueStr(nullptr, nullptr, "default-reverb")))
1239 LoadReverbPreset(defrevopt->c_str(), &DefaultEffect);
1241 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1244 /************************************************
1245 * Device enumeration
1246 ************************************************/
1247 void ProbeAllDevicesList()
1249 DO_INITCONFIG();
1251 std::lock_guard<std::recursive_mutex> _{ListLock};
1252 if(!PlaybackFactory)
1253 decltype(alcAllDevicesList){}.swap(alcAllDevicesList);
1254 else
1256 std::string names{PlaybackFactory->probe(BackendType::Playback)};
1257 if(names.empty()) names += '\0';
1258 names.swap(alcAllDevicesList);
1261 void ProbeCaptureDeviceList()
1263 DO_INITCONFIG();
1265 std::lock_guard<std::recursive_mutex> _{ListLock};
1266 if(!CaptureFactory)
1267 decltype(alcCaptureDeviceList){}.swap(alcCaptureDeviceList);
1268 else
1270 std::string names{CaptureFactory->probe(BackendType::Capture)};
1271 if(names.empty()) names += '\0';
1272 names.swap(alcCaptureDeviceList);
1276 } // namespace
1278 /* Mixing thread piority level */
1279 int RTPrioLevel{1};
1281 FILE *gLogFile{stderr};
1282 #ifdef _DEBUG
1283 LogLevel gLogLevel{LogLevel::Warning};
1284 #else
1285 LogLevel gLogLevel{LogLevel::Error};
1286 #endif
1288 /************************************************
1289 * Library initialization
1290 ************************************************/
1291 #if defined(_WIN32) && !defined(AL_LIBTYPE_STATIC)
1292 BOOL APIENTRY DllMain(HINSTANCE module, DWORD reason, LPVOID /*reserved*/)
1294 switch(reason)
1296 case DLL_PROCESS_ATTACH:
1297 /* Pin the DLL so we won't get unloaded until the process terminates */
1298 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
1299 reinterpret_cast<WCHAR*>(module), &module);
1300 break;
1302 return TRUE;
1304 #endif
1306 /************************************************
1307 * Device format information
1308 ************************************************/
1309 const ALCchar *DevFmtTypeString(DevFmtType type) noexcept
1311 switch(type)
1313 case DevFmtByte: return "Int8";
1314 case DevFmtUByte: return "UInt8";
1315 case DevFmtShort: return "Int16";
1316 case DevFmtUShort: return "UInt16";
1317 case DevFmtInt: return "Int32";
1318 case DevFmtUInt: return "UInt32";
1319 case DevFmtFloat: return "Float32";
1321 return "(unknown type)";
1323 const ALCchar *DevFmtChannelsString(DevFmtChannels chans) noexcept
1325 switch(chans)
1327 case DevFmtMono: return "Mono";
1328 case DevFmtStereo: return "Stereo";
1329 case DevFmtQuad: return "Quadraphonic";
1330 case DevFmtX51: return "5.1 Surround";
1331 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1332 case DevFmtX61: return "6.1 Surround";
1333 case DevFmtX71: return "7.1 Surround";
1334 case DevFmtAmbi3D: return "Ambisonic 3D";
1336 return "(unknown channels)";
1339 ALuint BytesFromDevFmt(DevFmtType type) noexcept
1341 switch(type)
1343 case DevFmtByte: return sizeof(int8_t);
1344 case DevFmtUByte: return sizeof(uint8_t);
1345 case DevFmtShort: return sizeof(int16_t);
1346 case DevFmtUShort: return sizeof(uint16_t);
1347 case DevFmtInt: return sizeof(int32_t);
1348 case DevFmtUInt: return sizeof(uint32_t);
1349 case DevFmtFloat: return sizeof(float);
1351 return 0;
1353 ALuint ChannelsFromDevFmt(DevFmtChannels chans, ALuint ambiorder) noexcept
1355 switch(chans)
1357 case DevFmtMono: return 1;
1358 case DevFmtStereo: return 2;
1359 case DevFmtQuad: return 4;
1360 case DevFmtX51: return 6;
1361 case DevFmtX51Rear: return 6;
1362 case DevFmtX61: return 7;
1363 case DevFmtX71: return 8;
1364 case DevFmtAmbi3D: return (ambiorder+1) * (ambiorder+1);
1366 return 0;
1369 namespace {
1371 struct DevFmtPair { DevFmtChannels chans; DevFmtType type; };
1372 al::optional<DevFmtPair> DecomposeDevFormat(ALenum format)
1374 static const struct {
1375 ALenum format;
1376 DevFmtChannels channels;
1377 DevFmtType type;
1378 } list[] = {
1379 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1380 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1381 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1383 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1384 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1385 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1387 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1388 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1389 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1391 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1392 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1393 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1395 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1396 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1397 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1399 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1400 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1401 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1404 for(const auto &item : list)
1406 if(item.format == format)
1407 return al::make_optional(DevFmtPair{item.channels, item.type});
1410 return al::nullopt;
1413 bool IsValidALCType(ALCenum type)
1415 switch(type)
1417 case ALC_BYTE_SOFT:
1418 case ALC_UNSIGNED_BYTE_SOFT:
1419 case ALC_SHORT_SOFT:
1420 case ALC_UNSIGNED_SHORT_SOFT:
1421 case ALC_INT_SOFT:
1422 case ALC_UNSIGNED_INT_SOFT:
1423 case ALC_FLOAT_SOFT:
1424 return true;
1426 return false;
1429 bool IsValidALCChannels(ALCenum channels)
1431 switch(channels)
1433 case ALC_MONO_SOFT:
1434 case ALC_STEREO_SOFT:
1435 case ALC_QUAD_SOFT:
1436 case ALC_5POINT1_SOFT:
1437 case ALC_6POINT1_SOFT:
1438 case ALC_7POINT1_SOFT:
1439 case ALC_BFORMAT3D_SOFT:
1440 return true;
1442 return false;
1445 bool IsValidAmbiLayout(ALCenum layout)
1447 switch(layout)
1449 case ALC_ACN_SOFT:
1450 case ALC_FUMA_SOFT:
1451 return true;
1453 return false;
1456 bool IsValidAmbiScaling(ALCenum scaling)
1458 switch(scaling)
1460 case ALC_N3D_SOFT:
1461 case ALC_SN3D_SOFT:
1462 case ALC_FUMA_SOFT:
1463 return true;
1465 return false;
1469 /* Downmixing channel arrays, to map the given format's missing channels to
1470 * existing ones. Based on Wine's DSound downmix values, which are based on
1471 * PulseAudio's.
1473 const std::array<InputRemixMap,7> MonoDownmix{{
1474 { FrontLeft, {{{FrontCenter, 0.5f}, {LFE, 0.0f}}} },
1475 { FrontRight, {{{FrontCenter, 0.5f}, {LFE, 0.0f}}} },
1476 { SideLeft, {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1477 { SideRight, {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1478 { BackLeft, {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1479 { BackRight, {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1480 { BackCenter, {{{FrontCenter, 1.0f/9.0f}, {LFE, 0.0f}}} },
1482 const std::array<InputRemixMap,6> StereoDownmix{{
1483 { FrontCenter, {{{FrontLeft, 0.5f}, {FrontRight, 0.5f}}} },
1484 { SideLeft, {{{FrontLeft, 1.0f/9.0f}, {FrontRight, 0.0f}}} },
1485 { SideRight, {{{FrontLeft, 0.0f}, {FrontRight, 1.0f/9.0f}}} },
1486 { BackLeft, {{{FrontLeft, 1.0f/9.0f}, {FrontRight, 0.0f}}} },
1487 { BackRight, {{{FrontLeft, 0.0f}, {FrontRight, 1.0f/9.0f}}} },
1488 { BackCenter, {{{FrontLeft, 0.5f/9.0f}, {FrontRight, 0.5f/9.0f}}} },
1490 const std::array<InputRemixMap,4> QuadDownmix{{
1491 { FrontCenter, {{{FrontLeft, 0.5f}, {FrontRight, 0.5f}}} },
1492 { SideLeft, {{{FrontLeft, 0.5f}, {BackLeft, 0.5f}}} },
1493 { SideRight, {{{FrontRight, 0.5f}, {BackRight, 0.5f}}} },
1494 { BackCenter, {{{BackLeft, 0.5f}, {BackRight, 0.5f}}} },
1496 const std::array<InputRemixMap,3> X51Downmix{{
1497 { BackLeft, {{{SideLeft, 1.0f}, {SideRight, 0.0f}}} },
1498 { BackRight, {{{SideLeft, 0.0f}, {SideRight, 1.0f}}} },
1499 { BackCenter, {{{SideLeft, 0.5f}, {SideRight, 0.5f}}} },
1501 const std::array<InputRemixMap,3> X51RearDownmix{{
1502 { SideLeft, {{{BackLeft, 1.0f}, {BackRight, 0.0f}}} },
1503 { SideRight, {{{BackLeft, 0.0f}, {BackRight, 1.0f}}} },
1504 { BackCenter, {{{BackLeft, 0.5f}, {BackRight, 0.5f}}} },
1506 const std::array<InputRemixMap,2> X61Downmix{{
1507 { BackLeft, {{{BackCenter, 0.5f}, {SideLeft, 0.5f}}} },
1508 { BackRight, {{{BackCenter, 0.5f}, {SideRight, 0.5f}}} },
1510 const std::array<InputRemixMap,1> X71Downmix{{
1511 { BackCenter, {{{BackLeft, 0.5f}, {BackRight, 0.5f}}} },
1514 } // namespace
1516 /************************************************
1517 * Miscellaneous ALC helpers
1518 ************************************************/
1520 void ALCcontext::processUpdates()
1522 std::lock_guard<std::mutex> _{mPropLock};
1523 if(mDeferUpdates.exchange(false, std::memory_order_acq_rel))
1525 /* Tell the mixer to stop applying updates, then wait for any active
1526 * updating to finish, before providing updates.
1528 mHoldUpdates.store(true, std::memory_order_release);
1529 while((mUpdateCount.load(std::memory_order_acquire)&1) != 0) {
1530 /* busy-wait */
1533 if(!mPropsClean.test_and_set(std::memory_order_acq_rel))
1534 UpdateContextProps(this);
1535 if(!mListener.PropsClean.test_and_set(std::memory_order_acq_rel))
1536 UpdateListenerProps(this);
1537 UpdateAllEffectSlotProps(this);
1538 UpdateAllSourceProps(this);
1540 /* Now with all updates declared, let the mixer continue applying them
1541 * so they all happen at once.
1543 mHoldUpdates.store(false, std::memory_order_release);
1548 void ALCcontext::allocVoiceChanges(size_t addcount)
1550 constexpr size_t clustersize{128};
1551 /* Convert element count to cluster count. */
1552 addcount = (addcount+(clustersize-1)) / clustersize;
1553 while(addcount)
1555 VoiceChangeCluster cluster{std::make_unique<VoiceChange[]>(clustersize)};
1556 for(size_t i{1};i < clustersize;++i)
1557 cluster[i-1].mNext.store(std::addressof(cluster[i]), std::memory_order_relaxed);
1558 cluster[clustersize-1].mNext.store(mVoiceChangeTail, std::memory_order_relaxed);
1559 mVoiceChangeClusters.emplace_back(std::move(cluster));
1560 mVoiceChangeTail = mVoiceChangeClusters.back().get();
1561 --addcount;
1565 void ALCcontext::allocVoices(size_t addcount)
1567 constexpr size_t clustersize{32};
1568 /* Convert element count to cluster count. */
1569 addcount = (addcount+(clustersize-1)) / clustersize;
1571 if(addcount >= std::numeric_limits<int>::max()/clustersize - mVoiceClusters.size())
1572 throw std::runtime_error{"Allocating too many voices"};
1573 const size_t totalcount{(mVoiceClusters.size()+addcount) * clustersize};
1574 TRACE("Increasing allocated voices to %zu\n", totalcount);
1576 auto newarray = VoiceArray::Create(totalcount);
1577 while(addcount)
1579 mVoiceClusters.emplace_back(std::make_unique<Voice[]>(clustersize));
1580 --addcount;
1583 auto voice_iter = newarray->begin();
1584 for(VoiceCluster &cluster : mVoiceClusters)
1586 for(size_t i{0};i < clustersize;++i)
1587 *(voice_iter++) = &cluster[i];
1590 if(auto *oldvoices = mVoices.exchange(newarray.release(), std::memory_order_acq_rel))
1592 mDevice->waitForMix();
1593 delete oldvoices;
1598 /** Stores the latest ALC device error. */
1599 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1601 WARN("Error generated on device %p, code 0x%04x\n", decltype(std::declval<void*>()){device},
1602 errorCode);
1603 if(TrapALCError)
1605 #ifdef _WIN32
1606 /* DebugBreak() will cause an exception if there is no debugger */
1607 if(IsDebuggerPresent())
1608 DebugBreak();
1609 #elif defined(SIGTRAP)
1610 raise(SIGTRAP);
1611 #endif
1614 if(device)
1615 device->LastError.store(errorCode);
1616 else
1617 LastNullDeviceError.store(errorCode);
1621 static std::unique_ptr<Compressor> CreateDeviceLimiter(const ALCdevice *device, const float threshold)
1623 constexpr bool AutoKnee{true};
1624 constexpr bool AutoAttack{true};
1625 constexpr bool AutoRelease{true};
1626 constexpr bool AutoPostGain{true};
1627 constexpr bool AutoDeclip{true};
1628 constexpr float LookAheadTime{0.001f};
1629 constexpr float HoldTime{0.002f};
1630 constexpr float PreGainDb{0.0f};
1631 constexpr float PostGainDb{0.0f};
1632 constexpr float Ratio{std::numeric_limits<float>::infinity()};
1633 constexpr float KneeDb{0.0f};
1634 constexpr float AttackTime{0.02f};
1635 constexpr float ReleaseTime{0.2f};
1637 return Compressor::Create(device->RealOut.Buffer.size(), static_cast<float>(device->Frequency),
1638 AutoKnee, AutoAttack, AutoRelease, AutoPostGain, AutoDeclip, LookAheadTime, HoldTime,
1639 PreGainDb, PostGainDb, threshold, Ratio, KneeDb, AttackTime, ReleaseTime);
1643 * Updates the device's base clock time with however many samples have been
1644 * done. This is used so frequency changes on the device don't cause the time
1645 * to jump forward or back. Must not be called while the device is running/
1646 * mixing.
1648 static inline void UpdateClockBase(ALCdevice *device)
1650 IncrementRef(device->MixCount);
1651 device->ClockBase += nanoseconds{seconds{device->SamplesDone}} / device->Frequency;
1652 device->SamplesDone = 0;
1653 IncrementRef(device->MixCount);
1657 * Updates device parameters according to the attribute list (caller is
1658 * responsible for holding the list lock).
1660 static ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
1662 HrtfRequestMode hrtf_userreq{Hrtf_Default};
1663 HrtfRequestMode hrtf_appreq{Hrtf_Default};
1664 ALCenum gainLimiter{device->LimiterState};
1665 ALCuint new_sends{device->NumAuxSends};
1666 DevFmtChannels oldChans;
1667 DevFmtType oldType;
1668 ALCsizei hrtf_id{-1};
1669 ALCuint oldFreq;
1671 if((!attrList || !attrList[0]) && device->Type == DeviceType::Loopback)
1673 WARN("Missing attributes for loopback device\n");
1674 return ALC_INVALID_VALUE;
1677 // Check for attributes
1678 if(attrList && attrList[0])
1680 ALCenum alayout{AL_NONE};
1681 ALCenum ascale{AL_NONE};
1682 ALCenum schans{AL_NONE};
1683 ALCenum stype{AL_NONE};
1684 ALCsizei attrIdx{0};
1685 ALCuint aorder{0};
1686 ALCuint freq{0u};
1688 ALuint numMono{device->NumMonoSources};
1689 ALuint numStereo{device->NumStereoSources};
1690 ALuint numSends{device->NumAuxSends};
1692 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1693 while(attrList[attrIdx])
1695 switch(attrList[attrIdx])
1697 case ALC_FORMAT_CHANNELS_SOFT:
1698 schans = attrList[attrIdx + 1];
1699 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1700 break;
1702 case ALC_FORMAT_TYPE_SOFT:
1703 stype = attrList[attrIdx + 1];
1704 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1705 break;
1707 case ALC_FREQUENCY:
1708 freq = static_cast<ALuint>(attrList[attrIdx + 1]);
1709 TRACE_ATTR(ALC_FREQUENCY, freq);
1710 break;
1712 case ALC_AMBISONIC_LAYOUT_SOFT:
1713 alayout = attrList[attrIdx + 1];
1714 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1715 break;
1717 case ALC_AMBISONIC_SCALING_SOFT:
1718 ascale = attrList[attrIdx + 1];
1719 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1720 break;
1722 case ALC_AMBISONIC_ORDER_SOFT:
1723 aorder = static_cast<ALuint>(attrList[attrIdx + 1]);
1724 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1725 break;
1727 case ALC_MONO_SOURCES:
1728 numMono = static_cast<ALuint>(attrList[attrIdx + 1]);
1729 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1730 if(numMono > INT_MAX) numMono = 0;
1731 break;
1733 case ALC_STEREO_SOURCES:
1734 numStereo = static_cast<ALuint>(attrList[attrIdx + 1]);
1735 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1736 if(numStereo > INT_MAX) numStereo = 0;
1737 break;
1739 case ALC_MAX_AUXILIARY_SENDS:
1740 numSends = static_cast<ALuint>(attrList[attrIdx + 1]);
1741 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1742 if(numSends > INT_MAX) numSends = 0;
1743 else numSends = minu(numSends, MAX_SENDS);
1744 break;
1746 case ALC_HRTF_SOFT:
1747 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1748 if(attrList[attrIdx + 1] == ALC_FALSE)
1749 hrtf_appreq = Hrtf_Disable;
1750 else if(attrList[attrIdx + 1] == ALC_TRUE)
1751 hrtf_appreq = Hrtf_Enable;
1752 else
1753 hrtf_appreq = Hrtf_Default;
1754 break;
1756 case ALC_HRTF_ID_SOFT:
1757 hrtf_id = attrList[attrIdx + 1];
1758 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1759 break;
1761 case ALC_OUTPUT_LIMITER_SOFT:
1762 gainLimiter = attrList[attrIdx + 1];
1763 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1764 break;
1766 default:
1767 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1768 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1769 break;
1772 attrIdx += 2;
1774 #undef TRACE_ATTR
1776 const bool loopback{device->Type == DeviceType::Loopback};
1777 if(loopback)
1779 if(!schans || !stype || !freq)
1781 WARN("Missing format for loopback device\n");
1782 return ALC_INVALID_VALUE;
1784 if(!IsValidALCChannels(schans) || !IsValidALCType(stype) || freq < MIN_OUTPUT_RATE
1785 || freq > MAX_OUTPUT_RATE)
1786 return ALC_INVALID_VALUE;
1787 if(schans == ALC_BFORMAT3D_SOFT)
1789 if(!alayout || !ascale || !aorder)
1791 WARN("Missing ambisonic info for loopback device\n");
1792 return ALC_INVALID_VALUE;
1794 if(!IsValidAmbiLayout(alayout) || !IsValidAmbiScaling(ascale))
1795 return ALC_INVALID_VALUE;
1796 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1797 return ALC_INVALID_VALUE;
1798 if((alayout == ALC_FUMA_SOFT || ascale == ALC_FUMA_SOFT) && aorder > 3)
1799 return ALC_INVALID_VALUE;
1803 /* If a context is already running on the device, stop playback so the
1804 * device attributes can be updated.
1806 if(device->Flags.get<DeviceRunning>())
1807 device->Backend->stop();
1808 device->Flags.unset<DeviceRunning>();
1810 UpdateClockBase(device);
1812 const char *devname{nullptr};
1813 if(!loopback)
1815 devname = device->DeviceName.c_str();
1817 device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
1818 device->UpdateSize = DEFAULT_UPDATE_SIZE;
1819 device->Frequency = DEFAULT_OUTPUT_RATE;
1821 freq = ConfigValueUInt(devname, nullptr, "frequency").value_or(freq);
1822 if(freq < 1)
1823 device->Flags.unset<FrequencyRequest>();
1824 else
1826 freq = clampu(freq, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE);
1828 const double scale{static_cast<double>(freq) / device->Frequency};
1829 device->UpdateSize = static_cast<ALuint>(device->UpdateSize*scale + 0.5);
1830 device->BufferSize = static_cast<ALuint>(device->BufferSize*scale + 0.5);
1832 device->Frequency = freq;
1833 device->Flags.set<FrequencyRequest>();
1836 if(auto persizeopt = ConfigValueUInt(devname, nullptr, "period_size"))
1837 device->UpdateSize = clampu(*persizeopt, 64, 8192);
1839 if(auto peropt = ConfigValueUInt(devname, nullptr, "periods"))
1840 device->BufferSize = device->UpdateSize * clampu(*peropt, 2, 16);
1841 else
1842 device->BufferSize = maxu(device->BufferSize, device->UpdateSize*2);
1844 else
1846 device->Frequency = freq;
1847 device->FmtChans = static_cast<DevFmtChannels>(schans);
1848 device->FmtType = static_cast<DevFmtType>(stype);
1849 if(schans == ALC_BFORMAT3D_SOFT)
1851 device->mAmbiOrder = aorder;
1852 device->mAmbiLayout = static_cast<DevAmbiLayout>(alayout);
1853 device->mAmbiScale = static_cast<DevAmbiScaling>(ascale);
1857 if(numMono > INT_MAX-numStereo)
1858 numMono = INT_MAX-numStereo;
1859 numMono += numStereo;
1860 if(auto srcsopt = ConfigValueUInt(devname, nullptr, "sources"))
1862 if(*srcsopt <= 0) numMono = 256;
1863 else numMono = *srcsopt;
1865 else
1866 numMono = maxu(numMono, 256);
1867 numStereo = minu(numStereo, numMono);
1868 numMono -= numStereo;
1869 device->SourcesMax = numMono + numStereo;
1871 device->NumMonoSources = numMono;
1872 device->NumStereoSources = numStereo;
1874 if(auto sendsopt = ConfigValueInt(devname, nullptr, "sends"))
1875 new_sends = minu(numSends, static_cast<ALuint>(clampi(*sendsopt, 0, MAX_SENDS)));
1876 else
1877 new_sends = numSends;
1880 if(device->Flags.get<DeviceRunning>())
1881 return ALC_NO_ERROR;
1883 device->AvgSpeakerDist = 0.0f;
1884 device->Uhj_Encoder = nullptr;
1885 device->AmbiDecoder = nullptr;
1886 device->Bs2b = nullptr;
1887 device->PostProcess = nullptr;
1889 device->Limiter = nullptr;
1890 device->ChannelDelay.clear();
1892 std::fill(std::begin(device->HrtfAccumData), std::end(device->HrtfAccumData), float2{});
1894 device->Dry.AmbiMap.fill(BFChannelConfig{});
1895 device->Dry.Buffer = {};
1896 std::fill(std::begin(device->NumChannelsPerOrder), std::end(device->NumChannelsPerOrder), 0u);
1897 device->RealOut.RemixMap = {};
1898 device->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
1899 device->RealOut.Buffer = {};
1900 device->MixBuffer.clear();
1901 device->MixBuffer.shrink_to_fit();
1903 UpdateClockBase(device);
1904 device->FixedLatency = nanoseconds::zero();
1906 device->DitherDepth = 0.0f;
1907 device->DitherSeed = DitherRNGSeed;
1909 /*************************************************************************
1910 * Update device format request if HRTF is requested
1912 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
1913 if(device->Type != DeviceType::Loopback)
1915 if(auto hrtfopt = ConfigValueStr(device->DeviceName.c_str(), nullptr, "hrtf"))
1917 const char *hrtf{hrtfopt->c_str()};
1918 if(al::strcasecmp(hrtf, "true") == 0)
1919 hrtf_userreq = Hrtf_Enable;
1920 else if(al::strcasecmp(hrtf, "false") == 0)
1921 hrtf_userreq = Hrtf_Disable;
1922 else if(al::strcasecmp(hrtf, "auto") != 0)
1923 ERR("Unexpected hrtf value: %s\n", hrtf);
1926 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
1928 device->FmtChans = DevFmtStereo;
1929 device->Flags.set<ChannelsRequest>();
1933 oldFreq = device->Frequency;
1934 oldChans = device->FmtChans;
1935 oldType = device->FmtType;
1937 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u / %u buffer\n",
1938 device->Flags.get<ChannelsRequest>()?"*":"", DevFmtChannelsString(device->FmtChans),
1939 device->Flags.get<SampleTypeRequest>()?"*":"", DevFmtTypeString(device->FmtType),
1940 device->Flags.get<FrequencyRequest>()?"*":"", device->Frequency,
1941 device->UpdateSize, device->BufferSize);
1943 try {
1944 auto backend = device->Backend.get();
1945 if(!backend->reset())
1946 throw al::backend_exception{ALC_INVALID_DEVICE, "Device reset failure"};
1948 catch(std::exception &e) {
1949 device->handleDisconnect("%s", e.what());
1950 return ALC_INVALID_DEVICE;
1953 if(device->FmtChans != oldChans && device->Flags.get<ChannelsRequest>())
1955 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1956 DevFmtChannelsString(device->FmtChans));
1957 device->Flags.unset<ChannelsRequest>();
1959 if(device->FmtType != oldType && device->Flags.get<SampleTypeRequest>())
1961 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1962 DevFmtTypeString(device->FmtType));
1963 device->Flags.unset<SampleTypeRequest>();
1965 if(device->Frequency != oldFreq && device->Flags.get<FrequencyRequest>())
1967 WARN("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1968 device->Flags.unset<FrequencyRequest>();
1971 TRACE("Post-reset: %s, %s, %uhz, %u / %u buffer\n",
1972 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
1973 device->Frequency, device->UpdateSize, device->BufferSize);
1975 switch(device->FmtChans)
1977 case DevFmtMono: device->RealOut.RemixMap = MonoDownmix; break;
1978 case DevFmtStereo: device->RealOut.RemixMap = StereoDownmix; break;
1979 case DevFmtQuad: device->RealOut.RemixMap = QuadDownmix; break;
1980 case DevFmtX51: device->RealOut.RemixMap = X51Downmix; break;
1981 case DevFmtX51Rear: device->RealOut.RemixMap = X51RearDownmix; break;
1982 case DevFmtX61: device->RealOut.RemixMap = X61Downmix; break;
1983 case DevFmtX71: device->RealOut.RemixMap = X71Downmix; break;
1984 case DevFmtAmbi3D: break;
1987 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
1989 device->NumAuxSends = new_sends;
1990 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
1991 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
1992 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
1994 nanoseconds::rep sample_delay{0};
1995 if(device->Uhj_Encoder)
1996 sample_delay += Uhj2Encoder::sFilterSize;
1997 if(device->mHrtfState)
1998 sample_delay += HRTF_DIRECT_DELAY;
1999 if(auto *ambidec = device->AmbiDecoder.get())
2001 if(ambidec->hasStablizer())
2002 sample_delay += FrontStablizer::DelayLength;
2005 if(GetConfigValueBool(device->DeviceName.c_str(), nullptr, "dither", 1))
2007 int depth{ConfigValueInt(device->DeviceName.c_str(), nullptr, "dither-depth").value_or(0)};
2008 if(depth <= 0)
2010 switch(device->FmtType)
2012 case DevFmtByte:
2013 case DevFmtUByte:
2014 depth = 8;
2015 break;
2016 case DevFmtShort:
2017 case DevFmtUShort:
2018 depth = 16;
2019 break;
2020 case DevFmtInt:
2021 case DevFmtUInt:
2022 case DevFmtFloat:
2023 break;
2027 if(depth > 0)
2029 depth = clampi(depth, 2, 24);
2030 device->DitherDepth = std::pow(2.0f, static_cast<float>(depth-1));
2033 if(!(device->DitherDepth > 0.0f))
2034 TRACE("Dithering disabled\n");
2035 else
2036 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device->DitherDepth)+0.5f)+1,
2037 device->DitherDepth);
2039 device->LimiterState = gainLimiter;
2040 if(auto limopt = ConfigValueBool(device->DeviceName.c_str(), nullptr, "output-limiter"))
2041 gainLimiter = *limopt ? ALC_TRUE : ALC_FALSE;
2043 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2044 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2045 * output (where samples must be clamped), and don't for floating-point
2046 * (which can take unclamped samples).
2048 if(gainLimiter == ALC_DONT_CARE_SOFT)
2050 switch(device->FmtType)
2052 case DevFmtByte:
2053 case DevFmtUByte:
2054 case DevFmtShort:
2055 case DevFmtUShort:
2056 case DevFmtInt:
2057 case DevFmtUInt:
2058 gainLimiter = ALC_TRUE;
2059 break;
2060 case DevFmtFloat:
2061 gainLimiter = ALC_FALSE;
2062 break;
2065 if(gainLimiter == ALC_FALSE)
2066 TRACE("Output limiter disabled\n");
2067 else
2069 float thrshld{1.0f};
2070 switch(device->FmtType)
2072 case DevFmtByte:
2073 case DevFmtUByte:
2074 thrshld = 127.0f / 128.0f;
2075 break;
2076 case DevFmtShort:
2077 case DevFmtUShort:
2078 thrshld = 32767.0f / 32768.0f;
2079 break;
2080 case DevFmtInt:
2081 case DevFmtUInt:
2082 case DevFmtFloat:
2083 break;
2085 if(device->DitherDepth > 0.0f)
2086 thrshld -= 1.0f / device->DitherDepth;
2088 const float thrshld_dB{std::log10(thrshld) * 20.0f};
2089 auto limiter = CreateDeviceLimiter(device, thrshld_dB);
2091 sample_delay += limiter->getLookAhead();
2092 device->Limiter = std::move(limiter);
2093 TRACE("Output limiter enabled, %.4fdB limit\n", thrshld_dB);
2096 /* Convert the sample delay from samples to nanosamples to nanoseconds. */
2097 device->FixedLatency += nanoseconds{seconds{sample_delay}} / device->Frequency;
2098 TRACE("Fixed device latency: %" PRId64 "ns\n", int64_t{device->FixedLatency.count()});
2100 FPUCtl mixer_mode{};
2101 for(ALCcontext *context : *device->mContexts.load())
2103 std::unique_lock<std::mutex> proplock{context->mPropLock};
2104 std::unique_lock<std::mutex> slotlock{context->mEffectSlotLock};
2106 /* Clear out unused wet buffers. */
2107 auto buffer_not_in_use = [](WetBufferPtr &wetbuffer) noexcept -> bool
2108 { return !wetbuffer->mInUse; };
2109 auto wetbuffer_iter = std::remove_if(context->mWetBuffers.begin(),
2110 context->mWetBuffers.end(), buffer_not_in_use);
2111 context->mWetBuffers.erase(wetbuffer_iter, context->mWetBuffers.end());
2113 if(ALeffectslot *slot{context->mDefaultSlot.get()})
2115 aluInitEffectPanning(slot, context);
2117 EffectState *state{slot->Effect.State.get()};
2118 state->mOutTarget = device->Dry.Buffer;
2119 state->deviceUpdate(device);
2120 if(ALbuffer *buffer{slot->Buffer})
2121 state->setBuffer(device, &buffer->mBuffer);
2122 slot->updateProps(context);
2125 if(ALeffectslotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_relaxed)})
2126 std::fill_n(curarray->end(), curarray->size(), nullptr);
2127 for(auto &sublist : context->mEffectSlotList)
2129 uint64_t usemask{~sublist.FreeMask};
2130 while(usemask)
2132 const ALsizei idx{CountTrailingZeros(usemask)};
2133 ALeffectslot *slot{sublist.EffectSlots + idx};
2134 usemask &= ~(1_u64 << idx);
2136 aluInitEffectPanning(slot, context);
2138 EffectState *state{slot->Effect.State.get()};
2139 state->mOutTarget = device->Dry.Buffer;
2140 state->deviceUpdate(device);
2141 if(ALbuffer *buffer{slot->Buffer})
2142 state->setBuffer(device, &buffer->mBuffer);
2143 slot->updateProps(context);
2146 slotlock.unlock();
2148 const ALuint num_sends{device->NumAuxSends};
2149 std::unique_lock<std::mutex> srclock{context->mSourceLock};
2150 for(auto &sublist : context->mSourceList)
2152 uint64_t usemask{~sublist.FreeMask};
2153 while(usemask)
2155 const ALsizei idx{CountTrailingZeros(usemask)};
2156 ALsource *source{sublist.Sources + idx};
2157 usemask &= ~(1_u64 << idx);
2159 auto clear_send = [](ALsource::SendData &send) -> void
2161 if(send.Slot)
2162 DecrementRef(send.Slot->ref);
2163 send.Slot = nullptr;
2164 send.Gain = 1.0f;
2165 send.GainHF = 1.0f;
2166 send.HFReference = LOWPASSFREQREF;
2167 send.GainLF = 1.0f;
2168 send.LFReference = HIGHPASSFREQREF;
2170 auto send_begin = source->Send.begin() + static_cast<ptrdiff_t>(num_sends);
2171 std::for_each(send_begin, source->Send.end(), clear_send);
2173 source->PropsClean.clear(std::memory_order_release);
2177 /* Clear any pre-existing voice property structs, in case the number of
2178 * auxiliary sends is changing. Active sources will have updates
2179 * respecified in UpdateAllSourceProps.
2181 VoicePropsItem *vprops{context->mFreeVoiceProps.exchange(nullptr, std::memory_order_acq_rel)};
2182 while(vprops)
2184 VoicePropsItem *next = vprops->next.load(std::memory_order_relaxed);
2185 delete vprops;
2186 vprops = next;
2189 auto voicelist = context->getVoicesSpan();
2190 for(Voice *voice : voicelist)
2192 /* Clear extraneous property set sends. */
2193 std::fill(std::begin(voice->mProps.Send)+num_sends, std::end(voice->mProps.Send),
2194 VoiceProps::SendData{});
2196 std::fill(voice->mSend.begin()+num_sends, voice->mSend.end(), Voice::TargetData{});
2197 for(auto &chandata : voice->mChans)
2199 std::fill(chandata.mWetParams.begin()+num_sends, chandata.mWetParams.end(),
2200 SendParams{});
2203 delete voice->mUpdate.exchange(nullptr, std::memory_order_acq_rel);
2205 /* Force the voice to stopped if it was stopping. */
2206 Voice::State vstate{Voice::Stopping};
2207 voice->mPlayState.compare_exchange_strong(vstate, Voice::Stopped,
2208 std::memory_order_acquire, std::memory_order_acquire);
2209 if(voice->mSourceID.load(std::memory_order_relaxed) == 0u)
2210 continue;
2212 voice->mStep = 0;
2213 voice->mFlags |= VoiceIsFading;
2215 if(voice->mAmbiOrder && device->mAmbiOrder > voice->mAmbiOrder)
2217 const uint8_t *OrderFromChan{(voice->mFmtChannels == FmtBFormat2D) ?
2218 AmbiIndex::OrderFrom2DChannel.data() :
2219 AmbiIndex::OrderFromChannel.data()};
2221 const BandSplitter splitter{400.0f / static_cast<float>(device->Frequency)};
2223 const auto scales = BFormatDec::GetHFOrderScales(voice->mAmbiOrder,
2224 device->mAmbiOrder);
2225 for(auto &chandata : voice->mChans)
2227 chandata.mPrevSamples.fill(0.0f);
2228 chandata.mAmbiScale = scales[*(OrderFromChan++)];
2229 chandata.mAmbiSplitter = splitter;
2230 chandata.mDryParams = DirectParams{};
2231 std::fill_n(chandata.mWetParams.begin(), num_sends, SendParams{});
2234 voice->mFlags |= VoiceIsAmbisonic;
2236 else
2238 /* Clear previous samples. */
2239 for(auto &chandata : voice->mChans)
2241 chandata.mPrevSamples.fill(0.0f);
2242 chandata.mDryParams = DirectParams{};
2243 std::fill_n(chandata.mWetParams.begin(), num_sends, SendParams{});
2246 voice->mFlags &= ~VoiceIsAmbisonic;
2249 if(device->AvgSpeakerDist > 0.0f)
2251 /* Reinitialize the NFC filters for new parameters. */
2252 const float w1{SpeedOfSoundMetersPerSec /
2253 (device->AvgSpeakerDist * static_cast<float>(device->Frequency))};
2254 for(auto &chandata : voice->mChans)
2255 chandata.mDryParams.NFCtrlFilter.init(w1);
2258 srclock.unlock();
2260 context->mPropsClean.test_and_set(std::memory_order_release);
2261 UpdateContextProps(context);
2262 context->mListener.PropsClean.test_and_set(std::memory_order_release);
2263 UpdateListenerProps(context);
2264 UpdateAllSourceProps(context);
2266 mixer_mode.leave();
2268 if(!device->Flags.get<DevicePaused>())
2270 try {
2271 auto backend = device->Backend.get();
2272 backend->start();
2273 device->Flags.set<DeviceRunning>();
2275 catch(al::backend_exception& e) {
2276 device->handleDisconnect("%s", e.what());
2277 return ALC_INVALID_DEVICE;
2281 return ALC_NO_ERROR;
2285 ALCdevice::ALCdevice(DeviceType type) : Type{type}, mContexts{&EmptyContextArray}
2289 ALCdevice::~ALCdevice()
2291 TRACE("Freeing device %p\n", decltype(std::declval<void*>()){this});
2293 Backend = nullptr;
2295 size_t count{std::accumulate(BufferList.cbegin(), BufferList.cend(), size_t{0u},
2296 [](size_t cur, const BufferSubList &sublist) noexcept -> size_t
2297 { return cur + static_cast<ALuint>(PopCount(~sublist.FreeMask)); })};
2298 if(count > 0)
2299 WARN("%zu Buffer%s not deleted\n", count, (count==1)?"":"s");
2301 count = std::accumulate(EffectList.cbegin(), EffectList.cend(), size_t{0u},
2302 [](size_t cur, const EffectSubList &sublist) noexcept -> size_t
2303 { return cur + static_cast<ALuint>(PopCount(~sublist.FreeMask)); });
2304 if(count > 0)
2305 WARN("%zu Effect%s not deleted\n", count, (count==1)?"":"s");
2307 count = std::accumulate(FilterList.cbegin(), FilterList.cend(), size_t{0u},
2308 [](size_t cur, const FilterSubList &sublist) noexcept -> size_t
2309 { return cur + static_cast<ALuint>(PopCount(~sublist.FreeMask)); });
2310 if(count > 0)
2311 WARN("%zu Filter%s not deleted\n", count, (count==1)?"":"s");
2313 mHrtf = nullptr;
2315 auto *oldarray = mContexts.exchange(nullptr, std::memory_order_relaxed);
2316 if(oldarray != &EmptyContextArray) delete oldarray;
2320 /** Checks if the device handle is valid, and returns a new reference if so. */
2321 static DeviceRef VerifyDevice(ALCdevice *device)
2323 std::lock_guard<std::recursive_mutex> _{ListLock};
2324 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
2325 if(iter != DeviceList.end() && *iter == device)
2327 (*iter)->add_ref();
2328 return DeviceRef{*iter};
2330 return nullptr;
2334 ALCcontext::ALCcontext(al::intrusive_ptr<ALCdevice> device) : mDevice{std::move(device)}
2336 mPropsClean.test_and_set(std::memory_order_relaxed);
2339 ALCcontext::~ALCcontext()
2341 TRACE("Freeing context %p\n", decltype(std::declval<void*>()){this});
2343 size_t count{0};
2344 ALcontextProps *cprops{mUpdate.exchange(nullptr, std::memory_order_relaxed)};
2345 if(cprops)
2347 ++count;
2348 delete cprops;
2350 cprops = mFreeContextProps.exchange(nullptr, std::memory_order_acquire);
2351 while(cprops)
2353 ALcontextProps *next{cprops->next.load(std::memory_order_relaxed)};
2354 delete cprops;
2355 cprops = next;
2356 ++count;
2358 TRACE("Freed %zu context property object%s\n", count, (count==1)?"":"s");
2360 count = std::accumulate(mSourceList.cbegin(), mSourceList.cend(), size_t{0u},
2361 [](size_t cur, const SourceSubList &sublist) noexcept -> size_t
2362 { return cur + static_cast<ALuint>(PopCount(~sublist.FreeMask)); });
2363 if(count > 0)
2364 WARN("%zu Source%s not deleted\n", count, (count==1)?"":"s");
2365 mSourceList.clear();
2366 mNumSources = 0;
2368 count = 0;
2369 ALeffectslotProps *eprops{mFreeEffectslotProps.exchange(nullptr, std::memory_order_acquire)};
2370 while(eprops)
2372 ALeffectslotProps *next{eprops->next.load(std::memory_order_relaxed)};
2373 delete eprops;
2374 eprops = next;
2375 ++count;
2377 TRACE("Freed %zu AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2379 if(ALeffectslotArray *curarray{mActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed)})
2381 al::destroy_n(curarray->end(), curarray->size());
2382 delete curarray;
2384 mDefaultSlot = nullptr;
2386 count = std::accumulate(mEffectSlotList.cbegin(), mEffectSlotList.cend(), size_t{0u},
2387 [](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t
2388 { return cur + static_cast<ALuint>(PopCount(~sublist.FreeMask)); });
2389 if(count > 0)
2390 WARN("%zu AuxiliaryEffectSlot%s not deleted\n", count, (count==1)?"":"s");
2391 mEffectSlotList.clear();
2392 mNumEffectSlots = 0;
2394 count = 0;
2395 VoicePropsItem *vprops{mFreeVoiceProps.exchange(nullptr, std::memory_order_acquire)};
2396 while(vprops)
2398 VoicePropsItem *next{vprops->next.load(std::memory_order_relaxed)};
2399 delete vprops;
2400 vprops = next;
2401 ++count;
2403 TRACE("Freed %zu voice property object%s\n", count, (count==1)?"":"s");
2405 delete mVoices.exchange(nullptr, std::memory_order_relaxed);
2407 count = 0;
2408 ALlistenerProps *lprops{mListener.Params.Update.exchange(nullptr, std::memory_order_relaxed)};
2409 if(lprops)
2411 ++count;
2412 delete lprops;
2414 lprops = mFreeListenerProps.exchange(nullptr, std::memory_order_acquire);
2415 while(lprops)
2417 ALlistenerProps *next{lprops->next.load(std::memory_order_relaxed)};
2418 delete lprops;
2419 lprops = next;
2420 ++count;
2422 TRACE("Freed %zu listener property object%s\n", count, (count==1)?"":"s");
2424 if(mAsyncEvents)
2426 count = 0;
2427 auto evt_vec = mAsyncEvents->getReadVector();
2428 if(evt_vec.first.len > 0)
2430 al::destroy_n(reinterpret_cast<AsyncEvent*>(evt_vec.first.buf), evt_vec.first.len);
2431 count += evt_vec.first.len;
2433 if(evt_vec.second.len > 0)
2435 al::destroy_n(reinterpret_cast<AsyncEvent*>(evt_vec.second.buf), evt_vec.second.len);
2436 count += evt_vec.second.len;
2438 if(count > 0)
2439 TRACE("Destructed %zu orphaned event%s\n", count, (count==1)?"":"s");
2440 mAsyncEvents->readAdvance(count);
2444 void ALCcontext::init()
2446 if(DefaultEffect.type != AL_EFFECT_NULL && mDevice->Type == DeviceType::Playback)
2448 mDefaultSlot = std::unique_ptr<ALeffectslot>{new ALeffectslot{}};
2449 if(mDefaultSlot->init() == AL_NO_ERROR)
2450 aluInitEffectPanning(mDefaultSlot.get(), this);
2451 else
2453 mDefaultSlot = nullptr;
2454 ERR("Failed to initialize the default effect slot\n");
2458 ALeffectslotArray *auxslots;
2459 if(!mDefaultSlot)
2460 auxslots = ALeffectslot::CreatePtrArray(0);
2461 else
2463 auxslots = ALeffectslot::CreatePtrArray(1);
2464 (*auxslots)[0] = mDefaultSlot.get();
2465 mDefaultSlot->mState = SlotState::Playing;
2467 mActiveAuxSlots.store(auxslots, std::memory_order_relaxed);
2469 allocVoiceChanges(1);
2471 VoiceChange *cur{mVoiceChangeTail};
2472 while(VoiceChange *next{cur->mNext.load(std::memory_order_relaxed)})
2473 cur = next;
2474 mCurrentVoiceChange.store(cur, std::memory_order_relaxed);
2477 mExtensionList = alExtList;
2480 mListener.Params.Matrix = alu::Matrix::Identity();
2481 mListener.Params.Velocity = alu::Vector{};
2482 mListener.Params.Gain = mListener.Gain;
2483 mListener.Params.MetersPerUnit = mListener.mMetersPerUnit;
2484 mListener.Params.DopplerFactor = mDopplerFactor;
2485 mListener.Params.SpeedOfSound = mSpeedOfSound * mDopplerVelocity;
2486 mListener.Params.SourceDistanceModel = mSourceDistanceModel;
2487 mListener.Params.mDistanceModel = mDistanceModel;
2490 mAsyncEvents = RingBuffer::Create(511, sizeof(AsyncEvent), false);
2491 StartEventThrd(this);
2494 allocVoices(256);
2495 mActiveVoiceCount.store(64, std::memory_order_relaxed);
2498 bool ALCcontext::deinit()
2500 if(LocalContext == this)
2502 WARN("%p released while current on thread\n", decltype(std::declval<void*>()){this});
2503 ThreadContext.set(nullptr);
2504 release();
2507 ALCcontext *origctx{this};
2508 if(GlobalContext.compare_exchange_strong(origctx, nullptr))
2509 release();
2511 bool ret{};
2512 /* First make sure this context exists in the device's list. */
2513 auto *oldarray = mDevice->mContexts.load(std::memory_order_acquire);
2514 if(auto toremove = static_cast<size_t>(std::count(oldarray->begin(), oldarray->end(), this)))
2516 using ContextArray = al::FlexArray<ALCcontext*>;
2517 auto alloc_ctx_array = [](const size_t count) -> ContextArray*
2519 if(count == 0) return &EmptyContextArray;
2520 return ContextArray::Create(count).release();
2522 auto *newarray = alloc_ctx_array(oldarray->size() - toremove);
2524 /* Copy the current/old context handles to the new array, excluding the
2525 * given context.
2527 std::copy_if(oldarray->begin(), oldarray->end(), newarray->begin(),
2528 std::bind(std::not_equal_to<ALCcontext*>{}, _1, this));
2530 /* Store the new context array in the device. Wait for any current mix
2531 * to finish before deleting the old array.
2533 mDevice->mContexts.store(newarray);
2534 if(oldarray != &EmptyContextArray)
2536 mDevice->waitForMix();
2537 delete oldarray;
2540 ret = !newarray->empty();
2542 else
2543 ret = !oldarray->empty();
2545 StopEventThrd(this);
2547 return ret;
2552 * Checks if the given context is valid, returning a new reference to it if so.
2554 static ContextRef VerifyContext(ALCcontext *context)
2556 std::lock_guard<std::recursive_mutex> _{ListLock};
2557 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
2558 if(iter != ContextList.end() && *iter == context)
2560 (*iter)->add_ref();
2561 return ContextRef{*iter};
2563 return nullptr;
2566 /** Returns a new reference to the currently active context for this thread. */
2567 ContextRef GetContextRef(void)
2569 ALCcontext *context{LocalContext};
2570 if(context)
2571 context->add_ref();
2572 else
2574 std::lock_guard<std::recursive_mutex> _{ListLock};
2575 context = GlobalContext.load(std::memory_order_acquire);
2576 if(context) context->add_ref();
2578 return ContextRef{context};
2582 /************************************************
2583 * Standard ALC functions
2584 ************************************************/
2586 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2587 START_API_FUNC
2589 DeviceRef dev{VerifyDevice(device)};
2590 if(dev) return dev->LastError.exchange(ALC_NO_ERROR);
2591 return LastNullDeviceError.exchange(ALC_NO_ERROR);
2593 END_API_FUNC
2596 ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2597 START_API_FUNC
2599 if(!SuspendDefers)
2600 return;
2602 ContextRef ctx{VerifyContext(context)};
2603 if(!ctx)
2604 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2605 else
2606 ctx->deferUpdates();
2608 END_API_FUNC
2610 ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context)
2611 START_API_FUNC
2613 if(!SuspendDefers)
2614 return;
2616 ContextRef ctx{VerifyContext(context)};
2617 if(!ctx)
2618 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2619 else
2620 ctx->processUpdates();
2622 END_API_FUNC
2625 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2626 START_API_FUNC
2628 const ALCchar *value{nullptr};
2630 switch(param)
2632 case ALC_NO_ERROR:
2633 value = alcNoError;
2634 break;
2636 case ALC_INVALID_ENUM:
2637 value = alcErrInvalidEnum;
2638 break;
2640 case ALC_INVALID_VALUE:
2641 value = alcErrInvalidValue;
2642 break;
2644 case ALC_INVALID_DEVICE:
2645 value = alcErrInvalidDevice;
2646 break;
2648 case ALC_INVALID_CONTEXT:
2649 value = alcErrInvalidContext;
2650 break;
2652 case ALC_OUT_OF_MEMORY:
2653 value = alcErrOutOfMemory;
2654 break;
2656 case ALC_DEVICE_SPECIFIER:
2657 value = alcDefaultName;
2658 break;
2660 case ALC_ALL_DEVICES_SPECIFIER:
2661 if(DeviceRef dev{VerifyDevice(Device)})
2662 value = dev->DeviceName.c_str();
2663 else
2665 ProbeAllDevicesList();
2666 value = alcAllDevicesList.c_str();
2668 break;
2670 case ALC_CAPTURE_DEVICE_SPECIFIER:
2671 if(DeviceRef dev{VerifyDevice(Device)})
2672 value = dev->DeviceName.c_str();
2673 else
2675 ProbeCaptureDeviceList();
2676 value = alcCaptureDeviceList.c_str();
2678 break;
2680 /* Default devices are always first in the list */
2681 case ALC_DEFAULT_DEVICE_SPECIFIER:
2682 value = alcDefaultName;
2683 break;
2685 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2686 if(alcAllDevicesList.empty())
2687 ProbeAllDevicesList();
2689 /* Copy first entry as default. */
2690 alcDefaultAllDevicesSpecifier = alcAllDevicesList.c_str();
2691 value = alcDefaultAllDevicesSpecifier.c_str();
2692 break;
2694 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2695 if(alcCaptureDeviceList.empty())
2696 ProbeCaptureDeviceList();
2698 /* Copy first entry as default. */
2699 alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList.c_str();
2700 value = alcCaptureDefaultDeviceSpecifier.c_str();
2701 break;
2703 case ALC_EXTENSIONS:
2704 if(VerifyDevice(Device))
2705 value = alcExtensionList;
2706 else
2707 value = alcNoDeviceExtList;
2708 break;
2710 case ALC_HRTF_SPECIFIER_SOFT:
2711 if(DeviceRef dev{VerifyDevice(Device)})
2713 std::lock_guard<std::mutex> _{dev->StateLock};
2714 value = (dev->mHrtf ? dev->HrtfName.c_str() : "");
2716 else
2717 alcSetError(nullptr, ALC_INVALID_DEVICE);
2718 break;
2720 default:
2721 alcSetError(VerifyDevice(Device).get(), ALC_INVALID_ENUM);
2722 break;
2725 return value;
2727 END_API_FUNC
2730 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
2732 if(device->Type == DeviceType::Capture) return 9;
2733 if(device->Type != DeviceType::Loopback) return 29;
2734 if(device->FmtChans == DevFmtAmbi3D)
2735 return 35;
2736 return 29;
2739 static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span<int> values)
2741 size_t i;
2743 if(values.empty())
2745 alcSetError(device, ALC_INVALID_VALUE);
2746 return 0;
2749 if(!device)
2751 switch(param)
2753 case ALC_MAJOR_VERSION:
2754 values[0] = alcMajorVersion;
2755 return 1;
2756 case ALC_MINOR_VERSION:
2757 values[0] = alcMinorVersion;
2758 return 1;
2760 case ALC_ATTRIBUTES_SIZE:
2761 case ALC_ALL_ATTRIBUTES:
2762 case ALC_FREQUENCY:
2763 case ALC_REFRESH:
2764 case ALC_SYNC:
2765 case ALC_MONO_SOURCES:
2766 case ALC_STEREO_SOURCES:
2767 case ALC_CAPTURE_SAMPLES:
2768 case ALC_FORMAT_CHANNELS_SOFT:
2769 case ALC_FORMAT_TYPE_SOFT:
2770 case ALC_AMBISONIC_LAYOUT_SOFT:
2771 case ALC_AMBISONIC_SCALING_SOFT:
2772 case ALC_AMBISONIC_ORDER_SOFT:
2773 case ALC_MAX_AMBISONIC_ORDER_SOFT:
2774 alcSetError(nullptr, ALC_INVALID_DEVICE);
2775 return 0;
2777 default:
2778 alcSetError(nullptr, ALC_INVALID_ENUM);
2780 return 0;
2783 if(device->Type == DeviceType::Capture)
2785 switch(param)
2787 case ALC_ATTRIBUTES_SIZE:
2788 values[0] = NumAttrsForDevice(device);
2789 return 1;
2791 case ALC_ALL_ATTRIBUTES:
2792 i = 0;
2793 if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2794 alcSetError(device, ALC_INVALID_VALUE);
2795 else
2797 std::lock_guard<std::mutex> _{device->StateLock};
2798 values[i++] = ALC_MAJOR_VERSION;
2799 values[i++] = alcMajorVersion;
2800 values[i++] = ALC_MINOR_VERSION;
2801 values[i++] = alcMinorVersion;
2802 values[i++] = ALC_CAPTURE_SAMPLES;
2803 values[i++] = static_cast<int>(device->Backend->availableSamples());
2804 values[i++] = ALC_CONNECTED;
2805 values[i++] = device->Connected.load(std::memory_order_relaxed);
2806 values[i++] = 0;
2808 return i;
2810 case ALC_MAJOR_VERSION:
2811 values[0] = alcMajorVersion;
2812 return 1;
2813 case ALC_MINOR_VERSION:
2814 values[0] = alcMinorVersion;
2815 return 1;
2817 case ALC_CAPTURE_SAMPLES:
2819 std::lock_guard<std::mutex> _{device->StateLock};
2820 values[0] = static_cast<int>(device->Backend->availableSamples());
2822 return 1;
2824 case ALC_CONNECTED:
2826 std::lock_guard<std::mutex> _{device->StateLock};
2827 values[0] = device->Connected.load(std::memory_order_acquire);
2829 return 1;
2831 default:
2832 alcSetError(device, ALC_INVALID_ENUM);
2834 return 0;
2837 /* render device */
2838 switch(param)
2840 case ALC_ATTRIBUTES_SIZE:
2841 values[0] = NumAttrsForDevice(device);
2842 return 1;
2844 case ALC_ALL_ATTRIBUTES:
2845 i = 0;
2846 if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2847 alcSetError(device, ALC_INVALID_VALUE);
2848 else
2850 std::lock_guard<std::mutex> _{device->StateLock};
2851 values[i++] = ALC_MAJOR_VERSION;
2852 values[i++] = alcMajorVersion;
2853 values[i++] = ALC_MINOR_VERSION;
2854 values[i++] = alcMinorVersion;
2855 values[i++] = ALC_EFX_MAJOR_VERSION;
2856 values[i++] = alcEFXMajorVersion;
2857 values[i++] = ALC_EFX_MINOR_VERSION;
2858 values[i++] = alcEFXMinorVersion;
2860 values[i++] = ALC_FREQUENCY;
2861 values[i++] = static_cast<int>(device->Frequency);
2862 if(device->Type != DeviceType::Loopback)
2864 values[i++] = ALC_REFRESH;
2865 values[i++] = static_cast<int>(device->Frequency / device->UpdateSize);
2867 values[i++] = ALC_SYNC;
2868 values[i++] = ALC_FALSE;
2870 else
2872 if(device->FmtChans == DevFmtAmbi3D)
2874 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
2875 values[i++] = static_cast<int>(device->mAmbiLayout);
2877 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
2878 values[i++] = static_cast<int>(device->mAmbiScale);
2880 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
2881 values[i++] = static_cast<int>(device->mAmbiOrder);
2884 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2885 values[i++] = device->FmtChans;
2887 values[i++] = ALC_FORMAT_TYPE_SOFT;
2888 values[i++] = device->FmtType;
2891 values[i++] = ALC_MONO_SOURCES;
2892 values[i++] = static_cast<int>(device->NumMonoSources);
2894 values[i++] = ALC_STEREO_SOURCES;
2895 values[i++] = static_cast<int>(device->NumStereoSources);
2897 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2898 values[i++] = static_cast<int>(device->NumAuxSends);
2900 values[i++] = ALC_HRTF_SOFT;
2901 values[i++] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
2903 values[i++] = ALC_HRTF_STATUS_SOFT;
2904 values[i++] = device->HrtfStatus;
2906 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
2907 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
2909 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
2910 values[i++] = MAX_AMBI_ORDER;
2912 values[i++] = 0;
2914 return i;
2916 case ALC_MAJOR_VERSION:
2917 values[0] = alcMajorVersion;
2918 return 1;
2920 case ALC_MINOR_VERSION:
2921 values[0] = alcMinorVersion;
2922 return 1;
2924 case ALC_EFX_MAJOR_VERSION:
2925 values[0] = alcEFXMajorVersion;
2926 return 1;
2928 case ALC_EFX_MINOR_VERSION:
2929 values[0] = alcEFXMinorVersion;
2930 return 1;
2932 case ALC_FREQUENCY:
2933 values[0] = static_cast<int>(device->Frequency);
2934 return 1;
2936 case ALC_REFRESH:
2937 if(device->Type == DeviceType::Loopback)
2939 alcSetError(device, ALC_INVALID_DEVICE);
2940 return 0;
2943 std::lock_guard<std::mutex> _{device->StateLock};
2944 values[0] = static_cast<int>(device->Frequency / device->UpdateSize);
2946 return 1;
2948 case ALC_SYNC:
2949 if(device->Type == DeviceType::Loopback)
2951 alcSetError(device, ALC_INVALID_DEVICE);
2952 return 0;
2954 values[0] = ALC_FALSE;
2955 return 1;
2957 case ALC_FORMAT_CHANNELS_SOFT:
2958 if(device->Type != DeviceType::Loopback)
2960 alcSetError(device, ALC_INVALID_DEVICE);
2961 return 0;
2963 values[0] = device->FmtChans;
2964 return 1;
2966 case ALC_FORMAT_TYPE_SOFT:
2967 if(device->Type != DeviceType::Loopback)
2969 alcSetError(device, ALC_INVALID_DEVICE);
2970 return 0;
2972 values[0] = device->FmtType;
2973 return 1;
2975 case ALC_AMBISONIC_LAYOUT_SOFT:
2976 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2978 alcSetError(device, ALC_INVALID_DEVICE);
2979 return 0;
2981 values[0] = static_cast<int>(device->mAmbiLayout);
2982 return 1;
2984 case ALC_AMBISONIC_SCALING_SOFT:
2985 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2987 alcSetError(device, ALC_INVALID_DEVICE);
2988 return 0;
2990 values[0] = static_cast<int>(device->mAmbiScale);
2991 return 1;
2993 case ALC_AMBISONIC_ORDER_SOFT:
2994 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2996 alcSetError(device, ALC_INVALID_DEVICE);
2997 return 0;
2999 values[0] = static_cast<int>(device->mAmbiOrder);
3000 return 1;
3002 case ALC_MONO_SOURCES:
3003 values[0] = static_cast<int>(device->NumMonoSources);
3004 return 1;
3006 case ALC_STEREO_SOURCES:
3007 values[0] = static_cast<int>(device->NumStereoSources);
3008 return 1;
3010 case ALC_MAX_AUXILIARY_SENDS:
3011 values[0] = static_cast<int>(device->NumAuxSends);
3012 return 1;
3014 case ALC_CONNECTED:
3016 std::lock_guard<std::mutex> _{device->StateLock};
3017 values[0] = device->Connected.load(std::memory_order_acquire);
3019 return 1;
3021 case ALC_HRTF_SOFT:
3022 values[0] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
3023 return 1;
3025 case ALC_HRTF_STATUS_SOFT:
3026 values[0] = device->HrtfStatus;
3027 return 1;
3029 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3031 std::lock_guard<std::mutex> _{device->StateLock};
3032 device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
3033 values[0] = static_cast<int>(minz(device->HrtfList.size(),
3034 std::numeric_limits<int>::max()));
3036 return 1;
3038 case ALC_OUTPUT_LIMITER_SOFT:
3039 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3040 return 1;
3042 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3043 values[0] = MAX_AMBI_ORDER;
3044 return 1;
3046 default:
3047 alcSetError(device, ALC_INVALID_ENUM);
3049 return 0;
3052 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3053 START_API_FUNC
3055 DeviceRef dev{VerifyDevice(device)};
3056 if(size <= 0 || values == nullptr)
3057 alcSetError(dev.get(), ALC_INVALID_VALUE);
3058 else
3059 GetIntegerv(dev.get(), param, {values, static_cast<ALuint>(size)});
3061 END_API_FUNC
3063 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3064 START_API_FUNC
3066 DeviceRef dev{VerifyDevice(device)};
3067 if(size <= 0 || values == nullptr)
3069 alcSetError(dev.get(), ALC_INVALID_VALUE);
3070 return;
3072 if(!dev || dev->Type == DeviceType::Capture)
3074 auto ivals = al::vector<int>(static_cast<ALuint>(size));
3075 size_t got{GetIntegerv(dev.get(), pname, ivals)};
3076 std::copy_n(ivals.begin(), got, values);
3077 return;
3079 /* render device */
3080 switch(pname)
3082 case ALC_ATTRIBUTES_SIZE:
3083 *values = NumAttrsForDevice(dev.get())+4;
3084 break;
3086 case ALC_ALL_ATTRIBUTES:
3087 if(size < NumAttrsForDevice(dev.get())+4)
3088 alcSetError(dev.get(), ALC_INVALID_VALUE);
3089 else
3091 size_t i{0};
3092 std::lock_guard<std::mutex> _{dev->StateLock};
3093 values[i++] = ALC_FREQUENCY;
3094 values[i++] = dev->Frequency;
3096 if(dev->Type != DeviceType::Loopback)
3098 values[i++] = ALC_REFRESH;
3099 values[i++] = dev->Frequency / dev->UpdateSize;
3101 values[i++] = ALC_SYNC;
3102 values[i++] = ALC_FALSE;
3104 else
3106 if(dev->FmtChans == DevFmtAmbi3D)
3108 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3109 values[i++] = static_cast<int64_t>(dev->mAmbiLayout);
3111 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3112 values[i++] = static_cast<int64_t>(dev->mAmbiScale);
3114 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3115 values[i++] = dev->mAmbiOrder;
3118 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3119 values[i++] = dev->FmtChans;
3121 values[i++] = ALC_FORMAT_TYPE_SOFT;
3122 values[i++] = dev->FmtType;
3125 values[i++] = ALC_MONO_SOURCES;
3126 values[i++] = dev->NumMonoSources;
3128 values[i++] = ALC_STEREO_SOURCES;
3129 values[i++] = dev->NumStereoSources;
3131 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3132 values[i++] = dev->NumAuxSends;
3134 values[i++] = ALC_HRTF_SOFT;
3135 values[i++] = (dev->mHrtf ? ALC_TRUE : ALC_FALSE);
3137 values[i++] = ALC_HRTF_STATUS_SOFT;
3138 values[i++] = dev->HrtfStatus;
3140 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3141 values[i++] = dev->Limiter ? ALC_TRUE : ALC_FALSE;
3143 ClockLatency clock{GetClockLatency(dev.get())};
3144 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3145 values[i++] = clock.ClockTime.count();
3147 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3148 values[i++] = clock.Latency.count();
3150 values[i++] = 0;
3152 break;
3154 case ALC_DEVICE_CLOCK_SOFT:
3156 std::lock_guard<std::mutex> _{dev->StateLock};
3157 ALuint samplecount, refcount;
3158 nanoseconds basecount;
3159 do {
3160 refcount = dev->waitForMix();
3161 basecount = dev->ClockBase;
3162 samplecount = dev->SamplesDone;
3163 } while(refcount != ReadRef(dev->MixCount));
3164 basecount += nanoseconds{seconds{samplecount}} / dev->Frequency;
3165 *values = basecount.count();
3167 break;
3169 case ALC_DEVICE_LATENCY_SOFT:
3171 std::lock_guard<std::mutex> _{dev->StateLock};
3172 ClockLatency clock{GetClockLatency(dev.get())};
3173 *values = clock.Latency.count();
3175 break;
3177 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3178 if(size < 2)
3179 alcSetError(dev.get(), ALC_INVALID_VALUE);
3180 else
3182 std::lock_guard<std::mutex> _{dev->StateLock};
3183 ClockLatency clock{GetClockLatency(dev.get())};
3184 values[0] = clock.ClockTime.count();
3185 values[1] = clock.Latency.count();
3187 break;
3189 default:
3190 auto ivals = al::vector<int>(static_cast<ALuint>(size));
3191 size_t got{GetIntegerv(dev.get(), pname, ivals)};
3192 std::copy_n(ivals.begin(), got, values);
3193 break;
3196 END_API_FUNC
3199 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3200 START_API_FUNC
3202 DeviceRef dev{VerifyDevice(device)};
3203 if(!extName)
3204 alcSetError(dev.get(), ALC_INVALID_VALUE);
3205 else
3207 size_t len = strlen(extName);
3208 const char *ptr = (dev ? alcExtensionList : alcNoDeviceExtList);
3209 while(ptr && *ptr)
3211 if(al::strncasecmp(ptr, extName, len) == 0 && (ptr[len] == '\0' || isspace(ptr[len])))
3212 return ALC_TRUE;
3214 if((ptr=strchr(ptr, ' ')) != nullptr)
3216 do {
3217 ++ptr;
3218 } while(isspace(*ptr));
3222 return ALC_FALSE;
3224 END_API_FUNC
3227 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3228 START_API_FUNC
3230 if(!funcName)
3232 DeviceRef dev{VerifyDevice(device)};
3233 alcSetError(dev.get(), ALC_INVALID_VALUE);
3235 else
3237 for(const auto &func : alcFunctions)
3239 if(strcmp(func.funcName, funcName) == 0)
3240 return func.address;
3243 return nullptr;
3245 END_API_FUNC
3248 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3249 START_API_FUNC
3251 if(!enumName)
3253 DeviceRef dev{VerifyDevice(device)};
3254 alcSetError(dev.get(), ALC_INVALID_VALUE);
3256 else
3258 for(const auto &enm : alcEnumerations)
3260 if(strcmp(enm.enumName, enumName) == 0)
3261 return enm.value;
3264 return 0;
3266 END_API_FUNC
3269 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3270 START_API_FUNC
3272 /* Explicitly hold the list lock while taking the StateLock in case the
3273 * device is asynchronously destroyed, to ensure this new context is
3274 * properly cleaned up after being made.
3276 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3277 DeviceRef dev{VerifyDevice(device)};
3278 if(!dev || dev->Type == DeviceType::Capture || !dev->Connected.load(std::memory_order_relaxed))
3280 listlock.unlock();
3281 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3282 return nullptr;
3284 std::unique_lock<std::mutex> statelock{dev->StateLock};
3285 listlock.unlock();
3287 dev->LastError.store(ALC_NO_ERROR);
3289 ALCenum err{UpdateDeviceParams(dev.get(), attrList)};
3290 if(err != ALC_NO_ERROR)
3292 alcSetError(dev.get(), err);
3293 return nullptr;
3296 ContextRef context{new ALCcontext{dev}};
3297 context->init();
3299 if(auto volopt = ConfigValueFloat(dev->DeviceName.c_str(), nullptr, "volume-adjust"))
3301 const float valf{*volopt};
3302 if(!std::isfinite(valf))
3303 ERR("volume-adjust must be finite: %f\n", valf);
3304 else
3306 const float db{clampf(valf, -24.0f, 24.0f)};
3307 if(db != valf)
3308 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3309 context->mGainBoost = std::pow(10.0f, db/20.0f);
3310 TRACE("volume-adjust gain: %f\n", context->mGainBoost);
3313 UpdateListenerProps(context.get());
3316 using ContextArray = al::FlexArray<ALCcontext*>;
3318 /* Allocate a new context array, which holds 1 more than the current/
3319 * old array.
3321 auto *oldarray = device->mContexts.load();
3322 const size_t newcount{oldarray->size()+1};
3323 std::unique_ptr<ContextArray> newarray{ContextArray::Create(newcount)};
3325 /* Copy the current/old context handles to the new array, appending the
3326 * new context.
3328 auto iter = std::copy(oldarray->begin(), oldarray->end(), newarray->begin());
3329 *iter = context.get();
3331 /* Store the new context array in the device. Wait for any current mix
3332 * to finish before deleting the old array.
3334 dev->mContexts.store(newarray.release());
3335 if(oldarray != &EmptyContextArray)
3337 dev->waitForMix();
3338 delete oldarray;
3341 statelock.unlock();
3344 std::lock_guard<std::recursive_mutex> _{ListLock};
3345 auto iter = std::lower_bound(ContextList.cbegin(), ContextList.cend(), context.get());
3346 ContextList.emplace(iter, context.get());
3349 if(ALeffectslot *slot{context->mDefaultSlot.get()})
3351 if(slot->initEffect(&DefaultEffect, context.get()) == AL_NO_ERROR)
3352 slot->updateProps(context.get());
3353 else
3354 ERR("Failed to initialize the default effect\n");
3357 TRACE("Created context %p\n", decltype(std::declval<void*>()){context.get()});
3358 return context.release();
3360 END_API_FUNC
3362 ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3363 START_API_FUNC
3365 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3366 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
3367 if(iter == ContextList.end() || *iter != context)
3369 listlock.unlock();
3370 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3371 return;
3373 /* Hold a reference to this context so it remains valid until the ListLock
3374 * is released.
3376 ContextRef ctx{*iter};
3377 ContextList.erase(iter);
3379 ALCdevice *Device{ctx->mDevice.get()};
3381 std::lock_guard<std::mutex> _{Device->StateLock};
3382 if(!ctx->deinit() && Device->Flags.get<DeviceRunning>())
3384 Device->Backend->stop();
3385 Device->Flags.unset<DeviceRunning>();
3388 END_API_FUNC
3391 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3392 START_API_FUNC
3394 ALCcontext *Context{LocalContext};
3395 if(!Context) Context = GlobalContext.load();
3396 return Context;
3398 END_API_FUNC
3400 /** Returns the currently active thread-local context. */
3401 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3402 START_API_FUNC
3403 { return LocalContext; }
3404 END_API_FUNC
3406 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3407 START_API_FUNC
3409 /* context must be valid or nullptr */
3410 ContextRef ctx;
3411 if(context)
3413 ctx = VerifyContext(context);
3414 if(!ctx)
3416 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3417 return ALC_FALSE;
3420 /* Release this reference (if any) to store it in the GlobalContext
3421 * pointer. Take ownership of the reference (if any) that was previously
3422 * stored there.
3424 ctx = ContextRef{GlobalContext.exchange(ctx.release())};
3426 /* Reset (decrement) the previous global reference by replacing it with the
3427 * thread-local context. Take ownership of the thread-local context
3428 * reference (if any), clearing the storage to null.
3430 ctx = ContextRef{LocalContext};
3431 if(ctx) ThreadContext.set(nullptr);
3432 /* Reset (decrement) the previous thread-local reference. */
3434 return ALC_TRUE;
3436 END_API_FUNC
3438 /** Makes the given context the active context for the current thread. */
3439 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3440 START_API_FUNC
3442 /* context must be valid or nullptr */
3443 ContextRef ctx;
3444 if(context)
3446 ctx = VerifyContext(context);
3447 if(!ctx)
3449 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3450 return ALC_FALSE;
3453 /* context's reference count is already incremented */
3454 ContextRef old{LocalContext};
3455 ThreadContext.set(ctx.release());
3457 return ALC_TRUE;
3459 END_API_FUNC
3462 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3463 START_API_FUNC
3465 ContextRef ctx{VerifyContext(Context)};
3466 if(!ctx)
3468 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3469 return nullptr;
3471 return ctx->mDevice.get();
3473 END_API_FUNC
3476 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3477 START_API_FUNC
3479 DO_INITCONFIG();
3481 if(!PlaybackFactory)
3483 alcSetError(nullptr, ALC_INVALID_VALUE);
3484 return nullptr;
3487 if(deviceName)
3489 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3490 #ifdef _WIN32
3491 /* Some old Windows apps hardcode these expecting OpenAL to use a
3492 * specific audio API, even when they're not enumerated. Creative's
3493 * router effectively ignores them too.
3495 || al::strcasecmp(deviceName, "DirectSound3D") == 0
3496 || al::strcasecmp(deviceName, "DirectSound") == 0
3497 || al::strcasecmp(deviceName, "MMSYSTEM") == 0
3498 #endif
3499 || al::strcasecmp(deviceName, "openal-soft") == 0)
3500 deviceName = nullptr;
3503 DeviceRef device{new ALCdevice{DeviceType::Playback}};
3505 /* Set output format */
3506 device->FmtChans = DevFmtChannelsDefault;
3507 device->FmtType = DevFmtTypeDefault;
3508 device->Frequency = DEFAULT_OUTPUT_RATE;
3509 device->UpdateSize = DEFAULT_UPDATE_SIZE;
3510 device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
3512 device->SourcesMax = 256;
3513 device->AuxiliaryEffectSlotMax = 64;
3514 device->NumAuxSends = DEFAULT_SENDS;
3516 try {
3517 auto backend = PlaybackFactory->createBackend(device.get(), BackendType::Playback);
3518 std::lock_guard<std::recursive_mutex> _{ListLock};
3519 backend->open(deviceName);
3520 device->Backend = std::move(backend);
3522 catch(al::backend_exception &e) {
3523 WARN("Failed to open playback device: %s\n", e.what());
3524 alcSetError(nullptr, e.errorCode());
3525 return nullptr;
3528 deviceName = device->DeviceName.c_str();
3529 if(auto chanopt = ConfigValueStr(deviceName, nullptr, "channels"))
3531 static const struct ChannelMap {
3532 const char name[16];
3533 DevFmtChannels chans;
3534 ALuint order;
3535 } chanlist[] = {
3536 { "mono", DevFmtMono, 0 },
3537 { "stereo", DevFmtStereo, 0 },
3538 { "quad", DevFmtQuad, 0 },
3539 { "surround51", DevFmtX51, 0 },
3540 { "surround61", DevFmtX61, 0 },
3541 { "surround71", DevFmtX71, 0 },
3542 { "surround51rear", DevFmtX51Rear, 0 },
3543 { "ambi1", DevFmtAmbi3D, 1 },
3544 { "ambi2", DevFmtAmbi3D, 2 },
3545 { "ambi3", DevFmtAmbi3D, 3 },
3548 const ALCchar *fmt{chanopt->c_str()};
3549 auto iter = std::find_if(std::begin(chanlist), std::end(chanlist),
3550 [fmt](const ChannelMap &entry) -> bool
3551 { return al::strcasecmp(entry.name, fmt) == 0; }
3553 if(iter == std::end(chanlist))
3554 ERR("Unsupported channels: %s\n", fmt);
3555 else
3557 device->FmtChans = iter->chans;
3558 device->mAmbiOrder = iter->order;
3559 device->Flags.set<ChannelsRequest>();
3562 if(auto typeopt = ConfigValueStr(deviceName, nullptr, "sample-type"))
3564 static const struct TypeMap {
3565 const char name[16];
3566 DevFmtType type;
3567 } typelist[] = {
3568 { "int8", DevFmtByte },
3569 { "uint8", DevFmtUByte },
3570 { "int16", DevFmtShort },
3571 { "uint16", DevFmtUShort },
3572 { "int32", DevFmtInt },
3573 { "uint32", DevFmtUInt },
3574 { "float32", DevFmtFloat },
3577 const ALCchar *fmt{typeopt->c_str()};
3578 auto iter = std::find_if(std::begin(typelist), std::end(typelist),
3579 [fmt](const TypeMap &entry) -> bool
3580 { return al::strcasecmp(entry.name, fmt) == 0; }
3582 if(iter == std::end(typelist))
3583 ERR("Unsupported sample-type: %s\n", fmt);
3584 else
3586 device->FmtType = iter->type;
3587 device->Flags.set<SampleTypeRequest>();
3591 if(ALuint freq{ConfigValueUInt(deviceName, nullptr, "frequency").value_or(0)})
3593 if(freq < MIN_OUTPUT_RATE || freq > MAX_OUTPUT_RATE)
3595 const ALuint newfreq{clampu(freq, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE)};
3596 ERR("%uhz request clamped to %uhz\n", freq, newfreq);
3597 freq = newfreq;
3599 const double scale{static_cast<double>(freq) / device->Frequency};
3600 device->UpdateSize = static_cast<ALuint>(device->UpdateSize*scale + 0.5);
3601 device->BufferSize = static_cast<ALuint>(device->BufferSize*scale + 0.5);
3602 device->Frequency = freq;
3603 device->Flags.set<FrequencyRequest>();
3606 if(auto persizeopt = ConfigValueUInt(deviceName, nullptr, "period_size"))
3607 device->UpdateSize = clampu(*persizeopt, 64, 8192);
3609 if(auto peropt = ConfigValueUInt(deviceName, nullptr, "periods"))
3610 device->BufferSize = device->UpdateSize * clampu(*peropt, 2, 16);
3611 else
3612 device->BufferSize = maxu(device->BufferSize, device->UpdateSize*2);
3614 if(auto srcsmax = ConfigValueUInt(deviceName, nullptr, "sources").value_or(0))
3615 device->SourcesMax = srcsmax;
3617 if(auto slotsmax = ConfigValueUInt(deviceName, nullptr, "slots").value_or(0))
3618 device->AuxiliaryEffectSlotMax = minu(slotsmax, INT_MAX);
3620 if(auto sendsopt = ConfigValueInt(deviceName, nullptr, "sends"))
3621 device->NumAuxSends = minu(DEFAULT_SENDS,
3622 static_cast<ALuint>(clampi(*sendsopt, 0, MAX_SENDS)));
3624 device->NumStereoSources = 1;
3625 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3627 if(auto ambiopt = ConfigValueStr(deviceName, nullptr, "ambi-format"))
3629 const ALCchar *fmt{ambiopt->c_str()};
3630 if(al::strcasecmp(fmt, "fuma") == 0)
3632 if(device->mAmbiOrder > 3)
3633 ERR("FuMa is incompatible with %d%s order ambisonics (up to third-order only)\n",
3634 device->mAmbiOrder,
3635 (((device->mAmbiOrder%100)/10) == 1) ? "th" :
3636 ((device->mAmbiOrder%10) == 1) ? "st" :
3637 ((device->mAmbiOrder%10) == 2) ? "nd" :
3638 ((device->mAmbiOrder%10) == 3) ? "rd" : "th");
3639 else
3641 device->mAmbiLayout = DevAmbiLayout::FuMa;
3642 device->mAmbiScale = DevAmbiScaling::FuMa;
3645 else if(al::strcasecmp(fmt, "ambix") == 0 || al::strcasecmp(fmt, "acn+sn3d") == 0)
3647 device->mAmbiLayout = DevAmbiLayout::ACN;
3648 device->mAmbiScale = DevAmbiScaling::SN3D;
3650 else if(al::strcasecmp(fmt, "acn+n3d") == 0)
3652 device->mAmbiLayout = DevAmbiLayout::ACN;
3653 device->mAmbiScale = DevAmbiScaling::N3D;
3655 else
3656 ERR("Unsupported ambi-format: %s\n", fmt);
3660 std::lock_guard<std::recursive_mutex> _{ListLock};
3661 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3662 DeviceList.emplace(iter, device.get());
3665 TRACE("Created device %p, \"%s\"\n", decltype(std::declval<void*>()){device.get()},
3666 device->DeviceName.c_str());
3667 return device.release();
3669 END_API_FUNC
3671 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3672 START_API_FUNC
3674 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3675 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3676 if(iter == DeviceList.end() || *iter != device)
3678 alcSetError(nullptr, ALC_INVALID_DEVICE);
3679 return ALC_FALSE;
3681 if((*iter)->Type == DeviceType::Capture)
3683 alcSetError(*iter, ALC_INVALID_DEVICE);
3684 return ALC_FALSE;
3687 /* Erase the device, and any remaining contexts left on it, from their
3688 * respective lists.
3690 DeviceRef dev{*iter};
3691 DeviceList.erase(iter);
3693 std::unique_lock<std::mutex> statelock{dev->StateLock};
3694 al::vector<ContextRef> orphanctxs;
3695 for(ALCcontext *ctx : *dev->mContexts.load())
3697 auto ctxiter = std::lower_bound(ContextList.begin(), ContextList.end(), ctx);
3698 if(ctxiter != ContextList.end() && *ctxiter == ctx)
3700 orphanctxs.emplace_back(ContextRef{*ctxiter});
3701 ContextList.erase(ctxiter);
3704 listlock.unlock();
3706 for(ContextRef &context : orphanctxs)
3708 WARN("Releasing orphaned context %p\n", decltype(std::declval<void*>()){context.get()});
3709 context->deinit();
3711 orphanctxs.clear();
3713 if(dev->Flags.get<DeviceRunning>())
3714 dev->Backend->stop();
3715 dev->Flags.unset<DeviceRunning>();
3717 return ALC_TRUE;
3719 END_API_FUNC
3722 /************************************************
3723 * ALC capture functions
3724 ************************************************/
3725 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3726 START_API_FUNC
3728 DO_INITCONFIG();
3730 if(!CaptureFactory)
3732 alcSetError(nullptr, ALC_INVALID_VALUE);
3733 return nullptr;
3736 if(samples <= 0)
3738 alcSetError(nullptr, ALC_INVALID_VALUE);
3739 return nullptr;
3742 if(deviceName)
3744 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3745 || al::strcasecmp(deviceName, "openal-soft") == 0)
3746 deviceName = nullptr;
3749 DeviceRef device{new ALCdevice{DeviceType::Capture}};
3751 auto decompfmt = DecomposeDevFormat(format);
3752 if(!decompfmt)
3754 alcSetError(nullptr, ALC_INVALID_ENUM);
3755 return nullptr;
3758 device->Frequency = frequency;
3759 device->FmtChans = decompfmt->chans;
3760 device->FmtType = decompfmt->type;
3761 device->Flags.set<FrequencyRequest, ChannelsRequest, SampleTypeRequest>();
3763 device->UpdateSize = static_cast<ALuint>(samples);
3764 device->BufferSize = static_cast<ALuint>(samples);
3766 try {
3767 TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n",
3768 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
3769 device->Frequency, device->UpdateSize, device->BufferSize);
3771 auto backend = CaptureFactory->createBackend(device.get(), BackendType::Capture);
3772 std::lock_guard<std::recursive_mutex> _{ListLock};
3773 backend->open(deviceName);
3774 device->Backend = std::move(backend);
3776 catch(al::backend_exception &e) {
3777 WARN("Failed to open capture device: %s\n", e.what());
3778 alcSetError(nullptr, e.errorCode());
3779 return nullptr;
3783 std::lock_guard<std::recursive_mutex> _{ListLock};
3784 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3785 DeviceList.emplace(iter, device.get());
3788 TRACE("Created capture device %p, \"%s\"\n", decltype(std::declval<void*>()){device.get()},
3789 device->DeviceName.c_str());
3790 return device.release();
3792 END_API_FUNC
3794 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3795 START_API_FUNC
3797 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3798 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3799 if(iter == DeviceList.end() || *iter != device)
3801 alcSetError(nullptr, ALC_INVALID_DEVICE);
3802 return ALC_FALSE;
3804 if((*iter)->Type != DeviceType::Capture)
3806 alcSetError(*iter, ALC_INVALID_DEVICE);
3807 return ALC_FALSE;
3810 DeviceRef dev{*iter};
3811 DeviceList.erase(iter);
3812 listlock.unlock();
3814 std::lock_guard<std::mutex> _{dev->StateLock};
3815 if(dev->Flags.get<DeviceRunning>())
3816 dev->Backend->stop();
3817 dev->Flags.unset<DeviceRunning>();
3819 return ALC_TRUE;
3821 END_API_FUNC
3823 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3824 START_API_FUNC
3826 DeviceRef dev{VerifyDevice(device)};
3827 if(!dev || dev->Type != DeviceType::Capture)
3829 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3830 return;
3833 std::lock_guard<std::mutex> _{dev->StateLock};
3834 if(!dev->Connected.load(std::memory_order_acquire))
3835 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3836 else if(!dev->Flags.get<DeviceRunning>())
3838 try {
3839 auto backend = dev->Backend.get();
3840 backend->start();
3841 dev->Flags.set<DeviceRunning>();
3843 catch(al::backend_exception& e) {
3844 dev->handleDisconnect("%s", e.what());
3845 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3849 END_API_FUNC
3851 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3852 START_API_FUNC
3854 DeviceRef dev{VerifyDevice(device)};
3855 if(!dev || dev->Type != DeviceType::Capture)
3856 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3857 else
3859 std::lock_guard<std::mutex> _{dev->StateLock};
3860 if(dev->Flags.get<DeviceRunning>())
3861 dev->Backend->stop();
3862 dev->Flags.unset<DeviceRunning>();
3865 END_API_FUNC
3867 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3868 START_API_FUNC
3870 DeviceRef dev{VerifyDevice(device)};
3871 if(!dev || dev->Type != DeviceType::Capture)
3873 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3874 return;
3877 if(samples < 0 || (samples > 0 && buffer == nullptr))
3879 alcSetError(dev.get(), ALC_INVALID_VALUE);
3880 return;
3882 if(samples < 1)
3883 return;
3885 std::lock_guard<std::mutex> _{dev->StateLock};
3886 BackendBase *backend{dev->Backend.get()};
3888 const auto usamples = static_cast<ALCuint>(samples);
3889 if(usamples > backend->availableSamples())
3891 alcSetError(dev.get(), ALC_INVALID_VALUE);
3892 return;
3895 auto *bbuffer = static_cast<al::byte*>(buffer);
3896 if(ALCenum err{backend->captureSamples(bbuffer, usamples)})
3897 alcSetError(dev.get(), err);
3899 END_API_FUNC
3902 /************************************************
3903 * ALC loopback functions
3904 ************************************************/
3906 /** Open a loopback device, for manual rendering. */
3907 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3908 START_API_FUNC
3910 DO_INITCONFIG();
3912 /* Make sure the device name, if specified, is us. */
3913 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3915 alcSetError(nullptr, ALC_INVALID_VALUE);
3916 return nullptr;
3919 DeviceRef device{new ALCdevice{DeviceType::Loopback}};
3921 device->SourcesMax = 256;
3922 device->AuxiliaryEffectSlotMax = 64;
3923 device->NumAuxSends = DEFAULT_SENDS;
3925 //Set output format
3926 device->BufferSize = 0;
3927 device->UpdateSize = 0;
3929 device->Frequency = DEFAULT_OUTPUT_RATE;
3930 device->FmtChans = DevFmtChannelsDefault;
3931 device->FmtType = DevFmtTypeDefault;
3933 if(auto srcsmax = ConfigValueUInt(nullptr, nullptr, "sources").value_or(0))
3934 device->SourcesMax = srcsmax;
3936 if(auto slotsmax = ConfigValueUInt(nullptr, nullptr, "slots").value_or(0))
3937 device->AuxiliaryEffectSlotMax = minu(slotsmax, INT_MAX);
3939 if(auto sendsopt = ConfigValueInt(nullptr, nullptr, "sends"))
3940 device->NumAuxSends = minu(DEFAULT_SENDS,
3941 static_cast<ALuint>(clampi(*sendsopt, 0, MAX_SENDS)));
3943 device->NumStereoSources = 1;
3944 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3946 try {
3947 auto backend = LoopbackBackendFactory::getFactory().createBackend(device.get(),
3948 BackendType::Playback);
3949 backend->open("Loopback");
3950 device->Backend = std::move(backend);
3952 catch(al::backend_exception &e) {
3953 WARN("Failed to open loopback device: %s\n", e.what());
3954 alcSetError(nullptr, e.errorCode());
3955 return nullptr;
3959 std::lock_guard<std::recursive_mutex> _{ListLock};
3960 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3961 DeviceList.emplace(iter, device.get());
3964 TRACE("Created loopback device %p\n", decltype(std::declval<void*>()){device.get()});
3965 return device.release();
3967 END_API_FUNC
3970 * Determines if the loopback device supports the given format for rendering.
3972 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3973 START_API_FUNC
3975 DeviceRef dev{VerifyDevice(device)};
3976 if(!dev || dev->Type != DeviceType::Loopback)
3977 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3978 else if(freq <= 0)
3979 alcSetError(dev.get(), ALC_INVALID_VALUE);
3980 else
3982 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE
3983 && freq <= MAX_OUTPUT_RATE)
3984 return ALC_TRUE;
3987 return ALC_FALSE;
3989 END_API_FUNC
3992 * Renders some samples into a buffer, using the format last set by the
3993 * attributes given to alcCreateContext.
3995 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3996 START_API_FUNC
3998 DeviceRef dev{VerifyDevice(device)};
3999 if(!dev || dev->Type != DeviceType::Loopback)
4000 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4001 else if(samples < 0 || (samples > 0 && buffer == nullptr))
4002 alcSetError(dev.get(), ALC_INVALID_VALUE);
4003 else
4004 dev->renderSamples(buffer, static_cast<ALuint>(samples), dev->channelsFromFmt());
4006 END_API_FUNC
4009 /************************************************
4010 * ALC DSP pause/resume functions
4011 ************************************************/
4013 /** Pause the DSP to stop audio processing. */
4014 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4015 START_API_FUNC
4017 DeviceRef dev{VerifyDevice(device)};
4018 if(!dev || dev->Type != DeviceType::Playback)
4019 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4020 else
4022 std::lock_guard<std::mutex> _{dev->StateLock};
4023 if(dev->Flags.get<DeviceRunning>())
4024 dev->Backend->stop();
4025 dev->Flags.unset<DeviceRunning>();
4026 dev->Flags.set<DevicePaused>();
4029 END_API_FUNC
4031 /** Resume the DSP to restart audio processing. */
4032 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4033 START_API_FUNC
4035 DeviceRef dev{VerifyDevice(device)};
4036 if(!dev || dev->Type != DeviceType::Playback)
4038 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4039 return;
4042 std::lock_guard<std::mutex> _{dev->StateLock};
4043 if(!dev->Flags.get<DevicePaused>())
4044 return;
4045 dev->Flags.unset<DevicePaused>();
4046 if(dev->mContexts.load()->empty())
4047 return;
4049 try {
4050 auto backend = dev->Backend.get();
4051 backend->start();
4052 dev->Flags.set<DeviceRunning>();
4054 catch(al::backend_exception& e) {
4055 dev->handleDisconnect("%s", e.what());
4056 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4059 END_API_FUNC
4062 /************************************************
4063 * ALC HRTF functions
4064 ************************************************/
4066 /** Gets a string parameter at the given index. */
4067 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4068 START_API_FUNC
4070 DeviceRef dev{VerifyDevice(device)};
4071 if(!dev || dev->Type == DeviceType::Capture)
4072 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4073 else switch(paramName)
4075 case ALC_HRTF_SPECIFIER_SOFT:
4076 if(index >= 0 && static_cast<size_t>(index) < dev->HrtfList.size())
4077 return dev->HrtfList[static_cast<ALuint>(index)].c_str();
4078 alcSetError(dev.get(), ALC_INVALID_VALUE);
4079 break;
4081 default:
4082 alcSetError(dev.get(), ALC_INVALID_ENUM);
4083 break;
4086 return nullptr;
4088 END_API_FUNC
4090 /** Resets the given device output, using the specified attribute list. */
4091 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4092 START_API_FUNC
4094 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4095 DeviceRef dev{VerifyDevice(device)};
4096 if(!dev || dev->Type == DeviceType::Capture)
4098 listlock.unlock();
4099 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4100 return ALC_FALSE;
4102 std::lock_guard<std::mutex> _{dev->StateLock};
4103 listlock.unlock();
4105 /* Force the backend to stop mixing first since we're resetting. Also reset
4106 * the connected state so lost devices can attempt recover.
4108 if(dev->Flags.get<DeviceRunning>())
4109 dev->Backend->stop();
4110 dev->Flags.unset<DeviceRunning>();
4111 if(!dev->Connected.load(std::memory_order_relaxed))
4113 /* Make sure disconnection is finished before continuing on. */
4114 dev->waitForMix();
4116 for(ALCcontext *ctx : *dev->mContexts.load(std::memory_order_acquire))
4118 /* Clear any pending voice changes and reallocate voices to get a
4119 * clean restart.
4121 std::lock_guard<std::mutex> __{ctx->mSourceLock};
4122 auto *vchg = ctx->mCurrentVoiceChange.load(std::memory_order_acquire);
4123 while(auto *next = vchg->mNext.load(std::memory_order_acquire))
4124 vchg = next;
4125 ctx->mCurrentVoiceChange.store(vchg, std::memory_order_release);
4127 ctx->mVoiceClusters.clear();
4128 ctx->allocVoices(std::max<size_t>(256,
4129 ctx->mActiveVoiceCount.load(std::memory_order_relaxed)));
4132 dev->Connected.store(true);
4135 ALCenum err{UpdateDeviceParams(dev.get(), attribs)};
4136 if LIKELY(err == ALC_NO_ERROR) return ALC_TRUE;
4138 alcSetError(dev.get(), err);
4139 return ALC_FALSE;
4141 END_API_FUNC