Pass a BufferStorage to EffectState::createBuffer
[openal-soft.git] / alc / alc.cpp
blob7841df288a69ecba59c661f2003b5b0059c25e1d
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 #undef DECL
409 #define DECL(x) { #x, (x) }
410 constexpr struct {
411 const ALCchar *enumName;
412 ALCenum value;
413 } alcEnumerations[] = {
414 DECL(ALC_INVALID),
415 DECL(ALC_FALSE),
416 DECL(ALC_TRUE),
418 DECL(ALC_MAJOR_VERSION),
419 DECL(ALC_MINOR_VERSION),
420 DECL(ALC_ATTRIBUTES_SIZE),
421 DECL(ALC_ALL_ATTRIBUTES),
422 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
423 DECL(ALC_DEVICE_SPECIFIER),
424 DECL(ALC_ALL_DEVICES_SPECIFIER),
425 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
426 DECL(ALC_EXTENSIONS),
427 DECL(ALC_FREQUENCY),
428 DECL(ALC_REFRESH),
429 DECL(ALC_SYNC),
430 DECL(ALC_MONO_SOURCES),
431 DECL(ALC_STEREO_SOURCES),
432 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
433 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
434 DECL(ALC_CAPTURE_SAMPLES),
435 DECL(ALC_CONNECTED),
437 DECL(ALC_EFX_MAJOR_VERSION),
438 DECL(ALC_EFX_MINOR_VERSION),
439 DECL(ALC_MAX_AUXILIARY_SENDS),
441 DECL(ALC_FORMAT_CHANNELS_SOFT),
442 DECL(ALC_FORMAT_TYPE_SOFT),
444 DECL(ALC_MONO_SOFT),
445 DECL(ALC_STEREO_SOFT),
446 DECL(ALC_QUAD_SOFT),
447 DECL(ALC_5POINT1_SOFT),
448 DECL(ALC_6POINT1_SOFT),
449 DECL(ALC_7POINT1_SOFT),
450 DECL(ALC_BFORMAT3D_SOFT),
452 DECL(ALC_BYTE_SOFT),
453 DECL(ALC_UNSIGNED_BYTE_SOFT),
454 DECL(ALC_SHORT_SOFT),
455 DECL(ALC_UNSIGNED_SHORT_SOFT),
456 DECL(ALC_INT_SOFT),
457 DECL(ALC_UNSIGNED_INT_SOFT),
458 DECL(ALC_FLOAT_SOFT),
460 DECL(ALC_HRTF_SOFT),
461 DECL(ALC_DONT_CARE_SOFT),
462 DECL(ALC_HRTF_STATUS_SOFT),
463 DECL(ALC_HRTF_DISABLED_SOFT),
464 DECL(ALC_HRTF_ENABLED_SOFT),
465 DECL(ALC_HRTF_DENIED_SOFT),
466 DECL(ALC_HRTF_REQUIRED_SOFT),
467 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
468 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
469 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
470 DECL(ALC_HRTF_SPECIFIER_SOFT),
471 DECL(ALC_HRTF_ID_SOFT),
473 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
474 DECL(ALC_AMBISONIC_SCALING_SOFT),
475 DECL(ALC_AMBISONIC_ORDER_SOFT),
476 DECL(ALC_ACN_SOFT),
477 DECL(ALC_FUMA_SOFT),
478 DECL(ALC_N3D_SOFT),
479 DECL(ALC_SN3D_SOFT),
481 DECL(ALC_OUTPUT_LIMITER_SOFT),
483 DECL(ALC_NO_ERROR),
484 DECL(ALC_INVALID_DEVICE),
485 DECL(ALC_INVALID_CONTEXT),
486 DECL(ALC_INVALID_ENUM),
487 DECL(ALC_INVALID_VALUE),
488 DECL(ALC_OUT_OF_MEMORY),
491 DECL(AL_INVALID),
492 DECL(AL_NONE),
493 DECL(AL_FALSE),
494 DECL(AL_TRUE),
496 DECL(AL_SOURCE_RELATIVE),
497 DECL(AL_CONE_INNER_ANGLE),
498 DECL(AL_CONE_OUTER_ANGLE),
499 DECL(AL_PITCH),
500 DECL(AL_POSITION),
501 DECL(AL_DIRECTION),
502 DECL(AL_VELOCITY),
503 DECL(AL_LOOPING),
504 DECL(AL_BUFFER),
505 DECL(AL_GAIN),
506 DECL(AL_MIN_GAIN),
507 DECL(AL_MAX_GAIN),
508 DECL(AL_ORIENTATION),
509 DECL(AL_REFERENCE_DISTANCE),
510 DECL(AL_ROLLOFF_FACTOR),
511 DECL(AL_CONE_OUTER_GAIN),
512 DECL(AL_MAX_DISTANCE),
513 DECL(AL_SEC_OFFSET),
514 DECL(AL_SAMPLE_OFFSET),
515 DECL(AL_BYTE_OFFSET),
516 DECL(AL_SOURCE_TYPE),
517 DECL(AL_STATIC),
518 DECL(AL_STREAMING),
519 DECL(AL_UNDETERMINED),
520 DECL(AL_METERS_PER_UNIT),
521 DECL(AL_LOOP_POINTS_SOFT),
522 DECL(AL_DIRECT_CHANNELS_SOFT),
524 DECL(AL_DIRECT_FILTER),
525 DECL(AL_AUXILIARY_SEND_FILTER),
526 DECL(AL_AIR_ABSORPTION_FACTOR),
527 DECL(AL_ROOM_ROLLOFF_FACTOR),
528 DECL(AL_CONE_OUTER_GAINHF),
529 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
530 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
531 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
533 DECL(AL_SOURCE_STATE),
534 DECL(AL_INITIAL),
535 DECL(AL_PLAYING),
536 DECL(AL_PAUSED),
537 DECL(AL_STOPPED),
539 DECL(AL_BUFFERS_QUEUED),
540 DECL(AL_BUFFERS_PROCESSED),
542 DECL(AL_FORMAT_MONO8),
543 DECL(AL_FORMAT_MONO16),
544 DECL(AL_FORMAT_MONO_FLOAT32),
545 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
546 DECL(AL_FORMAT_STEREO8),
547 DECL(AL_FORMAT_STEREO16),
548 DECL(AL_FORMAT_STEREO_FLOAT32),
549 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
550 DECL(AL_FORMAT_MONO_IMA4),
551 DECL(AL_FORMAT_STEREO_IMA4),
552 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
553 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
554 DECL(AL_FORMAT_QUAD8_LOKI),
555 DECL(AL_FORMAT_QUAD16_LOKI),
556 DECL(AL_FORMAT_QUAD8),
557 DECL(AL_FORMAT_QUAD16),
558 DECL(AL_FORMAT_QUAD32),
559 DECL(AL_FORMAT_51CHN8),
560 DECL(AL_FORMAT_51CHN16),
561 DECL(AL_FORMAT_51CHN32),
562 DECL(AL_FORMAT_61CHN8),
563 DECL(AL_FORMAT_61CHN16),
564 DECL(AL_FORMAT_61CHN32),
565 DECL(AL_FORMAT_71CHN8),
566 DECL(AL_FORMAT_71CHN16),
567 DECL(AL_FORMAT_71CHN32),
568 DECL(AL_FORMAT_REAR8),
569 DECL(AL_FORMAT_REAR16),
570 DECL(AL_FORMAT_REAR32),
571 DECL(AL_FORMAT_MONO_MULAW),
572 DECL(AL_FORMAT_MONO_MULAW_EXT),
573 DECL(AL_FORMAT_STEREO_MULAW),
574 DECL(AL_FORMAT_STEREO_MULAW_EXT),
575 DECL(AL_FORMAT_QUAD_MULAW),
576 DECL(AL_FORMAT_51CHN_MULAW),
577 DECL(AL_FORMAT_61CHN_MULAW),
578 DECL(AL_FORMAT_71CHN_MULAW),
579 DECL(AL_FORMAT_REAR_MULAW),
580 DECL(AL_FORMAT_MONO_ALAW_EXT),
581 DECL(AL_FORMAT_STEREO_ALAW_EXT),
583 DECL(AL_FORMAT_BFORMAT2D_8),
584 DECL(AL_FORMAT_BFORMAT2D_16),
585 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
586 DECL(AL_FORMAT_BFORMAT2D_MULAW),
587 DECL(AL_FORMAT_BFORMAT3D_8),
588 DECL(AL_FORMAT_BFORMAT3D_16),
589 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
590 DECL(AL_FORMAT_BFORMAT3D_MULAW),
592 DECL(AL_FREQUENCY),
593 DECL(AL_BITS),
594 DECL(AL_CHANNELS),
595 DECL(AL_SIZE),
596 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
597 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
599 DECL(AL_SOURCE_RADIUS),
601 DECL(AL_STEREO_ANGLES),
603 DECL(AL_UNUSED),
604 DECL(AL_PENDING),
605 DECL(AL_PROCESSED),
607 DECL(AL_NO_ERROR),
608 DECL(AL_INVALID_NAME),
609 DECL(AL_INVALID_ENUM),
610 DECL(AL_INVALID_VALUE),
611 DECL(AL_INVALID_OPERATION),
612 DECL(AL_OUT_OF_MEMORY),
614 DECL(AL_VENDOR),
615 DECL(AL_VERSION),
616 DECL(AL_RENDERER),
617 DECL(AL_EXTENSIONS),
619 DECL(AL_DOPPLER_FACTOR),
620 DECL(AL_DOPPLER_VELOCITY),
621 DECL(AL_DISTANCE_MODEL),
622 DECL(AL_SPEED_OF_SOUND),
623 DECL(AL_SOURCE_DISTANCE_MODEL),
624 DECL(AL_DEFERRED_UPDATES_SOFT),
625 DECL(AL_GAIN_LIMIT_SOFT),
627 DECL(AL_INVERSE_DISTANCE),
628 DECL(AL_INVERSE_DISTANCE_CLAMPED),
629 DECL(AL_LINEAR_DISTANCE),
630 DECL(AL_LINEAR_DISTANCE_CLAMPED),
631 DECL(AL_EXPONENT_DISTANCE),
632 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
634 DECL(AL_FILTER_TYPE),
635 DECL(AL_FILTER_NULL),
636 DECL(AL_FILTER_LOWPASS),
637 DECL(AL_FILTER_HIGHPASS),
638 DECL(AL_FILTER_BANDPASS),
640 DECL(AL_LOWPASS_GAIN),
641 DECL(AL_LOWPASS_GAINHF),
643 DECL(AL_HIGHPASS_GAIN),
644 DECL(AL_HIGHPASS_GAINLF),
646 DECL(AL_BANDPASS_GAIN),
647 DECL(AL_BANDPASS_GAINHF),
648 DECL(AL_BANDPASS_GAINLF),
650 DECL(AL_EFFECT_TYPE),
651 DECL(AL_EFFECT_NULL),
652 DECL(AL_EFFECT_REVERB),
653 DECL(AL_EFFECT_EAXREVERB),
654 DECL(AL_EFFECT_CHORUS),
655 DECL(AL_EFFECT_DISTORTION),
656 DECL(AL_EFFECT_ECHO),
657 DECL(AL_EFFECT_FLANGER),
658 DECL(AL_EFFECT_PITCH_SHIFTER),
659 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
660 DECL(AL_EFFECT_VOCAL_MORPHER),
661 DECL(AL_EFFECT_RING_MODULATOR),
662 DECL(AL_EFFECT_AUTOWAH),
663 DECL(AL_EFFECT_COMPRESSOR),
664 DECL(AL_EFFECT_EQUALIZER),
665 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
666 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
668 DECL(AL_EFFECTSLOT_EFFECT),
669 DECL(AL_EFFECTSLOT_GAIN),
670 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
671 DECL(AL_EFFECTSLOT_NULL),
673 DECL(AL_EAXREVERB_DENSITY),
674 DECL(AL_EAXREVERB_DIFFUSION),
675 DECL(AL_EAXREVERB_GAIN),
676 DECL(AL_EAXREVERB_GAINHF),
677 DECL(AL_EAXREVERB_GAINLF),
678 DECL(AL_EAXREVERB_DECAY_TIME),
679 DECL(AL_EAXREVERB_DECAY_HFRATIO),
680 DECL(AL_EAXREVERB_DECAY_LFRATIO),
681 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
682 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
683 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
684 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
685 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
686 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
687 DECL(AL_EAXREVERB_ECHO_TIME),
688 DECL(AL_EAXREVERB_ECHO_DEPTH),
689 DECL(AL_EAXREVERB_MODULATION_TIME),
690 DECL(AL_EAXREVERB_MODULATION_DEPTH),
691 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
692 DECL(AL_EAXREVERB_HFREFERENCE),
693 DECL(AL_EAXREVERB_LFREFERENCE),
694 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
695 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
697 DECL(AL_REVERB_DENSITY),
698 DECL(AL_REVERB_DIFFUSION),
699 DECL(AL_REVERB_GAIN),
700 DECL(AL_REVERB_GAINHF),
701 DECL(AL_REVERB_DECAY_TIME),
702 DECL(AL_REVERB_DECAY_HFRATIO),
703 DECL(AL_REVERB_REFLECTIONS_GAIN),
704 DECL(AL_REVERB_REFLECTIONS_DELAY),
705 DECL(AL_REVERB_LATE_REVERB_GAIN),
706 DECL(AL_REVERB_LATE_REVERB_DELAY),
707 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
708 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
709 DECL(AL_REVERB_DECAY_HFLIMIT),
711 DECL(AL_CHORUS_WAVEFORM),
712 DECL(AL_CHORUS_PHASE),
713 DECL(AL_CHORUS_RATE),
714 DECL(AL_CHORUS_DEPTH),
715 DECL(AL_CHORUS_FEEDBACK),
716 DECL(AL_CHORUS_DELAY),
718 DECL(AL_DISTORTION_EDGE),
719 DECL(AL_DISTORTION_GAIN),
720 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
721 DECL(AL_DISTORTION_EQCENTER),
722 DECL(AL_DISTORTION_EQBANDWIDTH),
724 DECL(AL_ECHO_DELAY),
725 DECL(AL_ECHO_LRDELAY),
726 DECL(AL_ECHO_DAMPING),
727 DECL(AL_ECHO_FEEDBACK),
728 DECL(AL_ECHO_SPREAD),
730 DECL(AL_FLANGER_WAVEFORM),
731 DECL(AL_FLANGER_PHASE),
732 DECL(AL_FLANGER_RATE),
733 DECL(AL_FLANGER_DEPTH),
734 DECL(AL_FLANGER_FEEDBACK),
735 DECL(AL_FLANGER_DELAY),
737 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY),
738 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION),
739 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION),
741 DECL(AL_RING_MODULATOR_FREQUENCY),
742 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
743 DECL(AL_RING_MODULATOR_WAVEFORM),
745 DECL(AL_PITCH_SHIFTER_COARSE_TUNE),
746 DECL(AL_PITCH_SHIFTER_FINE_TUNE),
748 DECL(AL_COMPRESSOR_ONOFF),
750 DECL(AL_EQUALIZER_LOW_GAIN),
751 DECL(AL_EQUALIZER_LOW_CUTOFF),
752 DECL(AL_EQUALIZER_MID1_GAIN),
753 DECL(AL_EQUALIZER_MID1_CENTER),
754 DECL(AL_EQUALIZER_MID1_WIDTH),
755 DECL(AL_EQUALIZER_MID2_GAIN),
756 DECL(AL_EQUALIZER_MID2_CENTER),
757 DECL(AL_EQUALIZER_MID2_WIDTH),
758 DECL(AL_EQUALIZER_HIGH_GAIN),
759 DECL(AL_EQUALIZER_HIGH_CUTOFF),
761 DECL(AL_DEDICATED_GAIN),
763 DECL(AL_AUTOWAH_ATTACK_TIME),
764 DECL(AL_AUTOWAH_RELEASE_TIME),
765 DECL(AL_AUTOWAH_RESONANCE),
766 DECL(AL_AUTOWAH_PEAK_GAIN),
768 DECL(AL_VOCAL_MORPHER_PHONEMEA),
769 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING),
770 DECL(AL_VOCAL_MORPHER_PHONEMEB),
771 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING),
772 DECL(AL_VOCAL_MORPHER_WAVEFORM),
773 DECL(AL_VOCAL_MORPHER_RATE),
775 DECL(AL_NUM_RESAMPLERS_SOFT),
776 DECL(AL_DEFAULT_RESAMPLER_SOFT),
777 DECL(AL_SOURCE_RESAMPLER_SOFT),
778 DECL(AL_RESAMPLER_NAME_SOFT),
780 DECL(AL_SOURCE_SPATIALIZE_SOFT),
781 DECL(AL_AUTO_SOFT),
783 DECL(AL_MAP_READ_BIT_SOFT),
784 DECL(AL_MAP_WRITE_BIT_SOFT),
785 DECL(AL_MAP_PERSISTENT_BIT_SOFT),
786 DECL(AL_PRESERVE_DATA_BIT_SOFT),
788 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT),
789 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT),
790 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT),
791 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT),
792 DECL(AL_EVENT_TYPE_ERROR_SOFT),
793 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT),
794 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT),
796 DECL(AL_DROP_UNMATCHED_SOFT),
797 DECL(AL_REMIX_UNMATCHED_SOFT),
799 DECL(AL_AMBISONIC_LAYOUT_SOFT),
800 DECL(AL_AMBISONIC_SCALING_SOFT),
801 DECL(AL_FUMA_SOFT),
802 DECL(AL_ACN_SOFT),
803 DECL(AL_SN3D_SOFT),
804 DECL(AL_N3D_SOFT),
806 DECL(AL_BUFFER_CALLBACK_FUNCTION_SOFT),
807 DECL(AL_BUFFER_CALLBACK_USER_PARAM_SOFT),
809 DECL(AL_UNPACK_AMBISONIC_ORDER_SOFT),
811 #undef DECL
813 constexpr ALCchar alcNoError[] = "No Error";
814 constexpr ALCchar alcErrInvalidDevice[] = "Invalid Device";
815 constexpr ALCchar alcErrInvalidContext[] = "Invalid Context";
816 constexpr ALCchar alcErrInvalidEnum[] = "Invalid Enum";
817 constexpr ALCchar alcErrInvalidValue[] = "Invalid Value";
818 constexpr ALCchar alcErrOutOfMemory[] = "Out of Memory";
821 /************************************************
822 * Global variables
823 ************************************************/
825 /* Enumerated device names */
826 constexpr ALCchar alcDefaultName[] = "OpenAL Soft\0";
828 std::string alcAllDevicesList;
829 std::string alcCaptureDeviceList;
831 /* Default is always the first in the list */
832 al::string alcDefaultAllDevicesSpecifier;
833 al::string alcCaptureDefaultDeviceSpecifier;
835 /* Default context extensions */
836 constexpr ALchar alExtList[] =
837 "AL_EXT_ALAW "
838 "AL_EXT_BFORMAT "
839 "AL_EXT_DOUBLE "
840 "AL_EXT_EXPONENT_DISTANCE "
841 "AL_EXT_FLOAT32 "
842 "AL_EXT_IMA4 "
843 "AL_EXT_LINEAR_DISTANCE "
844 "AL_EXT_MCFORMATS "
845 "AL_EXT_MULAW "
846 "AL_EXT_MULAW_BFORMAT "
847 "AL_EXT_MULAW_MCFORMATS "
848 "AL_EXT_OFFSET "
849 "AL_EXT_source_distance_model "
850 "AL_EXT_SOURCE_RADIUS "
851 "AL_EXT_STEREO_ANGLES "
852 "AL_LOKI_quadriphonic "
853 "AL_SOFT_bformat_ex "
854 "AL_SOFTX_bformat_hoa "
855 "AL_SOFT_block_alignment "
856 "AL_SOFTX_callback_buffer "
857 "AL_SOFT_deferred_updates "
858 "AL_SOFT_direct_channels "
859 "AL_SOFT_direct_channels_remix "
860 "AL_SOFTX_effect_target "
861 "AL_SOFTX_events "
862 "AL_SOFTX_filter_gain_ex "
863 "AL_SOFT_gain_clamp_ex "
864 "AL_SOFT_loop_points "
865 "AL_SOFTX_map_buffer "
866 "AL_SOFT_MSADPCM "
867 "AL_SOFT_source_latency "
868 "AL_SOFT_source_length "
869 "AL_SOFT_source_resampler "
870 "AL_SOFT_source_spatialize";
872 std::atomic<ALCenum> LastNullDeviceError{ALC_NO_ERROR};
874 /* Thread-local current context. The handling may look a little obtuse, but
875 * it's designed this way to avoid a bug with 32-bit GCC/MinGW, which causes
876 * thread-local object destructors to get a junk 'this' pointer. This method
877 * has the benefit of making LocalContext access more efficient since it's a
878 * a plain pointer, with the ThreadContext object used to check it at thread
879 * exit (and given no data fields, 'this' being junk is inconsequential since
880 * it's never accessed).
882 thread_local ALCcontext *LocalContext{nullptr};
883 class ThreadCtx {
884 public:
885 ~ThreadCtx()
887 if(ALCcontext *ctx{LocalContext})
889 const bool result{ctx->releaseIfNoDelete()};
890 ERR("Context %p current for thread being destroyed%s!\n",
891 decltype(std::declval<void*>()){ctx}, result ? "" : ", leak detected");
895 void set(ALCcontext *ctx) const noexcept { LocalContext = ctx; }
897 thread_local ThreadCtx ThreadContext;
899 /* Process-wide current context */
900 std::atomic<ALCcontext*> GlobalContext{nullptr};
902 /* Flag to trap ALC device errors */
903 bool TrapALCError{false};
905 /* One-time configuration init control */
906 std::once_flag alc_config_once{};
908 /* Default effect that applies to sources that don't have an effect on send 0 */
909 ALeffect DefaultEffect;
911 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
912 * updates.
914 bool SuspendDefers{true};
916 /* Initial seed for dithering. */
917 constexpr ALuint DitherRNGSeed{22222u};
920 /************************************************
921 * ALC information
922 ************************************************/
923 constexpr ALCchar alcNoDeviceExtList[] =
924 "ALC_ENUMERATE_ALL_EXT "
925 "ALC_ENUMERATION_EXT "
926 "ALC_EXT_CAPTURE "
927 "ALC_EXT_thread_local_context "
928 "ALC_SOFT_loopback";
929 constexpr ALCchar alcExtensionList[] =
930 "ALC_ENUMERATE_ALL_EXT "
931 "ALC_ENUMERATION_EXT "
932 "ALC_EXT_CAPTURE "
933 "ALC_EXT_DEDICATED "
934 "ALC_EXT_disconnect "
935 "ALC_EXT_EFX "
936 "ALC_EXT_thread_local_context "
937 "ALC_SOFT_device_clock "
938 "ALC_SOFT_HRTF "
939 "ALC_SOFT_loopback "
940 "ALC_SOFT_output_limiter "
941 "ALC_SOFT_pause_device";
942 constexpr int alcMajorVersion{1};
943 constexpr int alcMinorVersion{1};
945 constexpr int alcEFXMajorVersion{1};
946 constexpr int alcEFXMinorVersion{0};
949 /* To avoid extraneous allocations, a 0-sized FlexArray<ALCcontext*> is defined
950 * globally as a sharable object.
952 al::FlexArray<ALCcontext*> EmptyContextArray{0u};
955 using DeviceRef = al::intrusive_ptr<ALCdevice>;
958 /************************************************
959 * Device lists
960 ************************************************/
961 al::vector<ALCdevice*> DeviceList;
962 al::vector<ALCcontext*> ContextList;
964 std::recursive_mutex ListLock;
967 void alc_initconfig(void)
969 if(auto loglevel = al::getenv("ALSOFT_LOGLEVEL"))
971 long lvl = strtol(loglevel->c_str(), nullptr, 0);
972 if(lvl >= NoLog && lvl <= LogRef)
973 gLogLevel = static_cast<LogLevel>(lvl);
976 #ifdef _WIN32
977 if(const auto logfile = al::getenv(L"ALSOFT_LOGFILE"))
979 FILE *logf{_wfopen(logfile->c_str(), L"wt")};
980 if(logf) gLogFile = logf;
981 else
983 auto u8name = wstr_to_utf8(logfile->c_str());
984 ERR("Failed to open log file '%s'\n", u8name.c_str());
987 #else
988 if(const auto logfile = al::getenv("ALSOFT_LOGFILE"))
990 FILE *logf{fopen(logfile->c_str(), "wt")};
991 if(logf) gLogFile = logf;
992 else ERR("Failed to open log file '%s'\n", logfile->c_str());
994 #endif
996 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION, ALSOFT_GIT_COMMIT_HASH,
997 ALSOFT_GIT_BRANCH);
999 al::string names;
1000 if(al::size(BackendList) < 1)
1001 names = "(none)";
1002 else
1004 const al::span<const BackendInfo> infos{BackendList};
1005 names = infos[0].name;
1006 for(const auto &backend : infos.subspan<1>())
1008 names += ", ";
1009 names += backend.name;
1012 TRACE("Supported backends: %s\n", names.c_str());
1014 ReadALConfig();
1016 if(auto suspendmode = al::getenv("__ALSOFT_SUSPEND_CONTEXT"))
1018 if(al::strcasecmp(suspendmode->c_str(), "ignore") == 0)
1020 SuspendDefers = false;
1021 TRACE("Selected context suspend behavior, \"ignore\"\n");
1023 else
1024 ERR("Unhandled context suspend behavior setting: \"%s\"\n", suspendmode->c_str());
1027 int capfilter{0};
1028 #if defined(HAVE_SSE4_1)
1029 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
1030 #elif defined(HAVE_SSE3)
1031 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
1032 #elif defined(HAVE_SSE2)
1033 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
1034 #elif defined(HAVE_SSE)
1035 capfilter |= CPU_CAP_SSE;
1036 #endif
1037 #ifdef HAVE_NEON
1038 capfilter |= CPU_CAP_NEON;
1039 #endif
1040 if(auto cpuopt = ConfigValueStr(nullptr, nullptr, "disable-cpu-exts"))
1042 const char *str{cpuopt->c_str()};
1043 if(al::strcasecmp(str, "all") == 0)
1044 capfilter = 0;
1045 else
1047 const char *next = str;
1048 do {
1049 str = next;
1050 while(isspace(str[0]))
1051 str++;
1052 next = strchr(str, ',');
1054 if(!str[0] || str[0] == ',')
1055 continue;
1057 size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1058 while(len > 0 && isspace(str[len-1]))
1059 len--;
1060 if(len == 3 && al::strncasecmp(str, "sse", len) == 0)
1061 capfilter &= ~CPU_CAP_SSE;
1062 else if(len == 4 && al::strncasecmp(str, "sse2", len) == 0)
1063 capfilter &= ~CPU_CAP_SSE2;
1064 else if(len == 4 && al::strncasecmp(str, "sse3", len) == 0)
1065 capfilter &= ~CPU_CAP_SSE3;
1066 else if(len == 6 && al::strncasecmp(str, "sse4.1", len) == 0)
1067 capfilter &= ~CPU_CAP_SSE4_1;
1068 else if(len == 4 && al::strncasecmp(str, "neon", len) == 0)
1069 capfilter &= ~CPU_CAP_NEON;
1070 else
1071 WARN("Invalid CPU extension \"%s\"\n", str);
1072 } while(next++);
1075 FillCPUCaps(capfilter);
1077 if(auto priopt = ConfigValueInt(nullptr, nullptr, "rt-prio"))
1078 RTPrioLevel = *priopt;
1080 aluInit();
1081 aluInitMixer();
1083 auto traperr = al::getenv("ALSOFT_TRAP_ERROR");
1084 if(traperr && (al::strcasecmp(traperr->c_str(), "true") == 0
1085 || std::strtol(traperr->c_str(), nullptr, 0) == 1))
1087 TrapALError = true;
1088 TrapALCError = true;
1090 else
1092 traperr = al::getenv("ALSOFT_TRAP_AL_ERROR");
1093 if(traperr)
1094 TrapALError = al::strcasecmp(traperr->c_str(), "true") == 0
1095 || strtol(traperr->c_str(), nullptr, 0) == 1;
1096 else
1097 TrapALError = !!GetConfigValueBool(nullptr, nullptr, "trap-al-error", false);
1099 traperr = al::getenv("ALSOFT_TRAP_ALC_ERROR");
1100 if(traperr)
1101 TrapALCError = al::strcasecmp(traperr->c_str(), "true") == 0
1102 || strtol(traperr->c_str(), nullptr, 0) == 1;
1103 else
1104 TrapALCError = !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", false);
1107 if(auto boostopt = ConfigValueFloat(nullptr, "reverb", "boost"))
1109 const float valf{std::isfinite(*boostopt) ? clampf(*boostopt, -24.0f, 24.0f) : 0.0f};
1110 ReverbBoost *= std::pow(10.0f, valf / 20.0f);
1113 auto BackendListEnd = std::end(BackendList);
1114 auto devopt = al::getenv("ALSOFT_DRIVERS");
1115 if(devopt || (devopt=ConfigValueStr(nullptr, nullptr, "drivers")))
1117 auto backendlist_cur = std::begin(BackendList);
1119 bool endlist{true};
1120 const char *next{devopt->c_str()};
1121 do {
1122 const char *devs{next};
1123 while(isspace(devs[0]))
1124 devs++;
1125 next = strchr(devs, ',');
1127 const bool delitem{devs[0] == '-'};
1128 if(devs[0] == '-') devs++;
1130 if(!devs[0] || devs[0] == ',')
1132 endlist = false;
1133 continue;
1135 endlist = true;
1137 size_t len{next ? (static_cast<size_t>(next-devs)) : strlen(devs)};
1138 while(len > 0 && isspace(devs[len-1])) --len;
1139 #ifdef HAVE_WASAPI
1140 /* HACK: For backwards compatibility, convert backend references of
1141 * mmdevapi to wasapi. This should eventually be removed.
1143 if(len == 8 && strncmp(devs, "mmdevapi", len) == 0)
1145 devs = "wasapi";
1146 len = 6;
1148 #endif
1150 auto find_backend = [devs,len](const BackendInfo &backend) -> bool
1151 { return len == strlen(backend.name) && strncmp(backend.name, devs, len) == 0; };
1152 auto this_backend = std::find_if(std::begin(BackendList), BackendListEnd,
1153 find_backend);
1155 if(this_backend == BackendListEnd)
1156 continue;
1158 if(delitem)
1159 BackendListEnd = std::move(this_backend+1, BackendListEnd, this_backend);
1160 else
1161 backendlist_cur = std::rotate(backendlist_cur, this_backend, this_backend+1);
1162 } while(next++);
1164 if(endlist)
1165 BackendListEnd = backendlist_cur;
1168 auto init_backend = [](BackendInfo &backend) -> void
1170 if(PlaybackFactory && CaptureFactory)
1171 return;
1173 BackendFactory &factory = backend.getFactory();
1174 if(!factory.init())
1176 WARN("Failed to initialize backend \"%s\"\n", backend.name);
1177 return;
1180 TRACE("Initialized backend \"%s\"\n", backend.name);
1181 if(!PlaybackFactory && factory.querySupport(BackendType::Playback))
1183 PlaybackFactory = &factory;
1184 TRACE("Added \"%s\" for playback\n", backend.name);
1186 if(!CaptureFactory && factory.querySupport(BackendType::Capture))
1188 CaptureFactory = &factory;
1189 TRACE("Added \"%s\" for capture\n", backend.name);
1192 std::for_each(std::begin(BackendList), BackendListEnd, init_backend);
1194 LoopbackBackendFactory::getFactory().init();
1196 if(!PlaybackFactory)
1197 WARN("No playback backend available!\n");
1198 if(!CaptureFactory)
1199 WARN("No capture backend available!\n");
1201 if(auto exclopt = ConfigValueStr(nullptr, nullptr, "excludefx"))
1203 const char *next{exclopt->c_str()};
1204 do {
1205 const char *str{next};
1206 next = strchr(str, ',');
1208 if(!str[0] || next == str)
1209 continue;
1211 size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1212 for(const EffectList &effectitem : gEffectList)
1214 if(len == strlen(effectitem.name) &&
1215 strncmp(effectitem.name, str, len) == 0)
1216 DisabledEffects[effectitem.type] = true;
1218 } while(next++);
1221 InitEffect(&DefaultEffect);
1222 auto defrevopt = al::getenv("ALSOFT_DEFAULT_REVERB");
1223 if(defrevopt || (defrevopt=ConfigValueStr(nullptr, nullptr, "default-reverb")))
1224 LoadReverbPreset(defrevopt->c_str(), &DefaultEffect);
1226 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1229 /************************************************
1230 * Device enumeration
1231 ************************************************/
1232 void ProbeAllDevicesList()
1234 DO_INITCONFIG();
1236 std::lock_guard<std::recursive_mutex> _{ListLock};
1237 if(!PlaybackFactory)
1238 decltype(alcAllDevicesList){}.swap(alcAllDevicesList);
1239 else
1241 std::string names{PlaybackFactory->probe(BackendType::Playback)};
1242 if(names.empty()) names += '\0';
1243 names.swap(alcAllDevicesList);
1246 void ProbeCaptureDeviceList()
1248 DO_INITCONFIG();
1250 std::lock_guard<std::recursive_mutex> _{ListLock};
1251 if(!CaptureFactory)
1252 decltype(alcCaptureDeviceList){}.swap(alcCaptureDeviceList);
1253 else
1255 std::string names{CaptureFactory->probe(BackendType::Capture)};
1256 if(names.empty()) names += '\0';
1257 names.swap(alcCaptureDeviceList);
1261 } // namespace
1263 /* Mixing thread piority level */
1264 int RTPrioLevel{1};
1266 FILE *gLogFile{stderr};
1267 #ifdef _DEBUG
1268 LogLevel gLogLevel{LogWarning};
1269 #else
1270 LogLevel gLogLevel{LogError};
1271 #endif
1273 /************************************************
1274 * Library initialization
1275 ************************************************/
1276 #if defined(_WIN32) && !defined(AL_LIBTYPE_STATIC)
1277 BOOL APIENTRY DllMain(HINSTANCE module, DWORD reason, LPVOID /*reserved*/)
1279 switch(reason)
1281 case DLL_PROCESS_ATTACH:
1282 /* Pin the DLL so we won't get unloaded until the process terminates */
1283 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
1284 reinterpret_cast<WCHAR*>(module), &module);
1285 break;
1287 return TRUE;
1289 #endif
1291 /************************************************
1292 * Device format information
1293 ************************************************/
1294 const ALCchar *DevFmtTypeString(DevFmtType type) noexcept
1296 switch(type)
1298 case DevFmtByte: return "Int8";
1299 case DevFmtUByte: return "UInt8";
1300 case DevFmtShort: return "Int16";
1301 case DevFmtUShort: return "UInt16";
1302 case DevFmtInt: return "Int32";
1303 case DevFmtUInt: return "UInt32";
1304 case DevFmtFloat: return "Float32";
1306 return "(unknown type)";
1308 const ALCchar *DevFmtChannelsString(DevFmtChannels chans) noexcept
1310 switch(chans)
1312 case DevFmtMono: return "Mono";
1313 case DevFmtStereo: return "Stereo";
1314 case DevFmtQuad: return "Quadraphonic";
1315 case DevFmtX51: return "5.1 Surround";
1316 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1317 case DevFmtX61: return "6.1 Surround";
1318 case DevFmtX71: return "7.1 Surround";
1319 case DevFmtAmbi3D: return "Ambisonic 3D";
1321 return "(unknown channels)";
1324 ALuint BytesFromDevFmt(DevFmtType type) noexcept
1326 switch(type)
1328 case DevFmtByte: return sizeof(int8_t);
1329 case DevFmtUByte: return sizeof(uint8_t);
1330 case DevFmtShort: return sizeof(int16_t);
1331 case DevFmtUShort: return sizeof(uint16_t);
1332 case DevFmtInt: return sizeof(int32_t);
1333 case DevFmtUInt: return sizeof(uint32_t);
1334 case DevFmtFloat: return sizeof(float);
1336 return 0;
1338 ALuint ChannelsFromDevFmt(DevFmtChannels chans, ALuint ambiorder) noexcept
1340 switch(chans)
1342 case DevFmtMono: return 1;
1343 case DevFmtStereo: return 2;
1344 case DevFmtQuad: return 4;
1345 case DevFmtX51: return 6;
1346 case DevFmtX51Rear: return 6;
1347 case DevFmtX61: return 7;
1348 case DevFmtX71: return 8;
1349 case DevFmtAmbi3D: return (ambiorder+1) * (ambiorder+1);
1351 return 0;
1354 namespace {
1356 struct DevFmtPair { DevFmtChannels chans; DevFmtType type; };
1357 al::optional<DevFmtPair> DecomposeDevFormat(ALenum format)
1359 static const struct {
1360 ALenum format;
1361 DevFmtChannels channels;
1362 DevFmtType type;
1363 } list[] = {
1364 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1365 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1366 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1368 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1369 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1370 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1372 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1373 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1374 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1376 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1377 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1378 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1380 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1381 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1382 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1384 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1385 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1386 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1389 for(const auto &item : list)
1391 if(item.format == format)
1392 return al::make_optional(DevFmtPair{item.channels, item.type});
1395 return al::nullopt;
1398 bool IsValidALCType(ALCenum type)
1400 switch(type)
1402 case ALC_BYTE_SOFT:
1403 case ALC_UNSIGNED_BYTE_SOFT:
1404 case ALC_SHORT_SOFT:
1405 case ALC_UNSIGNED_SHORT_SOFT:
1406 case ALC_INT_SOFT:
1407 case ALC_UNSIGNED_INT_SOFT:
1408 case ALC_FLOAT_SOFT:
1409 return true;
1411 return false;
1414 bool IsValidALCChannels(ALCenum channels)
1416 switch(channels)
1418 case ALC_MONO_SOFT:
1419 case ALC_STEREO_SOFT:
1420 case ALC_QUAD_SOFT:
1421 case ALC_5POINT1_SOFT:
1422 case ALC_6POINT1_SOFT:
1423 case ALC_7POINT1_SOFT:
1424 case ALC_BFORMAT3D_SOFT:
1425 return true;
1427 return false;
1430 bool IsValidAmbiLayout(ALCenum layout)
1432 switch(layout)
1434 case ALC_ACN_SOFT:
1435 case ALC_FUMA_SOFT:
1436 return true;
1438 return false;
1441 bool IsValidAmbiScaling(ALCenum scaling)
1443 switch(scaling)
1445 case ALC_N3D_SOFT:
1446 case ALC_SN3D_SOFT:
1447 case ALC_FUMA_SOFT:
1448 return true;
1450 return false;
1454 /* Downmixing channel arrays, to map the given format's missing channels to
1455 * existing ones. Based on Wine's DSound downmix values, which are based on
1456 * PulseAudio's.
1458 const std::array<InputRemixMap,7> MonoDownmix{{
1459 { FrontLeft, {{{FrontCenter, 0.5f}, {LFE, 0.0f}}} },
1460 { FrontRight, {{{FrontCenter, 0.5f}, {LFE, 0.0f}}} },
1461 { SideLeft, {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1462 { SideRight, {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1463 { BackLeft, {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1464 { BackRight, {{{FrontCenter, 0.5f/9.0f}, {LFE, 0.0f}}} },
1465 { BackCenter, {{{FrontCenter, 1.0f/9.0f}, {LFE, 0.0f}}} },
1467 const std::array<InputRemixMap,6> StereoDownmix{{
1468 { FrontCenter, {{{FrontLeft, 0.5f}, {FrontRight, 0.5f}}} },
1469 { SideLeft, {{{FrontLeft, 1.0f/9.0f}, {FrontRight, 0.0f}}} },
1470 { SideRight, {{{FrontLeft, 0.0f}, {FrontRight, 1.0f/9.0f}}} },
1471 { BackLeft, {{{FrontLeft, 1.0f/9.0f}, {FrontRight, 0.0f}}} },
1472 { BackRight, {{{FrontLeft, 0.0f}, {FrontRight, 1.0f/9.0f}}} },
1473 { BackCenter, {{{FrontLeft, 0.5f/9.0f}, {FrontRight, 0.5f/9.0f}}} },
1475 const std::array<InputRemixMap,4> QuadDownmix{{
1476 { FrontCenter, {{{FrontLeft, 0.5f}, {FrontRight, 0.5f}}} },
1477 { SideLeft, {{{FrontLeft, 0.5f}, {BackLeft, 0.5f}}} },
1478 { SideRight, {{{FrontRight, 0.5f}, {BackRight, 0.5f}}} },
1479 { BackCenter, {{{BackLeft, 0.5f}, {BackRight, 0.5f}}} },
1481 const std::array<InputRemixMap,3> X51Downmix{{
1482 { BackLeft, {{{SideLeft, 1.0f}, {SideRight, 0.0f}}} },
1483 { BackRight, {{{SideLeft, 0.0f}, {SideRight, 1.0f}}} },
1484 { BackCenter, {{{SideLeft, 0.5f}, {SideRight, 0.5f}}} },
1486 const std::array<InputRemixMap,3> X51RearDownmix{{
1487 { SideLeft, {{{BackLeft, 1.0f}, {BackRight, 0.0f}}} },
1488 { SideRight, {{{BackLeft, 0.0f}, {BackRight, 1.0f}}} },
1489 { BackCenter, {{{BackLeft, 0.5f}, {BackRight, 0.5f}}} },
1491 const std::array<InputRemixMap,2> X61Downmix{{
1492 { BackLeft, {{{BackCenter, 0.5f}, {SideLeft, 0.5f}}} },
1493 { BackRight, {{{BackCenter, 0.5f}, {SideRight, 0.5f}}} },
1495 const std::array<InputRemixMap,1> X71Downmix{{
1496 { BackCenter, {{{BackLeft, 0.5f}, {BackRight, 0.5f}}} },
1499 } // namespace
1501 /************************************************
1502 * Miscellaneous ALC helpers
1503 ************************************************/
1505 void ALCcontext::processUpdates()
1507 std::lock_guard<std::mutex> _{mPropLock};
1508 if(mDeferUpdates.exchange(false, std::memory_order_acq_rel))
1510 /* Tell the mixer to stop applying updates, then wait for any active
1511 * updating to finish, before providing updates.
1513 mHoldUpdates.store(true, std::memory_order_release);
1514 while((mUpdateCount.load(std::memory_order_acquire)&1) != 0) {
1515 /* busy-wait */
1518 if(!mPropsClean.test_and_set(std::memory_order_acq_rel))
1519 UpdateContextProps(this);
1520 if(!mListener.PropsClean.test_and_set(std::memory_order_acq_rel))
1521 UpdateListenerProps(this);
1522 UpdateAllEffectSlotProps(this);
1523 UpdateAllSourceProps(this);
1525 /* Now with all updates declared, let the mixer continue applying them
1526 * so they all happen at once.
1528 mHoldUpdates.store(false, std::memory_order_release);
1533 void ALCcontext::allocVoiceChanges(size_t addcount)
1535 constexpr size_t clustersize{128};
1536 /* Convert element count to cluster count. */
1537 addcount = (addcount+(clustersize-1)) / clustersize;
1538 while(addcount)
1540 VoiceChangeCluster cluster{std::make_unique<VoiceChange[]>(clustersize)};
1541 for(size_t i{1};i < clustersize;++i)
1542 cluster[i-1].mNext.store(std::addressof(cluster[i]), std::memory_order_relaxed);
1543 cluster[clustersize-1].mNext.store(mVoiceChangeTail, std::memory_order_relaxed);
1544 mVoiceChangeClusters.emplace_back(std::move(cluster));
1545 mVoiceChangeTail = mVoiceChangeClusters.back().get();
1546 --addcount;
1550 void ALCcontext::allocVoices(size_t addcount)
1552 constexpr size_t clustersize{32};
1553 /* Convert element count to cluster count. */
1554 addcount = (addcount+(clustersize-1)) / clustersize;
1556 if(addcount >= std::numeric_limits<int>::max()/clustersize - mVoiceClusters.size())
1557 throw std::runtime_error{"Allocating too many voices"};
1558 const size_t totalcount{(mVoiceClusters.size()+addcount) * clustersize};
1559 TRACE("Increasing allocated voices to %zu\n", totalcount);
1561 auto newarray = VoiceArray::Create(totalcount);
1562 while(addcount)
1564 mVoiceClusters.emplace_back(std::make_unique<Voice[]>(clustersize));
1565 --addcount;
1568 auto voice_iter = newarray->begin();
1569 for(VoiceCluster &cluster : mVoiceClusters)
1571 for(size_t i{0};i < clustersize;++i)
1572 *(voice_iter++) = &cluster[i];
1575 if(auto *oldvoices = mVoices.exchange(newarray.release(), std::memory_order_acq_rel))
1577 mDevice->waitForMix();
1578 delete oldvoices;
1583 /** Stores the latest ALC device error. */
1584 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1586 WARN("Error generated on device %p, code 0x%04x\n", decltype(std::declval<void*>()){device},
1587 errorCode);
1588 if(TrapALCError)
1590 #ifdef _WIN32
1591 /* DebugBreak() will cause an exception if there is no debugger */
1592 if(IsDebuggerPresent())
1593 DebugBreak();
1594 #elif defined(SIGTRAP)
1595 raise(SIGTRAP);
1596 #endif
1599 if(device)
1600 device->LastError.store(errorCode);
1601 else
1602 LastNullDeviceError.store(errorCode);
1606 static std::unique_ptr<Compressor> CreateDeviceLimiter(const ALCdevice *device, const float threshold)
1608 constexpr bool AutoKnee{true};
1609 constexpr bool AutoAttack{true};
1610 constexpr bool AutoRelease{true};
1611 constexpr bool AutoPostGain{true};
1612 constexpr bool AutoDeclip{true};
1613 constexpr float LookAheadTime{0.001f};
1614 constexpr float HoldTime{0.002f};
1615 constexpr float PreGainDb{0.0f};
1616 constexpr float PostGainDb{0.0f};
1617 constexpr float Ratio{std::numeric_limits<float>::infinity()};
1618 constexpr float KneeDb{0.0f};
1619 constexpr float AttackTime{0.02f};
1620 constexpr float ReleaseTime{0.2f};
1622 return Compressor::Create(device->RealOut.Buffer.size(), static_cast<float>(device->Frequency),
1623 AutoKnee, AutoAttack, AutoRelease, AutoPostGain, AutoDeclip, LookAheadTime, HoldTime,
1624 PreGainDb, PostGainDb, threshold, Ratio, KneeDb, AttackTime, ReleaseTime);
1628 * Updates the device's base clock time with however many samples have been
1629 * done. This is used so frequency changes on the device don't cause the time
1630 * to jump forward or back. Must not be called while the device is running/
1631 * mixing.
1633 static inline void UpdateClockBase(ALCdevice *device)
1635 IncrementRef(device->MixCount);
1636 device->ClockBase += nanoseconds{seconds{device->SamplesDone}} / device->Frequency;
1637 device->SamplesDone = 0;
1638 IncrementRef(device->MixCount);
1642 * Updates device parameters according to the attribute list (caller is
1643 * responsible for holding the list lock).
1645 static ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
1647 HrtfRequestMode hrtf_userreq{Hrtf_Default};
1648 HrtfRequestMode hrtf_appreq{Hrtf_Default};
1649 ALCenum gainLimiter{device->LimiterState};
1650 ALCuint new_sends{device->NumAuxSends};
1651 DevFmtChannels oldChans;
1652 DevFmtType oldType;
1653 ALCsizei hrtf_id{-1};
1654 ALCuint oldFreq;
1656 if((!attrList || !attrList[0]) && device->Type == Loopback)
1658 WARN("Missing attributes for loopback device\n");
1659 return ALC_INVALID_VALUE;
1662 // Check for attributes
1663 if(attrList && attrList[0])
1665 ALCenum alayout{AL_NONE};
1666 ALCenum ascale{AL_NONE};
1667 ALCenum schans{AL_NONE};
1668 ALCenum stype{AL_NONE};
1669 ALCsizei attrIdx{0};
1670 ALCuint aorder{0};
1671 ALCuint freq{0u};
1673 ALuint numMono{device->NumMonoSources};
1674 ALuint numStereo{device->NumStereoSources};
1675 ALuint numSends{device->NumAuxSends};
1677 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1678 while(attrList[attrIdx])
1680 switch(attrList[attrIdx])
1682 case ALC_FORMAT_CHANNELS_SOFT:
1683 schans = attrList[attrIdx + 1];
1684 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1685 break;
1687 case ALC_FORMAT_TYPE_SOFT:
1688 stype = attrList[attrIdx + 1];
1689 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1690 break;
1692 case ALC_FREQUENCY:
1693 freq = static_cast<ALuint>(attrList[attrIdx + 1]);
1694 TRACE_ATTR(ALC_FREQUENCY, freq);
1695 break;
1697 case ALC_AMBISONIC_LAYOUT_SOFT:
1698 alayout = attrList[attrIdx + 1];
1699 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1700 break;
1702 case ALC_AMBISONIC_SCALING_SOFT:
1703 ascale = attrList[attrIdx + 1];
1704 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1705 break;
1707 case ALC_AMBISONIC_ORDER_SOFT:
1708 aorder = static_cast<ALuint>(attrList[attrIdx + 1]);
1709 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1710 break;
1712 case ALC_MONO_SOURCES:
1713 numMono = static_cast<ALuint>(attrList[attrIdx + 1]);
1714 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1715 if(numMono > INT_MAX) numMono = 0;
1716 break;
1718 case ALC_STEREO_SOURCES:
1719 numStereo = static_cast<ALuint>(attrList[attrIdx + 1]);
1720 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1721 if(numStereo > INT_MAX) numStereo = 0;
1722 break;
1724 case ALC_MAX_AUXILIARY_SENDS:
1725 numSends = static_cast<ALuint>(attrList[attrIdx + 1]);
1726 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1727 if(numSends > INT_MAX) numSends = 0;
1728 else numSends = minu(numSends, MAX_SENDS);
1729 break;
1731 case ALC_HRTF_SOFT:
1732 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1733 if(attrList[attrIdx + 1] == ALC_FALSE)
1734 hrtf_appreq = Hrtf_Disable;
1735 else if(attrList[attrIdx + 1] == ALC_TRUE)
1736 hrtf_appreq = Hrtf_Enable;
1737 else
1738 hrtf_appreq = Hrtf_Default;
1739 break;
1741 case ALC_HRTF_ID_SOFT:
1742 hrtf_id = attrList[attrIdx + 1];
1743 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1744 break;
1746 case ALC_OUTPUT_LIMITER_SOFT:
1747 gainLimiter = attrList[attrIdx + 1];
1748 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1749 break;
1751 default:
1752 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1753 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1754 break;
1757 attrIdx += 2;
1759 #undef TRACE_ATTR
1761 const bool loopback{device->Type == Loopback};
1762 if(loopback)
1764 if(!schans || !stype || !freq)
1766 WARN("Missing format for loopback device\n");
1767 return ALC_INVALID_VALUE;
1769 if(!IsValidALCChannels(schans) || !IsValidALCType(stype) || freq < MIN_OUTPUT_RATE
1770 || freq > MAX_OUTPUT_RATE)
1771 return ALC_INVALID_VALUE;
1772 if(schans == ALC_BFORMAT3D_SOFT)
1774 if(!alayout || !ascale || !aorder)
1776 WARN("Missing ambisonic info for loopback device\n");
1777 return ALC_INVALID_VALUE;
1779 if(!IsValidAmbiLayout(alayout) || !IsValidAmbiScaling(ascale))
1780 return ALC_INVALID_VALUE;
1781 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1782 return ALC_INVALID_VALUE;
1783 if((alayout == ALC_FUMA_SOFT || ascale == ALC_FUMA_SOFT) && aorder > 3)
1784 return ALC_INVALID_VALUE;
1788 /* If a context is already running on the device, stop playback so the
1789 * device attributes can be updated.
1791 if(device->Flags.get<DeviceRunning>())
1792 device->Backend->stop();
1793 device->Flags.unset<DeviceRunning>();
1795 UpdateClockBase(device);
1797 const char *devname{nullptr};
1798 if(!loopback)
1800 devname = device->DeviceName.c_str();
1802 device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
1803 device->UpdateSize = DEFAULT_UPDATE_SIZE;
1804 device->Frequency = DEFAULT_OUTPUT_RATE;
1806 freq = ConfigValueUInt(devname, nullptr, "frequency").value_or(freq);
1807 if(freq < 1)
1808 device->Flags.unset<FrequencyRequest>();
1809 else
1811 freq = clampu(freq, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE);
1813 const double scale{static_cast<double>(freq) / device->Frequency};
1814 device->UpdateSize = static_cast<ALuint>(device->UpdateSize*scale + 0.5);
1815 device->BufferSize = static_cast<ALuint>(device->BufferSize*scale + 0.5);
1817 device->Frequency = freq;
1818 device->Flags.set<FrequencyRequest>();
1821 if(auto persizeopt = ConfigValueUInt(devname, nullptr, "period_size"))
1822 device->UpdateSize = clampu(*persizeopt, 64, 8192);
1824 if(auto peropt = ConfigValueUInt(devname, nullptr, "periods"))
1825 device->BufferSize = device->UpdateSize * clampu(*peropt, 2, 16);
1826 else
1827 device->BufferSize = maxu(device->BufferSize, device->UpdateSize*2);
1829 else
1831 device->Frequency = freq;
1832 device->FmtChans = static_cast<DevFmtChannels>(schans);
1833 device->FmtType = static_cast<DevFmtType>(stype);
1834 if(schans == ALC_BFORMAT3D_SOFT)
1836 device->mAmbiOrder = aorder;
1837 device->mAmbiLayout = static_cast<DevAmbiLayout>(alayout);
1838 device->mAmbiScale = static_cast<DevAmbiScaling>(ascale);
1842 if(numMono > INT_MAX-numStereo)
1843 numMono = INT_MAX-numStereo;
1844 numMono += numStereo;
1845 if(auto srcsopt = ConfigValueUInt(devname, nullptr, "sources"))
1847 if(*srcsopt <= 0) numMono = 256;
1848 else numMono = *srcsopt;
1850 else
1851 numMono = maxu(numMono, 256);
1852 numStereo = minu(numStereo, numMono);
1853 numMono -= numStereo;
1854 device->SourcesMax = numMono + numStereo;
1856 device->NumMonoSources = numMono;
1857 device->NumStereoSources = numStereo;
1859 if(auto sendsopt = ConfigValueInt(devname, nullptr, "sends"))
1860 new_sends = minu(numSends, static_cast<ALuint>(clampi(*sendsopt, 0, MAX_SENDS)));
1861 else
1862 new_sends = numSends;
1865 if(device->Flags.get<DeviceRunning>())
1866 return ALC_NO_ERROR;
1868 device->AvgSpeakerDist = 0.0f;
1869 device->Uhj_Encoder = nullptr;
1870 device->AmbiDecoder = nullptr;
1871 device->Bs2b = nullptr;
1872 device->PostProcess = nullptr;
1874 device->Limiter = nullptr;
1875 device->ChannelDelay.clear();
1877 std::fill(std::begin(device->HrtfAccumData), std::end(device->HrtfAccumData), float2{});
1879 device->Dry.AmbiMap.fill(BFChannelConfig{});
1880 device->Dry.Buffer = {};
1881 std::fill(std::begin(device->NumChannelsPerOrder), std::end(device->NumChannelsPerOrder), 0u);
1882 device->RealOut.RemixMap = {};
1883 device->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
1884 device->RealOut.Buffer = {};
1885 device->MixBuffer.clear();
1886 device->MixBuffer.shrink_to_fit();
1888 UpdateClockBase(device);
1889 device->FixedLatency = nanoseconds::zero();
1891 device->DitherDepth = 0.0f;
1892 device->DitherSeed = DitherRNGSeed;
1894 /*************************************************************************
1895 * Update device format request if HRTF is requested
1897 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
1898 if(device->Type != Loopback)
1900 if(auto hrtfopt = ConfigValueStr(device->DeviceName.c_str(), nullptr, "hrtf"))
1902 const char *hrtf{hrtfopt->c_str()};
1903 if(al::strcasecmp(hrtf, "true") == 0)
1904 hrtf_userreq = Hrtf_Enable;
1905 else if(al::strcasecmp(hrtf, "false") == 0)
1906 hrtf_userreq = Hrtf_Disable;
1907 else if(al::strcasecmp(hrtf, "auto") != 0)
1908 ERR("Unexpected hrtf value: %s\n", hrtf);
1911 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
1913 device->FmtChans = DevFmtStereo;
1914 device->Flags.set<ChannelsRequest>();
1918 oldFreq = device->Frequency;
1919 oldChans = device->FmtChans;
1920 oldType = device->FmtType;
1922 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u / %u buffer\n",
1923 device->Flags.get<ChannelsRequest>()?"*":"", DevFmtChannelsString(device->FmtChans),
1924 device->Flags.get<SampleTypeRequest>()?"*":"", DevFmtTypeString(device->FmtType),
1925 device->Flags.get<FrequencyRequest>()?"*":"", device->Frequency,
1926 device->UpdateSize, device->BufferSize);
1928 try {
1929 auto backend = device->Backend.get();
1930 if(!backend->reset())
1931 throw al::backend_exception{ALC_INVALID_DEVICE, "Device reset failure"};
1933 catch(std::exception &e) {
1934 device->handleDisconnect("%s", e.what());
1935 return ALC_INVALID_DEVICE;
1938 if(device->FmtChans != oldChans && device->Flags.get<ChannelsRequest>())
1940 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1941 DevFmtChannelsString(device->FmtChans));
1942 device->Flags.unset<ChannelsRequest>();
1944 if(device->FmtType != oldType && device->Flags.get<SampleTypeRequest>())
1946 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1947 DevFmtTypeString(device->FmtType));
1948 device->Flags.unset<SampleTypeRequest>();
1950 if(device->Frequency != oldFreq && device->Flags.get<FrequencyRequest>())
1952 WARN("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1953 device->Flags.unset<FrequencyRequest>();
1956 TRACE("Post-reset: %s, %s, %uhz, %u / %u buffer\n",
1957 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
1958 device->Frequency, device->UpdateSize, device->BufferSize);
1960 switch(device->FmtChans)
1962 case DevFmtMono: device->RealOut.RemixMap = MonoDownmix; break;
1963 case DevFmtStereo: device->RealOut.RemixMap = StereoDownmix; break;
1964 case DevFmtQuad: device->RealOut.RemixMap = QuadDownmix; break;
1965 case DevFmtX51: device->RealOut.RemixMap = X51Downmix; break;
1966 case DevFmtX51Rear: device->RealOut.RemixMap = X51RearDownmix; break;
1967 case DevFmtX61: device->RealOut.RemixMap = X61Downmix; break;
1968 case DevFmtX71: device->RealOut.RemixMap = X71Downmix; break;
1969 case DevFmtAmbi3D: break;
1972 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
1974 device->NumAuxSends = new_sends;
1975 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
1976 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
1977 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
1979 if(device->Uhj_Encoder)
1981 /* NOTE: Don't know why this has to be "copied" into a local constexpr
1982 * variable to avoid a reference on Uhj2Encoder::sFilterSize...
1984 constexpr size_t filter_len{Uhj2Encoder::sFilterSize};
1985 device->FixedLatency += nanoseconds{seconds{filter_len}} / device->Frequency;
1987 if(device->mHrtfState)
1988 device->FixedLatency += nanoseconds{seconds{HRTF_DIRECT_DELAY}} / device->Frequency;
1989 if(auto *ambidec = device->AmbiDecoder.get())
1991 if(ambidec->hasStablizer())
1993 constexpr size_t StablizerDelay{FrontStablizer::DelayLength};
1994 device->FixedLatency += nanoseconds{seconds{StablizerDelay}} / device->Frequency;
1998 if(GetConfigValueBool(device->DeviceName.c_str(), nullptr, "dither", 1))
2000 int depth{ConfigValueInt(device->DeviceName.c_str(), nullptr, "dither-depth").value_or(0)};
2001 if(depth <= 0)
2003 switch(device->FmtType)
2005 case DevFmtByte:
2006 case DevFmtUByte:
2007 depth = 8;
2008 break;
2009 case DevFmtShort:
2010 case DevFmtUShort:
2011 depth = 16;
2012 break;
2013 case DevFmtInt:
2014 case DevFmtUInt:
2015 case DevFmtFloat:
2016 break;
2020 if(depth > 0)
2022 depth = clampi(depth, 2, 24);
2023 device->DitherDepth = std::pow(2.0f, static_cast<float>(depth-1));
2026 if(!(device->DitherDepth > 0.0f))
2027 TRACE("Dithering disabled\n");
2028 else
2029 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device->DitherDepth)+0.5f)+1,
2030 device->DitherDepth);
2032 device->LimiterState = gainLimiter;
2033 if(auto limopt = ConfigValueBool(device->DeviceName.c_str(), nullptr, "output-limiter"))
2034 gainLimiter = *limopt ? ALC_TRUE : ALC_FALSE;
2036 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2037 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2038 * output (where samples must be clamped), and don't for floating-point
2039 * (which can take unclamped samples).
2041 if(gainLimiter == ALC_DONT_CARE_SOFT)
2043 switch(device->FmtType)
2045 case DevFmtByte:
2046 case DevFmtUByte:
2047 case DevFmtShort:
2048 case DevFmtUShort:
2049 case DevFmtInt:
2050 case DevFmtUInt:
2051 gainLimiter = ALC_TRUE;
2052 break;
2053 case DevFmtFloat:
2054 gainLimiter = ALC_FALSE;
2055 break;
2058 if(gainLimiter == ALC_FALSE)
2059 TRACE("Output limiter disabled\n");
2060 else
2062 float thrshld{1.0f};
2063 switch(device->FmtType)
2065 case DevFmtByte:
2066 case DevFmtUByte:
2067 thrshld = 127.0f / 128.0f;
2068 break;
2069 case DevFmtShort:
2070 case DevFmtUShort:
2071 thrshld = 32767.0f / 32768.0f;
2072 break;
2073 case DevFmtInt:
2074 case DevFmtUInt:
2075 case DevFmtFloat:
2076 break;
2078 if(device->DitherDepth > 0.0f)
2079 thrshld -= 1.0f / device->DitherDepth;
2081 const float thrshld_dB{std::log10(thrshld) * 20.0f};
2082 auto limiter = CreateDeviceLimiter(device, thrshld_dB);
2083 /* Convert the lookahead from samples to nanosamples to nanoseconds. */
2084 device->FixedLatency += nanoseconds{seconds{limiter->getLookAhead()}} / device->Frequency;
2085 device->Limiter = std::move(limiter);
2086 TRACE("Output limiter enabled, %.4fdB limit\n", thrshld_dB);
2089 TRACE("Fixed device latency: %" PRId64 "ns\n", int64_t{device->FixedLatency.count()});
2091 FPUCtl mixer_mode{};
2092 for(ALCcontext *context : *device->mContexts.load())
2094 if(ALeffectslot *slot{context->mDefaultSlot.get()})
2096 aluInitEffectPanning(slot, device);
2098 EffectState *state{slot->Effect.State.get()};
2099 state->mOutTarget = device->Dry.Buffer;
2100 state->deviceUpdate(device);
2101 if(ALbuffer *buffer{slot->Buffer})
2103 slot->Effect.Buffer = nullptr;
2104 slot->Effect.Buffer.reset(state->createBuffer(device, buffer->mBuffer));
2106 slot->updateProps(context);
2109 std::unique_lock<std::mutex> proplock{context->mPropLock};
2110 std::unique_lock<std::mutex> slotlock{context->mEffectSlotLock};
2111 if(ALeffectslotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_relaxed)})
2112 std::fill_n(curarray->end(), curarray->size(), nullptr);
2113 for(auto &sublist : context->mEffectSlotList)
2115 uint64_t usemask{~sublist.FreeMask};
2116 while(usemask)
2118 ALsizei idx{CTZ64(usemask)};
2119 ALeffectslot *slot{sublist.EffectSlots + idx};
2120 usemask &= ~(1_u64 << idx);
2122 aluInitEffectPanning(slot, device);
2124 EffectState *state{slot->Effect.State.get()};
2125 state->mOutTarget = device->Dry.Buffer;
2126 state->deviceUpdate(device);
2127 if(ALbuffer *buffer{slot->Buffer})
2129 slot->Effect.Buffer = nullptr;
2130 slot->Effect.Buffer.reset(state->createBuffer(device, buffer->mBuffer));
2132 slot->updateProps(context);
2135 slotlock.unlock();
2137 const ALuint num_sends{device->NumAuxSends};
2138 std::unique_lock<std::mutex> srclock{context->mSourceLock};
2139 for(auto &sublist : context->mSourceList)
2141 uint64_t usemask{~sublist.FreeMask};
2142 while(usemask)
2144 ALsizei idx{CTZ64(usemask)};
2145 ALsource *source{sublist.Sources + idx};
2146 usemask &= ~(1_u64 << idx);
2148 auto clear_send = [](ALsource::SendData &send) -> void
2150 if(send.Slot)
2151 DecrementRef(send.Slot->ref);
2152 send.Slot = nullptr;
2153 send.Gain = 1.0f;
2154 send.GainHF = 1.0f;
2155 send.HFReference = LOWPASSFREQREF;
2156 send.GainLF = 1.0f;
2157 send.LFReference = HIGHPASSFREQREF;
2159 auto send_begin = source->Send.begin() + static_cast<ptrdiff_t>(num_sends);
2160 std::for_each(send_begin, source->Send.end(), clear_send);
2162 source->PropsClean.clear(std::memory_order_release);
2166 /* Clear any pre-existing voice property structs, in case the number of
2167 * auxiliary sends is changing. Active sources will have updates
2168 * respecified in UpdateAllSourceProps.
2170 VoicePropsItem *vprops{context->mFreeVoiceProps.exchange(nullptr, std::memory_order_acq_rel)};
2171 while(vprops)
2173 VoicePropsItem *next = vprops->next.load(std::memory_order_relaxed);
2174 delete vprops;
2175 vprops = next;
2178 auto voicelist = context->getVoicesSpan();
2179 for(Voice *voice : voicelist)
2181 /* Clear extraneous property set sends. */
2182 std::fill(std::begin(voice->mProps.Send)+num_sends, std::end(voice->mProps.Send),
2183 VoiceProps::SendData{});
2185 std::fill(voice->mSend.begin()+num_sends, voice->mSend.end(), Voice::TargetData{});
2186 for(auto &chandata : voice->mChans)
2188 std::fill(chandata.mWetParams.begin()+num_sends, chandata.mWetParams.end(),
2189 SendParams{});
2192 delete voice->mUpdate.exchange(nullptr, std::memory_order_acq_rel);
2194 /* Force the voice to stopped if it was stopping. */
2195 Voice::State vstate{Voice::Stopping};
2196 voice->mPlayState.compare_exchange_strong(vstate, Voice::Stopped,
2197 std::memory_order_acquire, std::memory_order_acquire);
2198 if(voice->mSourceID.load(std::memory_order_relaxed) == 0u)
2199 continue;
2201 voice->mStep = 0;
2202 voice->mFlags |= VOICE_IS_FADING;
2204 if(voice->mAmbiOrder && device->mAmbiOrder > voice->mAmbiOrder)
2206 const uint8_t *OrderFromChan{(voice->mFmtChannels == FmtBFormat2D) ?
2207 AmbiIndex::OrderFrom2DChannel.data() :
2208 AmbiIndex::OrderFromChannel.data()};
2210 const BandSplitter splitter{400.0f / static_cast<float>(device->Frequency)};
2212 const auto scales = BFormatDec::GetHFOrderScales(voice->mAmbiOrder,
2213 device->mAmbiOrder);
2214 for(auto &chandata : voice->mChans)
2216 chandata.mPrevSamples.fill(0.0f);
2217 chandata.mAmbiScale = scales[*(OrderFromChan++)];
2218 chandata.mAmbiSplitter = splitter;
2219 chandata.mDryParams = DirectParams{};
2220 std::fill_n(chandata.mWetParams.begin(), num_sends, SendParams{});
2223 voice->mFlags |= VOICE_IS_AMBISONIC;
2225 else
2227 /* Clear previous samples. */
2228 for(auto &chandata : voice->mChans)
2230 chandata.mPrevSamples.fill(0.0f);
2231 chandata.mDryParams = DirectParams{};
2232 std::fill_n(chandata.mWetParams.begin(), num_sends, SendParams{});
2235 voice->mFlags &= ~VOICE_IS_AMBISONIC;
2238 if(device->AvgSpeakerDist > 0.0f)
2240 /* Reinitialize the NFC filters for new parameters. */
2241 const float w1{SPEEDOFSOUNDMETRESPERSEC /
2242 (device->AvgSpeakerDist * static_cast<float>(device->Frequency))};
2243 for(auto &chandata : voice->mChans)
2244 chandata.mDryParams.NFCtrlFilter.init(w1);
2247 srclock.unlock();
2249 context->mPropsClean.test_and_set(std::memory_order_release);
2250 UpdateContextProps(context);
2251 context->mListener.PropsClean.test_and_set(std::memory_order_release);
2252 UpdateListenerProps(context);
2253 UpdateAllSourceProps(context);
2255 mixer_mode.leave();
2257 if(!device->Flags.get<DevicePaused>())
2259 try {
2260 auto backend = device->Backend.get();
2261 backend->start();
2262 device->Flags.set<DeviceRunning>();
2264 catch(al::backend_exception& e) {
2265 device->handleDisconnect("%s", e.what());
2266 return ALC_INVALID_DEVICE;
2270 return ALC_NO_ERROR;
2274 ALCdevice::ALCdevice(DeviceType type) : Type{type}, mContexts{&EmptyContextArray}
2278 ALCdevice::~ALCdevice()
2280 TRACE("Freeing device %p\n", decltype(std::declval<void*>()){this});
2282 Backend = nullptr;
2284 size_t count{std::accumulate(BufferList.cbegin(), BufferList.cend(), size_t{0u},
2285 [](size_t cur, const BufferSubList &sublist) noexcept -> size_t
2286 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2288 if(count > 0)
2289 WARN("%zu Buffer%s not deleted\n", count, (count==1)?"":"s");
2291 count = std::accumulate(EffectList.cbegin(), EffectList.cend(), size_t{0u},
2292 [](size_t cur, const EffectSubList &sublist) noexcept -> size_t
2293 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2295 if(count > 0)
2296 WARN("%zu Effect%s not deleted\n", count, (count==1)?"":"s");
2298 count = std::accumulate(FilterList.cbegin(), FilterList.cend(), size_t{0u},
2299 [](size_t cur, const FilterSubList &sublist) noexcept -> size_t
2300 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2302 if(count > 0)
2303 WARN("%zu Filter%s not deleted\n", count, (count==1)?"":"s");
2305 mHrtf = nullptr;
2307 auto *oldarray = mContexts.exchange(nullptr, std::memory_order_relaxed);
2308 if(oldarray != &EmptyContextArray) delete oldarray;
2312 /** Checks if the device handle is valid, and returns a new reference if so. */
2313 static DeviceRef VerifyDevice(ALCdevice *device)
2315 std::lock_guard<std::recursive_mutex> _{ListLock};
2316 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
2317 if(iter != DeviceList.end() && *iter == device)
2319 (*iter)->add_ref();
2320 return DeviceRef{*iter};
2322 return nullptr;
2326 ALCcontext::ALCcontext(al::intrusive_ptr<ALCdevice> device) : mDevice{std::move(device)}
2328 mPropsClean.test_and_set(std::memory_order_relaxed);
2331 ALCcontext::~ALCcontext()
2333 TRACE("Freeing context %p\n", decltype(std::declval<void*>()){this});
2335 size_t count{0};
2336 ALcontextProps *cprops{mUpdate.exchange(nullptr, std::memory_order_relaxed)};
2337 if(cprops)
2339 ++count;
2340 delete cprops;
2342 cprops = mFreeContextProps.exchange(nullptr, std::memory_order_acquire);
2343 while(cprops)
2345 ALcontextProps *next{cprops->next.load(std::memory_order_relaxed)};
2346 delete cprops;
2347 cprops = next;
2348 ++count;
2350 TRACE("Freed %zu context property object%s\n", count, (count==1)?"":"s");
2352 count = std::accumulate(mSourceList.cbegin(), mSourceList.cend(), size_t{0u},
2353 [](size_t cur, const SourceSubList &sublist) noexcept -> size_t
2354 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2356 if(count > 0)
2357 WARN("%zu Source%s not deleted\n", count, (count==1)?"":"s");
2358 mSourceList.clear();
2359 mNumSources = 0;
2361 count = 0;
2362 ALeffectslotProps *eprops{mFreeEffectslotProps.exchange(nullptr, std::memory_order_acquire)};
2363 while(eprops)
2365 ALeffectslotProps *next{eprops->next.load(std::memory_order_relaxed)};
2366 delete eprops;
2367 eprops = next;
2368 ++count;
2370 TRACE("Freed %zu AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2372 if(ALeffectslotArray *curarray{mActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed)})
2374 al::destroy_n(curarray->end(), curarray->size());
2375 delete curarray;
2377 mDefaultSlot = nullptr;
2379 count = std::accumulate(mEffectSlotList.cbegin(), mEffectSlotList.cend(), size_t{0u},
2380 [](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t
2381 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2383 if(count > 0)
2384 WARN("%zu AuxiliaryEffectSlot%s not deleted\n", count, (count==1)?"":"s");
2385 mEffectSlotList.clear();
2386 mNumEffectSlots = 0;
2388 count = 0;
2389 VoicePropsItem *vprops{mFreeVoiceProps.exchange(nullptr, std::memory_order_acquire)};
2390 while(vprops)
2392 VoicePropsItem *next{vprops->next.load(std::memory_order_relaxed)};
2393 delete vprops;
2394 vprops = next;
2395 ++count;
2397 TRACE("Freed %zu voice property object%s\n", count, (count==1)?"":"s");
2399 delete mVoices.exchange(nullptr, std::memory_order_relaxed);
2401 count = 0;
2402 ALlistenerProps *lprops{mListener.Params.Update.exchange(nullptr, std::memory_order_relaxed)};
2403 if(lprops)
2405 ++count;
2406 delete lprops;
2408 lprops = mFreeListenerProps.exchange(nullptr, std::memory_order_acquire);
2409 while(lprops)
2411 ALlistenerProps *next{lprops->next.load(std::memory_order_relaxed)};
2412 delete lprops;
2413 lprops = next;
2414 ++count;
2416 TRACE("Freed %zu listener property object%s\n", count, (count==1)?"":"s");
2418 if(mAsyncEvents)
2420 count = 0;
2421 auto evt_vec = mAsyncEvents->getReadVector();
2422 if(evt_vec.first.len > 0)
2424 al::destroy_n(reinterpret_cast<AsyncEvent*>(evt_vec.first.buf), evt_vec.first.len);
2425 count += evt_vec.first.len;
2427 if(evt_vec.second.len > 0)
2429 al::destroy_n(reinterpret_cast<AsyncEvent*>(evt_vec.second.buf), evt_vec.second.len);
2430 count += evt_vec.second.len;
2432 if(count > 0)
2433 TRACE("Destructed %zu orphaned event%s\n", count, (count==1)?"":"s");
2434 mAsyncEvents->readAdvance(count);
2438 void ALCcontext::init()
2440 if(DefaultEffect.type != AL_EFFECT_NULL && mDevice->Type == Playback)
2442 mDefaultSlot = std::unique_ptr<ALeffectslot>{new ALeffectslot{}};
2443 if(mDefaultSlot->init() == AL_NO_ERROR)
2444 aluInitEffectPanning(mDefaultSlot.get(), mDevice.get());
2445 else
2447 mDefaultSlot = nullptr;
2448 ERR("Failed to initialize the default effect slot\n");
2452 ALeffectslotArray *auxslots;
2453 if(!mDefaultSlot)
2454 auxslots = ALeffectslot::CreatePtrArray(0);
2455 else
2457 auxslots = ALeffectslot::CreatePtrArray(1);
2458 (*auxslots)[0] = mDefaultSlot.get();
2460 mActiveAuxSlots.store(auxslots, std::memory_order_relaxed);
2462 allocVoiceChanges(1);
2464 VoiceChange *cur{mVoiceChangeTail};
2465 while(VoiceChange *next{cur->mNext.load(std::memory_order_relaxed)})
2466 cur = next;
2467 mCurrentVoiceChange.store(cur, std::memory_order_relaxed);
2470 mExtensionList = alExtList;
2473 mListener.Params.Matrix = alu::Matrix::Identity();
2474 mListener.Params.Velocity = alu::Vector{};
2475 mListener.Params.Gain = mListener.Gain;
2476 mListener.Params.MetersPerUnit = mListener.mMetersPerUnit;
2477 mListener.Params.DopplerFactor = mDopplerFactor;
2478 mListener.Params.SpeedOfSound = mSpeedOfSound * mDopplerVelocity;
2479 mListener.Params.SourceDistanceModel = mSourceDistanceModel;
2480 mListener.Params.mDistanceModel = mDistanceModel;
2483 mAsyncEvents = RingBuffer::Create(511, sizeof(AsyncEvent), false);
2484 StartEventThrd(this);
2487 allocVoices(256);
2488 mActiveVoiceCount.store(64, std::memory_order_relaxed);
2491 bool ALCcontext::deinit()
2493 if(LocalContext == this)
2495 WARN("%p released while current on thread\n", decltype(std::declval<void*>()){this});
2496 ThreadContext.set(nullptr);
2497 release();
2500 ALCcontext *origctx{this};
2501 if(GlobalContext.compare_exchange_strong(origctx, nullptr))
2502 release();
2504 bool ret{};
2505 /* First make sure this context exists in the device's list. */
2506 auto *oldarray = mDevice->mContexts.load(std::memory_order_acquire);
2507 if(auto toremove = static_cast<size_t>(std::count(oldarray->begin(), oldarray->end(), this)))
2509 using ContextArray = al::FlexArray<ALCcontext*>;
2510 auto alloc_ctx_array = [](const size_t count) -> ContextArray*
2512 if(count == 0) return &EmptyContextArray;
2513 return ContextArray::Create(count).release();
2515 auto *newarray = alloc_ctx_array(oldarray->size() - toremove);
2517 /* Copy the current/old context handles to the new array, excluding the
2518 * given context.
2520 std::copy_if(oldarray->begin(), oldarray->end(), newarray->begin(),
2521 std::bind(std::not_equal_to<ALCcontext*>{}, _1, this));
2523 /* Store the new context array in the device. Wait for any current mix
2524 * to finish before deleting the old array.
2526 mDevice->mContexts.store(newarray);
2527 if(oldarray != &EmptyContextArray)
2529 mDevice->waitForMix();
2530 delete oldarray;
2533 ret = !newarray->empty();
2535 else
2536 ret = !oldarray->empty();
2538 StopEventThrd(this);
2540 return ret;
2545 * Checks if the given context is valid, returning a new reference to it if so.
2547 static ContextRef VerifyContext(ALCcontext *context)
2549 std::lock_guard<std::recursive_mutex> _{ListLock};
2550 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
2551 if(iter != ContextList.end() && *iter == context)
2553 (*iter)->add_ref();
2554 return ContextRef{*iter};
2556 return nullptr;
2559 /** Returns a new reference to the currently active context for this thread. */
2560 ContextRef GetContextRef(void)
2562 ALCcontext *context{LocalContext};
2563 if(context)
2564 context->add_ref();
2565 else
2567 std::lock_guard<std::recursive_mutex> _{ListLock};
2568 context = GlobalContext.load(std::memory_order_acquire);
2569 if(context) context->add_ref();
2571 return ContextRef{context};
2575 /************************************************
2576 * Standard ALC functions
2577 ************************************************/
2579 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2580 START_API_FUNC
2582 DeviceRef dev{VerifyDevice(device)};
2583 if(dev) return dev->LastError.exchange(ALC_NO_ERROR);
2584 return LastNullDeviceError.exchange(ALC_NO_ERROR);
2586 END_API_FUNC
2589 ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2590 START_API_FUNC
2592 if(!SuspendDefers)
2593 return;
2595 ContextRef ctx{VerifyContext(context)};
2596 if(!ctx)
2597 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2598 else
2599 ctx->deferUpdates();
2601 END_API_FUNC
2603 ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context)
2604 START_API_FUNC
2606 if(!SuspendDefers)
2607 return;
2609 ContextRef ctx{VerifyContext(context)};
2610 if(!ctx)
2611 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2612 else
2613 ctx->processUpdates();
2615 END_API_FUNC
2618 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2619 START_API_FUNC
2621 const ALCchar *value{nullptr};
2623 switch(param)
2625 case ALC_NO_ERROR:
2626 value = alcNoError;
2627 break;
2629 case ALC_INVALID_ENUM:
2630 value = alcErrInvalidEnum;
2631 break;
2633 case ALC_INVALID_VALUE:
2634 value = alcErrInvalidValue;
2635 break;
2637 case ALC_INVALID_DEVICE:
2638 value = alcErrInvalidDevice;
2639 break;
2641 case ALC_INVALID_CONTEXT:
2642 value = alcErrInvalidContext;
2643 break;
2645 case ALC_OUT_OF_MEMORY:
2646 value = alcErrOutOfMemory;
2647 break;
2649 case ALC_DEVICE_SPECIFIER:
2650 value = alcDefaultName;
2651 break;
2653 case ALC_ALL_DEVICES_SPECIFIER:
2654 if(DeviceRef dev{VerifyDevice(Device)})
2655 value = dev->DeviceName.c_str();
2656 else
2658 ProbeAllDevicesList();
2659 value = alcAllDevicesList.c_str();
2661 break;
2663 case ALC_CAPTURE_DEVICE_SPECIFIER:
2664 if(DeviceRef dev{VerifyDevice(Device)})
2665 value = dev->DeviceName.c_str();
2666 else
2668 ProbeCaptureDeviceList();
2669 value = alcCaptureDeviceList.c_str();
2671 break;
2673 /* Default devices are always first in the list */
2674 case ALC_DEFAULT_DEVICE_SPECIFIER:
2675 value = alcDefaultName;
2676 break;
2678 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2679 if(alcAllDevicesList.empty())
2680 ProbeAllDevicesList();
2682 /* Copy first entry as default. */
2683 alcDefaultAllDevicesSpecifier = alcAllDevicesList.c_str();
2684 value = alcDefaultAllDevicesSpecifier.c_str();
2685 break;
2687 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2688 if(alcCaptureDeviceList.empty())
2689 ProbeCaptureDeviceList();
2691 /* Copy first entry as default. */
2692 alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList.c_str();
2693 value = alcCaptureDefaultDeviceSpecifier.c_str();
2694 break;
2696 case ALC_EXTENSIONS:
2697 if(VerifyDevice(Device))
2698 value = alcExtensionList;
2699 else
2700 value = alcNoDeviceExtList;
2701 break;
2703 case ALC_HRTF_SPECIFIER_SOFT:
2704 if(DeviceRef dev{VerifyDevice(Device)})
2706 std::lock_guard<std::mutex> _{dev->StateLock};
2707 value = (dev->mHrtf ? dev->HrtfName.c_str() : "");
2709 else
2710 alcSetError(nullptr, ALC_INVALID_DEVICE);
2711 break;
2713 default:
2714 alcSetError(VerifyDevice(Device).get(), ALC_INVALID_ENUM);
2715 break;
2718 return value;
2720 END_API_FUNC
2723 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
2725 if(device->Type == Capture) return 9;
2726 if(device->Type != Loopback) return 29;
2727 if(device->FmtChans == DevFmtAmbi3D)
2728 return 35;
2729 return 29;
2732 static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span<int> values)
2734 size_t i;
2736 if(values.empty())
2738 alcSetError(device, ALC_INVALID_VALUE);
2739 return 0;
2742 if(!device)
2744 switch(param)
2746 case ALC_MAJOR_VERSION:
2747 values[0] = alcMajorVersion;
2748 return 1;
2749 case ALC_MINOR_VERSION:
2750 values[0] = alcMinorVersion;
2751 return 1;
2753 case ALC_ATTRIBUTES_SIZE:
2754 case ALC_ALL_ATTRIBUTES:
2755 case ALC_FREQUENCY:
2756 case ALC_REFRESH:
2757 case ALC_SYNC:
2758 case ALC_MONO_SOURCES:
2759 case ALC_STEREO_SOURCES:
2760 case ALC_CAPTURE_SAMPLES:
2761 case ALC_FORMAT_CHANNELS_SOFT:
2762 case ALC_FORMAT_TYPE_SOFT:
2763 case ALC_AMBISONIC_LAYOUT_SOFT:
2764 case ALC_AMBISONIC_SCALING_SOFT:
2765 case ALC_AMBISONIC_ORDER_SOFT:
2766 case ALC_MAX_AMBISONIC_ORDER_SOFT:
2767 alcSetError(nullptr, ALC_INVALID_DEVICE);
2768 return 0;
2770 default:
2771 alcSetError(nullptr, ALC_INVALID_ENUM);
2773 return 0;
2776 if(device->Type == Capture)
2778 switch(param)
2780 case ALC_ATTRIBUTES_SIZE:
2781 values[0] = NumAttrsForDevice(device);
2782 return 1;
2784 case ALC_ALL_ATTRIBUTES:
2785 i = 0;
2786 if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2787 alcSetError(device, ALC_INVALID_VALUE);
2788 else
2790 std::lock_guard<std::mutex> _{device->StateLock};
2791 values[i++] = ALC_MAJOR_VERSION;
2792 values[i++] = alcMajorVersion;
2793 values[i++] = ALC_MINOR_VERSION;
2794 values[i++] = alcMinorVersion;
2795 values[i++] = ALC_CAPTURE_SAMPLES;
2796 values[i++] = static_cast<int>(device->Backend->availableSamples());
2797 values[i++] = ALC_CONNECTED;
2798 values[i++] = device->Connected.load(std::memory_order_relaxed);
2799 values[i++] = 0;
2801 return i;
2803 case ALC_MAJOR_VERSION:
2804 values[0] = alcMajorVersion;
2805 return 1;
2806 case ALC_MINOR_VERSION:
2807 values[0] = alcMinorVersion;
2808 return 1;
2810 case ALC_CAPTURE_SAMPLES:
2812 std::lock_guard<std::mutex> _{device->StateLock};
2813 values[0] = static_cast<int>(device->Backend->availableSamples());
2815 return 1;
2817 case ALC_CONNECTED:
2819 std::lock_guard<std::mutex> _{device->StateLock};
2820 values[0] = device->Connected.load(std::memory_order_acquire);
2822 return 1;
2824 default:
2825 alcSetError(device, ALC_INVALID_ENUM);
2827 return 0;
2830 /* render device */
2831 switch(param)
2833 case ALC_ATTRIBUTES_SIZE:
2834 values[0] = NumAttrsForDevice(device);
2835 return 1;
2837 case ALC_ALL_ATTRIBUTES:
2838 i = 0;
2839 if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2840 alcSetError(device, ALC_INVALID_VALUE);
2841 else
2843 std::lock_guard<std::mutex> _{device->StateLock};
2844 values[i++] = ALC_MAJOR_VERSION;
2845 values[i++] = alcMajorVersion;
2846 values[i++] = ALC_MINOR_VERSION;
2847 values[i++] = alcMinorVersion;
2848 values[i++] = ALC_EFX_MAJOR_VERSION;
2849 values[i++] = alcEFXMajorVersion;
2850 values[i++] = ALC_EFX_MINOR_VERSION;
2851 values[i++] = alcEFXMinorVersion;
2853 values[i++] = ALC_FREQUENCY;
2854 values[i++] = static_cast<int>(device->Frequency);
2855 if(device->Type != Loopback)
2857 values[i++] = ALC_REFRESH;
2858 values[i++] = static_cast<int>(device->Frequency / device->UpdateSize);
2860 values[i++] = ALC_SYNC;
2861 values[i++] = ALC_FALSE;
2863 else
2865 if(device->FmtChans == DevFmtAmbi3D)
2867 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
2868 values[i++] = static_cast<int>(device->mAmbiLayout);
2870 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
2871 values[i++] = static_cast<int>(device->mAmbiScale);
2873 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
2874 values[i++] = static_cast<int>(device->mAmbiOrder);
2877 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2878 values[i++] = device->FmtChans;
2880 values[i++] = ALC_FORMAT_TYPE_SOFT;
2881 values[i++] = device->FmtType;
2884 values[i++] = ALC_MONO_SOURCES;
2885 values[i++] = static_cast<int>(device->NumMonoSources);
2887 values[i++] = ALC_STEREO_SOURCES;
2888 values[i++] = static_cast<int>(device->NumStereoSources);
2890 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2891 values[i++] = static_cast<int>(device->NumAuxSends);
2893 values[i++] = ALC_HRTF_SOFT;
2894 values[i++] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
2896 values[i++] = ALC_HRTF_STATUS_SOFT;
2897 values[i++] = device->HrtfStatus;
2899 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
2900 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
2902 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
2903 values[i++] = MAX_AMBI_ORDER;
2905 values[i++] = 0;
2907 return i;
2909 case ALC_MAJOR_VERSION:
2910 values[0] = alcMajorVersion;
2911 return 1;
2913 case ALC_MINOR_VERSION:
2914 values[0] = alcMinorVersion;
2915 return 1;
2917 case ALC_EFX_MAJOR_VERSION:
2918 values[0] = alcEFXMajorVersion;
2919 return 1;
2921 case ALC_EFX_MINOR_VERSION:
2922 values[0] = alcEFXMinorVersion;
2923 return 1;
2925 case ALC_FREQUENCY:
2926 values[0] = static_cast<int>(device->Frequency);
2927 return 1;
2929 case ALC_REFRESH:
2930 if(device->Type == Loopback)
2932 alcSetError(device, ALC_INVALID_DEVICE);
2933 return 0;
2936 std::lock_guard<std::mutex> _{device->StateLock};
2937 values[0] = static_cast<int>(device->Frequency / device->UpdateSize);
2939 return 1;
2941 case ALC_SYNC:
2942 if(device->Type == Loopback)
2944 alcSetError(device, ALC_INVALID_DEVICE);
2945 return 0;
2947 values[0] = ALC_FALSE;
2948 return 1;
2950 case ALC_FORMAT_CHANNELS_SOFT:
2951 if(device->Type != Loopback)
2953 alcSetError(device, ALC_INVALID_DEVICE);
2954 return 0;
2956 values[0] = device->FmtChans;
2957 return 1;
2959 case ALC_FORMAT_TYPE_SOFT:
2960 if(device->Type != Loopback)
2962 alcSetError(device, ALC_INVALID_DEVICE);
2963 return 0;
2965 values[0] = device->FmtType;
2966 return 1;
2968 case ALC_AMBISONIC_LAYOUT_SOFT:
2969 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
2971 alcSetError(device, ALC_INVALID_DEVICE);
2972 return 0;
2974 values[0] = static_cast<int>(device->mAmbiLayout);
2975 return 1;
2977 case ALC_AMBISONIC_SCALING_SOFT:
2978 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
2980 alcSetError(device, ALC_INVALID_DEVICE);
2981 return 0;
2983 values[0] = static_cast<int>(device->mAmbiScale);
2984 return 1;
2986 case ALC_AMBISONIC_ORDER_SOFT:
2987 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
2989 alcSetError(device, ALC_INVALID_DEVICE);
2990 return 0;
2992 values[0] = static_cast<int>(device->mAmbiOrder);
2993 return 1;
2995 case ALC_MONO_SOURCES:
2996 values[0] = static_cast<int>(device->NumMonoSources);
2997 return 1;
2999 case ALC_STEREO_SOURCES:
3000 values[0] = static_cast<int>(device->NumStereoSources);
3001 return 1;
3003 case ALC_MAX_AUXILIARY_SENDS:
3004 values[0] = static_cast<int>(device->NumAuxSends);
3005 return 1;
3007 case ALC_CONNECTED:
3009 std::lock_guard<std::mutex> _{device->StateLock};
3010 values[0] = device->Connected.load(std::memory_order_acquire);
3012 return 1;
3014 case ALC_HRTF_SOFT:
3015 values[0] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
3016 return 1;
3018 case ALC_HRTF_STATUS_SOFT:
3019 values[0] = device->HrtfStatus;
3020 return 1;
3022 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3024 std::lock_guard<std::mutex> _{device->StateLock};
3025 device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
3026 values[0] = static_cast<int>(minz(device->HrtfList.size(),
3027 std::numeric_limits<int>::max()));
3029 return 1;
3031 case ALC_OUTPUT_LIMITER_SOFT:
3032 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3033 return 1;
3035 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3036 values[0] = MAX_AMBI_ORDER;
3037 return 1;
3039 default:
3040 alcSetError(device, ALC_INVALID_ENUM);
3042 return 0;
3045 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3046 START_API_FUNC
3048 DeviceRef dev{VerifyDevice(device)};
3049 if(size <= 0 || values == nullptr)
3050 alcSetError(dev.get(), ALC_INVALID_VALUE);
3051 else
3052 GetIntegerv(dev.get(), param, {values, static_cast<ALuint>(size)});
3054 END_API_FUNC
3056 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3057 START_API_FUNC
3059 DeviceRef dev{VerifyDevice(device)};
3060 if(size <= 0 || values == nullptr)
3062 alcSetError(dev.get(), ALC_INVALID_VALUE);
3063 return;
3065 if(!dev || dev->Type == Capture)
3067 auto ivals = al::vector<int>(static_cast<ALuint>(size));
3068 size_t got{GetIntegerv(dev.get(), pname, ivals)};
3069 std::copy_n(ivals.begin(), got, values);
3070 return;
3072 /* render device */
3073 switch(pname)
3075 case ALC_ATTRIBUTES_SIZE:
3076 *values = NumAttrsForDevice(dev.get())+4;
3077 break;
3079 case ALC_ALL_ATTRIBUTES:
3080 if(size < NumAttrsForDevice(dev.get())+4)
3081 alcSetError(dev.get(), ALC_INVALID_VALUE);
3082 else
3084 size_t i{0};
3085 std::lock_guard<std::mutex> _{dev->StateLock};
3086 values[i++] = ALC_FREQUENCY;
3087 values[i++] = dev->Frequency;
3089 if(dev->Type != Loopback)
3091 values[i++] = ALC_REFRESH;
3092 values[i++] = dev->Frequency / dev->UpdateSize;
3094 values[i++] = ALC_SYNC;
3095 values[i++] = ALC_FALSE;
3097 else
3099 if(dev->FmtChans == DevFmtAmbi3D)
3101 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3102 values[i++] = static_cast<int64_t>(dev->mAmbiLayout);
3104 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3105 values[i++] = static_cast<int64_t>(dev->mAmbiScale);
3107 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3108 values[i++] = dev->mAmbiOrder;
3111 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3112 values[i++] = dev->FmtChans;
3114 values[i++] = ALC_FORMAT_TYPE_SOFT;
3115 values[i++] = dev->FmtType;
3118 values[i++] = ALC_MONO_SOURCES;
3119 values[i++] = dev->NumMonoSources;
3121 values[i++] = ALC_STEREO_SOURCES;
3122 values[i++] = dev->NumStereoSources;
3124 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3125 values[i++] = dev->NumAuxSends;
3127 values[i++] = ALC_HRTF_SOFT;
3128 values[i++] = (dev->mHrtf ? ALC_TRUE : ALC_FALSE);
3130 values[i++] = ALC_HRTF_STATUS_SOFT;
3131 values[i++] = dev->HrtfStatus;
3133 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3134 values[i++] = dev->Limiter ? ALC_TRUE : ALC_FALSE;
3136 ClockLatency clock{GetClockLatency(dev.get())};
3137 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3138 values[i++] = clock.ClockTime.count();
3140 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3141 values[i++] = clock.Latency.count();
3143 values[i++] = 0;
3145 break;
3147 case ALC_DEVICE_CLOCK_SOFT:
3149 std::lock_guard<std::mutex> _{dev->StateLock};
3150 ALuint samplecount, refcount;
3151 nanoseconds basecount;
3152 do {
3153 refcount = dev->waitForMix();
3154 basecount = dev->ClockBase;
3155 samplecount = dev->SamplesDone;
3156 } while(refcount != ReadRef(dev->MixCount));
3157 basecount += nanoseconds{seconds{samplecount}} / dev->Frequency;
3158 *values = basecount.count();
3160 break;
3162 case ALC_DEVICE_LATENCY_SOFT:
3164 std::lock_guard<std::mutex> _{dev->StateLock};
3165 ClockLatency clock{GetClockLatency(dev.get())};
3166 *values = clock.Latency.count();
3168 break;
3170 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3171 if(size < 2)
3172 alcSetError(dev.get(), ALC_INVALID_VALUE);
3173 else
3175 std::lock_guard<std::mutex> _{dev->StateLock};
3176 ClockLatency clock{GetClockLatency(dev.get())};
3177 values[0] = clock.ClockTime.count();
3178 values[1] = clock.Latency.count();
3180 break;
3182 default:
3183 auto ivals = al::vector<int>(static_cast<ALuint>(size));
3184 size_t got{GetIntegerv(dev.get(), pname, ivals)};
3185 std::copy_n(ivals.begin(), got, values);
3186 break;
3189 END_API_FUNC
3192 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3193 START_API_FUNC
3195 DeviceRef dev{VerifyDevice(device)};
3196 if(!extName)
3197 alcSetError(dev.get(), ALC_INVALID_VALUE);
3198 else
3200 size_t len = strlen(extName);
3201 const char *ptr = (dev ? alcExtensionList : alcNoDeviceExtList);
3202 while(ptr && *ptr)
3204 if(al::strncasecmp(ptr, extName, len) == 0 && (ptr[len] == '\0' || isspace(ptr[len])))
3205 return ALC_TRUE;
3207 if((ptr=strchr(ptr, ' ')) != nullptr)
3209 do {
3210 ++ptr;
3211 } while(isspace(*ptr));
3215 return ALC_FALSE;
3217 END_API_FUNC
3220 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3221 START_API_FUNC
3223 if(!funcName)
3225 DeviceRef dev{VerifyDevice(device)};
3226 alcSetError(dev.get(), ALC_INVALID_VALUE);
3228 else
3230 for(const auto &func : alcFunctions)
3232 if(strcmp(func.funcName, funcName) == 0)
3233 return func.address;
3236 return nullptr;
3238 END_API_FUNC
3241 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3242 START_API_FUNC
3244 if(!enumName)
3246 DeviceRef dev{VerifyDevice(device)};
3247 alcSetError(dev.get(), ALC_INVALID_VALUE);
3249 else
3251 for(const auto &enm : alcEnumerations)
3253 if(strcmp(enm.enumName, enumName) == 0)
3254 return enm.value;
3257 return 0;
3259 END_API_FUNC
3262 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3263 START_API_FUNC
3265 /* Explicitly hold the list lock while taking the StateLock in case the
3266 * device is asynchronously destroyed, to ensure this new context is
3267 * properly cleaned up after being made.
3269 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3270 DeviceRef dev{VerifyDevice(device)};
3271 if(!dev || dev->Type == Capture || !dev->Connected.load(std::memory_order_relaxed))
3273 listlock.unlock();
3274 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3275 return nullptr;
3277 std::unique_lock<std::mutex> statelock{dev->StateLock};
3278 listlock.unlock();
3280 dev->LastError.store(ALC_NO_ERROR);
3282 ALCenum err{UpdateDeviceParams(dev.get(), attrList)};
3283 if(err != ALC_NO_ERROR)
3285 alcSetError(dev.get(), err);
3286 return nullptr;
3289 ContextRef context{new ALCcontext{dev}};
3290 context->init();
3292 if(auto volopt = ConfigValueFloat(dev->DeviceName.c_str(), nullptr, "volume-adjust"))
3294 const float valf{*volopt};
3295 if(!std::isfinite(valf))
3296 ERR("volume-adjust must be finite: %f\n", valf);
3297 else
3299 const float db{clampf(valf, -24.0f, 24.0f)};
3300 if(db != valf)
3301 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3302 context->mGainBoost = std::pow(10.0f, db/20.0f);
3303 TRACE("volume-adjust gain: %f\n", context->mGainBoost);
3306 UpdateListenerProps(context.get());
3309 using ContextArray = al::FlexArray<ALCcontext*>;
3311 /* Allocate a new context array, which holds 1 more than the current/
3312 * old array.
3314 auto *oldarray = device->mContexts.load();
3315 const size_t newcount{oldarray->size()+1};
3316 std::unique_ptr<ContextArray> newarray{ContextArray::Create(newcount)};
3318 /* Copy the current/old context handles to the new array, appending the
3319 * new context.
3321 auto iter = std::copy(oldarray->begin(), oldarray->end(), newarray->begin());
3322 *iter = context.get();
3324 /* Store the new context array in the device. Wait for any current mix
3325 * to finish before deleting the old array.
3327 dev->mContexts.store(newarray.release());
3328 if(oldarray != &EmptyContextArray)
3330 dev->waitForMix();
3331 delete oldarray;
3334 statelock.unlock();
3337 std::lock_guard<std::recursive_mutex> _{ListLock};
3338 auto iter = std::lower_bound(ContextList.cbegin(), ContextList.cend(), context.get());
3339 ContextList.emplace(iter, context.get());
3342 if(ALeffectslot *slot{context->mDefaultSlot.get()})
3344 if(slot->initEffect(&DefaultEffect, context.get()) == AL_NO_ERROR)
3345 slot->updateProps(context.get());
3346 else
3347 ERR("Failed to initialize the default effect\n");
3350 TRACE("Created context %p\n", decltype(std::declval<void*>()){context.get()});
3351 return context.release();
3353 END_API_FUNC
3355 ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3356 START_API_FUNC
3358 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3359 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
3360 if(iter == ContextList.end() || *iter != context)
3362 listlock.unlock();
3363 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3364 return;
3366 /* Hold a reference to this context so it remains valid until the ListLock
3367 * is released.
3369 ContextRef ctx{*iter};
3370 ContextList.erase(iter);
3372 ALCdevice *Device{ctx->mDevice.get()};
3374 std::lock_guard<std::mutex> _{Device->StateLock};
3375 if(!ctx->deinit() && Device->Flags.get<DeviceRunning>())
3377 Device->Backend->stop();
3378 Device->Flags.unset<DeviceRunning>();
3381 END_API_FUNC
3384 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3385 START_API_FUNC
3387 ALCcontext *Context{LocalContext};
3388 if(!Context) Context = GlobalContext.load();
3389 return Context;
3391 END_API_FUNC
3393 /** Returns the currently active thread-local context. */
3394 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3395 START_API_FUNC
3396 { return LocalContext; }
3397 END_API_FUNC
3399 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3400 START_API_FUNC
3402 /* context must be valid or nullptr */
3403 ContextRef ctx;
3404 if(context)
3406 ctx = VerifyContext(context);
3407 if(!ctx)
3409 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3410 return ALC_FALSE;
3413 /* Release this reference (if any) to store it in the GlobalContext
3414 * pointer. Take ownership of the reference (if any) that was previously
3415 * stored there.
3417 ctx = ContextRef{GlobalContext.exchange(ctx.release())};
3419 /* Reset (decrement) the previous global reference by replacing it with the
3420 * thread-local context. Take ownership of the thread-local context
3421 * reference (if any), clearing the storage to null.
3423 ctx = ContextRef{LocalContext};
3424 if(ctx) ThreadContext.set(nullptr);
3425 /* Reset (decrement) the previous thread-local reference. */
3427 return ALC_TRUE;
3429 END_API_FUNC
3431 /** Makes the given context the active context for the current thread. */
3432 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3433 START_API_FUNC
3435 /* context must be valid or nullptr */
3436 ContextRef ctx;
3437 if(context)
3439 ctx = VerifyContext(context);
3440 if(!ctx)
3442 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3443 return ALC_FALSE;
3446 /* context's reference count is already incremented */
3447 ContextRef old{LocalContext};
3448 ThreadContext.set(ctx.release());
3450 return ALC_TRUE;
3452 END_API_FUNC
3455 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3456 START_API_FUNC
3458 ContextRef ctx{VerifyContext(Context)};
3459 if(!ctx)
3461 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3462 return nullptr;
3464 return ctx->mDevice.get();
3466 END_API_FUNC
3469 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3470 START_API_FUNC
3472 DO_INITCONFIG();
3474 if(!PlaybackFactory)
3476 alcSetError(nullptr, ALC_INVALID_VALUE);
3477 return nullptr;
3480 if(deviceName)
3482 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3483 #ifdef _WIN32
3484 /* Some old Windows apps hardcode these expecting OpenAL to use a
3485 * specific audio API, even when they're not enumerated. Creative's
3486 * router effectively ignores them too.
3488 || al::strcasecmp(deviceName, "DirectSound3D") == 0
3489 || al::strcasecmp(deviceName, "DirectSound") == 0
3490 || al::strcasecmp(deviceName, "MMSYSTEM") == 0
3491 #endif
3492 || al::strcasecmp(deviceName, "openal-soft") == 0)
3493 deviceName = nullptr;
3496 DeviceRef device{new ALCdevice{Playback}};
3498 /* Set output format */
3499 device->FmtChans = DevFmtChannelsDefault;
3500 device->FmtType = DevFmtTypeDefault;
3501 device->Frequency = DEFAULT_OUTPUT_RATE;
3502 device->UpdateSize = DEFAULT_UPDATE_SIZE;
3503 device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
3505 device->SourcesMax = 256;
3506 device->AuxiliaryEffectSlotMax = 64;
3507 device->NumAuxSends = DEFAULT_SENDS;
3509 try {
3510 auto backend = PlaybackFactory->createBackend(device.get(), BackendType::Playback);
3511 std::lock_guard<std::recursive_mutex> _{ListLock};
3512 backend->open(deviceName);
3513 device->Backend = std::move(backend);
3515 catch(al::backend_exception &e) {
3516 WARN("Failed to open playback device: %s\n", e.what());
3517 alcSetError(nullptr, e.errorCode());
3518 return nullptr;
3521 deviceName = device->DeviceName.c_str();
3522 if(auto chanopt = ConfigValueStr(deviceName, nullptr, "channels"))
3524 static const struct ChannelMap {
3525 const char name[16];
3526 DevFmtChannels chans;
3527 ALuint order;
3528 } chanlist[] = {
3529 { "mono", DevFmtMono, 0 },
3530 { "stereo", DevFmtStereo, 0 },
3531 { "quad", DevFmtQuad, 0 },
3532 { "surround51", DevFmtX51, 0 },
3533 { "surround61", DevFmtX61, 0 },
3534 { "surround71", DevFmtX71, 0 },
3535 { "surround51rear", DevFmtX51Rear, 0 },
3536 { "ambi1", DevFmtAmbi3D, 1 },
3537 { "ambi2", DevFmtAmbi3D, 2 },
3538 { "ambi3", DevFmtAmbi3D, 3 },
3541 const ALCchar *fmt{chanopt->c_str()};
3542 auto iter = std::find_if(std::begin(chanlist), std::end(chanlist),
3543 [fmt](const ChannelMap &entry) -> bool
3544 { return al::strcasecmp(entry.name, fmt) == 0; }
3546 if(iter == std::end(chanlist))
3547 ERR("Unsupported channels: %s\n", fmt);
3548 else
3550 device->FmtChans = iter->chans;
3551 device->mAmbiOrder = iter->order;
3552 device->Flags.set<ChannelsRequest>();
3555 if(auto typeopt = ConfigValueStr(deviceName, nullptr, "sample-type"))
3557 static const struct TypeMap {
3558 const char name[16];
3559 DevFmtType type;
3560 } typelist[] = {
3561 { "int8", DevFmtByte },
3562 { "uint8", DevFmtUByte },
3563 { "int16", DevFmtShort },
3564 { "uint16", DevFmtUShort },
3565 { "int32", DevFmtInt },
3566 { "uint32", DevFmtUInt },
3567 { "float32", DevFmtFloat },
3570 const ALCchar *fmt{typeopt->c_str()};
3571 auto iter = std::find_if(std::begin(typelist), std::end(typelist),
3572 [fmt](const TypeMap &entry) -> bool
3573 { return al::strcasecmp(entry.name, fmt) == 0; }
3575 if(iter == std::end(typelist))
3576 ERR("Unsupported sample-type: %s\n", fmt);
3577 else
3579 device->FmtType = iter->type;
3580 device->Flags.set<SampleTypeRequest>();
3584 if(ALuint freq{ConfigValueUInt(deviceName, nullptr, "frequency").value_or(0)})
3586 if(freq < MIN_OUTPUT_RATE || freq > MAX_OUTPUT_RATE)
3588 const ALuint newfreq{clampu(freq, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE)};
3589 ERR("%uhz request clamped to %uhz\n", freq, newfreq);
3590 freq = newfreq;
3592 const double scale{static_cast<double>(freq) / device->Frequency};
3593 device->UpdateSize = static_cast<ALuint>(device->UpdateSize*scale + 0.5);
3594 device->BufferSize = static_cast<ALuint>(device->BufferSize*scale + 0.5);
3595 device->Frequency = freq;
3596 device->Flags.set<FrequencyRequest>();
3599 if(auto persizeopt = ConfigValueUInt(deviceName, nullptr, "period_size"))
3600 device->UpdateSize = clampu(*persizeopt, 64, 8192);
3602 if(auto peropt = ConfigValueUInt(deviceName, nullptr, "periods"))
3603 device->BufferSize = device->UpdateSize * clampu(*peropt, 2, 16);
3604 else
3605 device->BufferSize = maxu(device->BufferSize, device->UpdateSize*2);
3607 if(auto srcsmax = ConfigValueUInt(deviceName, nullptr, "sources").value_or(0))
3608 device->SourcesMax = srcsmax;
3610 if(auto slotsmax = ConfigValueUInt(deviceName, nullptr, "slots").value_or(0))
3611 device->AuxiliaryEffectSlotMax = minu(slotsmax, INT_MAX);
3613 if(auto sendsopt = ConfigValueInt(deviceName, nullptr, "sends"))
3614 device->NumAuxSends = minu(DEFAULT_SENDS,
3615 static_cast<ALuint>(clampi(*sendsopt, 0, MAX_SENDS)));
3617 device->NumStereoSources = 1;
3618 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3620 if(auto ambiopt = ConfigValueStr(deviceName, nullptr, "ambi-format"))
3622 const ALCchar *fmt{ambiopt->c_str()};
3623 if(al::strcasecmp(fmt, "fuma") == 0)
3625 if(device->mAmbiOrder > 3)
3626 ERR("FuMa is incompatible with %d%s order ambisonics (up to third-order only)\n",
3627 device->mAmbiOrder,
3628 (((device->mAmbiOrder%100)/10) == 1) ? "th" :
3629 ((device->mAmbiOrder%10) == 1) ? "st" :
3630 ((device->mAmbiOrder%10) == 2) ? "nd" :
3631 ((device->mAmbiOrder%10) == 3) ? "rd" : "th");
3632 else
3634 device->mAmbiLayout = DevAmbiLayout::FuMa;
3635 device->mAmbiScale = DevAmbiScaling::FuMa;
3638 else if(al::strcasecmp(fmt, "ambix") == 0 || al::strcasecmp(fmt, "acn+sn3d") == 0)
3640 device->mAmbiLayout = DevAmbiLayout::ACN;
3641 device->mAmbiScale = DevAmbiScaling::SN3D;
3643 else if(al::strcasecmp(fmt, "acn+n3d") == 0)
3645 device->mAmbiLayout = DevAmbiLayout::ACN;
3646 device->mAmbiScale = DevAmbiScaling::N3D;
3648 else
3649 ERR("Unsupported ambi-format: %s\n", fmt);
3653 std::lock_guard<std::recursive_mutex> _{ListLock};
3654 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3655 DeviceList.emplace(iter, device.get());
3658 TRACE("Created device %p, \"%s\"\n", decltype(std::declval<void*>()){device.get()},
3659 device->DeviceName.c_str());
3660 return device.release();
3662 END_API_FUNC
3664 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3665 START_API_FUNC
3667 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3668 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3669 if(iter == DeviceList.end() || *iter != device)
3671 alcSetError(nullptr, ALC_INVALID_DEVICE);
3672 return ALC_FALSE;
3674 if((*iter)->Type == Capture)
3676 alcSetError(*iter, ALC_INVALID_DEVICE);
3677 return ALC_FALSE;
3680 /* Erase the device, and any remaining contexts left on it, from their
3681 * respective lists.
3683 DeviceRef dev{*iter};
3684 DeviceList.erase(iter);
3686 std::unique_lock<std::mutex> statelock{dev->StateLock};
3687 al::vector<ContextRef> orphanctxs;
3688 for(ALCcontext *ctx : *dev->mContexts.load())
3690 auto ctxiter = std::lower_bound(ContextList.begin(), ContextList.end(), ctx);
3691 if(ctxiter != ContextList.end() && *ctxiter == ctx)
3693 orphanctxs.emplace_back(ContextRef{*ctxiter});
3694 ContextList.erase(ctxiter);
3697 listlock.unlock();
3699 for(ContextRef &context : orphanctxs)
3701 WARN("Releasing orphaned context %p\n", decltype(std::declval<void*>()){context.get()});
3702 context->deinit();
3704 orphanctxs.clear();
3706 if(dev->Flags.get<DeviceRunning>())
3707 dev->Backend->stop();
3708 dev->Flags.unset<DeviceRunning>();
3710 return ALC_TRUE;
3712 END_API_FUNC
3715 /************************************************
3716 * ALC capture functions
3717 ************************************************/
3718 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3719 START_API_FUNC
3721 DO_INITCONFIG();
3723 if(!CaptureFactory)
3725 alcSetError(nullptr, ALC_INVALID_VALUE);
3726 return nullptr;
3729 if(samples <= 0)
3731 alcSetError(nullptr, ALC_INVALID_VALUE);
3732 return nullptr;
3735 if(deviceName)
3737 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3738 || al::strcasecmp(deviceName, "openal-soft") == 0)
3739 deviceName = nullptr;
3742 DeviceRef device{new ALCdevice{Capture}};
3744 auto decompfmt = DecomposeDevFormat(format);
3745 if(!decompfmt)
3747 alcSetError(nullptr, ALC_INVALID_ENUM);
3748 return nullptr;
3751 device->Frequency = frequency;
3752 device->FmtChans = decompfmt->chans;
3753 device->FmtType = decompfmt->type;
3754 device->Flags.set<FrequencyRequest, ChannelsRequest, SampleTypeRequest>();
3756 device->UpdateSize = static_cast<ALuint>(samples);
3757 device->BufferSize = static_cast<ALuint>(samples);
3759 try {
3760 TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n",
3761 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
3762 device->Frequency, device->UpdateSize, device->BufferSize);
3764 auto backend = CaptureFactory->createBackend(device.get(), BackendType::Capture);
3765 std::lock_guard<std::recursive_mutex> _{ListLock};
3766 backend->open(deviceName);
3767 device->Backend = std::move(backend);
3769 catch(al::backend_exception &e) {
3770 WARN("Failed to open capture device: %s\n", e.what());
3771 alcSetError(nullptr, e.errorCode());
3772 return nullptr;
3776 std::lock_guard<std::recursive_mutex> _{ListLock};
3777 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3778 DeviceList.emplace(iter, device.get());
3781 TRACE("Created capture device %p, \"%s\"\n", decltype(std::declval<void*>()){device.get()},
3782 device->DeviceName.c_str());
3783 return device.release();
3785 END_API_FUNC
3787 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3788 START_API_FUNC
3790 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3791 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3792 if(iter == DeviceList.end() || *iter != device)
3794 alcSetError(nullptr, ALC_INVALID_DEVICE);
3795 return ALC_FALSE;
3797 if((*iter)->Type != Capture)
3799 alcSetError(*iter, ALC_INVALID_DEVICE);
3800 return ALC_FALSE;
3803 DeviceRef dev{*iter};
3804 DeviceList.erase(iter);
3805 listlock.unlock();
3807 std::lock_guard<std::mutex> _{dev->StateLock};
3808 if(dev->Flags.get<DeviceRunning>())
3809 dev->Backend->stop();
3810 dev->Flags.unset<DeviceRunning>();
3812 return ALC_TRUE;
3814 END_API_FUNC
3816 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3817 START_API_FUNC
3819 DeviceRef dev{VerifyDevice(device)};
3820 if(!dev || dev->Type != Capture)
3822 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3823 return;
3826 std::lock_guard<std::mutex> _{dev->StateLock};
3827 if(!dev->Connected.load(std::memory_order_acquire))
3828 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3829 else if(!dev->Flags.get<DeviceRunning>())
3831 try {
3832 auto backend = dev->Backend.get();
3833 backend->start();
3834 dev->Flags.set<DeviceRunning>();
3836 catch(al::backend_exception& e) {
3837 dev->handleDisconnect("%s", e.what());
3838 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3842 END_API_FUNC
3844 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3845 START_API_FUNC
3847 DeviceRef dev{VerifyDevice(device)};
3848 if(!dev || dev->Type != Capture)
3849 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3850 else
3852 std::lock_guard<std::mutex> _{dev->StateLock};
3853 if(dev->Flags.get<DeviceRunning>())
3854 dev->Backend->stop();
3855 dev->Flags.unset<DeviceRunning>();
3858 END_API_FUNC
3860 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3861 START_API_FUNC
3863 DeviceRef dev{VerifyDevice(device)};
3864 if(!dev || dev->Type != Capture)
3866 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3867 return;
3870 if(samples < 0 || (samples > 0 && buffer == nullptr))
3872 alcSetError(dev.get(), ALC_INVALID_VALUE);
3873 return;
3875 if(samples < 1)
3876 return;
3878 std::lock_guard<std::mutex> _{dev->StateLock};
3879 BackendBase *backend{dev->Backend.get()};
3881 const auto usamples = static_cast<ALCuint>(samples);
3882 if(usamples > backend->availableSamples())
3884 alcSetError(dev.get(), ALC_INVALID_VALUE);
3885 return;
3888 auto *bbuffer = static_cast<al::byte*>(buffer);
3889 if(ALCenum err{backend->captureSamples(bbuffer, usamples)})
3890 alcSetError(dev.get(), err);
3892 END_API_FUNC
3895 /************************************************
3896 * ALC loopback functions
3897 ************************************************/
3899 /** Open a loopback device, for manual rendering. */
3900 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3901 START_API_FUNC
3903 DO_INITCONFIG();
3905 /* Make sure the device name, if specified, is us. */
3906 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3908 alcSetError(nullptr, ALC_INVALID_VALUE);
3909 return nullptr;
3912 DeviceRef device{new ALCdevice{Loopback}};
3914 device->SourcesMax = 256;
3915 device->AuxiliaryEffectSlotMax = 64;
3916 device->NumAuxSends = DEFAULT_SENDS;
3918 //Set output format
3919 device->BufferSize = 0;
3920 device->UpdateSize = 0;
3922 device->Frequency = DEFAULT_OUTPUT_RATE;
3923 device->FmtChans = DevFmtChannelsDefault;
3924 device->FmtType = DevFmtTypeDefault;
3926 if(auto srcsmax = ConfigValueUInt(nullptr, nullptr, "sources").value_or(0))
3927 device->SourcesMax = srcsmax;
3929 if(auto slotsmax = ConfigValueUInt(nullptr, nullptr, "slots").value_or(0))
3930 device->AuxiliaryEffectSlotMax = minu(slotsmax, INT_MAX);
3932 if(auto sendsopt = ConfigValueInt(nullptr, nullptr, "sends"))
3933 device->NumAuxSends = minu(DEFAULT_SENDS,
3934 static_cast<ALuint>(clampi(*sendsopt, 0, MAX_SENDS)));
3936 device->NumStereoSources = 1;
3937 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3939 try {
3940 auto backend = LoopbackBackendFactory::getFactory().createBackend(device.get(),
3941 BackendType::Playback);
3942 backend->open("Loopback");
3943 device->Backend = std::move(backend);
3945 catch(al::backend_exception &e) {
3946 WARN("Failed to open loopback device: %s\n", e.what());
3947 alcSetError(nullptr, e.errorCode());
3948 return nullptr;
3952 std::lock_guard<std::recursive_mutex> _{ListLock};
3953 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3954 DeviceList.emplace(iter, device.get());
3957 TRACE("Created loopback device %p\n", decltype(std::declval<void*>()){device.get()});
3958 return device.release();
3960 END_API_FUNC
3963 * Determines if the loopback device supports the given format for rendering.
3965 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3966 START_API_FUNC
3968 DeviceRef dev{VerifyDevice(device)};
3969 if(!dev || dev->Type != Loopback)
3970 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3971 else if(freq <= 0)
3972 alcSetError(dev.get(), ALC_INVALID_VALUE);
3973 else
3975 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE
3976 && freq <= MAX_OUTPUT_RATE)
3977 return ALC_TRUE;
3980 return ALC_FALSE;
3982 END_API_FUNC
3985 * Renders some samples into a buffer, using the format last set by the
3986 * attributes given to alcCreateContext.
3988 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3989 START_API_FUNC
3991 DeviceRef dev{VerifyDevice(device)};
3992 if(!dev || dev->Type != Loopback)
3993 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3994 else if(samples < 0 || (samples > 0 && buffer == nullptr))
3995 alcSetError(dev.get(), ALC_INVALID_VALUE);
3996 else
3997 dev->renderSamples(buffer, static_cast<ALuint>(samples), dev->channelsFromFmt());
3999 END_API_FUNC
4002 /************************************************
4003 * ALC DSP pause/resume functions
4004 ************************************************/
4006 /** Pause the DSP to stop audio processing. */
4007 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4008 START_API_FUNC
4010 DeviceRef dev{VerifyDevice(device)};
4011 if(!dev || dev->Type != Playback)
4012 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4013 else
4015 std::lock_guard<std::mutex> _{dev->StateLock};
4016 if(dev->Flags.get<DeviceRunning>())
4017 dev->Backend->stop();
4018 dev->Flags.unset<DeviceRunning>();
4019 dev->Flags.set<DevicePaused>();
4022 END_API_FUNC
4024 /** Resume the DSP to restart audio processing. */
4025 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4026 START_API_FUNC
4028 DeviceRef dev{VerifyDevice(device)};
4029 if(!dev || dev->Type != Playback)
4031 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4032 return;
4035 std::lock_guard<std::mutex> _{dev->StateLock};
4036 if(!dev->Flags.get<DevicePaused>())
4037 return;
4038 dev->Flags.unset<DevicePaused>();
4039 if(dev->mContexts.load()->empty())
4040 return;
4042 try {
4043 auto backend = dev->Backend.get();
4044 backend->start();
4045 dev->Flags.set<DeviceRunning>();
4047 catch(al::backend_exception& e) {
4048 dev->handleDisconnect("%s", e.what());
4049 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4052 END_API_FUNC
4055 /************************************************
4056 * ALC HRTF functions
4057 ************************************************/
4059 /** Gets a string parameter at the given index. */
4060 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4061 START_API_FUNC
4063 DeviceRef dev{VerifyDevice(device)};
4064 if(!dev || dev->Type == Capture)
4065 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4066 else switch(paramName)
4068 case ALC_HRTF_SPECIFIER_SOFT:
4069 if(index >= 0 && static_cast<size_t>(index) < dev->HrtfList.size())
4070 return dev->HrtfList[static_cast<ALuint>(index)].c_str();
4071 alcSetError(dev.get(), ALC_INVALID_VALUE);
4072 break;
4074 default:
4075 alcSetError(dev.get(), ALC_INVALID_ENUM);
4076 break;
4079 return nullptr;
4081 END_API_FUNC
4083 /** Resets the given device output, using the specified attribute list. */
4084 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4085 START_API_FUNC
4087 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4088 DeviceRef dev{VerifyDevice(device)};
4089 if(!dev || dev->Type == Capture)
4091 listlock.unlock();
4092 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4093 return ALC_FALSE;
4095 std::lock_guard<std::mutex> _{dev->StateLock};
4096 listlock.unlock();
4098 /* Force the backend to stop mixing first since we're resetting. Also reset
4099 * the connected state so lost devices can attempt recover.
4101 if(dev->Flags.get<DeviceRunning>())
4102 dev->Backend->stop();
4103 dev->Flags.unset<DeviceRunning>();
4104 if(!dev->Connected.load(std::memory_order_relaxed))
4106 /* Make sure disconnection is finished before continuing on. */
4107 dev->waitForMix();
4109 for(ALCcontext *ctx : *dev->mContexts.load(std::memory_order_acquire))
4111 /* Clear any pending voice changes and reallocate voices to get a
4112 * clean restart.
4114 std::lock_guard<std::mutex> __{ctx->mSourceLock};
4115 auto *vchg = ctx->mCurrentVoiceChange.load(std::memory_order_acquire);
4116 while(auto *next = vchg->mNext.load(std::memory_order_acquire))
4117 vchg = next;
4118 ctx->mCurrentVoiceChange.store(vchg, std::memory_order_release);
4120 ctx->mVoiceClusters.clear();
4121 ctx->allocVoices(std::max<size_t>(256,
4122 ctx->mActiveVoiceCount.load(std::memory_order_relaxed)));
4125 dev->Connected.store(true);
4128 ALCenum err{UpdateDeviceParams(dev.get(), attribs)};
4129 if LIKELY(err == ALC_NO_ERROR) return ALC_TRUE;
4131 alcSetError(dev.get(), err);
4132 return ALC_FALSE;
4134 END_API_FUNC