Add missing linear resampler to the option setting list
[openal-soft.git] / alc / alc.cpp
bloba870a565e37da1713ca75121b7d8786aa11bcf11
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_NUM_RESAMPLERS_SOFT),
781 DECL(AL_DEFAULT_RESAMPLER_SOFT),
782 DECL(AL_SOURCE_RESAMPLER_SOFT),
783 DECL(AL_RESAMPLER_NAME_SOFT),
785 DECL(AL_SOURCE_SPATIALIZE_SOFT),
786 DECL(AL_AUTO_SOFT),
788 DECL(AL_MAP_READ_BIT_SOFT),
789 DECL(AL_MAP_WRITE_BIT_SOFT),
790 DECL(AL_MAP_PERSISTENT_BIT_SOFT),
791 DECL(AL_PRESERVE_DATA_BIT_SOFT),
793 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT),
794 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT),
795 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT),
796 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT),
797 DECL(AL_EVENT_TYPE_DISCONNECTED_SOFT),
799 DECL(AL_DROP_UNMATCHED_SOFT),
800 DECL(AL_REMIX_UNMATCHED_SOFT),
802 DECL(AL_AMBISONIC_LAYOUT_SOFT),
803 DECL(AL_AMBISONIC_SCALING_SOFT),
804 DECL(AL_FUMA_SOFT),
805 DECL(AL_ACN_SOFT),
806 DECL(AL_SN3D_SOFT),
807 DECL(AL_N3D_SOFT),
809 DECL(AL_BUFFER_CALLBACK_FUNCTION_SOFT),
810 DECL(AL_BUFFER_CALLBACK_USER_PARAM_SOFT),
812 DECL(AL_UNPACK_AMBISONIC_ORDER_SOFT),
814 DECL(AL_EFFECT_CONVOLUTION_REVERB_SOFT),
815 DECL(AL_EFFECTSLOT_STATE_SOFT),
817 #undef DECL
819 constexpr ALCchar alcNoError[] = "No Error";
820 constexpr ALCchar alcErrInvalidDevice[] = "Invalid Device";
821 constexpr ALCchar alcErrInvalidContext[] = "Invalid Context";
822 constexpr ALCchar alcErrInvalidEnum[] = "Invalid Enum";
823 constexpr ALCchar alcErrInvalidValue[] = "Invalid Value";
824 constexpr ALCchar alcErrOutOfMemory[] = "Out of Memory";
827 /************************************************
828 * Global variables
829 ************************************************/
831 /* Enumerated device names */
832 constexpr ALCchar alcDefaultName[] = "OpenAL Soft\0";
834 std::string alcAllDevicesList;
835 std::string alcCaptureDeviceList;
837 /* Default is always the first in the list */
838 al::string alcDefaultAllDevicesSpecifier;
839 al::string alcCaptureDefaultDeviceSpecifier;
841 /* Default context extensions */
842 constexpr ALchar alExtList[] =
843 "AL_EXT_ALAW "
844 "AL_EXT_BFORMAT "
845 "AL_EXT_DOUBLE "
846 "AL_EXT_EXPONENT_DISTANCE "
847 "AL_EXT_FLOAT32 "
848 "AL_EXT_IMA4 "
849 "AL_EXT_LINEAR_DISTANCE "
850 "AL_EXT_MCFORMATS "
851 "AL_EXT_MULAW "
852 "AL_EXT_MULAW_BFORMAT "
853 "AL_EXT_MULAW_MCFORMATS "
854 "AL_EXT_OFFSET "
855 "AL_EXT_source_distance_model "
856 "AL_EXT_SOURCE_RADIUS "
857 "AL_EXT_STEREO_ANGLES "
858 "AL_LOKI_quadriphonic "
859 "AL_SOFT_bformat_ex "
860 "AL_SOFTX_bformat_hoa "
861 "AL_SOFT_block_alignment "
862 "AL_SOFTX_callback_buffer "
863 "AL_SOFTX_convolution_reverb "
864 "AL_SOFT_deferred_updates "
865 "AL_SOFT_direct_channels "
866 "AL_SOFT_direct_channels_remix "
867 "AL_SOFTX_effect_target "
868 "AL_SOFTX_events "
869 "AL_SOFTX_filter_gain_ex "
870 "AL_SOFT_gain_clamp_ex "
871 "AL_SOFT_loop_points "
872 "AL_SOFTX_map_buffer "
873 "AL_SOFT_MSADPCM "
874 "AL_SOFT_source_latency "
875 "AL_SOFT_source_length "
876 "AL_SOFT_source_resampler "
877 "AL_SOFT_source_spatialize";
879 std::atomic<ALCenum> LastNullDeviceError{ALC_NO_ERROR};
881 /* Thread-local current context. The handling may look a little obtuse, but
882 * it's designed this way to avoid a bug with 32-bit GCC/MinGW, which causes
883 * thread-local object destructors to get a junk 'this' pointer. This method
884 * has the benefit of making LocalContext access more efficient since it's a
885 * a plain pointer, with the ThreadContext object used to check it at thread
886 * exit (and given no data fields, 'this' being junk is inconsequential since
887 * it's never accessed).
889 thread_local ALCcontext *LocalContext{nullptr};
890 class ThreadCtx {
891 public:
892 ~ThreadCtx()
894 if(ALCcontext *ctx{LocalContext})
896 const bool result{ctx->releaseIfNoDelete()};
897 ERR("Context %p current for thread being destroyed%s!\n",
898 decltype(std::declval<void*>()){ctx}, result ? "" : ", leak detected");
902 void set(ALCcontext *ctx) const noexcept { LocalContext = ctx; }
904 thread_local ThreadCtx ThreadContext;
906 /* Process-wide current context */
907 std::atomic<ALCcontext*> GlobalContext{nullptr};
909 /* Flag to trap ALC device errors */
910 bool TrapALCError{false};
912 /* One-time configuration init control */
913 std::once_flag alc_config_once{};
915 /* Default effect that applies to sources that don't have an effect on send 0 */
916 ALeffect DefaultEffect;
918 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
919 * updates.
921 bool SuspendDefers{true};
923 /* Initial seed for dithering. */
924 constexpr ALuint DitherRNGSeed{22222u};
927 /************************************************
928 * ALC information
929 ************************************************/
930 constexpr ALCchar alcNoDeviceExtList[] =
931 "ALC_ENUMERATE_ALL_EXT "
932 "ALC_ENUMERATION_EXT "
933 "ALC_EXT_CAPTURE "
934 "ALC_EXT_thread_local_context "
935 "ALC_SOFT_loopback";
936 constexpr ALCchar alcExtensionList[] =
937 "ALC_ENUMERATE_ALL_EXT "
938 "ALC_ENUMERATION_EXT "
939 "ALC_EXT_CAPTURE "
940 "ALC_EXT_DEDICATED "
941 "ALC_EXT_disconnect "
942 "ALC_EXT_EFX "
943 "ALC_EXT_thread_local_context "
944 "ALC_SOFT_device_clock "
945 "ALC_SOFT_HRTF "
946 "ALC_SOFT_loopback "
947 "ALC_SOFT_output_limiter "
948 "ALC_SOFT_pause_device";
949 constexpr int alcMajorVersion{1};
950 constexpr int alcMinorVersion{1};
952 constexpr int alcEFXMajorVersion{1};
953 constexpr int alcEFXMinorVersion{0};
956 /* To avoid extraneous allocations, a 0-sized FlexArray<ALCcontext*> is defined
957 * globally as a sharable object.
959 al::FlexArray<ALCcontext*> EmptyContextArray{0u};
962 using DeviceRef = al::intrusive_ptr<ALCdevice>;
965 /************************************************
966 * Device lists
967 ************************************************/
968 al::vector<ALCdevice*> DeviceList;
969 al::vector<ALCcontext*> ContextList;
971 std::recursive_mutex ListLock;
974 void alc_initconfig(void)
976 if(auto loglevel = al::getenv("ALSOFT_LOGLEVEL"))
978 long lvl = strtol(loglevel->c_str(), nullptr, 0);
979 if(lvl >= NoLog && lvl <= LogRef)
980 gLogLevel = static_cast<LogLevel>(lvl);
983 #ifdef _WIN32
984 if(const auto logfile = al::getenv(L"ALSOFT_LOGFILE"))
986 FILE *logf{_wfopen(logfile->c_str(), L"wt")};
987 if(logf) gLogFile = logf;
988 else
990 auto u8name = wstr_to_utf8(logfile->c_str());
991 ERR("Failed to open log file '%s'\n", u8name.c_str());
994 #else
995 if(const auto logfile = al::getenv("ALSOFT_LOGFILE"))
997 FILE *logf{fopen(logfile->c_str(), "wt")};
998 if(logf) gLogFile = logf;
999 else ERR("Failed to open log file '%s'\n", logfile->c_str());
1001 #endif
1003 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION, ALSOFT_GIT_COMMIT_HASH,
1004 ALSOFT_GIT_BRANCH);
1006 al::string names;
1007 if(al::size(BackendList) < 1)
1008 names = "(none)";
1009 else
1011 const al::span<const BackendInfo> infos{BackendList};
1012 names = infos[0].name;
1013 for(const auto &backend : infos.subspan<1>())
1015 names += ", ";
1016 names += backend.name;
1019 TRACE("Supported backends: %s\n", names.c_str());
1021 ReadALConfig();
1023 if(auto suspendmode = al::getenv("__ALSOFT_SUSPEND_CONTEXT"))
1025 if(al::strcasecmp(suspendmode->c_str(), "ignore") == 0)
1027 SuspendDefers = false;
1028 TRACE("Selected context suspend behavior, \"ignore\"\n");
1030 else
1031 ERR("Unhandled context suspend behavior setting: \"%s\"\n", suspendmode->c_str());
1034 int capfilter{0};
1035 #if defined(HAVE_SSE4_1)
1036 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
1037 #elif defined(HAVE_SSE3)
1038 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
1039 #elif defined(HAVE_SSE2)
1040 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
1041 #elif defined(HAVE_SSE)
1042 capfilter |= CPU_CAP_SSE;
1043 #endif
1044 #ifdef HAVE_NEON
1045 capfilter |= CPU_CAP_NEON;
1046 #endif
1047 if(auto cpuopt = ConfigValueStr(nullptr, nullptr, "disable-cpu-exts"))
1049 const char *str{cpuopt->c_str()};
1050 if(al::strcasecmp(str, "all") == 0)
1051 capfilter = 0;
1052 else
1054 const char *next = str;
1055 do {
1056 str = next;
1057 while(isspace(str[0]))
1058 str++;
1059 next = strchr(str, ',');
1061 if(!str[0] || str[0] == ',')
1062 continue;
1064 size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1065 while(len > 0 && isspace(str[len-1]))
1066 len--;
1067 if(len == 3 && al::strncasecmp(str, "sse", len) == 0)
1068 capfilter &= ~CPU_CAP_SSE;
1069 else if(len == 4 && al::strncasecmp(str, "sse2", len) == 0)
1070 capfilter &= ~CPU_CAP_SSE2;
1071 else if(len == 4 && al::strncasecmp(str, "sse3", len) == 0)
1072 capfilter &= ~CPU_CAP_SSE3;
1073 else if(len == 6 && al::strncasecmp(str, "sse4.1", len) == 0)
1074 capfilter &= ~CPU_CAP_SSE4_1;
1075 else if(len == 4 && al::strncasecmp(str, "neon", len) == 0)
1076 capfilter &= ~CPU_CAP_NEON;
1077 else
1078 WARN("Invalid CPU extension \"%s\"\n", str);
1079 } while(next++);
1082 FillCPUCaps(capfilter);
1084 if(auto priopt = ConfigValueInt(nullptr, nullptr, "rt-prio"))
1085 RTPrioLevel = *priopt;
1087 aluInit();
1088 aluInitMixer();
1090 auto traperr = al::getenv("ALSOFT_TRAP_ERROR");
1091 if(traperr && (al::strcasecmp(traperr->c_str(), "true") == 0
1092 || std::strtol(traperr->c_str(), nullptr, 0) == 1))
1094 TrapALError = true;
1095 TrapALCError = true;
1097 else
1099 traperr = al::getenv("ALSOFT_TRAP_AL_ERROR");
1100 if(traperr)
1101 TrapALError = al::strcasecmp(traperr->c_str(), "true") == 0
1102 || strtol(traperr->c_str(), nullptr, 0) == 1;
1103 else
1104 TrapALError = !!GetConfigValueBool(nullptr, nullptr, "trap-al-error", false);
1106 traperr = al::getenv("ALSOFT_TRAP_ALC_ERROR");
1107 if(traperr)
1108 TrapALCError = al::strcasecmp(traperr->c_str(), "true") == 0
1109 || strtol(traperr->c_str(), nullptr, 0) == 1;
1110 else
1111 TrapALCError = !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", false);
1114 if(auto boostopt = ConfigValueFloat(nullptr, "reverb", "boost"))
1116 const float valf{std::isfinite(*boostopt) ? clampf(*boostopt, -24.0f, 24.0f) : 0.0f};
1117 ReverbBoost *= std::pow(10.0f, valf / 20.0f);
1120 auto BackendListEnd = std::end(BackendList);
1121 auto devopt = al::getenv("ALSOFT_DRIVERS");
1122 if(devopt || (devopt=ConfigValueStr(nullptr, nullptr, "drivers")))
1124 auto backendlist_cur = std::begin(BackendList);
1126 bool endlist{true};
1127 const char *next{devopt->c_str()};
1128 do {
1129 const char *devs{next};
1130 while(isspace(devs[0]))
1131 devs++;
1132 next = strchr(devs, ',');
1134 const bool delitem{devs[0] == '-'};
1135 if(devs[0] == '-') devs++;
1137 if(!devs[0] || devs[0] == ',')
1139 endlist = false;
1140 continue;
1142 endlist = true;
1144 size_t len{next ? (static_cast<size_t>(next-devs)) : strlen(devs)};
1145 while(len > 0 && isspace(devs[len-1])) --len;
1146 #ifdef HAVE_WASAPI
1147 /* HACK: For backwards compatibility, convert backend references of
1148 * mmdevapi to wasapi. This should eventually be removed.
1150 if(len == 8 && strncmp(devs, "mmdevapi", len) == 0)
1152 devs = "wasapi";
1153 len = 6;
1155 #endif
1157 auto find_backend = [devs,len](const BackendInfo &backend) -> bool
1158 { return len == strlen(backend.name) && strncmp(backend.name, devs, len) == 0; };
1159 auto this_backend = std::find_if(std::begin(BackendList), BackendListEnd,
1160 find_backend);
1162 if(this_backend == BackendListEnd)
1163 continue;
1165 if(delitem)
1166 BackendListEnd = std::move(this_backend+1, BackendListEnd, this_backend);
1167 else
1168 backendlist_cur = std::rotate(backendlist_cur, this_backend, this_backend+1);
1169 } while(next++);
1171 if(endlist)
1172 BackendListEnd = backendlist_cur;
1175 auto init_backend = [](BackendInfo &backend) -> void
1177 if(PlaybackFactory && CaptureFactory)
1178 return;
1180 BackendFactory &factory = backend.getFactory();
1181 if(!factory.init())
1183 WARN("Failed to initialize backend \"%s\"\n", backend.name);
1184 return;
1187 TRACE("Initialized backend \"%s\"\n", backend.name);
1188 if(!PlaybackFactory && factory.querySupport(BackendType::Playback))
1190 PlaybackFactory = &factory;
1191 TRACE("Added \"%s\" for playback\n", backend.name);
1193 if(!CaptureFactory && factory.querySupport(BackendType::Capture))
1195 CaptureFactory = &factory;
1196 TRACE("Added \"%s\" for capture\n", backend.name);
1199 std::for_each(std::begin(BackendList), BackendListEnd, init_backend);
1201 LoopbackBackendFactory::getFactory().init();
1203 if(!PlaybackFactory)
1204 WARN("No playback backend available!\n");
1205 if(!CaptureFactory)
1206 WARN("No capture backend available!\n");
1208 if(auto exclopt = ConfigValueStr(nullptr, nullptr, "excludefx"))
1210 const char *next{exclopt->c_str()};
1211 do {
1212 const char *str{next};
1213 next = strchr(str, ',');
1215 if(!str[0] || next == str)
1216 continue;
1218 size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1219 for(const EffectList &effectitem : gEffectList)
1221 if(len == strlen(effectitem.name) &&
1222 strncmp(effectitem.name, str, len) == 0)
1223 DisabledEffects[effectitem.type] = true;
1225 } while(next++);
1228 InitEffect(&DefaultEffect);
1229 auto defrevopt = al::getenv("ALSOFT_DEFAULT_REVERB");
1230 if(defrevopt || (defrevopt=ConfigValueStr(nullptr, nullptr, "default-reverb")))
1231 LoadReverbPreset(defrevopt->c_str(), &DefaultEffect);
1233 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1236 /************************************************
1237 * Device enumeration
1238 ************************************************/
1239 void ProbeAllDevicesList()
1241 DO_INITCONFIG();
1243 std::lock_guard<std::recursive_mutex> _{ListLock};
1244 if(!PlaybackFactory)
1245 decltype(alcAllDevicesList){}.swap(alcAllDevicesList);
1246 else
1248 std::string names{PlaybackFactory->probe(BackendType::Playback)};
1249 if(names.empty()) names += '\0';
1250 names.swap(alcAllDevicesList);
1253 void ProbeCaptureDeviceList()
1255 DO_INITCONFIG();
1257 std::lock_guard<std::recursive_mutex> _{ListLock};
1258 if(!CaptureFactory)
1259 decltype(alcCaptureDeviceList){}.swap(alcCaptureDeviceList);
1260 else
1262 std::string names{CaptureFactory->probe(BackendType::Capture)};
1263 if(names.empty()) names += '\0';
1264 names.swap(alcCaptureDeviceList);
1268 } // namespace
1270 /* Mixing thread piority level */
1271 int RTPrioLevel{1};
1273 FILE *gLogFile{stderr};
1274 #ifdef _DEBUG
1275 LogLevel gLogLevel{LogWarning};
1276 #else
1277 LogLevel gLogLevel{LogError};
1278 #endif
1280 /************************************************
1281 * Library initialization
1282 ************************************************/
1283 #if defined(_WIN32) && !defined(AL_LIBTYPE_STATIC)
1284 BOOL APIENTRY DllMain(HINSTANCE module, DWORD reason, LPVOID /*reserved*/)
1286 switch(reason)
1288 case DLL_PROCESS_ATTACH:
1289 /* Pin the DLL so we won't get unloaded until the process terminates */
1290 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
1291 reinterpret_cast<WCHAR*>(module), &module);
1292 break;
1294 return TRUE;
1296 #endif
1298 /************************************************
1299 * Device format information
1300 ************************************************/
1301 const ALCchar *DevFmtTypeString(DevFmtType type) noexcept
1303 switch(type)
1305 case DevFmtByte: return "Int8";
1306 case DevFmtUByte: return "UInt8";
1307 case DevFmtShort: return "Int16";
1308 case DevFmtUShort: return "UInt16";
1309 case DevFmtInt: return "Int32";
1310 case DevFmtUInt: return "UInt32";
1311 case DevFmtFloat: return "Float32";
1313 return "(unknown type)";
1315 const ALCchar *DevFmtChannelsString(DevFmtChannels chans) noexcept
1317 switch(chans)
1319 case DevFmtMono: return "Mono";
1320 case DevFmtStereo: return "Stereo";
1321 case DevFmtQuad: return "Quadraphonic";
1322 case DevFmtX51: return "5.1 Surround";
1323 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1324 case DevFmtX61: return "6.1 Surround";
1325 case DevFmtX71: return "7.1 Surround";
1326 case DevFmtAmbi3D: return "Ambisonic 3D";
1328 return "(unknown channels)";
1331 ALuint BytesFromDevFmt(DevFmtType type) noexcept
1333 switch(type)
1335 case DevFmtByte: return sizeof(int8_t);
1336 case DevFmtUByte: return sizeof(uint8_t);
1337 case DevFmtShort: return sizeof(int16_t);
1338 case DevFmtUShort: return sizeof(uint16_t);
1339 case DevFmtInt: return sizeof(int32_t);
1340 case DevFmtUInt: return sizeof(uint32_t);
1341 case DevFmtFloat: return sizeof(float);
1343 return 0;
1345 ALuint ChannelsFromDevFmt(DevFmtChannels chans, ALuint ambiorder) noexcept
1347 switch(chans)
1349 case DevFmtMono: return 1;
1350 case DevFmtStereo: return 2;
1351 case DevFmtQuad: return 4;
1352 case DevFmtX51: return 6;
1353 case DevFmtX51Rear: return 6;
1354 case DevFmtX61: return 7;
1355 case DevFmtX71: return 8;
1356 case DevFmtAmbi3D: return (ambiorder+1) * (ambiorder+1);
1358 return 0;
1361 namespace {
1363 struct DevFmtPair { DevFmtChannels chans; DevFmtType type; };
1364 al::optional<DevFmtPair> DecomposeDevFormat(ALenum format)
1366 static const struct {
1367 ALenum format;
1368 DevFmtChannels channels;
1369 DevFmtType type;
1370 } list[] = {
1371 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1372 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1373 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1375 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1376 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1377 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1379 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1380 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1381 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1383 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1384 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1385 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1387 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1388 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1389 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1391 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1392 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1393 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1396 for(const auto &item : list)
1398 if(item.format == format)
1399 return al::make_optional(DevFmtPair{item.channels, item.type});
1402 return al::nullopt;
1405 bool IsValidALCType(ALCenum type)
1407 switch(type)
1409 case ALC_BYTE_SOFT:
1410 case ALC_UNSIGNED_BYTE_SOFT:
1411 case ALC_SHORT_SOFT:
1412 case ALC_UNSIGNED_SHORT_SOFT:
1413 case ALC_INT_SOFT:
1414 case ALC_UNSIGNED_INT_SOFT:
1415 case ALC_FLOAT_SOFT:
1416 return true;
1418 return false;
1421 bool IsValidALCChannels(ALCenum channels)
1423 switch(channels)
1425 case ALC_MONO_SOFT:
1426 case ALC_STEREO_SOFT:
1427 case ALC_QUAD_SOFT:
1428 case ALC_5POINT1_SOFT:
1429 case ALC_6POINT1_SOFT:
1430 case ALC_7POINT1_SOFT:
1431 case ALC_BFORMAT3D_SOFT:
1432 return true;
1434 return false;
1437 bool IsValidAmbiLayout(ALCenum layout)
1439 switch(layout)
1441 case ALC_ACN_SOFT:
1442 case ALC_FUMA_SOFT:
1443 return true;
1445 return false;
1448 bool IsValidAmbiScaling(ALCenum scaling)
1450 switch(scaling)
1452 case ALC_N3D_SOFT:
1453 case ALC_SN3D_SOFT:
1454 case ALC_FUMA_SOFT:
1455 return true;
1457 return false;
1461 /* Downmixing channel arrays, to map the given format's missing channels to
1462 * existing ones. Based on Wine's DSound downmix values, which are based on
1463 * PulseAudio's.
1465 const std::array<InputRemixMap,7> MonoDownmix{{
1466 { FrontLeft, {{{FrontCenter, 0.5f}, {LFE, 0.0f}}} },
1467 { FrontRight, {{{FrontCenter, 0.5f}, {LFE, 0.0f}}} },
1468 { SideLeft, {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1469 { SideRight, {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1470 { BackLeft, {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1471 { BackRight, {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1472 { BackCenter, {{{FrontCenter, 1.0f/9.0f}, {LFE, 0.0f}}} },
1474 const std::array<InputRemixMap,6> StereoDownmix{{
1475 { FrontCenter, {{{FrontLeft, 0.5f}, {FrontRight, 0.5f}}} },
1476 { SideLeft, {{{FrontLeft, 1.0f/9.0f}, {FrontRight, 0.0f}}} },
1477 { SideRight, {{{FrontLeft, 0.0f}, {FrontRight, 1.0f/9.0f}}} },
1478 { BackLeft, {{{FrontLeft, 1.0f/9.0f}, {FrontRight, 0.0f}}} },
1479 { BackRight, {{{FrontLeft, 0.0f}, {FrontRight, 1.0f/9.0f}}} },
1480 { BackCenter, {{{FrontLeft, 0.5f/9.0f}, {FrontRight, 0.5f/9.0f}}} },
1482 const std::array<InputRemixMap,4> QuadDownmix{{
1483 { FrontCenter, {{{FrontLeft, 0.5f}, {FrontRight, 0.5f}}} },
1484 { SideLeft, {{{FrontLeft, 0.5f}, {BackLeft, 0.5f}}} },
1485 { SideRight, {{{FrontRight, 0.5f}, {BackRight, 0.5f}}} },
1486 { BackCenter, {{{BackLeft, 0.5f}, {BackRight, 0.5f}}} },
1488 const std::array<InputRemixMap,3> X51Downmix{{
1489 { BackLeft, {{{SideLeft, 1.0f}, {SideRight, 0.0f}}} },
1490 { BackRight, {{{SideLeft, 0.0f}, {SideRight, 1.0f}}} },
1491 { BackCenter, {{{SideLeft, 0.5f}, {SideRight, 0.5f}}} },
1493 const std::array<InputRemixMap,3> X51RearDownmix{{
1494 { SideLeft, {{{BackLeft, 1.0f}, {BackRight, 0.0f}}} },
1495 { SideRight, {{{BackLeft, 0.0f}, {BackRight, 1.0f}}} },
1496 { BackCenter, {{{BackLeft, 0.5f}, {BackRight, 0.5f}}} },
1498 const std::array<InputRemixMap,2> X61Downmix{{
1499 { BackLeft, {{{BackCenter, 0.5f}, {SideLeft, 0.5f}}} },
1500 { BackRight, {{{BackCenter, 0.5f}, {SideRight, 0.5f}}} },
1502 const std::array<InputRemixMap,1> X71Downmix{{
1503 { BackCenter, {{{BackLeft, 0.5f}, {BackRight, 0.5f}}} },
1506 } // namespace
1508 /************************************************
1509 * Miscellaneous ALC helpers
1510 ************************************************/
1512 void ALCcontext::processUpdates()
1514 std::lock_guard<std::mutex> _{mPropLock};
1515 if(mDeferUpdates.exchange(false, std::memory_order_acq_rel))
1517 /* Tell the mixer to stop applying updates, then wait for any active
1518 * updating to finish, before providing updates.
1520 mHoldUpdates.store(true, std::memory_order_release);
1521 while((mUpdateCount.load(std::memory_order_acquire)&1) != 0) {
1522 /* busy-wait */
1525 if(!mPropsClean.test_and_set(std::memory_order_acq_rel))
1526 UpdateContextProps(this);
1527 if(!mListener.PropsClean.test_and_set(std::memory_order_acq_rel))
1528 UpdateListenerProps(this);
1529 UpdateAllEffectSlotProps(this);
1530 UpdateAllSourceProps(this);
1532 /* Now with all updates declared, let the mixer continue applying them
1533 * so they all happen at once.
1535 mHoldUpdates.store(false, std::memory_order_release);
1540 void ALCcontext::allocVoiceChanges(size_t addcount)
1542 constexpr size_t clustersize{128};
1543 /* Convert element count to cluster count. */
1544 addcount = (addcount+(clustersize-1)) / clustersize;
1545 while(addcount)
1547 VoiceChangeCluster cluster{std::make_unique<VoiceChange[]>(clustersize)};
1548 for(size_t i{1};i < clustersize;++i)
1549 cluster[i-1].mNext.store(std::addressof(cluster[i]), std::memory_order_relaxed);
1550 cluster[clustersize-1].mNext.store(mVoiceChangeTail, std::memory_order_relaxed);
1551 mVoiceChangeClusters.emplace_back(std::move(cluster));
1552 mVoiceChangeTail = mVoiceChangeClusters.back().get();
1553 --addcount;
1557 void ALCcontext::allocVoices(size_t addcount)
1559 constexpr size_t clustersize{32};
1560 /* Convert element count to cluster count. */
1561 addcount = (addcount+(clustersize-1)) / clustersize;
1563 if(addcount >= std::numeric_limits<int>::max()/clustersize - mVoiceClusters.size())
1564 throw std::runtime_error{"Allocating too many voices"};
1565 const size_t totalcount{(mVoiceClusters.size()+addcount) * clustersize};
1566 TRACE("Increasing allocated voices to %zu\n", totalcount);
1568 auto newarray = VoiceArray::Create(totalcount);
1569 while(addcount)
1571 mVoiceClusters.emplace_back(std::make_unique<Voice[]>(clustersize));
1572 --addcount;
1575 auto voice_iter = newarray->begin();
1576 for(VoiceCluster &cluster : mVoiceClusters)
1578 for(size_t i{0};i < clustersize;++i)
1579 *(voice_iter++) = &cluster[i];
1582 if(auto *oldvoices = mVoices.exchange(newarray.release(), std::memory_order_acq_rel))
1584 mDevice->waitForMix();
1585 delete oldvoices;
1590 /** Stores the latest ALC device error. */
1591 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1593 WARN("Error generated on device %p, code 0x%04x\n", decltype(std::declval<void*>()){device},
1594 errorCode);
1595 if(TrapALCError)
1597 #ifdef _WIN32
1598 /* DebugBreak() will cause an exception if there is no debugger */
1599 if(IsDebuggerPresent())
1600 DebugBreak();
1601 #elif defined(SIGTRAP)
1602 raise(SIGTRAP);
1603 #endif
1606 if(device)
1607 device->LastError.store(errorCode);
1608 else
1609 LastNullDeviceError.store(errorCode);
1613 static std::unique_ptr<Compressor> CreateDeviceLimiter(const ALCdevice *device, const float threshold)
1615 constexpr bool AutoKnee{true};
1616 constexpr bool AutoAttack{true};
1617 constexpr bool AutoRelease{true};
1618 constexpr bool AutoPostGain{true};
1619 constexpr bool AutoDeclip{true};
1620 constexpr float LookAheadTime{0.001f};
1621 constexpr float HoldTime{0.002f};
1622 constexpr float PreGainDb{0.0f};
1623 constexpr float PostGainDb{0.0f};
1624 constexpr float Ratio{std::numeric_limits<float>::infinity()};
1625 constexpr float KneeDb{0.0f};
1626 constexpr float AttackTime{0.02f};
1627 constexpr float ReleaseTime{0.2f};
1629 return Compressor::Create(device->RealOut.Buffer.size(), static_cast<float>(device->Frequency),
1630 AutoKnee, AutoAttack, AutoRelease, AutoPostGain, AutoDeclip, LookAheadTime, HoldTime,
1631 PreGainDb, PostGainDb, threshold, Ratio, KneeDb, AttackTime, ReleaseTime);
1635 * Updates the device's base clock time with however many samples have been
1636 * done. This is used so frequency changes on the device don't cause the time
1637 * to jump forward or back. Must not be called while the device is running/
1638 * mixing.
1640 static inline void UpdateClockBase(ALCdevice *device)
1642 IncrementRef(device->MixCount);
1643 device->ClockBase += nanoseconds{seconds{device->SamplesDone}} / device->Frequency;
1644 device->SamplesDone = 0;
1645 IncrementRef(device->MixCount);
1649 * Updates device parameters according to the attribute list (caller is
1650 * responsible for holding the list lock).
1652 static ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
1654 HrtfRequestMode hrtf_userreq{Hrtf_Default};
1655 HrtfRequestMode hrtf_appreq{Hrtf_Default};
1656 ALCenum gainLimiter{device->LimiterState};
1657 ALCuint new_sends{device->NumAuxSends};
1658 DevFmtChannels oldChans;
1659 DevFmtType oldType;
1660 ALCsizei hrtf_id{-1};
1661 ALCuint oldFreq;
1663 if((!attrList || !attrList[0]) && device->Type == DeviceType::Loopback)
1665 WARN("Missing attributes for loopback device\n");
1666 return ALC_INVALID_VALUE;
1669 // Check for attributes
1670 if(attrList && attrList[0])
1672 ALCenum alayout{AL_NONE};
1673 ALCenum ascale{AL_NONE};
1674 ALCenum schans{AL_NONE};
1675 ALCenum stype{AL_NONE};
1676 ALCsizei attrIdx{0};
1677 ALCuint aorder{0};
1678 ALCuint freq{0u};
1680 ALuint numMono{device->NumMonoSources};
1681 ALuint numStereo{device->NumStereoSources};
1682 ALuint numSends{device->NumAuxSends};
1684 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1685 while(attrList[attrIdx])
1687 switch(attrList[attrIdx])
1689 case ALC_FORMAT_CHANNELS_SOFT:
1690 schans = attrList[attrIdx + 1];
1691 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1692 break;
1694 case ALC_FORMAT_TYPE_SOFT:
1695 stype = attrList[attrIdx + 1];
1696 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1697 break;
1699 case ALC_FREQUENCY:
1700 freq = static_cast<ALuint>(attrList[attrIdx + 1]);
1701 TRACE_ATTR(ALC_FREQUENCY, freq);
1702 break;
1704 case ALC_AMBISONIC_LAYOUT_SOFT:
1705 alayout = attrList[attrIdx + 1];
1706 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1707 break;
1709 case ALC_AMBISONIC_SCALING_SOFT:
1710 ascale = attrList[attrIdx + 1];
1711 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1712 break;
1714 case ALC_AMBISONIC_ORDER_SOFT:
1715 aorder = static_cast<ALuint>(attrList[attrIdx + 1]);
1716 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1717 break;
1719 case ALC_MONO_SOURCES:
1720 numMono = static_cast<ALuint>(attrList[attrIdx + 1]);
1721 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1722 if(numMono > INT_MAX) numMono = 0;
1723 break;
1725 case ALC_STEREO_SOURCES:
1726 numStereo = static_cast<ALuint>(attrList[attrIdx + 1]);
1727 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1728 if(numStereo > INT_MAX) numStereo = 0;
1729 break;
1731 case ALC_MAX_AUXILIARY_SENDS:
1732 numSends = static_cast<ALuint>(attrList[attrIdx + 1]);
1733 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1734 if(numSends > INT_MAX) numSends = 0;
1735 else numSends = minu(numSends, MAX_SENDS);
1736 break;
1738 case ALC_HRTF_SOFT:
1739 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1740 if(attrList[attrIdx + 1] == ALC_FALSE)
1741 hrtf_appreq = Hrtf_Disable;
1742 else if(attrList[attrIdx + 1] == ALC_TRUE)
1743 hrtf_appreq = Hrtf_Enable;
1744 else
1745 hrtf_appreq = Hrtf_Default;
1746 break;
1748 case ALC_HRTF_ID_SOFT:
1749 hrtf_id = attrList[attrIdx + 1];
1750 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1751 break;
1753 case ALC_OUTPUT_LIMITER_SOFT:
1754 gainLimiter = attrList[attrIdx + 1];
1755 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1756 break;
1758 default:
1759 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1760 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1761 break;
1764 attrIdx += 2;
1766 #undef TRACE_ATTR
1768 const bool loopback{device->Type == DeviceType::Loopback};
1769 if(loopback)
1771 if(!schans || !stype || !freq)
1773 WARN("Missing format for loopback device\n");
1774 return ALC_INVALID_VALUE;
1776 if(!IsValidALCChannels(schans) || !IsValidALCType(stype) || freq < MIN_OUTPUT_RATE
1777 || freq > MAX_OUTPUT_RATE)
1778 return ALC_INVALID_VALUE;
1779 if(schans == ALC_BFORMAT3D_SOFT)
1781 if(!alayout || !ascale || !aorder)
1783 WARN("Missing ambisonic info for loopback device\n");
1784 return ALC_INVALID_VALUE;
1786 if(!IsValidAmbiLayout(alayout) || !IsValidAmbiScaling(ascale))
1787 return ALC_INVALID_VALUE;
1788 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1789 return ALC_INVALID_VALUE;
1790 if((alayout == ALC_FUMA_SOFT || ascale == ALC_FUMA_SOFT) && aorder > 3)
1791 return ALC_INVALID_VALUE;
1795 /* If a context is already running on the device, stop playback so the
1796 * device attributes can be updated.
1798 if(device->Flags.get<DeviceRunning>())
1799 device->Backend->stop();
1800 device->Flags.unset<DeviceRunning>();
1802 UpdateClockBase(device);
1804 const char *devname{nullptr};
1805 if(!loopback)
1807 devname = device->DeviceName.c_str();
1809 device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
1810 device->UpdateSize = DEFAULT_UPDATE_SIZE;
1811 device->Frequency = DEFAULT_OUTPUT_RATE;
1813 freq = ConfigValueUInt(devname, nullptr, "frequency").value_or(freq);
1814 if(freq < 1)
1815 device->Flags.unset<FrequencyRequest>();
1816 else
1818 freq = clampu(freq, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE);
1820 const double scale{static_cast<double>(freq) / device->Frequency};
1821 device->UpdateSize = static_cast<ALuint>(device->UpdateSize*scale + 0.5);
1822 device->BufferSize = static_cast<ALuint>(device->BufferSize*scale + 0.5);
1824 device->Frequency = freq;
1825 device->Flags.set<FrequencyRequest>();
1828 if(auto persizeopt = ConfigValueUInt(devname, nullptr, "period_size"))
1829 device->UpdateSize = clampu(*persizeopt, 64, 8192);
1831 if(auto peropt = ConfigValueUInt(devname, nullptr, "periods"))
1832 device->BufferSize = device->UpdateSize * clampu(*peropt, 2, 16);
1833 else
1834 device->BufferSize = maxu(device->BufferSize, device->UpdateSize*2);
1836 else
1838 device->Frequency = freq;
1839 device->FmtChans = static_cast<DevFmtChannels>(schans);
1840 device->FmtType = static_cast<DevFmtType>(stype);
1841 if(schans == ALC_BFORMAT3D_SOFT)
1843 device->mAmbiOrder = aorder;
1844 device->mAmbiLayout = static_cast<DevAmbiLayout>(alayout);
1845 device->mAmbiScale = static_cast<DevAmbiScaling>(ascale);
1849 if(numMono > INT_MAX-numStereo)
1850 numMono = INT_MAX-numStereo;
1851 numMono += numStereo;
1852 if(auto srcsopt = ConfigValueUInt(devname, nullptr, "sources"))
1854 if(*srcsopt <= 0) numMono = 256;
1855 else numMono = *srcsopt;
1857 else
1858 numMono = maxu(numMono, 256);
1859 numStereo = minu(numStereo, numMono);
1860 numMono -= numStereo;
1861 device->SourcesMax = numMono + numStereo;
1863 device->NumMonoSources = numMono;
1864 device->NumStereoSources = numStereo;
1866 if(auto sendsopt = ConfigValueInt(devname, nullptr, "sends"))
1867 new_sends = minu(numSends, static_cast<ALuint>(clampi(*sendsopt, 0, MAX_SENDS)));
1868 else
1869 new_sends = numSends;
1872 if(device->Flags.get<DeviceRunning>())
1873 return ALC_NO_ERROR;
1875 device->AvgSpeakerDist = 0.0f;
1876 device->Uhj_Encoder = nullptr;
1877 device->AmbiDecoder = nullptr;
1878 device->Bs2b = nullptr;
1879 device->PostProcess = nullptr;
1881 device->Limiter = nullptr;
1882 device->ChannelDelay.clear();
1884 std::fill(std::begin(device->HrtfAccumData), std::end(device->HrtfAccumData), float2{});
1886 device->Dry.AmbiMap.fill(BFChannelConfig{});
1887 device->Dry.Buffer = {};
1888 std::fill(std::begin(device->NumChannelsPerOrder), std::end(device->NumChannelsPerOrder), 0u);
1889 device->RealOut.RemixMap = {};
1890 device->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
1891 device->RealOut.Buffer = {};
1892 device->MixBuffer.clear();
1893 device->MixBuffer.shrink_to_fit();
1895 UpdateClockBase(device);
1896 device->FixedLatency = nanoseconds::zero();
1898 device->DitherDepth = 0.0f;
1899 device->DitherSeed = DitherRNGSeed;
1901 /*************************************************************************
1902 * Update device format request if HRTF is requested
1904 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
1905 if(device->Type != DeviceType::Loopback)
1907 if(auto hrtfopt = ConfigValueStr(device->DeviceName.c_str(), nullptr, "hrtf"))
1909 const char *hrtf{hrtfopt->c_str()};
1910 if(al::strcasecmp(hrtf, "true") == 0)
1911 hrtf_userreq = Hrtf_Enable;
1912 else if(al::strcasecmp(hrtf, "false") == 0)
1913 hrtf_userreq = Hrtf_Disable;
1914 else if(al::strcasecmp(hrtf, "auto") != 0)
1915 ERR("Unexpected hrtf value: %s\n", hrtf);
1918 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
1920 device->FmtChans = DevFmtStereo;
1921 device->Flags.set<ChannelsRequest>();
1925 oldFreq = device->Frequency;
1926 oldChans = device->FmtChans;
1927 oldType = device->FmtType;
1929 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u / %u buffer\n",
1930 device->Flags.get<ChannelsRequest>()?"*":"", DevFmtChannelsString(device->FmtChans),
1931 device->Flags.get<SampleTypeRequest>()?"*":"", DevFmtTypeString(device->FmtType),
1932 device->Flags.get<FrequencyRequest>()?"*":"", device->Frequency,
1933 device->UpdateSize, device->BufferSize);
1935 try {
1936 auto backend = device->Backend.get();
1937 if(!backend->reset())
1938 throw al::backend_exception{ALC_INVALID_DEVICE, "Device reset failure"};
1940 catch(std::exception &e) {
1941 device->handleDisconnect("%s", e.what());
1942 return ALC_INVALID_DEVICE;
1945 if(device->FmtChans != oldChans && device->Flags.get<ChannelsRequest>())
1947 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1948 DevFmtChannelsString(device->FmtChans));
1949 device->Flags.unset<ChannelsRequest>();
1951 if(device->FmtType != oldType && device->Flags.get<SampleTypeRequest>())
1953 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1954 DevFmtTypeString(device->FmtType));
1955 device->Flags.unset<SampleTypeRequest>();
1957 if(device->Frequency != oldFreq && device->Flags.get<FrequencyRequest>())
1959 WARN("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1960 device->Flags.unset<FrequencyRequest>();
1963 TRACE("Post-reset: %s, %s, %uhz, %u / %u buffer\n",
1964 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
1965 device->Frequency, device->UpdateSize, device->BufferSize);
1967 switch(device->FmtChans)
1969 case DevFmtMono: device->RealOut.RemixMap = MonoDownmix; break;
1970 case DevFmtStereo: device->RealOut.RemixMap = StereoDownmix; break;
1971 case DevFmtQuad: device->RealOut.RemixMap = QuadDownmix; break;
1972 case DevFmtX51: device->RealOut.RemixMap = X51Downmix; break;
1973 case DevFmtX51Rear: device->RealOut.RemixMap = X51RearDownmix; break;
1974 case DevFmtX61: device->RealOut.RemixMap = X61Downmix; break;
1975 case DevFmtX71: device->RealOut.RemixMap = X71Downmix; break;
1976 case DevFmtAmbi3D: break;
1979 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
1981 device->NumAuxSends = new_sends;
1982 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
1983 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
1984 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
1986 nanoseconds::rep sample_delay{0};
1987 if(device->Uhj_Encoder)
1988 sample_delay += Uhj2Encoder::sFilterSize;
1989 if(device->mHrtfState)
1990 sample_delay += HRTF_DIRECT_DELAY;
1991 if(auto *ambidec = device->AmbiDecoder.get())
1993 if(ambidec->hasStablizer())
1994 sample_delay += FrontStablizer::DelayLength;
1997 if(GetConfigValueBool(device->DeviceName.c_str(), nullptr, "dither", 1))
1999 int depth{ConfigValueInt(device->DeviceName.c_str(), nullptr, "dither-depth").value_or(0)};
2000 if(depth <= 0)
2002 switch(device->FmtType)
2004 case DevFmtByte:
2005 case DevFmtUByte:
2006 depth = 8;
2007 break;
2008 case DevFmtShort:
2009 case DevFmtUShort:
2010 depth = 16;
2011 break;
2012 case DevFmtInt:
2013 case DevFmtUInt:
2014 case DevFmtFloat:
2015 break;
2019 if(depth > 0)
2021 depth = clampi(depth, 2, 24);
2022 device->DitherDepth = std::pow(2.0f, static_cast<float>(depth-1));
2025 if(!(device->DitherDepth > 0.0f))
2026 TRACE("Dithering disabled\n");
2027 else
2028 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device->DitherDepth)+0.5f)+1,
2029 device->DitherDepth);
2031 device->LimiterState = gainLimiter;
2032 if(auto limopt = ConfigValueBool(device->DeviceName.c_str(), nullptr, "output-limiter"))
2033 gainLimiter = *limopt ? ALC_TRUE : ALC_FALSE;
2035 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2036 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2037 * output (where samples must be clamped), and don't for floating-point
2038 * (which can take unclamped samples).
2040 if(gainLimiter == ALC_DONT_CARE_SOFT)
2042 switch(device->FmtType)
2044 case DevFmtByte:
2045 case DevFmtUByte:
2046 case DevFmtShort:
2047 case DevFmtUShort:
2048 case DevFmtInt:
2049 case DevFmtUInt:
2050 gainLimiter = ALC_TRUE;
2051 break;
2052 case DevFmtFloat:
2053 gainLimiter = ALC_FALSE;
2054 break;
2057 if(gainLimiter == ALC_FALSE)
2058 TRACE("Output limiter disabled\n");
2059 else
2061 float thrshld{1.0f};
2062 switch(device->FmtType)
2064 case DevFmtByte:
2065 case DevFmtUByte:
2066 thrshld = 127.0f / 128.0f;
2067 break;
2068 case DevFmtShort:
2069 case DevFmtUShort:
2070 thrshld = 32767.0f / 32768.0f;
2071 break;
2072 case DevFmtInt:
2073 case DevFmtUInt:
2074 case DevFmtFloat:
2075 break;
2077 if(device->DitherDepth > 0.0f)
2078 thrshld -= 1.0f / device->DitherDepth;
2080 const float thrshld_dB{std::log10(thrshld) * 20.0f};
2081 auto limiter = CreateDeviceLimiter(device, thrshld_dB);
2083 sample_delay += limiter->getLookAhead();
2084 device->Limiter = std::move(limiter);
2085 TRACE("Output limiter enabled, %.4fdB limit\n", thrshld_dB);
2088 /* Convert the sample delay from samples to nanosamples to nanoseconds. */
2089 device->FixedLatency += nanoseconds{seconds{sample_delay}} / device->Frequency;
2090 TRACE("Fixed device latency: %" PRId64 "ns\n", int64_t{device->FixedLatency.count()});
2092 FPUCtl mixer_mode{};
2093 for(ALCcontext *context : *device->mContexts.load())
2095 if(ALeffectslot *slot{context->mDefaultSlot.get()})
2097 aluInitEffectPanning(slot, device);
2099 EffectState *state{slot->Effect.State.get()};
2100 state->mOutTarget = device->Dry.Buffer;
2101 state->deviceUpdate(device);
2102 if(ALbuffer *buffer{slot->Buffer})
2103 state->setBuffer(device, &buffer->mBuffer);
2104 slot->updateProps(context);
2107 std::unique_lock<std::mutex> proplock{context->mPropLock};
2108 std::unique_lock<std::mutex> slotlock{context->mEffectSlotLock};
2109 if(ALeffectslotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_relaxed)})
2110 std::fill_n(curarray->end(), curarray->size(), nullptr);
2111 for(auto &sublist : context->mEffectSlotList)
2113 uint64_t usemask{~sublist.FreeMask};
2114 while(usemask)
2116 ALsizei idx{CTZ64(usemask)};
2117 ALeffectslot *slot{sublist.EffectSlots + idx};
2118 usemask &= ~(1_u64 << idx);
2120 aluInitEffectPanning(slot, device);
2122 EffectState *state{slot->Effect.State.get()};
2123 state->mOutTarget = device->Dry.Buffer;
2124 state->deviceUpdate(device);
2125 if(ALbuffer *buffer{slot->Buffer})
2126 state->setBuffer(device, &buffer->mBuffer);
2127 slot->updateProps(context);
2130 slotlock.unlock();
2132 const ALuint num_sends{device->NumAuxSends};
2133 std::unique_lock<std::mutex> srclock{context->mSourceLock};
2134 for(auto &sublist : context->mSourceList)
2136 uint64_t usemask{~sublist.FreeMask};
2137 while(usemask)
2139 ALsizei idx{CTZ64(usemask)};
2140 ALsource *source{sublist.Sources + idx};
2141 usemask &= ~(1_u64 << idx);
2143 auto clear_send = [](ALsource::SendData &send) -> void
2145 if(send.Slot)
2146 DecrementRef(send.Slot->ref);
2147 send.Slot = nullptr;
2148 send.Gain = 1.0f;
2149 send.GainHF = 1.0f;
2150 send.HFReference = LOWPASSFREQREF;
2151 send.GainLF = 1.0f;
2152 send.LFReference = HIGHPASSFREQREF;
2154 auto send_begin = source->Send.begin() + static_cast<ptrdiff_t>(num_sends);
2155 std::for_each(send_begin, source->Send.end(), clear_send);
2157 source->PropsClean.clear(std::memory_order_release);
2161 /* Clear any pre-existing voice property structs, in case the number of
2162 * auxiliary sends is changing. Active sources will have updates
2163 * respecified in UpdateAllSourceProps.
2165 VoicePropsItem *vprops{context->mFreeVoiceProps.exchange(nullptr, std::memory_order_acq_rel)};
2166 while(vprops)
2168 VoicePropsItem *next = vprops->next.load(std::memory_order_relaxed);
2169 delete vprops;
2170 vprops = next;
2173 auto voicelist = context->getVoicesSpan();
2174 for(Voice *voice : voicelist)
2176 /* Clear extraneous property set sends. */
2177 std::fill(std::begin(voice->mProps.Send)+num_sends, std::end(voice->mProps.Send),
2178 VoiceProps::SendData{});
2180 std::fill(voice->mSend.begin()+num_sends, voice->mSend.end(), Voice::TargetData{});
2181 for(auto &chandata : voice->mChans)
2183 std::fill(chandata.mWetParams.begin()+num_sends, chandata.mWetParams.end(),
2184 SendParams{});
2187 delete voice->mUpdate.exchange(nullptr, std::memory_order_acq_rel);
2189 /* Force the voice to stopped if it was stopping. */
2190 Voice::State vstate{Voice::Stopping};
2191 voice->mPlayState.compare_exchange_strong(vstate, Voice::Stopped,
2192 std::memory_order_acquire, std::memory_order_acquire);
2193 if(voice->mSourceID.load(std::memory_order_relaxed) == 0u)
2194 continue;
2196 voice->mStep = 0;
2197 voice->mFlags |= VOICE_IS_FADING;
2199 if(voice->mAmbiOrder && device->mAmbiOrder > voice->mAmbiOrder)
2201 const uint8_t *OrderFromChan{(voice->mFmtChannels == FmtBFormat2D) ?
2202 AmbiIndex::OrderFrom2DChannel.data() :
2203 AmbiIndex::OrderFromChannel.data()};
2205 const BandSplitter splitter{400.0f / static_cast<float>(device->Frequency)};
2207 const auto scales = BFormatDec::GetHFOrderScales(voice->mAmbiOrder,
2208 device->mAmbiOrder);
2209 for(auto &chandata : voice->mChans)
2211 chandata.mPrevSamples.fill(0.0f);
2212 chandata.mAmbiScale = scales[*(OrderFromChan++)];
2213 chandata.mAmbiSplitter = splitter;
2214 chandata.mDryParams = DirectParams{};
2215 std::fill_n(chandata.mWetParams.begin(), num_sends, SendParams{});
2218 voice->mFlags |= VOICE_IS_AMBISONIC;
2220 else
2222 /* Clear previous samples. */
2223 for(auto &chandata : voice->mChans)
2225 chandata.mPrevSamples.fill(0.0f);
2226 chandata.mDryParams = DirectParams{};
2227 std::fill_n(chandata.mWetParams.begin(), num_sends, SendParams{});
2230 voice->mFlags &= ~VOICE_IS_AMBISONIC;
2233 if(device->AvgSpeakerDist > 0.0f)
2235 /* Reinitialize the NFC filters for new parameters. */
2236 const float w1{SPEEDOFSOUNDMETRESPERSEC /
2237 (device->AvgSpeakerDist * static_cast<float>(device->Frequency))};
2238 for(auto &chandata : voice->mChans)
2239 chandata.mDryParams.NFCtrlFilter.init(w1);
2242 srclock.unlock();
2244 context->mPropsClean.test_and_set(std::memory_order_release);
2245 UpdateContextProps(context);
2246 context->mListener.PropsClean.test_and_set(std::memory_order_release);
2247 UpdateListenerProps(context);
2248 UpdateAllSourceProps(context);
2250 mixer_mode.leave();
2252 if(!device->Flags.get<DevicePaused>())
2254 try {
2255 auto backend = device->Backend.get();
2256 backend->start();
2257 device->Flags.set<DeviceRunning>();
2259 catch(al::backend_exception& e) {
2260 device->handleDisconnect("%s", e.what());
2261 return ALC_INVALID_DEVICE;
2265 return ALC_NO_ERROR;
2269 ALCdevice::ALCdevice(DeviceType type) : Type{type}, mContexts{&EmptyContextArray}
2273 ALCdevice::~ALCdevice()
2275 TRACE("Freeing device %p\n", decltype(std::declval<void*>()){this});
2277 Backend = nullptr;
2279 size_t count{std::accumulate(BufferList.cbegin(), BufferList.cend(), size_t{0u},
2280 [](size_t cur, const BufferSubList &sublist) noexcept -> size_t
2281 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2283 if(count > 0)
2284 WARN("%zu Buffer%s not deleted\n", count, (count==1)?"":"s");
2286 count = std::accumulate(EffectList.cbegin(), EffectList.cend(), size_t{0u},
2287 [](size_t cur, const EffectSubList &sublist) noexcept -> size_t
2288 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2290 if(count > 0)
2291 WARN("%zu Effect%s not deleted\n", count, (count==1)?"":"s");
2293 count = std::accumulate(FilterList.cbegin(), FilterList.cend(), size_t{0u},
2294 [](size_t cur, const FilterSubList &sublist) noexcept -> size_t
2295 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2297 if(count > 0)
2298 WARN("%zu Filter%s not deleted\n", count, (count==1)?"":"s");
2300 mHrtf = nullptr;
2302 auto *oldarray = mContexts.exchange(nullptr, std::memory_order_relaxed);
2303 if(oldarray != &EmptyContextArray) delete oldarray;
2307 /** Checks if the device handle is valid, and returns a new reference if so. */
2308 static DeviceRef VerifyDevice(ALCdevice *device)
2310 std::lock_guard<std::recursive_mutex> _{ListLock};
2311 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
2312 if(iter != DeviceList.end() && *iter == device)
2314 (*iter)->add_ref();
2315 return DeviceRef{*iter};
2317 return nullptr;
2321 ALCcontext::ALCcontext(al::intrusive_ptr<ALCdevice> device) : mDevice{std::move(device)}
2323 mPropsClean.test_and_set(std::memory_order_relaxed);
2326 ALCcontext::~ALCcontext()
2328 TRACE("Freeing context %p\n", decltype(std::declval<void*>()){this});
2330 size_t count{0};
2331 ALcontextProps *cprops{mUpdate.exchange(nullptr, std::memory_order_relaxed)};
2332 if(cprops)
2334 ++count;
2335 delete cprops;
2337 cprops = mFreeContextProps.exchange(nullptr, std::memory_order_acquire);
2338 while(cprops)
2340 ALcontextProps *next{cprops->next.load(std::memory_order_relaxed)};
2341 delete cprops;
2342 cprops = next;
2343 ++count;
2345 TRACE("Freed %zu context property object%s\n", count, (count==1)?"":"s");
2347 count = std::accumulate(mSourceList.cbegin(), mSourceList.cend(), size_t{0u},
2348 [](size_t cur, const SourceSubList &sublist) noexcept -> size_t
2349 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2351 if(count > 0)
2352 WARN("%zu Source%s not deleted\n", count, (count==1)?"":"s");
2353 mSourceList.clear();
2354 mNumSources = 0;
2356 count = 0;
2357 ALeffectslotProps *eprops{mFreeEffectslotProps.exchange(nullptr, std::memory_order_acquire)};
2358 while(eprops)
2360 ALeffectslotProps *next{eprops->next.load(std::memory_order_relaxed)};
2361 delete eprops;
2362 eprops = next;
2363 ++count;
2365 TRACE("Freed %zu AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2367 if(ALeffectslotArray *curarray{mActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed)})
2369 al::destroy_n(curarray->end(), curarray->size());
2370 delete curarray;
2372 mDefaultSlot = nullptr;
2374 count = std::accumulate(mEffectSlotList.cbegin(), mEffectSlotList.cend(), size_t{0u},
2375 [](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t
2376 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2378 if(count > 0)
2379 WARN("%zu AuxiliaryEffectSlot%s not deleted\n", count, (count==1)?"":"s");
2380 mEffectSlotList.clear();
2381 mNumEffectSlots = 0;
2383 count = 0;
2384 VoicePropsItem *vprops{mFreeVoiceProps.exchange(nullptr, std::memory_order_acquire)};
2385 while(vprops)
2387 VoicePropsItem *next{vprops->next.load(std::memory_order_relaxed)};
2388 delete vprops;
2389 vprops = next;
2390 ++count;
2392 TRACE("Freed %zu voice property object%s\n", count, (count==1)?"":"s");
2394 delete mVoices.exchange(nullptr, std::memory_order_relaxed);
2396 count = 0;
2397 ALlistenerProps *lprops{mListener.Params.Update.exchange(nullptr, std::memory_order_relaxed)};
2398 if(lprops)
2400 ++count;
2401 delete lprops;
2403 lprops = mFreeListenerProps.exchange(nullptr, std::memory_order_acquire);
2404 while(lprops)
2406 ALlistenerProps *next{lprops->next.load(std::memory_order_relaxed)};
2407 delete lprops;
2408 lprops = next;
2409 ++count;
2411 TRACE("Freed %zu listener property object%s\n", count, (count==1)?"":"s");
2413 if(mAsyncEvents)
2415 count = 0;
2416 auto evt_vec = mAsyncEvents->getReadVector();
2417 if(evt_vec.first.len > 0)
2419 al::destroy_n(reinterpret_cast<AsyncEvent*>(evt_vec.first.buf), evt_vec.first.len);
2420 count += evt_vec.first.len;
2422 if(evt_vec.second.len > 0)
2424 al::destroy_n(reinterpret_cast<AsyncEvent*>(evt_vec.second.buf), evt_vec.second.len);
2425 count += evt_vec.second.len;
2427 if(count > 0)
2428 TRACE("Destructed %zu orphaned event%s\n", count, (count==1)?"":"s");
2429 mAsyncEvents->readAdvance(count);
2433 void ALCcontext::init()
2435 if(DefaultEffect.type != AL_EFFECT_NULL && mDevice->Type == DeviceType::Playback)
2437 mDefaultSlot = std::unique_ptr<ALeffectslot>{new ALeffectslot{}};
2438 if(mDefaultSlot->init() == AL_NO_ERROR)
2439 aluInitEffectPanning(mDefaultSlot.get(), mDevice.get());
2440 else
2442 mDefaultSlot = nullptr;
2443 ERR("Failed to initialize the default effect slot\n");
2447 ALeffectslotArray *auxslots;
2448 if(!mDefaultSlot)
2449 auxslots = ALeffectslot::CreatePtrArray(0);
2450 else
2452 auxslots = ALeffectslot::CreatePtrArray(1);
2453 (*auxslots)[0] = mDefaultSlot.get();
2454 mDefaultSlot->mState = SlotState::Playing;
2456 mActiveAuxSlots.store(auxslots, std::memory_order_relaxed);
2458 allocVoiceChanges(1);
2460 VoiceChange *cur{mVoiceChangeTail};
2461 while(VoiceChange *next{cur->mNext.load(std::memory_order_relaxed)})
2462 cur = next;
2463 mCurrentVoiceChange.store(cur, std::memory_order_relaxed);
2466 mExtensionList = alExtList;
2469 mListener.Params.Matrix = alu::Matrix::Identity();
2470 mListener.Params.Velocity = alu::Vector{};
2471 mListener.Params.Gain = mListener.Gain;
2472 mListener.Params.MetersPerUnit = mListener.mMetersPerUnit;
2473 mListener.Params.DopplerFactor = mDopplerFactor;
2474 mListener.Params.SpeedOfSound = mSpeedOfSound * mDopplerVelocity;
2475 mListener.Params.SourceDistanceModel = mSourceDistanceModel;
2476 mListener.Params.mDistanceModel = mDistanceModel;
2479 mAsyncEvents = RingBuffer::Create(511, sizeof(AsyncEvent), false);
2480 StartEventThrd(this);
2483 allocVoices(256);
2484 mActiveVoiceCount.store(64, std::memory_order_relaxed);
2487 bool ALCcontext::deinit()
2489 if(LocalContext == this)
2491 WARN("%p released while current on thread\n", decltype(std::declval<void*>()){this});
2492 ThreadContext.set(nullptr);
2493 release();
2496 ALCcontext *origctx{this};
2497 if(GlobalContext.compare_exchange_strong(origctx, nullptr))
2498 release();
2500 bool ret{};
2501 /* First make sure this context exists in the device's list. */
2502 auto *oldarray = mDevice->mContexts.load(std::memory_order_acquire);
2503 if(auto toremove = static_cast<size_t>(std::count(oldarray->begin(), oldarray->end(), this)))
2505 using ContextArray = al::FlexArray<ALCcontext*>;
2506 auto alloc_ctx_array = [](const size_t count) -> ContextArray*
2508 if(count == 0) return &EmptyContextArray;
2509 return ContextArray::Create(count).release();
2511 auto *newarray = alloc_ctx_array(oldarray->size() - toremove);
2513 /* Copy the current/old context handles to the new array, excluding the
2514 * given context.
2516 std::copy_if(oldarray->begin(), oldarray->end(), newarray->begin(),
2517 std::bind(std::not_equal_to<ALCcontext*>{}, _1, this));
2519 /* Store the new context array in the device. Wait for any current mix
2520 * to finish before deleting the old array.
2522 mDevice->mContexts.store(newarray);
2523 if(oldarray != &EmptyContextArray)
2525 mDevice->waitForMix();
2526 delete oldarray;
2529 ret = !newarray->empty();
2531 else
2532 ret = !oldarray->empty();
2534 StopEventThrd(this);
2536 return ret;
2541 * Checks if the given context is valid, returning a new reference to it if so.
2543 static ContextRef VerifyContext(ALCcontext *context)
2545 std::lock_guard<std::recursive_mutex> _{ListLock};
2546 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
2547 if(iter != ContextList.end() && *iter == context)
2549 (*iter)->add_ref();
2550 return ContextRef{*iter};
2552 return nullptr;
2555 /** Returns a new reference to the currently active context for this thread. */
2556 ContextRef GetContextRef(void)
2558 ALCcontext *context{LocalContext};
2559 if(context)
2560 context->add_ref();
2561 else
2563 std::lock_guard<std::recursive_mutex> _{ListLock};
2564 context = GlobalContext.load(std::memory_order_acquire);
2565 if(context) context->add_ref();
2567 return ContextRef{context};
2571 /************************************************
2572 * Standard ALC functions
2573 ************************************************/
2575 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2576 START_API_FUNC
2578 DeviceRef dev{VerifyDevice(device)};
2579 if(dev) return dev->LastError.exchange(ALC_NO_ERROR);
2580 return LastNullDeviceError.exchange(ALC_NO_ERROR);
2582 END_API_FUNC
2585 ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2586 START_API_FUNC
2588 if(!SuspendDefers)
2589 return;
2591 ContextRef ctx{VerifyContext(context)};
2592 if(!ctx)
2593 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2594 else
2595 ctx->deferUpdates();
2597 END_API_FUNC
2599 ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context)
2600 START_API_FUNC
2602 if(!SuspendDefers)
2603 return;
2605 ContextRef ctx{VerifyContext(context)};
2606 if(!ctx)
2607 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2608 else
2609 ctx->processUpdates();
2611 END_API_FUNC
2614 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2615 START_API_FUNC
2617 const ALCchar *value{nullptr};
2619 switch(param)
2621 case ALC_NO_ERROR:
2622 value = alcNoError;
2623 break;
2625 case ALC_INVALID_ENUM:
2626 value = alcErrInvalidEnum;
2627 break;
2629 case ALC_INVALID_VALUE:
2630 value = alcErrInvalidValue;
2631 break;
2633 case ALC_INVALID_DEVICE:
2634 value = alcErrInvalidDevice;
2635 break;
2637 case ALC_INVALID_CONTEXT:
2638 value = alcErrInvalidContext;
2639 break;
2641 case ALC_OUT_OF_MEMORY:
2642 value = alcErrOutOfMemory;
2643 break;
2645 case ALC_DEVICE_SPECIFIER:
2646 value = alcDefaultName;
2647 break;
2649 case ALC_ALL_DEVICES_SPECIFIER:
2650 if(DeviceRef dev{VerifyDevice(Device)})
2651 value = dev->DeviceName.c_str();
2652 else
2654 ProbeAllDevicesList();
2655 value = alcAllDevicesList.c_str();
2657 break;
2659 case ALC_CAPTURE_DEVICE_SPECIFIER:
2660 if(DeviceRef dev{VerifyDevice(Device)})
2661 value = dev->DeviceName.c_str();
2662 else
2664 ProbeCaptureDeviceList();
2665 value = alcCaptureDeviceList.c_str();
2667 break;
2669 /* Default devices are always first in the list */
2670 case ALC_DEFAULT_DEVICE_SPECIFIER:
2671 value = alcDefaultName;
2672 break;
2674 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2675 if(alcAllDevicesList.empty())
2676 ProbeAllDevicesList();
2678 /* Copy first entry as default. */
2679 alcDefaultAllDevicesSpecifier = alcAllDevicesList.c_str();
2680 value = alcDefaultAllDevicesSpecifier.c_str();
2681 break;
2683 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2684 if(alcCaptureDeviceList.empty())
2685 ProbeCaptureDeviceList();
2687 /* Copy first entry as default. */
2688 alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList.c_str();
2689 value = alcCaptureDefaultDeviceSpecifier.c_str();
2690 break;
2692 case ALC_EXTENSIONS:
2693 if(VerifyDevice(Device))
2694 value = alcExtensionList;
2695 else
2696 value = alcNoDeviceExtList;
2697 break;
2699 case ALC_HRTF_SPECIFIER_SOFT:
2700 if(DeviceRef dev{VerifyDevice(Device)})
2702 std::lock_guard<std::mutex> _{dev->StateLock};
2703 value = (dev->mHrtf ? dev->HrtfName.c_str() : "");
2705 else
2706 alcSetError(nullptr, ALC_INVALID_DEVICE);
2707 break;
2709 default:
2710 alcSetError(VerifyDevice(Device).get(), ALC_INVALID_ENUM);
2711 break;
2714 return value;
2716 END_API_FUNC
2719 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
2721 if(device->Type == DeviceType::Capture) return 9;
2722 if(device->Type != DeviceType::Loopback) return 29;
2723 if(device->FmtChans == DevFmtAmbi3D)
2724 return 35;
2725 return 29;
2728 static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span<int> values)
2730 size_t i;
2732 if(values.empty())
2734 alcSetError(device, ALC_INVALID_VALUE);
2735 return 0;
2738 if(!device)
2740 switch(param)
2742 case ALC_MAJOR_VERSION:
2743 values[0] = alcMajorVersion;
2744 return 1;
2745 case ALC_MINOR_VERSION:
2746 values[0] = alcMinorVersion;
2747 return 1;
2749 case ALC_ATTRIBUTES_SIZE:
2750 case ALC_ALL_ATTRIBUTES:
2751 case ALC_FREQUENCY:
2752 case ALC_REFRESH:
2753 case ALC_SYNC:
2754 case ALC_MONO_SOURCES:
2755 case ALC_STEREO_SOURCES:
2756 case ALC_CAPTURE_SAMPLES:
2757 case ALC_FORMAT_CHANNELS_SOFT:
2758 case ALC_FORMAT_TYPE_SOFT:
2759 case ALC_AMBISONIC_LAYOUT_SOFT:
2760 case ALC_AMBISONIC_SCALING_SOFT:
2761 case ALC_AMBISONIC_ORDER_SOFT:
2762 case ALC_MAX_AMBISONIC_ORDER_SOFT:
2763 alcSetError(nullptr, ALC_INVALID_DEVICE);
2764 return 0;
2766 default:
2767 alcSetError(nullptr, ALC_INVALID_ENUM);
2769 return 0;
2772 if(device->Type == DeviceType::Capture)
2774 switch(param)
2776 case ALC_ATTRIBUTES_SIZE:
2777 values[0] = NumAttrsForDevice(device);
2778 return 1;
2780 case ALC_ALL_ATTRIBUTES:
2781 i = 0;
2782 if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2783 alcSetError(device, ALC_INVALID_VALUE);
2784 else
2786 std::lock_guard<std::mutex> _{device->StateLock};
2787 values[i++] = ALC_MAJOR_VERSION;
2788 values[i++] = alcMajorVersion;
2789 values[i++] = ALC_MINOR_VERSION;
2790 values[i++] = alcMinorVersion;
2791 values[i++] = ALC_CAPTURE_SAMPLES;
2792 values[i++] = static_cast<int>(device->Backend->availableSamples());
2793 values[i++] = ALC_CONNECTED;
2794 values[i++] = device->Connected.load(std::memory_order_relaxed);
2795 values[i++] = 0;
2797 return i;
2799 case ALC_MAJOR_VERSION:
2800 values[0] = alcMajorVersion;
2801 return 1;
2802 case ALC_MINOR_VERSION:
2803 values[0] = alcMinorVersion;
2804 return 1;
2806 case ALC_CAPTURE_SAMPLES:
2808 std::lock_guard<std::mutex> _{device->StateLock};
2809 values[0] = static_cast<int>(device->Backend->availableSamples());
2811 return 1;
2813 case ALC_CONNECTED:
2815 std::lock_guard<std::mutex> _{device->StateLock};
2816 values[0] = device->Connected.load(std::memory_order_acquire);
2818 return 1;
2820 default:
2821 alcSetError(device, ALC_INVALID_ENUM);
2823 return 0;
2826 /* render device */
2827 switch(param)
2829 case ALC_ATTRIBUTES_SIZE:
2830 values[0] = NumAttrsForDevice(device);
2831 return 1;
2833 case ALC_ALL_ATTRIBUTES:
2834 i = 0;
2835 if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2836 alcSetError(device, ALC_INVALID_VALUE);
2837 else
2839 std::lock_guard<std::mutex> _{device->StateLock};
2840 values[i++] = ALC_MAJOR_VERSION;
2841 values[i++] = alcMajorVersion;
2842 values[i++] = ALC_MINOR_VERSION;
2843 values[i++] = alcMinorVersion;
2844 values[i++] = ALC_EFX_MAJOR_VERSION;
2845 values[i++] = alcEFXMajorVersion;
2846 values[i++] = ALC_EFX_MINOR_VERSION;
2847 values[i++] = alcEFXMinorVersion;
2849 values[i++] = ALC_FREQUENCY;
2850 values[i++] = static_cast<int>(device->Frequency);
2851 if(device->Type != DeviceType::Loopback)
2853 values[i++] = ALC_REFRESH;
2854 values[i++] = static_cast<int>(device->Frequency / device->UpdateSize);
2856 values[i++] = ALC_SYNC;
2857 values[i++] = ALC_FALSE;
2859 else
2861 if(device->FmtChans == DevFmtAmbi3D)
2863 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
2864 values[i++] = static_cast<int>(device->mAmbiLayout);
2866 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
2867 values[i++] = static_cast<int>(device->mAmbiScale);
2869 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
2870 values[i++] = static_cast<int>(device->mAmbiOrder);
2873 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2874 values[i++] = device->FmtChans;
2876 values[i++] = ALC_FORMAT_TYPE_SOFT;
2877 values[i++] = device->FmtType;
2880 values[i++] = ALC_MONO_SOURCES;
2881 values[i++] = static_cast<int>(device->NumMonoSources);
2883 values[i++] = ALC_STEREO_SOURCES;
2884 values[i++] = static_cast<int>(device->NumStereoSources);
2886 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2887 values[i++] = static_cast<int>(device->NumAuxSends);
2889 values[i++] = ALC_HRTF_SOFT;
2890 values[i++] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
2892 values[i++] = ALC_HRTF_STATUS_SOFT;
2893 values[i++] = device->HrtfStatus;
2895 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
2896 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
2898 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
2899 values[i++] = MAX_AMBI_ORDER;
2901 values[i++] = 0;
2903 return i;
2905 case ALC_MAJOR_VERSION:
2906 values[0] = alcMajorVersion;
2907 return 1;
2909 case ALC_MINOR_VERSION:
2910 values[0] = alcMinorVersion;
2911 return 1;
2913 case ALC_EFX_MAJOR_VERSION:
2914 values[0] = alcEFXMajorVersion;
2915 return 1;
2917 case ALC_EFX_MINOR_VERSION:
2918 values[0] = alcEFXMinorVersion;
2919 return 1;
2921 case ALC_FREQUENCY:
2922 values[0] = static_cast<int>(device->Frequency);
2923 return 1;
2925 case ALC_REFRESH:
2926 if(device->Type == DeviceType::Loopback)
2928 alcSetError(device, ALC_INVALID_DEVICE);
2929 return 0;
2932 std::lock_guard<std::mutex> _{device->StateLock};
2933 values[0] = static_cast<int>(device->Frequency / device->UpdateSize);
2935 return 1;
2937 case ALC_SYNC:
2938 if(device->Type == DeviceType::Loopback)
2940 alcSetError(device, ALC_INVALID_DEVICE);
2941 return 0;
2943 values[0] = ALC_FALSE;
2944 return 1;
2946 case ALC_FORMAT_CHANNELS_SOFT:
2947 if(device->Type != DeviceType::Loopback)
2949 alcSetError(device, ALC_INVALID_DEVICE);
2950 return 0;
2952 values[0] = device->FmtChans;
2953 return 1;
2955 case ALC_FORMAT_TYPE_SOFT:
2956 if(device->Type != DeviceType::Loopback)
2958 alcSetError(device, ALC_INVALID_DEVICE);
2959 return 0;
2961 values[0] = device->FmtType;
2962 return 1;
2964 case ALC_AMBISONIC_LAYOUT_SOFT:
2965 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2967 alcSetError(device, ALC_INVALID_DEVICE);
2968 return 0;
2970 values[0] = static_cast<int>(device->mAmbiLayout);
2971 return 1;
2973 case ALC_AMBISONIC_SCALING_SOFT:
2974 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2976 alcSetError(device, ALC_INVALID_DEVICE);
2977 return 0;
2979 values[0] = static_cast<int>(device->mAmbiScale);
2980 return 1;
2982 case ALC_AMBISONIC_ORDER_SOFT:
2983 if(device->Type != DeviceType::Loopback || device->FmtChans != DevFmtAmbi3D)
2985 alcSetError(device, ALC_INVALID_DEVICE);
2986 return 0;
2988 values[0] = static_cast<int>(device->mAmbiOrder);
2989 return 1;
2991 case ALC_MONO_SOURCES:
2992 values[0] = static_cast<int>(device->NumMonoSources);
2993 return 1;
2995 case ALC_STEREO_SOURCES:
2996 values[0] = static_cast<int>(device->NumStereoSources);
2997 return 1;
2999 case ALC_MAX_AUXILIARY_SENDS:
3000 values[0] = static_cast<int>(device->NumAuxSends);
3001 return 1;
3003 case ALC_CONNECTED:
3005 std::lock_guard<std::mutex> _{device->StateLock};
3006 values[0] = device->Connected.load(std::memory_order_acquire);
3008 return 1;
3010 case ALC_HRTF_SOFT:
3011 values[0] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
3012 return 1;
3014 case ALC_HRTF_STATUS_SOFT:
3015 values[0] = device->HrtfStatus;
3016 return 1;
3018 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3020 std::lock_guard<std::mutex> _{device->StateLock};
3021 device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
3022 values[0] = static_cast<int>(minz(device->HrtfList.size(),
3023 std::numeric_limits<int>::max()));
3025 return 1;
3027 case ALC_OUTPUT_LIMITER_SOFT:
3028 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3029 return 1;
3031 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3032 values[0] = MAX_AMBI_ORDER;
3033 return 1;
3035 default:
3036 alcSetError(device, ALC_INVALID_ENUM);
3038 return 0;
3041 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3042 START_API_FUNC
3044 DeviceRef dev{VerifyDevice(device)};
3045 if(size <= 0 || values == nullptr)
3046 alcSetError(dev.get(), ALC_INVALID_VALUE);
3047 else
3048 GetIntegerv(dev.get(), param, {values, static_cast<ALuint>(size)});
3050 END_API_FUNC
3052 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3053 START_API_FUNC
3055 DeviceRef dev{VerifyDevice(device)};
3056 if(size <= 0 || values == nullptr)
3058 alcSetError(dev.get(), ALC_INVALID_VALUE);
3059 return;
3061 if(!dev || dev->Type == DeviceType::Capture)
3063 auto ivals = al::vector<int>(static_cast<ALuint>(size));
3064 size_t got{GetIntegerv(dev.get(), pname, ivals)};
3065 std::copy_n(ivals.begin(), got, values);
3066 return;
3068 /* render device */
3069 switch(pname)
3071 case ALC_ATTRIBUTES_SIZE:
3072 *values = NumAttrsForDevice(dev.get())+4;
3073 break;
3075 case ALC_ALL_ATTRIBUTES:
3076 if(size < NumAttrsForDevice(dev.get())+4)
3077 alcSetError(dev.get(), ALC_INVALID_VALUE);
3078 else
3080 size_t i{0};
3081 std::lock_guard<std::mutex> _{dev->StateLock};
3082 values[i++] = ALC_FREQUENCY;
3083 values[i++] = dev->Frequency;
3085 if(dev->Type != DeviceType::Loopback)
3087 values[i++] = ALC_REFRESH;
3088 values[i++] = dev->Frequency / dev->UpdateSize;
3090 values[i++] = ALC_SYNC;
3091 values[i++] = ALC_FALSE;
3093 else
3095 if(dev->FmtChans == DevFmtAmbi3D)
3097 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3098 values[i++] = static_cast<int64_t>(dev->mAmbiLayout);
3100 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3101 values[i++] = static_cast<int64_t>(dev->mAmbiScale);
3103 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3104 values[i++] = dev->mAmbiOrder;
3107 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3108 values[i++] = dev->FmtChans;
3110 values[i++] = ALC_FORMAT_TYPE_SOFT;
3111 values[i++] = dev->FmtType;
3114 values[i++] = ALC_MONO_SOURCES;
3115 values[i++] = dev->NumMonoSources;
3117 values[i++] = ALC_STEREO_SOURCES;
3118 values[i++] = dev->NumStereoSources;
3120 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3121 values[i++] = dev->NumAuxSends;
3123 values[i++] = ALC_HRTF_SOFT;
3124 values[i++] = (dev->mHrtf ? ALC_TRUE : ALC_FALSE);
3126 values[i++] = ALC_HRTF_STATUS_SOFT;
3127 values[i++] = dev->HrtfStatus;
3129 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3130 values[i++] = dev->Limiter ? ALC_TRUE : ALC_FALSE;
3132 ClockLatency clock{GetClockLatency(dev.get())};
3133 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3134 values[i++] = clock.ClockTime.count();
3136 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3137 values[i++] = clock.Latency.count();
3139 values[i++] = 0;
3141 break;
3143 case ALC_DEVICE_CLOCK_SOFT:
3145 std::lock_guard<std::mutex> _{dev->StateLock};
3146 ALuint samplecount, refcount;
3147 nanoseconds basecount;
3148 do {
3149 refcount = dev->waitForMix();
3150 basecount = dev->ClockBase;
3151 samplecount = dev->SamplesDone;
3152 } while(refcount != ReadRef(dev->MixCount));
3153 basecount += nanoseconds{seconds{samplecount}} / dev->Frequency;
3154 *values = basecount.count();
3156 break;
3158 case ALC_DEVICE_LATENCY_SOFT:
3160 std::lock_guard<std::mutex> _{dev->StateLock};
3161 ClockLatency clock{GetClockLatency(dev.get())};
3162 *values = clock.Latency.count();
3164 break;
3166 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3167 if(size < 2)
3168 alcSetError(dev.get(), ALC_INVALID_VALUE);
3169 else
3171 std::lock_guard<std::mutex> _{dev->StateLock};
3172 ClockLatency clock{GetClockLatency(dev.get())};
3173 values[0] = clock.ClockTime.count();
3174 values[1] = clock.Latency.count();
3176 break;
3178 default:
3179 auto ivals = al::vector<int>(static_cast<ALuint>(size));
3180 size_t got{GetIntegerv(dev.get(), pname, ivals)};
3181 std::copy_n(ivals.begin(), got, values);
3182 break;
3185 END_API_FUNC
3188 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3189 START_API_FUNC
3191 DeviceRef dev{VerifyDevice(device)};
3192 if(!extName)
3193 alcSetError(dev.get(), ALC_INVALID_VALUE);
3194 else
3196 size_t len = strlen(extName);
3197 const char *ptr = (dev ? alcExtensionList : alcNoDeviceExtList);
3198 while(ptr && *ptr)
3200 if(al::strncasecmp(ptr, extName, len) == 0 && (ptr[len] == '\0' || isspace(ptr[len])))
3201 return ALC_TRUE;
3203 if((ptr=strchr(ptr, ' ')) != nullptr)
3205 do {
3206 ++ptr;
3207 } while(isspace(*ptr));
3211 return ALC_FALSE;
3213 END_API_FUNC
3216 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3217 START_API_FUNC
3219 if(!funcName)
3221 DeviceRef dev{VerifyDevice(device)};
3222 alcSetError(dev.get(), ALC_INVALID_VALUE);
3224 else
3226 for(const auto &func : alcFunctions)
3228 if(strcmp(func.funcName, funcName) == 0)
3229 return func.address;
3232 return nullptr;
3234 END_API_FUNC
3237 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3238 START_API_FUNC
3240 if(!enumName)
3242 DeviceRef dev{VerifyDevice(device)};
3243 alcSetError(dev.get(), ALC_INVALID_VALUE);
3245 else
3247 for(const auto &enm : alcEnumerations)
3249 if(strcmp(enm.enumName, enumName) == 0)
3250 return enm.value;
3253 return 0;
3255 END_API_FUNC
3258 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3259 START_API_FUNC
3261 /* Explicitly hold the list lock while taking the StateLock in case the
3262 * device is asynchronously destroyed, to ensure this new context is
3263 * properly cleaned up after being made.
3265 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3266 DeviceRef dev{VerifyDevice(device)};
3267 if(!dev || dev->Type == DeviceType::Capture || !dev->Connected.load(std::memory_order_relaxed))
3269 listlock.unlock();
3270 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3271 return nullptr;
3273 std::unique_lock<std::mutex> statelock{dev->StateLock};
3274 listlock.unlock();
3276 dev->LastError.store(ALC_NO_ERROR);
3278 ALCenum err{UpdateDeviceParams(dev.get(), attrList)};
3279 if(err != ALC_NO_ERROR)
3281 alcSetError(dev.get(), err);
3282 return nullptr;
3285 ContextRef context{new ALCcontext{dev}};
3286 context->init();
3288 if(auto volopt = ConfigValueFloat(dev->DeviceName.c_str(), nullptr, "volume-adjust"))
3290 const float valf{*volopt};
3291 if(!std::isfinite(valf))
3292 ERR("volume-adjust must be finite: %f\n", valf);
3293 else
3295 const float db{clampf(valf, -24.0f, 24.0f)};
3296 if(db != valf)
3297 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3298 context->mGainBoost = std::pow(10.0f, db/20.0f);
3299 TRACE("volume-adjust gain: %f\n", context->mGainBoost);
3302 UpdateListenerProps(context.get());
3305 using ContextArray = al::FlexArray<ALCcontext*>;
3307 /* Allocate a new context array, which holds 1 more than the current/
3308 * old array.
3310 auto *oldarray = device->mContexts.load();
3311 const size_t newcount{oldarray->size()+1};
3312 std::unique_ptr<ContextArray> newarray{ContextArray::Create(newcount)};
3314 /* Copy the current/old context handles to the new array, appending the
3315 * new context.
3317 auto iter = std::copy(oldarray->begin(), oldarray->end(), newarray->begin());
3318 *iter = context.get();
3320 /* Store the new context array in the device. Wait for any current mix
3321 * to finish before deleting the old array.
3323 dev->mContexts.store(newarray.release());
3324 if(oldarray != &EmptyContextArray)
3326 dev->waitForMix();
3327 delete oldarray;
3330 statelock.unlock();
3333 std::lock_guard<std::recursive_mutex> _{ListLock};
3334 auto iter = std::lower_bound(ContextList.cbegin(), ContextList.cend(), context.get());
3335 ContextList.emplace(iter, context.get());
3338 if(ALeffectslot *slot{context->mDefaultSlot.get()})
3340 if(slot->initEffect(&DefaultEffect, context.get()) == AL_NO_ERROR)
3341 slot->updateProps(context.get());
3342 else
3343 ERR("Failed to initialize the default effect\n");
3346 TRACE("Created context %p\n", decltype(std::declval<void*>()){context.get()});
3347 return context.release();
3349 END_API_FUNC
3351 ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3352 START_API_FUNC
3354 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3355 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
3356 if(iter == ContextList.end() || *iter != context)
3358 listlock.unlock();
3359 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3360 return;
3362 /* Hold a reference to this context so it remains valid until the ListLock
3363 * is released.
3365 ContextRef ctx{*iter};
3366 ContextList.erase(iter);
3368 ALCdevice *Device{ctx->mDevice.get()};
3370 std::lock_guard<std::mutex> _{Device->StateLock};
3371 if(!ctx->deinit() && Device->Flags.get<DeviceRunning>())
3373 Device->Backend->stop();
3374 Device->Flags.unset<DeviceRunning>();
3377 END_API_FUNC
3380 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3381 START_API_FUNC
3383 ALCcontext *Context{LocalContext};
3384 if(!Context) Context = GlobalContext.load();
3385 return Context;
3387 END_API_FUNC
3389 /** Returns the currently active thread-local context. */
3390 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3391 START_API_FUNC
3392 { return LocalContext; }
3393 END_API_FUNC
3395 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3396 START_API_FUNC
3398 /* context must be valid or nullptr */
3399 ContextRef ctx;
3400 if(context)
3402 ctx = VerifyContext(context);
3403 if(!ctx)
3405 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3406 return ALC_FALSE;
3409 /* Release this reference (if any) to store it in the GlobalContext
3410 * pointer. Take ownership of the reference (if any) that was previously
3411 * stored there.
3413 ctx = ContextRef{GlobalContext.exchange(ctx.release())};
3415 /* Reset (decrement) the previous global reference by replacing it with the
3416 * thread-local context. Take ownership of the thread-local context
3417 * reference (if any), clearing the storage to null.
3419 ctx = ContextRef{LocalContext};
3420 if(ctx) ThreadContext.set(nullptr);
3421 /* Reset (decrement) the previous thread-local reference. */
3423 return ALC_TRUE;
3425 END_API_FUNC
3427 /** Makes the given context the active context for the current thread. */
3428 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3429 START_API_FUNC
3431 /* context must be valid or nullptr */
3432 ContextRef ctx;
3433 if(context)
3435 ctx = VerifyContext(context);
3436 if(!ctx)
3438 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3439 return ALC_FALSE;
3442 /* context's reference count is already incremented */
3443 ContextRef old{LocalContext};
3444 ThreadContext.set(ctx.release());
3446 return ALC_TRUE;
3448 END_API_FUNC
3451 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3452 START_API_FUNC
3454 ContextRef ctx{VerifyContext(Context)};
3455 if(!ctx)
3457 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3458 return nullptr;
3460 return ctx->mDevice.get();
3462 END_API_FUNC
3465 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3466 START_API_FUNC
3468 DO_INITCONFIG();
3470 if(!PlaybackFactory)
3472 alcSetError(nullptr, ALC_INVALID_VALUE);
3473 return nullptr;
3476 if(deviceName)
3478 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3479 #ifdef _WIN32
3480 /* Some old Windows apps hardcode these expecting OpenAL to use a
3481 * specific audio API, even when they're not enumerated. Creative's
3482 * router effectively ignores them too.
3484 || al::strcasecmp(deviceName, "DirectSound3D") == 0
3485 || al::strcasecmp(deviceName, "DirectSound") == 0
3486 || al::strcasecmp(deviceName, "MMSYSTEM") == 0
3487 #endif
3488 || al::strcasecmp(deviceName, "openal-soft") == 0)
3489 deviceName = nullptr;
3492 DeviceRef device{new ALCdevice{DeviceType::Playback}};
3494 /* Set output format */
3495 device->FmtChans = DevFmtChannelsDefault;
3496 device->FmtType = DevFmtTypeDefault;
3497 device->Frequency = DEFAULT_OUTPUT_RATE;
3498 device->UpdateSize = DEFAULT_UPDATE_SIZE;
3499 device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
3501 device->SourcesMax = 256;
3502 device->AuxiliaryEffectSlotMax = 64;
3503 device->NumAuxSends = DEFAULT_SENDS;
3505 try {
3506 auto backend = PlaybackFactory->createBackend(device.get(), BackendType::Playback);
3507 std::lock_guard<std::recursive_mutex> _{ListLock};
3508 backend->open(deviceName);
3509 device->Backend = std::move(backend);
3511 catch(al::backend_exception &e) {
3512 WARN("Failed to open playback device: %s\n", e.what());
3513 alcSetError(nullptr, e.errorCode());
3514 return nullptr;
3517 deviceName = device->DeviceName.c_str();
3518 if(auto chanopt = ConfigValueStr(deviceName, nullptr, "channels"))
3520 static const struct ChannelMap {
3521 const char name[16];
3522 DevFmtChannels chans;
3523 ALuint order;
3524 } chanlist[] = {
3525 { "mono", DevFmtMono, 0 },
3526 { "stereo", DevFmtStereo, 0 },
3527 { "quad", DevFmtQuad, 0 },
3528 { "surround51", DevFmtX51, 0 },
3529 { "surround61", DevFmtX61, 0 },
3530 { "surround71", DevFmtX71, 0 },
3531 { "surround51rear", DevFmtX51Rear, 0 },
3532 { "ambi1", DevFmtAmbi3D, 1 },
3533 { "ambi2", DevFmtAmbi3D, 2 },
3534 { "ambi3", DevFmtAmbi3D, 3 },
3537 const ALCchar *fmt{chanopt->c_str()};
3538 auto iter = std::find_if(std::begin(chanlist), std::end(chanlist),
3539 [fmt](const ChannelMap &entry) -> bool
3540 { return al::strcasecmp(entry.name, fmt) == 0; }
3542 if(iter == std::end(chanlist))
3543 ERR("Unsupported channels: %s\n", fmt);
3544 else
3546 device->FmtChans = iter->chans;
3547 device->mAmbiOrder = iter->order;
3548 device->Flags.set<ChannelsRequest>();
3551 if(auto typeopt = ConfigValueStr(deviceName, nullptr, "sample-type"))
3553 static const struct TypeMap {
3554 const char name[16];
3555 DevFmtType type;
3556 } typelist[] = {
3557 { "int8", DevFmtByte },
3558 { "uint8", DevFmtUByte },
3559 { "int16", DevFmtShort },
3560 { "uint16", DevFmtUShort },
3561 { "int32", DevFmtInt },
3562 { "uint32", DevFmtUInt },
3563 { "float32", DevFmtFloat },
3566 const ALCchar *fmt{typeopt->c_str()};
3567 auto iter = std::find_if(std::begin(typelist), std::end(typelist),
3568 [fmt](const TypeMap &entry) -> bool
3569 { return al::strcasecmp(entry.name, fmt) == 0; }
3571 if(iter == std::end(typelist))
3572 ERR("Unsupported sample-type: %s\n", fmt);
3573 else
3575 device->FmtType = iter->type;
3576 device->Flags.set<SampleTypeRequest>();
3580 if(ALuint freq{ConfigValueUInt(deviceName, nullptr, "frequency").value_or(0)})
3582 if(freq < MIN_OUTPUT_RATE || freq > MAX_OUTPUT_RATE)
3584 const ALuint newfreq{clampu(freq, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE)};
3585 ERR("%uhz request clamped to %uhz\n", freq, newfreq);
3586 freq = newfreq;
3588 const double scale{static_cast<double>(freq) / device->Frequency};
3589 device->UpdateSize = static_cast<ALuint>(device->UpdateSize*scale + 0.5);
3590 device->BufferSize = static_cast<ALuint>(device->BufferSize*scale + 0.5);
3591 device->Frequency = freq;
3592 device->Flags.set<FrequencyRequest>();
3595 if(auto persizeopt = ConfigValueUInt(deviceName, nullptr, "period_size"))
3596 device->UpdateSize = clampu(*persizeopt, 64, 8192);
3598 if(auto peropt = ConfigValueUInt(deviceName, nullptr, "periods"))
3599 device->BufferSize = device->UpdateSize * clampu(*peropt, 2, 16);
3600 else
3601 device->BufferSize = maxu(device->BufferSize, device->UpdateSize*2);
3603 if(auto srcsmax = ConfigValueUInt(deviceName, nullptr, "sources").value_or(0))
3604 device->SourcesMax = srcsmax;
3606 if(auto slotsmax = ConfigValueUInt(deviceName, nullptr, "slots").value_or(0))
3607 device->AuxiliaryEffectSlotMax = minu(slotsmax, INT_MAX);
3609 if(auto sendsopt = ConfigValueInt(deviceName, nullptr, "sends"))
3610 device->NumAuxSends = minu(DEFAULT_SENDS,
3611 static_cast<ALuint>(clampi(*sendsopt, 0, MAX_SENDS)));
3613 device->NumStereoSources = 1;
3614 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3616 if(auto ambiopt = ConfigValueStr(deviceName, nullptr, "ambi-format"))
3618 const ALCchar *fmt{ambiopt->c_str()};
3619 if(al::strcasecmp(fmt, "fuma") == 0)
3621 if(device->mAmbiOrder > 3)
3622 ERR("FuMa is incompatible with %d%s order ambisonics (up to third-order only)\n",
3623 device->mAmbiOrder,
3624 (((device->mAmbiOrder%100)/10) == 1) ? "th" :
3625 ((device->mAmbiOrder%10) == 1) ? "st" :
3626 ((device->mAmbiOrder%10) == 2) ? "nd" :
3627 ((device->mAmbiOrder%10) == 3) ? "rd" : "th");
3628 else
3630 device->mAmbiLayout = DevAmbiLayout::FuMa;
3631 device->mAmbiScale = DevAmbiScaling::FuMa;
3634 else if(al::strcasecmp(fmt, "ambix") == 0 || al::strcasecmp(fmt, "acn+sn3d") == 0)
3636 device->mAmbiLayout = DevAmbiLayout::ACN;
3637 device->mAmbiScale = DevAmbiScaling::SN3D;
3639 else if(al::strcasecmp(fmt, "acn+n3d") == 0)
3641 device->mAmbiLayout = DevAmbiLayout::ACN;
3642 device->mAmbiScale = DevAmbiScaling::N3D;
3644 else
3645 ERR("Unsupported ambi-format: %s\n", fmt);
3649 std::lock_guard<std::recursive_mutex> _{ListLock};
3650 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3651 DeviceList.emplace(iter, device.get());
3654 TRACE("Created device %p, \"%s\"\n", decltype(std::declval<void*>()){device.get()},
3655 device->DeviceName.c_str());
3656 return device.release();
3658 END_API_FUNC
3660 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3661 START_API_FUNC
3663 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3664 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3665 if(iter == DeviceList.end() || *iter != device)
3667 alcSetError(nullptr, ALC_INVALID_DEVICE);
3668 return ALC_FALSE;
3670 if((*iter)->Type == DeviceType::Capture)
3672 alcSetError(*iter, ALC_INVALID_DEVICE);
3673 return ALC_FALSE;
3676 /* Erase the device, and any remaining contexts left on it, from their
3677 * respective lists.
3679 DeviceRef dev{*iter};
3680 DeviceList.erase(iter);
3682 std::unique_lock<std::mutex> statelock{dev->StateLock};
3683 al::vector<ContextRef> orphanctxs;
3684 for(ALCcontext *ctx : *dev->mContexts.load())
3686 auto ctxiter = std::lower_bound(ContextList.begin(), ContextList.end(), ctx);
3687 if(ctxiter != ContextList.end() && *ctxiter == ctx)
3689 orphanctxs.emplace_back(ContextRef{*ctxiter});
3690 ContextList.erase(ctxiter);
3693 listlock.unlock();
3695 for(ContextRef &context : orphanctxs)
3697 WARN("Releasing orphaned context %p\n", decltype(std::declval<void*>()){context.get()});
3698 context->deinit();
3700 orphanctxs.clear();
3702 if(dev->Flags.get<DeviceRunning>())
3703 dev->Backend->stop();
3704 dev->Flags.unset<DeviceRunning>();
3706 return ALC_TRUE;
3708 END_API_FUNC
3711 /************************************************
3712 * ALC capture functions
3713 ************************************************/
3714 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3715 START_API_FUNC
3717 DO_INITCONFIG();
3719 if(!CaptureFactory)
3721 alcSetError(nullptr, ALC_INVALID_VALUE);
3722 return nullptr;
3725 if(samples <= 0)
3727 alcSetError(nullptr, ALC_INVALID_VALUE);
3728 return nullptr;
3731 if(deviceName)
3733 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3734 || al::strcasecmp(deviceName, "openal-soft") == 0)
3735 deviceName = nullptr;
3738 DeviceRef device{new ALCdevice{DeviceType::Capture}};
3740 auto decompfmt = DecomposeDevFormat(format);
3741 if(!decompfmt)
3743 alcSetError(nullptr, ALC_INVALID_ENUM);
3744 return nullptr;
3747 device->Frequency = frequency;
3748 device->FmtChans = decompfmt->chans;
3749 device->FmtType = decompfmt->type;
3750 device->Flags.set<FrequencyRequest, ChannelsRequest, SampleTypeRequest>();
3752 device->UpdateSize = static_cast<ALuint>(samples);
3753 device->BufferSize = static_cast<ALuint>(samples);
3755 try {
3756 TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n",
3757 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
3758 device->Frequency, device->UpdateSize, device->BufferSize);
3760 auto backend = CaptureFactory->createBackend(device.get(), BackendType::Capture);
3761 std::lock_guard<std::recursive_mutex> _{ListLock};
3762 backend->open(deviceName);
3763 device->Backend = std::move(backend);
3765 catch(al::backend_exception &e) {
3766 WARN("Failed to open capture device: %s\n", e.what());
3767 alcSetError(nullptr, e.errorCode());
3768 return nullptr;
3772 std::lock_guard<std::recursive_mutex> _{ListLock};
3773 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3774 DeviceList.emplace(iter, device.get());
3777 TRACE("Created capture device %p, \"%s\"\n", decltype(std::declval<void*>()){device.get()},
3778 device->DeviceName.c_str());
3779 return device.release();
3781 END_API_FUNC
3783 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3784 START_API_FUNC
3786 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3787 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3788 if(iter == DeviceList.end() || *iter != device)
3790 alcSetError(nullptr, ALC_INVALID_DEVICE);
3791 return ALC_FALSE;
3793 if((*iter)->Type != DeviceType::Capture)
3795 alcSetError(*iter, ALC_INVALID_DEVICE);
3796 return ALC_FALSE;
3799 DeviceRef dev{*iter};
3800 DeviceList.erase(iter);
3801 listlock.unlock();
3803 std::lock_guard<std::mutex> _{dev->StateLock};
3804 if(dev->Flags.get<DeviceRunning>())
3805 dev->Backend->stop();
3806 dev->Flags.unset<DeviceRunning>();
3808 return ALC_TRUE;
3810 END_API_FUNC
3812 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3813 START_API_FUNC
3815 DeviceRef dev{VerifyDevice(device)};
3816 if(!dev || dev->Type != DeviceType::Capture)
3818 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3819 return;
3822 std::lock_guard<std::mutex> _{dev->StateLock};
3823 if(!dev->Connected.load(std::memory_order_acquire))
3824 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3825 else if(!dev->Flags.get<DeviceRunning>())
3827 try {
3828 auto backend = dev->Backend.get();
3829 backend->start();
3830 dev->Flags.set<DeviceRunning>();
3832 catch(al::backend_exception& e) {
3833 dev->handleDisconnect("%s", e.what());
3834 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3838 END_API_FUNC
3840 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3841 START_API_FUNC
3843 DeviceRef dev{VerifyDevice(device)};
3844 if(!dev || dev->Type != DeviceType::Capture)
3845 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3846 else
3848 std::lock_guard<std::mutex> _{dev->StateLock};
3849 if(dev->Flags.get<DeviceRunning>())
3850 dev->Backend->stop();
3851 dev->Flags.unset<DeviceRunning>();
3854 END_API_FUNC
3856 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3857 START_API_FUNC
3859 DeviceRef dev{VerifyDevice(device)};
3860 if(!dev || dev->Type != DeviceType::Capture)
3862 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3863 return;
3866 if(samples < 0 || (samples > 0 && buffer == nullptr))
3868 alcSetError(dev.get(), ALC_INVALID_VALUE);
3869 return;
3871 if(samples < 1)
3872 return;
3874 std::lock_guard<std::mutex> _{dev->StateLock};
3875 BackendBase *backend{dev->Backend.get()};
3877 const auto usamples = static_cast<ALCuint>(samples);
3878 if(usamples > backend->availableSamples())
3880 alcSetError(dev.get(), ALC_INVALID_VALUE);
3881 return;
3884 auto *bbuffer = static_cast<al::byte*>(buffer);
3885 if(ALCenum err{backend->captureSamples(bbuffer, usamples)})
3886 alcSetError(dev.get(), err);
3888 END_API_FUNC
3891 /************************************************
3892 * ALC loopback functions
3893 ************************************************/
3895 /** Open a loopback device, for manual rendering. */
3896 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3897 START_API_FUNC
3899 DO_INITCONFIG();
3901 /* Make sure the device name, if specified, is us. */
3902 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3904 alcSetError(nullptr, ALC_INVALID_VALUE);
3905 return nullptr;
3908 DeviceRef device{new ALCdevice{DeviceType::Loopback}};
3910 device->SourcesMax = 256;
3911 device->AuxiliaryEffectSlotMax = 64;
3912 device->NumAuxSends = DEFAULT_SENDS;
3914 //Set output format
3915 device->BufferSize = 0;
3916 device->UpdateSize = 0;
3918 device->Frequency = DEFAULT_OUTPUT_RATE;
3919 device->FmtChans = DevFmtChannelsDefault;
3920 device->FmtType = DevFmtTypeDefault;
3922 if(auto srcsmax = ConfigValueUInt(nullptr, nullptr, "sources").value_or(0))
3923 device->SourcesMax = srcsmax;
3925 if(auto slotsmax = ConfigValueUInt(nullptr, nullptr, "slots").value_or(0))
3926 device->AuxiliaryEffectSlotMax = minu(slotsmax, INT_MAX);
3928 if(auto sendsopt = ConfigValueInt(nullptr, nullptr, "sends"))
3929 device->NumAuxSends = minu(DEFAULT_SENDS,
3930 static_cast<ALuint>(clampi(*sendsopt, 0, MAX_SENDS)));
3932 device->NumStereoSources = 1;
3933 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3935 try {
3936 auto backend = LoopbackBackendFactory::getFactory().createBackend(device.get(),
3937 BackendType::Playback);
3938 backend->open("Loopback");
3939 device->Backend = std::move(backend);
3941 catch(al::backend_exception &e) {
3942 WARN("Failed to open loopback device: %s\n", e.what());
3943 alcSetError(nullptr, e.errorCode());
3944 return nullptr;
3948 std::lock_guard<std::recursive_mutex> _{ListLock};
3949 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3950 DeviceList.emplace(iter, device.get());
3953 TRACE("Created loopback device %p\n", decltype(std::declval<void*>()){device.get()});
3954 return device.release();
3956 END_API_FUNC
3959 * Determines if the loopback device supports the given format for rendering.
3961 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3962 START_API_FUNC
3964 DeviceRef dev{VerifyDevice(device)};
3965 if(!dev || dev->Type != DeviceType::Loopback)
3966 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3967 else if(freq <= 0)
3968 alcSetError(dev.get(), ALC_INVALID_VALUE);
3969 else
3971 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE
3972 && freq <= MAX_OUTPUT_RATE)
3973 return ALC_TRUE;
3976 return ALC_FALSE;
3978 END_API_FUNC
3981 * Renders some samples into a buffer, using the format last set by the
3982 * attributes given to alcCreateContext.
3984 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3985 START_API_FUNC
3987 DeviceRef dev{VerifyDevice(device)};
3988 if(!dev || dev->Type != DeviceType::Loopback)
3989 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3990 else if(samples < 0 || (samples > 0 && buffer == nullptr))
3991 alcSetError(dev.get(), ALC_INVALID_VALUE);
3992 else
3993 dev->renderSamples(buffer, static_cast<ALuint>(samples), dev->channelsFromFmt());
3995 END_API_FUNC
3998 /************************************************
3999 * ALC DSP pause/resume functions
4000 ************************************************/
4002 /** Pause the DSP to stop audio processing. */
4003 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4004 START_API_FUNC
4006 DeviceRef dev{VerifyDevice(device)};
4007 if(!dev || dev->Type != DeviceType::Playback)
4008 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4009 else
4011 std::lock_guard<std::mutex> _{dev->StateLock};
4012 if(dev->Flags.get<DeviceRunning>())
4013 dev->Backend->stop();
4014 dev->Flags.unset<DeviceRunning>();
4015 dev->Flags.set<DevicePaused>();
4018 END_API_FUNC
4020 /** Resume the DSP to restart audio processing. */
4021 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4022 START_API_FUNC
4024 DeviceRef dev{VerifyDevice(device)};
4025 if(!dev || dev->Type != DeviceType::Playback)
4027 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4028 return;
4031 std::lock_guard<std::mutex> _{dev->StateLock};
4032 if(!dev->Flags.get<DevicePaused>())
4033 return;
4034 dev->Flags.unset<DevicePaused>();
4035 if(dev->mContexts.load()->empty())
4036 return;
4038 try {
4039 auto backend = dev->Backend.get();
4040 backend->start();
4041 dev->Flags.set<DeviceRunning>();
4043 catch(al::backend_exception& e) {
4044 dev->handleDisconnect("%s", e.what());
4045 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4048 END_API_FUNC
4051 /************************************************
4052 * ALC HRTF functions
4053 ************************************************/
4055 /** Gets a string parameter at the given index. */
4056 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4057 START_API_FUNC
4059 DeviceRef dev{VerifyDevice(device)};
4060 if(!dev || dev->Type == DeviceType::Capture)
4061 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4062 else switch(paramName)
4064 case ALC_HRTF_SPECIFIER_SOFT:
4065 if(index >= 0 && static_cast<size_t>(index) < dev->HrtfList.size())
4066 return dev->HrtfList[static_cast<ALuint>(index)].c_str();
4067 alcSetError(dev.get(), ALC_INVALID_VALUE);
4068 break;
4070 default:
4071 alcSetError(dev.get(), ALC_INVALID_ENUM);
4072 break;
4075 return nullptr;
4077 END_API_FUNC
4079 /** Resets the given device output, using the specified attribute list. */
4080 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4081 START_API_FUNC
4083 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4084 DeviceRef dev{VerifyDevice(device)};
4085 if(!dev || dev->Type == DeviceType::Capture)
4087 listlock.unlock();
4088 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4089 return ALC_FALSE;
4091 std::lock_guard<std::mutex> _{dev->StateLock};
4092 listlock.unlock();
4094 /* Force the backend to stop mixing first since we're resetting. Also reset
4095 * the connected state so lost devices can attempt recover.
4097 if(dev->Flags.get<DeviceRunning>())
4098 dev->Backend->stop();
4099 dev->Flags.unset<DeviceRunning>();
4100 if(!dev->Connected.load(std::memory_order_relaxed))
4102 /* Make sure disconnection is finished before continuing on. */
4103 dev->waitForMix();
4105 for(ALCcontext *ctx : *dev->mContexts.load(std::memory_order_acquire))
4107 /* Clear any pending voice changes and reallocate voices to get a
4108 * clean restart.
4110 std::lock_guard<std::mutex> __{ctx->mSourceLock};
4111 auto *vchg = ctx->mCurrentVoiceChange.load(std::memory_order_acquire);
4112 while(auto *next = vchg->mNext.load(std::memory_order_acquire))
4113 vchg = next;
4114 ctx->mCurrentVoiceChange.store(vchg, std::memory_order_release);
4116 ctx->mVoiceClusters.clear();
4117 ctx->allocVoices(std::max<size_t>(256,
4118 ctx->mActiveVoiceCount.load(std::memory_order_relaxed)));
4121 dev->Connected.store(true);
4124 ALCenum err{UpdateDeviceParams(dev.get(), attribs)};
4125 if LIKELY(err == ALC_NO_ERROR) return ALC_TRUE;
4127 alcSetError(dev.get(), err);
4128 return ALC_FALSE;
4130 END_API_FUNC