Avoid infs/nans in the crest detector
[openal-soft.git] / alc / alc.cpp
blob1b1e12dd43cd0e332edc4929e0590ad551fa071c
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 #include <exception>
26 #include <algorithm>
27 #include <array>
28 #include <atomic>
29 #include <cctype>
30 #include <chrono>
31 #include <cinttypes>
32 #include <climits>
33 #include <cmath>
34 #include <csignal>
35 #include <cstdint>
36 #include <cstdio>
37 #include <cstdlib>
38 #include <cstring>
39 #include <functional>
40 #include <iterator>
41 #include <limits>
42 #include <memory>
43 #include <mutex>
44 #include <new>
45 #include <numeric>
46 #include <string>
47 #include <thread>
48 #include <utility>
50 #include "AL/al.h"
51 #include "AL/alc.h"
52 #include "AL/alext.h"
53 #include "AL/efx.h"
55 #include "al/auxeffectslot.h"
56 #include "al/effect.h"
57 #include "al/event.h"
58 #include "al/filter.h"
59 #include "al/listener.h"
60 #include "al/source.h"
61 #include "alcmain.h"
62 #include "albyte.h"
63 #include "alconfig.h"
64 #include "alcontext.h"
65 #include "alexcpt.h"
66 #include "almalloc.h"
67 #include "alnumeric.h"
68 #include "aloptional.h"
69 #include "alspan.h"
70 #include "alstring.h"
71 #include "alu.h"
72 #include "ambidefs.h"
73 #include "atomic.h"
74 #include "bformatdec.h"
75 #include "bs2b.h"
76 #include "compat.h"
77 #include "cpu_caps.h"
78 #include "devformat.h"
79 #include "effects/base.h"
80 #include "filters/nfc.h"
81 #include "filters/splitter.h"
82 #include "fpu_modes.h"
83 #include "hrtf.h"
84 #include "inprogext.h"
85 #include "intrusive_ptr.h"
86 #include "logging.h"
87 #include "mastering.h"
88 #include "opthelpers.h"
89 #include "ringbuffer.h"
90 #include "strutils.h"
91 #include "threads.h"
92 #include "uhjfilter.h"
93 #include "vecmat.h"
94 #include "vector.h"
96 #include "backends/base.h"
97 #include "backends/null.h"
98 #include "backends/loopback.h"
99 #ifdef HAVE_JACK
100 #include "backends/jack.h"
101 #endif
102 #ifdef HAVE_PULSEAUDIO
103 #include "backends/pulseaudio.h"
104 #endif
105 #ifdef HAVE_ALSA
106 #include "backends/alsa.h"
107 #endif
108 #ifdef HAVE_WASAPI
109 #include "backends/wasapi.h"
110 #endif
111 #ifdef HAVE_COREAUDIO
112 #include "backends/coreaudio.h"
113 #endif
114 #ifdef HAVE_OPENSL
115 #include "backends/opensl.h"
116 #endif
117 #ifdef HAVE_SOLARIS
118 #include "backends/solaris.h"
119 #endif
120 #ifdef HAVE_SNDIO
121 #include "backends/sndio.h"
122 #endif
123 #ifdef HAVE_OSS
124 #include "backends/oss.h"
125 #endif
126 #ifdef HAVE_QSA
127 #include "backends/qsa.h"
128 #endif
129 #ifdef HAVE_DSOUND
130 #include "backends/dsound.h"
131 #endif
132 #ifdef HAVE_WINMM
133 #include "backends/winmm.h"
134 #endif
135 #ifdef HAVE_PORTAUDIO
136 #include "backends/portaudio.h"
137 #endif
138 #ifdef HAVE_SDL2
139 #include "backends/sdl2.h"
140 #endif
141 #ifdef HAVE_WAVE
142 #include "backends/wave.h"
143 #endif
146 namespace {
148 using namespace std::placeholders;
149 using std::chrono::seconds;
150 using std::chrono::nanoseconds;
153 /************************************************
154 * Backends
155 ************************************************/
156 struct BackendInfo {
157 const char *name;
158 BackendFactory& (*getFactory)(void);
161 BackendInfo BackendList[] = {
162 #ifdef HAVE_JACK
163 { "jack", JackBackendFactory::getFactory },
164 #endif
165 #ifdef HAVE_PULSEAUDIO
166 { "pulse", PulseBackendFactory::getFactory },
167 #endif
168 #ifdef HAVE_ALSA
169 { "alsa", AlsaBackendFactory::getFactory },
170 #endif
171 #ifdef HAVE_WASAPI
172 { "wasapi", WasapiBackendFactory::getFactory },
173 #endif
174 #ifdef HAVE_COREAUDIO
175 { "core", CoreAudioBackendFactory::getFactory },
176 #endif
177 #ifdef HAVE_OPENSL
178 { "opensl", OSLBackendFactory::getFactory },
179 #endif
180 #ifdef HAVE_SOLARIS
181 { "solaris", SolarisBackendFactory::getFactory },
182 #endif
183 #ifdef HAVE_SNDIO
184 { "sndio", SndIOBackendFactory::getFactory },
185 #endif
186 #ifdef HAVE_OSS
187 { "oss", OSSBackendFactory::getFactory },
188 #endif
189 #ifdef HAVE_QSA
190 { "qsa", QSABackendFactory::getFactory },
191 #endif
192 #ifdef HAVE_DSOUND
193 { "dsound", DSoundBackendFactory::getFactory },
194 #endif
195 #ifdef HAVE_WINMM
196 { "winmm", WinMMBackendFactory::getFactory },
197 #endif
198 #ifdef HAVE_PORTAUDIO
199 { "port", PortBackendFactory::getFactory },
200 #endif
201 #ifdef HAVE_SDL2
202 { "sdl2", SDL2BackendFactory::getFactory },
203 #endif
205 { "null", NullBackendFactory::getFactory },
206 #ifdef HAVE_WAVE
207 { "wave", WaveBackendFactory::getFactory },
208 #endif
210 auto BackendListEnd = std::end(BackendList);
212 BackendFactory *PlaybackFactory{};
213 BackendFactory *CaptureFactory{};
216 /************************************************
217 * Functions, enums, and errors
218 ************************************************/
219 #define DECL(x) { #x, reinterpret_cast<void*>(x) }
220 const struct {
221 const ALCchar *funcName;
222 ALCvoid *address;
223 } alcFunctions[] = {
224 DECL(alcCreateContext),
225 DECL(alcMakeContextCurrent),
226 DECL(alcProcessContext),
227 DECL(alcSuspendContext),
228 DECL(alcDestroyContext),
229 DECL(alcGetCurrentContext),
230 DECL(alcGetContextsDevice),
231 DECL(alcOpenDevice),
232 DECL(alcCloseDevice),
233 DECL(alcGetError),
234 DECL(alcIsExtensionPresent),
235 DECL(alcGetProcAddress),
236 DECL(alcGetEnumValue),
237 DECL(alcGetString),
238 DECL(alcGetIntegerv),
239 DECL(alcCaptureOpenDevice),
240 DECL(alcCaptureCloseDevice),
241 DECL(alcCaptureStart),
242 DECL(alcCaptureStop),
243 DECL(alcCaptureSamples),
245 DECL(alcSetThreadContext),
246 DECL(alcGetThreadContext),
248 DECL(alcLoopbackOpenDeviceSOFT),
249 DECL(alcIsRenderFormatSupportedSOFT),
250 DECL(alcRenderSamplesSOFT),
252 DECL(alcDevicePauseSOFT),
253 DECL(alcDeviceResumeSOFT),
255 DECL(alcGetStringiSOFT),
256 DECL(alcResetDeviceSOFT),
258 DECL(alcGetInteger64vSOFT),
260 DECL(alEnable),
261 DECL(alDisable),
262 DECL(alIsEnabled),
263 DECL(alGetString),
264 DECL(alGetBooleanv),
265 DECL(alGetIntegerv),
266 DECL(alGetFloatv),
267 DECL(alGetDoublev),
268 DECL(alGetBoolean),
269 DECL(alGetInteger),
270 DECL(alGetFloat),
271 DECL(alGetDouble),
272 DECL(alGetError),
273 DECL(alIsExtensionPresent),
274 DECL(alGetProcAddress),
275 DECL(alGetEnumValue),
276 DECL(alListenerf),
277 DECL(alListener3f),
278 DECL(alListenerfv),
279 DECL(alListeneri),
280 DECL(alListener3i),
281 DECL(alListeneriv),
282 DECL(alGetListenerf),
283 DECL(alGetListener3f),
284 DECL(alGetListenerfv),
285 DECL(alGetListeneri),
286 DECL(alGetListener3i),
287 DECL(alGetListeneriv),
288 DECL(alGenSources),
289 DECL(alDeleteSources),
290 DECL(alIsSource),
291 DECL(alSourcef),
292 DECL(alSource3f),
293 DECL(alSourcefv),
294 DECL(alSourcei),
295 DECL(alSource3i),
296 DECL(alSourceiv),
297 DECL(alGetSourcef),
298 DECL(alGetSource3f),
299 DECL(alGetSourcefv),
300 DECL(alGetSourcei),
301 DECL(alGetSource3i),
302 DECL(alGetSourceiv),
303 DECL(alSourcePlayv),
304 DECL(alSourceStopv),
305 DECL(alSourceRewindv),
306 DECL(alSourcePausev),
307 DECL(alSourcePlay),
308 DECL(alSourceStop),
309 DECL(alSourceRewind),
310 DECL(alSourcePause),
311 DECL(alSourceQueueBuffers),
312 DECL(alSourceUnqueueBuffers),
313 DECL(alGenBuffers),
314 DECL(alDeleteBuffers),
315 DECL(alIsBuffer),
316 DECL(alBufferData),
317 DECL(alBufferf),
318 DECL(alBuffer3f),
319 DECL(alBufferfv),
320 DECL(alBufferi),
321 DECL(alBuffer3i),
322 DECL(alBufferiv),
323 DECL(alGetBufferf),
324 DECL(alGetBuffer3f),
325 DECL(alGetBufferfv),
326 DECL(alGetBufferi),
327 DECL(alGetBuffer3i),
328 DECL(alGetBufferiv),
329 DECL(alDopplerFactor),
330 DECL(alDopplerVelocity),
331 DECL(alSpeedOfSound),
332 DECL(alDistanceModel),
334 DECL(alGenFilters),
335 DECL(alDeleteFilters),
336 DECL(alIsFilter),
337 DECL(alFilteri),
338 DECL(alFilteriv),
339 DECL(alFilterf),
340 DECL(alFilterfv),
341 DECL(alGetFilteri),
342 DECL(alGetFilteriv),
343 DECL(alGetFilterf),
344 DECL(alGetFilterfv),
345 DECL(alGenEffects),
346 DECL(alDeleteEffects),
347 DECL(alIsEffect),
348 DECL(alEffecti),
349 DECL(alEffectiv),
350 DECL(alEffectf),
351 DECL(alEffectfv),
352 DECL(alGetEffecti),
353 DECL(alGetEffectiv),
354 DECL(alGetEffectf),
355 DECL(alGetEffectfv),
356 DECL(alGenAuxiliaryEffectSlots),
357 DECL(alDeleteAuxiliaryEffectSlots),
358 DECL(alIsAuxiliaryEffectSlot),
359 DECL(alAuxiliaryEffectSloti),
360 DECL(alAuxiliaryEffectSlotiv),
361 DECL(alAuxiliaryEffectSlotf),
362 DECL(alAuxiliaryEffectSlotfv),
363 DECL(alGetAuxiliaryEffectSloti),
364 DECL(alGetAuxiliaryEffectSlotiv),
365 DECL(alGetAuxiliaryEffectSlotf),
366 DECL(alGetAuxiliaryEffectSlotfv),
368 DECL(alDeferUpdatesSOFT),
369 DECL(alProcessUpdatesSOFT),
371 DECL(alSourcedSOFT),
372 DECL(alSource3dSOFT),
373 DECL(alSourcedvSOFT),
374 DECL(alGetSourcedSOFT),
375 DECL(alGetSource3dSOFT),
376 DECL(alGetSourcedvSOFT),
377 DECL(alSourcei64SOFT),
378 DECL(alSource3i64SOFT),
379 DECL(alSourcei64vSOFT),
380 DECL(alGetSourcei64SOFT),
381 DECL(alGetSource3i64SOFT),
382 DECL(alGetSourcei64vSOFT),
384 DECL(alGetStringiSOFT),
386 DECL(alBufferStorageSOFT),
387 DECL(alMapBufferSOFT),
388 DECL(alUnmapBufferSOFT),
389 DECL(alFlushMappedBufferSOFT),
391 DECL(alEventControlSOFT),
392 DECL(alEventCallbackSOFT),
393 DECL(alGetPointerSOFT),
394 DECL(alGetPointervSOFT),
396 #undef DECL
398 #define DECL(x) { #x, (x) }
399 constexpr struct {
400 const ALCchar *enumName;
401 ALCenum value;
402 } alcEnumerations[] = {
403 DECL(ALC_INVALID),
404 DECL(ALC_FALSE),
405 DECL(ALC_TRUE),
407 DECL(ALC_MAJOR_VERSION),
408 DECL(ALC_MINOR_VERSION),
409 DECL(ALC_ATTRIBUTES_SIZE),
410 DECL(ALC_ALL_ATTRIBUTES),
411 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
412 DECL(ALC_DEVICE_SPECIFIER),
413 DECL(ALC_ALL_DEVICES_SPECIFIER),
414 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
415 DECL(ALC_EXTENSIONS),
416 DECL(ALC_FREQUENCY),
417 DECL(ALC_REFRESH),
418 DECL(ALC_SYNC),
419 DECL(ALC_MONO_SOURCES),
420 DECL(ALC_STEREO_SOURCES),
421 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
422 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
423 DECL(ALC_CAPTURE_SAMPLES),
424 DECL(ALC_CONNECTED),
426 DECL(ALC_EFX_MAJOR_VERSION),
427 DECL(ALC_EFX_MINOR_VERSION),
428 DECL(ALC_MAX_AUXILIARY_SENDS),
430 DECL(ALC_FORMAT_CHANNELS_SOFT),
431 DECL(ALC_FORMAT_TYPE_SOFT),
433 DECL(ALC_MONO_SOFT),
434 DECL(ALC_STEREO_SOFT),
435 DECL(ALC_QUAD_SOFT),
436 DECL(ALC_5POINT1_SOFT),
437 DECL(ALC_6POINT1_SOFT),
438 DECL(ALC_7POINT1_SOFT),
439 DECL(ALC_BFORMAT3D_SOFT),
441 DECL(ALC_BYTE_SOFT),
442 DECL(ALC_UNSIGNED_BYTE_SOFT),
443 DECL(ALC_SHORT_SOFT),
444 DECL(ALC_UNSIGNED_SHORT_SOFT),
445 DECL(ALC_INT_SOFT),
446 DECL(ALC_UNSIGNED_INT_SOFT),
447 DECL(ALC_FLOAT_SOFT),
449 DECL(ALC_HRTF_SOFT),
450 DECL(ALC_DONT_CARE_SOFT),
451 DECL(ALC_HRTF_STATUS_SOFT),
452 DECL(ALC_HRTF_DISABLED_SOFT),
453 DECL(ALC_HRTF_ENABLED_SOFT),
454 DECL(ALC_HRTF_DENIED_SOFT),
455 DECL(ALC_HRTF_REQUIRED_SOFT),
456 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
457 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
458 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
459 DECL(ALC_HRTF_SPECIFIER_SOFT),
460 DECL(ALC_HRTF_ID_SOFT),
462 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
463 DECL(ALC_AMBISONIC_SCALING_SOFT),
464 DECL(ALC_AMBISONIC_ORDER_SOFT),
465 DECL(ALC_ACN_SOFT),
466 DECL(ALC_FUMA_SOFT),
467 DECL(ALC_N3D_SOFT),
468 DECL(ALC_SN3D_SOFT),
470 DECL(ALC_OUTPUT_LIMITER_SOFT),
472 DECL(ALC_NO_ERROR),
473 DECL(ALC_INVALID_DEVICE),
474 DECL(ALC_INVALID_CONTEXT),
475 DECL(ALC_INVALID_ENUM),
476 DECL(ALC_INVALID_VALUE),
477 DECL(ALC_OUT_OF_MEMORY),
480 DECL(AL_INVALID),
481 DECL(AL_NONE),
482 DECL(AL_FALSE),
483 DECL(AL_TRUE),
485 DECL(AL_SOURCE_RELATIVE),
486 DECL(AL_CONE_INNER_ANGLE),
487 DECL(AL_CONE_OUTER_ANGLE),
488 DECL(AL_PITCH),
489 DECL(AL_POSITION),
490 DECL(AL_DIRECTION),
491 DECL(AL_VELOCITY),
492 DECL(AL_LOOPING),
493 DECL(AL_BUFFER),
494 DECL(AL_GAIN),
495 DECL(AL_MIN_GAIN),
496 DECL(AL_MAX_GAIN),
497 DECL(AL_ORIENTATION),
498 DECL(AL_REFERENCE_DISTANCE),
499 DECL(AL_ROLLOFF_FACTOR),
500 DECL(AL_CONE_OUTER_GAIN),
501 DECL(AL_MAX_DISTANCE),
502 DECL(AL_SEC_OFFSET),
503 DECL(AL_SAMPLE_OFFSET),
504 DECL(AL_BYTE_OFFSET),
505 DECL(AL_SOURCE_TYPE),
506 DECL(AL_STATIC),
507 DECL(AL_STREAMING),
508 DECL(AL_UNDETERMINED),
509 DECL(AL_METERS_PER_UNIT),
510 DECL(AL_LOOP_POINTS_SOFT),
511 DECL(AL_DIRECT_CHANNELS_SOFT),
513 DECL(AL_DIRECT_FILTER),
514 DECL(AL_AUXILIARY_SEND_FILTER),
515 DECL(AL_AIR_ABSORPTION_FACTOR),
516 DECL(AL_ROOM_ROLLOFF_FACTOR),
517 DECL(AL_CONE_OUTER_GAINHF),
518 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
519 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
520 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
522 DECL(AL_SOURCE_STATE),
523 DECL(AL_INITIAL),
524 DECL(AL_PLAYING),
525 DECL(AL_PAUSED),
526 DECL(AL_STOPPED),
528 DECL(AL_BUFFERS_QUEUED),
529 DECL(AL_BUFFERS_PROCESSED),
531 DECL(AL_FORMAT_MONO8),
532 DECL(AL_FORMAT_MONO16),
533 DECL(AL_FORMAT_MONO_FLOAT32),
534 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
535 DECL(AL_FORMAT_STEREO8),
536 DECL(AL_FORMAT_STEREO16),
537 DECL(AL_FORMAT_STEREO_FLOAT32),
538 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
539 DECL(AL_FORMAT_MONO_IMA4),
540 DECL(AL_FORMAT_STEREO_IMA4),
541 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
542 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
543 DECL(AL_FORMAT_QUAD8_LOKI),
544 DECL(AL_FORMAT_QUAD16_LOKI),
545 DECL(AL_FORMAT_QUAD8),
546 DECL(AL_FORMAT_QUAD16),
547 DECL(AL_FORMAT_QUAD32),
548 DECL(AL_FORMAT_51CHN8),
549 DECL(AL_FORMAT_51CHN16),
550 DECL(AL_FORMAT_51CHN32),
551 DECL(AL_FORMAT_61CHN8),
552 DECL(AL_FORMAT_61CHN16),
553 DECL(AL_FORMAT_61CHN32),
554 DECL(AL_FORMAT_71CHN8),
555 DECL(AL_FORMAT_71CHN16),
556 DECL(AL_FORMAT_71CHN32),
557 DECL(AL_FORMAT_REAR8),
558 DECL(AL_FORMAT_REAR16),
559 DECL(AL_FORMAT_REAR32),
560 DECL(AL_FORMAT_MONO_MULAW),
561 DECL(AL_FORMAT_MONO_MULAW_EXT),
562 DECL(AL_FORMAT_STEREO_MULAW),
563 DECL(AL_FORMAT_STEREO_MULAW_EXT),
564 DECL(AL_FORMAT_QUAD_MULAW),
565 DECL(AL_FORMAT_51CHN_MULAW),
566 DECL(AL_FORMAT_61CHN_MULAW),
567 DECL(AL_FORMAT_71CHN_MULAW),
568 DECL(AL_FORMAT_REAR_MULAW),
569 DECL(AL_FORMAT_MONO_ALAW_EXT),
570 DECL(AL_FORMAT_STEREO_ALAW_EXT),
572 DECL(AL_FORMAT_BFORMAT2D_8),
573 DECL(AL_FORMAT_BFORMAT2D_16),
574 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
575 DECL(AL_FORMAT_BFORMAT2D_MULAW),
576 DECL(AL_FORMAT_BFORMAT3D_8),
577 DECL(AL_FORMAT_BFORMAT3D_16),
578 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
579 DECL(AL_FORMAT_BFORMAT3D_MULAW),
581 DECL(AL_FREQUENCY),
582 DECL(AL_BITS),
583 DECL(AL_CHANNELS),
584 DECL(AL_SIZE),
585 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
586 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
588 DECL(AL_SOURCE_RADIUS),
590 DECL(AL_STEREO_ANGLES),
592 DECL(AL_UNUSED),
593 DECL(AL_PENDING),
594 DECL(AL_PROCESSED),
596 DECL(AL_NO_ERROR),
597 DECL(AL_INVALID_NAME),
598 DECL(AL_INVALID_ENUM),
599 DECL(AL_INVALID_VALUE),
600 DECL(AL_INVALID_OPERATION),
601 DECL(AL_OUT_OF_MEMORY),
603 DECL(AL_VENDOR),
604 DECL(AL_VERSION),
605 DECL(AL_RENDERER),
606 DECL(AL_EXTENSIONS),
608 DECL(AL_DOPPLER_FACTOR),
609 DECL(AL_DOPPLER_VELOCITY),
610 DECL(AL_DISTANCE_MODEL),
611 DECL(AL_SPEED_OF_SOUND),
612 DECL(AL_SOURCE_DISTANCE_MODEL),
613 DECL(AL_DEFERRED_UPDATES_SOFT),
614 DECL(AL_GAIN_LIMIT_SOFT),
616 DECL(AL_INVERSE_DISTANCE),
617 DECL(AL_INVERSE_DISTANCE_CLAMPED),
618 DECL(AL_LINEAR_DISTANCE),
619 DECL(AL_LINEAR_DISTANCE_CLAMPED),
620 DECL(AL_EXPONENT_DISTANCE),
621 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
623 DECL(AL_FILTER_TYPE),
624 DECL(AL_FILTER_NULL),
625 DECL(AL_FILTER_LOWPASS),
626 DECL(AL_FILTER_HIGHPASS),
627 DECL(AL_FILTER_BANDPASS),
629 DECL(AL_LOWPASS_GAIN),
630 DECL(AL_LOWPASS_GAINHF),
632 DECL(AL_HIGHPASS_GAIN),
633 DECL(AL_HIGHPASS_GAINLF),
635 DECL(AL_BANDPASS_GAIN),
636 DECL(AL_BANDPASS_GAINHF),
637 DECL(AL_BANDPASS_GAINLF),
639 DECL(AL_EFFECT_TYPE),
640 DECL(AL_EFFECT_NULL),
641 DECL(AL_EFFECT_REVERB),
642 DECL(AL_EFFECT_EAXREVERB),
643 DECL(AL_EFFECT_CHORUS),
644 DECL(AL_EFFECT_DISTORTION),
645 DECL(AL_EFFECT_ECHO),
646 DECL(AL_EFFECT_FLANGER),
647 DECL(AL_EFFECT_PITCH_SHIFTER),
648 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
649 DECL(AL_EFFECT_VOCAL_MORPHER),
650 DECL(AL_EFFECT_RING_MODULATOR),
651 DECL(AL_EFFECT_AUTOWAH),
652 DECL(AL_EFFECT_COMPRESSOR),
653 DECL(AL_EFFECT_EQUALIZER),
654 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
655 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
657 DECL(AL_EFFECTSLOT_EFFECT),
658 DECL(AL_EFFECTSLOT_GAIN),
659 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
660 DECL(AL_EFFECTSLOT_NULL),
662 DECL(AL_EAXREVERB_DENSITY),
663 DECL(AL_EAXREVERB_DIFFUSION),
664 DECL(AL_EAXREVERB_GAIN),
665 DECL(AL_EAXREVERB_GAINHF),
666 DECL(AL_EAXREVERB_GAINLF),
667 DECL(AL_EAXREVERB_DECAY_TIME),
668 DECL(AL_EAXREVERB_DECAY_HFRATIO),
669 DECL(AL_EAXREVERB_DECAY_LFRATIO),
670 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
671 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
672 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
673 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
674 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
675 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
676 DECL(AL_EAXREVERB_ECHO_TIME),
677 DECL(AL_EAXREVERB_ECHO_DEPTH),
678 DECL(AL_EAXREVERB_MODULATION_TIME),
679 DECL(AL_EAXREVERB_MODULATION_DEPTH),
680 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
681 DECL(AL_EAXREVERB_HFREFERENCE),
682 DECL(AL_EAXREVERB_LFREFERENCE),
683 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
684 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
686 DECL(AL_REVERB_DENSITY),
687 DECL(AL_REVERB_DIFFUSION),
688 DECL(AL_REVERB_GAIN),
689 DECL(AL_REVERB_GAINHF),
690 DECL(AL_REVERB_DECAY_TIME),
691 DECL(AL_REVERB_DECAY_HFRATIO),
692 DECL(AL_REVERB_REFLECTIONS_GAIN),
693 DECL(AL_REVERB_REFLECTIONS_DELAY),
694 DECL(AL_REVERB_LATE_REVERB_GAIN),
695 DECL(AL_REVERB_LATE_REVERB_DELAY),
696 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
697 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
698 DECL(AL_REVERB_DECAY_HFLIMIT),
700 DECL(AL_CHORUS_WAVEFORM),
701 DECL(AL_CHORUS_PHASE),
702 DECL(AL_CHORUS_RATE),
703 DECL(AL_CHORUS_DEPTH),
704 DECL(AL_CHORUS_FEEDBACK),
705 DECL(AL_CHORUS_DELAY),
707 DECL(AL_DISTORTION_EDGE),
708 DECL(AL_DISTORTION_GAIN),
709 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
710 DECL(AL_DISTORTION_EQCENTER),
711 DECL(AL_DISTORTION_EQBANDWIDTH),
713 DECL(AL_ECHO_DELAY),
714 DECL(AL_ECHO_LRDELAY),
715 DECL(AL_ECHO_DAMPING),
716 DECL(AL_ECHO_FEEDBACK),
717 DECL(AL_ECHO_SPREAD),
719 DECL(AL_FLANGER_WAVEFORM),
720 DECL(AL_FLANGER_PHASE),
721 DECL(AL_FLANGER_RATE),
722 DECL(AL_FLANGER_DEPTH),
723 DECL(AL_FLANGER_FEEDBACK),
724 DECL(AL_FLANGER_DELAY),
726 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY),
727 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION),
728 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION),
730 DECL(AL_RING_MODULATOR_FREQUENCY),
731 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
732 DECL(AL_RING_MODULATOR_WAVEFORM),
734 DECL(AL_PITCH_SHIFTER_COARSE_TUNE),
735 DECL(AL_PITCH_SHIFTER_FINE_TUNE),
737 DECL(AL_COMPRESSOR_ONOFF),
739 DECL(AL_EQUALIZER_LOW_GAIN),
740 DECL(AL_EQUALIZER_LOW_CUTOFF),
741 DECL(AL_EQUALIZER_MID1_GAIN),
742 DECL(AL_EQUALIZER_MID1_CENTER),
743 DECL(AL_EQUALIZER_MID1_WIDTH),
744 DECL(AL_EQUALIZER_MID2_GAIN),
745 DECL(AL_EQUALIZER_MID2_CENTER),
746 DECL(AL_EQUALIZER_MID2_WIDTH),
747 DECL(AL_EQUALIZER_HIGH_GAIN),
748 DECL(AL_EQUALIZER_HIGH_CUTOFF),
750 DECL(AL_DEDICATED_GAIN),
752 DECL(AL_AUTOWAH_ATTACK_TIME),
753 DECL(AL_AUTOWAH_RELEASE_TIME),
754 DECL(AL_AUTOWAH_RESONANCE),
755 DECL(AL_AUTOWAH_PEAK_GAIN),
757 DECL(AL_VOCAL_MORPHER_PHONEMEA),
758 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING),
759 DECL(AL_VOCAL_MORPHER_PHONEMEB),
760 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING),
761 DECL(AL_VOCAL_MORPHER_WAVEFORM),
762 DECL(AL_VOCAL_MORPHER_RATE),
764 DECL(AL_NUM_RESAMPLERS_SOFT),
765 DECL(AL_DEFAULT_RESAMPLER_SOFT),
766 DECL(AL_SOURCE_RESAMPLER_SOFT),
767 DECL(AL_RESAMPLER_NAME_SOFT),
769 DECL(AL_SOURCE_SPATIALIZE_SOFT),
770 DECL(AL_AUTO_SOFT),
772 DECL(AL_MAP_READ_BIT_SOFT),
773 DECL(AL_MAP_WRITE_BIT_SOFT),
774 DECL(AL_MAP_PERSISTENT_BIT_SOFT),
775 DECL(AL_PRESERVE_DATA_BIT_SOFT),
777 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT),
778 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT),
779 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT),
780 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT),
781 DECL(AL_EVENT_TYPE_ERROR_SOFT),
782 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT),
783 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT),
785 #undef DECL
787 constexpr ALCchar alcNoError[] = "No Error";
788 constexpr ALCchar alcErrInvalidDevice[] = "Invalid Device";
789 constexpr ALCchar alcErrInvalidContext[] = "Invalid Context";
790 constexpr ALCchar alcErrInvalidEnum[] = "Invalid Enum";
791 constexpr ALCchar alcErrInvalidValue[] = "Invalid Value";
792 constexpr ALCchar alcErrOutOfMemory[] = "Out of Memory";
795 /************************************************
796 * Global variables
797 ************************************************/
799 /* Enumerated device names */
800 constexpr ALCchar alcDefaultName[] = "OpenAL Soft\0";
802 std::string alcAllDevicesList;
803 std::string alcCaptureDeviceList;
805 /* Default is always the first in the list */
806 al::string alcDefaultAllDevicesSpecifier;
807 al::string alcCaptureDefaultDeviceSpecifier;
809 /* Default context extensions */
810 constexpr ALchar alExtList[] =
811 "AL_EXT_ALAW "
812 "AL_EXT_BFORMAT "
813 "AL_EXT_DOUBLE "
814 "AL_EXT_EXPONENT_DISTANCE "
815 "AL_EXT_FLOAT32 "
816 "AL_EXT_IMA4 "
817 "AL_EXT_LINEAR_DISTANCE "
818 "AL_EXT_MCFORMATS "
819 "AL_EXT_MULAW "
820 "AL_EXT_MULAW_BFORMAT "
821 "AL_EXT_MULAW_MCFORMATS "
822 "AL_EXT_OFFSET "
823 "AL_EXT_source_distance_model "
824 "AL_EXT_SOURCE_RADIUS "
825 "AL_EXT_STEREO_ANGLES "
826 "AL_LOKI_quadriphonic "
827 "AL_SOFT_block_alignment "
828 "AL_SOFT_deferred_updates "
829 "AL_SOFT_direct_channels "
830 "AL_SOFTX_effect_chain "
831 "AL_SOFTX_events "
832 "AL_SOFTX_filter_gain_ex "
833 "AL_SOFT_gain_clamp_ex "
834 "AL_SOFT_loop_points "
835 "AL_SOFTX_map_buffer "
836 "AL_SOFT_MSADPCM "
837 "AL_SOFT_source_latency "
838 "AL_SOFT_source_length "
839 "AL_SOFT_source_resampler "
840 "AL_SOFT_source_spatialize";
842 std::atomic<ALCenum> LastNullDeviceError{ALC_NO_ERROR};
844 /* Thread-local current context */
845 void ReleaseThreadCtx(ALCcontext *context)
847 const bool result{context->releaseIfNoDelete()};
848 ERR("Context %p current for thread being destroyed%s!\n",
849 decltype(std::declval<void*>()){context}, result ? "" : ", leak detected");
852 class ThreadCtx {
853 ALCcontext *ctx{nullptr};
855 public:
856 ~ThreadCtx()
858 if(ctx)
859 ReleaseThreadCtx(ctx);
860 ctx = nullptr;
863 ALCcontext *get() const noexcept { return ctx; }
864 void set(ALCcontext *ctx_) noexcept { ctx = ctx_; }
866 thread_local ThreadCtx LocalContext;
867 /* Process-wide current context */
868 std::atomic<ALCcontext*> GlobalContext{nullptr};
870 /* Flag to trap ALC device errors */
871 bool TrapALCError{false};
873 /* One-time configuration init control */
874 std::once_flag alc_config_once{};
876 /* Default effect that applies to sources that don't have an effect on send 0 */
877 ALeffect DefaultEffect;
879 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
880 * updates.
882 bool SuspendDefers{true};
885 /************************************************
886 * ALC information
887 ************************************************/
888 constexpr ALCchar alcNoDeviceExtList[] =
889 "ALC_ENUMERATE_ALL_EXT "
890 "ALC_ENUMERATION_EXT "
891 "ALC_EXT_CAPTURE "
892 "ALC_EXT_thread_local_context "
893 "ALC_SOFT_loopback";
894 constexpr ALCchar alcExtensionList[] =
895 "ALC_ENUMERATE_ALL_EXT "
896 "ALC_ENUMERATION_EXT "
897 "ALC_EXT_CAPTURE "
898 "ALC_EXT_DEDICATED "
899 "ALC_EXT_disconnect "
900 "ALC_EXT_EFX "
901 "ALC_EXT_thread_local_context "
902 "ALC_SOFT_device_clock "
903 "ALC_SOFT_HRTF "
904 "ALC_SOFT_loopback "
905 "ALC_SOFT_output_limiter "
906 "ALC_SOFT_pause_device";
907 constexpr ALCint alcMajorVersion = 1;
908 constexpr ALCint alcMinorVersion = 1;
910 constexpr ALCint alcEFXMajorVersion = 1;
911 constexpr ALCint alcEFXMinorVersion = 0;
914 /* To avoid extraneous allocations, a 0-sized FlexArray<ALCcontext*> is defined
915 * globally as a sharable object. MSVC warns that a zero-sized array will have
916 * zero objects here, so silence that.
918 DIAGNOSTIC_PUSH
919 MVSDIAGNOSTIC(warning(disable : 4815))
920 al::FlexArray<ALCcontext*> EmptyContextArray{0u};
921 DIAGNOSTIC_POP
924 using DeviceRef = al::intrusive_ptr<ALCdevice>;
927 /************************************************
928 * Device lists
929 ************************************************/
930 al::vector<DeviceRef> DeviceList;
931 al::vector<ContextRef> ContextList;
933 std::recursive_mutex ListLock;
936 void alc_initconfig(void)
938 if(auto loglevel = al::getenv("ALSOFT_LOGLEVEL"))
940 long lvl = strtol(loglevel->c_str(), nullptr, 0);
941 if(lvl >= NoLog && lvl <= LogRef)
942 gLogLevel = static_cast<LogLevel>(lvl);
945 if(auto logfile = al::getenv("ALSOFT_LOGFILE"))
947 #ifdef _WIN32
948 std::wstring wname{utf8_to_wstr(logfile->c_str())};
949 FILE *logf{_wfopen(wname.c_str(), L"wt")};
950 #else
951 FILE *logf{fopen(logfile->c_str(), "wt")};
952 #endif
953 if(logf) gLogFile = logf;
954 else ERR("Failed to open log file '%s'\n", logfile->c_str());
957 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION, ALSOFT_GIT_COMMIT_HASH,
958 ALSOFT_GIT_BRANCH);
960 al::string names;
961 if(std::begin(BackendList) == BackendListEnd)
962 names += "(none)";
963 else
965 const al::span<const BackendInfo> infos{std::begin(BackendList), BackendListEnd};
966 names += infos[0].name;
967 for(const auto &backend : infos.subspan(1))
969 names += ", ";
970 names += backend.name;
973 TRACE("Supported backends: %s\n", names.c_str());
975 ReadALConfig();
977 if(auto suspendmode = al::getenv("__ALSOFT_SUSPEND_CONTEXT"))
979 if(al::strcasecmp(suspendmode->c_str(), "ignore") == 0)
981 SuspendDefers = false;
982 TRACE("Selected context suspend behavior, \"ignore\"\n");
984 else
985 ERR("Unhandled context suspend behavior setting: \"%s\"\n", suspendmode->c_str());
988 int capfilter{0};
989 #if defined(HAVE_SSE4_1)
990 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
991 #elif defined(HAVE_SSE3)
992 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
993 #elif defined(HAVE_SSE2)
994 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
995 #elif defined(HAVE_SSE)
996 capfilter |= CPU_CAP_SSE;
997 #endif
998 #ifdef HAVE_NEON
999 capfilter |= CPU_CAP_NEON;
1000 #endif
1001 if(auto cpuopt = ConfigValueStr(nullptr, nullptr, "disable-cpu-exts"))
1003 const char *str{cpuopt->c_str()};
1004 if(al::strcasecmp(str, "all") == 0)
1005 capfilter = 0;
1006 else
1008 const char *next = str;
1009 do {
1010 str = next;
1011 while(isspace(str[0]))
1012 str++;
1013 next = strchr(str, ',');
1015 if(!str[0] || str[0] == ',')
1016 continue;
1018 size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1019 while(len > 0 && isspace(str[len-1]))
1020 len--;
1021 if(len == 3 && al::strncasecmp(str, "sse", len) == 0)
1022 capfilter &= ~CPU_CAP_SSE;
1023 else if(len == 4 && al::strncasecmp(str, "sse2", len) == 0)
1024 capfilter &= ~CPU_CAP_SSE2;
1025 else if(len == 4 && al::strncasecmp(str, "sse3", len) == 0)
1026 capfilter &= ~CPU_CAP_SSE3;
1027 else if(len == 6 && al::strncasecmp(str, "sse4.1", len) == 0)
1028 capfilter &= ~CPU_CAP_SSE4_1;
1029 else if(len == 4 && al::strncasecmp(str, "neon", len) == 0)
1030 capfilter &= ~CPU_CAP_NEON;
1031 else
1032 WARN("Invalid CPU extension \"%s\"\n", str);
1033 } while(next++);
1036 FillCPUCaps(capfilter);
1038 #ifdef _WIN32
1039 #define DEF_MIXER_PRIO 1
1040 #else
1041 #define DEF_MIXER_PRIO 0
1042 #endif
1043 RTPrioLevel = ConfigValueInt(nullptr, nullptr, "rt-prio").value_or(DEF_MIXER_PRIO);
1044 #undef DEF_MIXER_PRIO
1046 aluInit();
1047 aluInitMixer();
1049 auto traperr = al::getenv("ALSOFT_TRAP_ERROR");
1050 if(traperr && (al::strcasecmp(traperr->c_str(), "true") == 0
1051 || std::strtol(traperr->c_str(), nullptr, 0) == 1))
1053 TrapALError = true;
1054 TrapALCError = true;
1056 else
1058 traperr = al::getenv("ALSOFT_TRAP_AL_ERROR");
1059 if(traperr)
1060 TrapALError = al::strcasecmp(traperr->c_str(), "true") == 0
1061 || strtol(traperr->c_str(), nullptr, 0) == 1;
1062 else
1063 TrapALError = !!GetConfigValueBool(nullptr, nullptr, "trap-al-error", false);
1065 traperr = al::getenv("ALSOFT_TRAP_ALC_ERROR");
1066 if(traperr)
1067 TrapALCError = al::strcasecmp(traperr->c_str(), "true") == 0
1068 || strtol(traperr->c_str(), nullptr, 0) == 1;
1069 else
1070 TrapALCError = !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", false);
1073 if(auto boostopt = ConfigValueFloat(nullptr, "reverb", "boost"))
1075 const float valf{std::isfinite(*boostopt) ? clampf(*boostopt, -24.0f, 24.0f) : 0.0f};
1076 ReverbBoost *= std::pow(10.0f, valf / 20.0f);
1079 auto devopt = al::getenv("ALSOFT_DRIVERS");
1080 if(devopt || (devopt=ConfigValueStr(nullptr, nullptr, "drivers")))
1082 auto backendlist_cur = std::begin(BackendList);
1084 bool endlist{true};
1085 const char *next{devopt->c_str()};
1086 do {
1087 const char *devs{next};
1088 while(isspace(devs[0]))
1089 devs++;
1090 next = strchr(devs, ',');
1092 const bool delitem{devs[0] == '-'};
1093 if(devs[0] == '-') devs++;
1095 if(!devs[0] || devs[0] == ',')
1097 endlist = false;
1098 continue;
1100 endlist = true;
1102 size_t len{next ? (static_cast<size_t>(next-devs)) : strlen(devs)};
1103 while(len > 0 && isspace(devs[len-1])) --len;
1104 #ifdef HAVE_WASAPI
1105 /* HACK: For backwards compatibility, convert backend references of
1106 * mmdevapi to wasapi. This should eventually be removed.
1108 if(len == 8 && strncmp(devs, "mmdevapi", len) == 0)
1110 devs = "wasapi";
1111 len = 6;
1113 #endif
1115 auto find_backend = [devs,len](const BackendInfo &backend) -> bool
1116 { return len == strlen(backend.name) && strncmp(backend.name, devs, len) == 0; };
1117 auto this_backend = std::find_if(std::begin(BackendList), BackendListEnd,
1118 find_backend);
1120 if(this_backend == BackendListEnd)
1121 continue;
1123 if(delitem)
1124 BackendListEnd = std::move(this_backend+1, BackendListEnd, this_backend);
1125 else
1126 backendlist_cur = std::rotate(backendlist_cur, this_backend, this_backend+1);
1127 } while(next++);
1129 if(endlist)
1130 BackendListEnd = backendlist_cur;
1133 auto init_backend = [](BackendInfo &backend) -> bool
1135 if(PlaybackFactory && CaptureFactory)
1136 return true;
1138 BackendFactory &factory = backend.getFactory();
1139 if(!factory.init())
1141 WARN("Failed to initialize backend \"%s\"\n", backend.name);
1142 return true;
1145 TRACE("Initialized backend \"%s\"\n", backend.name);
1146 if(!PlaybackFactory && factory.querySupport(BackendType::Playback))
1148 PlaybackFactory = &factory;
1149 TRACE("Added \"%s\" for playback\n", backend.name);
1151 if(!CaptureFactory && factory.querySupport(BackendType::Capture))
1153 CaptureFactory = &factory;
1154 TRACE("Added \"%s\" for capture\n", backend.name);
1156 return false;
1158 BackendListEnd = std::remove_if(std::begin(BackendList), BackendListEnd, init_backend);
1160 LoopbackBackendFactory::getFactory().init();
1162 if(!PlaybackFactory)
1163 WARN("No playback backend available!\n");
1164 if(!CaptureFactory)
1165 WARN("No capture backend available!\n");
1167 if(auto exclopt = ConfigValueStr(nullptr, nullptr, "excludefx"))
1169 const char *next{exclopt->c_str()};
1170 do {
1171 const char *str{next};
1172 next = strchr(str, ',');
1174 if(!str[0] || next == str)
1175 continue;
1177 size_t len{next ? static_cast<size_t>(next-str) : strlen(str)};
1178 for(const EffectList &effectitem : gEffectList)
1180 if(len == strlen(effectitem.name) &&
1181 strncmp(effectitem.name, str, len) == 0)
1182 DisabledEffects[effectitem.type] = AL_TRUE;
1184 } while(next++);
1187 InitEffect(&DefaultEffect);
1188 auto defrevopt = al::getenv("ALSOFT_DEFAULT_REVERB");
1189 if(defrevopt || (defrevopt=ConfigValueStr(nullptr, nullptr, "default-reverb")))
1190 LoadReverbPreset(defrevopt->c_str(), &DefaultEffect);
1192 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1195 /************************************************
1196 * Device enumeration
1197 ************************************************/
1198 void ProbeAllDevicesList()
1200 DO_INITCONFIG();
1202 std::lock_guard<std::recursive_mutex> _{ListLock};
1203 alcAllDevicesList.clear();
1204 if(PlaybackFactory)
1205 PlaybackFactory->probe(DevProbe::Playback, &alcAllDevicesList);
1207 void ProbeCaptureDeviceList()
1209 DO_INITCONFIG();
1211 std::lock_guard<std::recursive_mutex> _{ListLock};
1212 alcCaptureDeviceList.clear();
1213 if(CaptureFactory)
1214 CaptureFactory->probe(DevProbe::Capture, &alcCaptureDeviceList);
1217 } // namespace
1219 /* Mixing thread piority level */
1220 ALint RTPrioLevel;
1222 FILE *gLogFile{stderr};
1223 #ifdef _DEBUG
1224 LogLevel gLogLevel{LogWarning};
1225 #else
1226 LogLevel gLogLevel{LogError};
1227 #endif
1229 /************************************************
1230 * Library initialization
1231 ************************************************/
1232 #if defined(_WIN32) && !defined(AL_LIBTYPE_STATIC)
1233 BOOL APIENTRY DllMain(HINSTANCE module, DWORD reason, LPVOID /*reserved*/)
1235 switch(reason)
1237 case DLL_PROCESS_ATTACH:
1238 /* Pin the DLL so we won't get unloaded until the process terminates */
1239 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
1240 reinterpret_cast<WCHAR*>(module), &module);
1241 break;
1243 return TRUE;
1245 #endif
1247 /************************************************
1248 * Device format information
1249 ************************************************/
1250 const ALCchar *DevFmtTypeString(DevFmtType type) noexcept
1252 switch(type)
1254 case DevFmtByte: return "Signed Byte";
1255 case DevFmtUByte: return "Unsigned Byte";
1256 case DevFmtShort: return "Signed Short";
1257 case DevFmtUShort: return "Unsigned Short";
1258 case DevFmtInt: return "Signed Int";
1259 case DevFmtUInt: return "Unsigned Int";
1260 case DevFmtFloat: return "Float";
1262 return "(unknown type)";
1264 const ALCchar *DevFmtChannelsString(DevFmtChannels chans) noexcept
1266 switch(chans)
1268 case DevFmtMono: return "Mono";
1269 case DevFmtStereo: return "Stereo";
1270 case DevFmtQuad: return "Quadraphonic";
1271 case DevFmtX51: return "5.1 Surround";
1272 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1273 case DevFmtX61: return "6.1 Surround";
1274 case DevFmtX71: return "7.1 Surround";
1275 case DevFmtAmbi3D: return "Ambisonic 3D";
1277 return "(unknown channels)";
1280 ALuint BytesFromDevFmt(DevFmtType type) noexcept
1282 switch(type)
1284 case DevFmtByte: return sizeof(ALbyte);
1285 case DevFmtUByte: return sizeof(ALubyte);
1286 case DevFmtShort: return sizeof(ALshort);
1287 case DevFmtUShort: return sizeof(ALushort);
1288 case DevFmtInt: return sizeof(ALint);
1289 case DevFmtUInt: return sizeof(ALuint);
1290 case DevFmtFloat: return sizeof(ALfloat);
1292 return 0;
1294 ALuint ChannelsFromDevFmt(DevFmtChannels chans, ALuint ambiorder) noexcept
1296 switch(chans)
1298 case DevFmtMono: return 1;
1299 case DevFmtStereo: return 2;
1300 case DevFmtQuad: return 4;
1301 case DevFmtX51: return 6;
1302 case DevFmtX51Rear: return 6;
1303 case DevFmtX61: return 7;
1304 case DevFmtX71: return 8;
1305 case DevFmtAmbi3D: return (ambiorder+1) * (ambiorder+1);
1307 return 0;
1310 struct DevFmtPair { DevFmtChannels chans; DevFmtType type; };
1311 static al::optional<DevFmtPair> DecomposeDevFormat(ALenum format)
1313 static const struct {
1314 ALenum format;
1315 DevFmtChannels channels;
1316 DevFmtType type;
1317 } list[] = {
1318 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1319 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1320 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1322 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1323 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1324 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1326 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1327 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1328 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1330 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1331 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1332 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1334 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1335 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1336 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1338 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1339 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1340 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1343 for(const auto &item : list)
1345 if(item.format == format)
1346 return al::make_optional(DevFmtPair{item.channels, item.type});
1349 return al::nullopt;
1352 static ALCboolean IsValidALCType(ALCenum type)
1354 switch(type)
1356 case ALC_BYTE_SOFT:
1357 case ALC_UNSIGNED_BYTE_SOFT:
1358 case ALC_SHORT_SOFT:
1359 case ALC_UNSIGNED_SHORT_SOFT:
1360 case ALC_INT_SOFT:
1361 case ALC_UNSIGNED_INT_SOFT:
1362 case ALC_FLOAT_SOFT:
1363 return ALC_TRUE;
1365 return ALC_FALSE;
1368 static ALCboolean IsValidALCChannels(ALCenum channels)
1370 switch(channels)
1372 case ALC_MONO_SOFT:
1373 case ALC_STEREO_SOFT:
1374 case ALC_QUAD_SOFT:
1375 case ALC_5POINT1_SOFT:
1376 case ALC_6POINT1_SOFT:
1377 case ALC_7POINT1_SOFT:
1378 case ALC_BFORMAT3D_SOFT:
1379 return ALC_TRUE;
1381 return ALC_FALSE;
1384 static ALCboolean IsValidAmbiLayout(ALCenum layout)
1386 switch(layout)
1388 case ALC_ACN_SOFT:
1389 case ALC_FUMA_SOFT:
1390 return ALC_TRUE;
1392 return ALC_FALSE;
1395 static ALCboolean IsValidAmbiScaling(ALCenum scaling)
1397 switch(scaling)
1399 case ALC_N3D_SOFT:
1400 case ALC_SN3D_SOFT:
1401 case ALC_FUMA_SOFT:
1402 return ALC_TRUE;
1404 return ALC_FALSE;
1407 /************************************************
1408 * Miscellaneous ALC helpers
1409 ************************************************/
1411 /* SetDefaultWFXChannelOrder
1413 * Sets the default channel order used by WaveFormatEx.
1415 void SetDefaultWFXChannelOrder(ALCdevice *device)
1417 device->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
1419 switch(device->FmtChans)
1421 case DevFmtMono:
1422 device->RealOut.ChannelIndex[FrontCenter] = 0;
1423 break;
1424 case DevFmtStereo:
1425 device->RealOut.ChannelIndex[FrontLeft] = 0;
1426 device->RealOut.ChannelIndex[FrontRight] = 1;
1427 break;
1428 case DevFmtQuad:
1429 device->RealOut.ChannelIndex[FrontLeft] = 0;
1430 device->RealOut.ChannelIndex[FrontRight] = 1;
1431 device->RealOut.ChannelIndex[BackLeft] = 2;
1432 device->RealOut.ChannelIndex[BackRight] = 3;
1433 break;
1434 case DevFmtX51:
1435 device->RealOut.ChannelIndex[FrontLeft] = 0;
1436 device->RealOut.ChannelIndex[FrontRight] = 1;
1437 device->RealOut.ChannelIndex[FrontCenter] = 2;
1438 device->RealOut.ChannelIndex[LFE] = 3;
1439 device->RealOut.ChannelIndex[SideLeft] = 4;
1440 device->RealOut.ChannelIndex[SideRight] = 5;
1441 break;
1442 case DevFmtX51Rear:
1443 device->RealOut.ChannelIndex[FrontLeft] = 0;
1444 device->RealOut.ChannelIndex[FrontRight] = 1;
1445 device->RealOut.ChannelIndex[FrontCenter] = 2;
1446 device->RealOut.ChannelIndex[LFE] = 3;
1447 device->RealOut.ChannelIndex[BackLeft] = 4;
1448 device->RealOut.ChannelIndex[BackRight] = 5;
1449 break;
1450 case DevFmtX61:
1451 device->RealOut.ChannelIndex[FrontLeft] = 0;
1452 device->RealOut.ChannelIndex[FrontRight] = 1;
1453 device->RealOut.ChannelIndex[FrontCenter] = 2;
1454 device->RealOut.ChannelIndex[LFE] = 3;
1455 device->RealOut.ChannelIndex[BackCenter] = 4;
1456 device->RealOut.ChannelIndex[SideLeft] = 5;
1457 device->RealOut.ChannelIndex[SideRight] = 6;
1458 break;
1459 case DevFmtX71:
1460 device->RealOut.ChannelIndex[FrontLeft] = 0;
1461 device->RealOut.ChannelIndex[FrontRight] = 1;
1462 device->RealOut.ChannelIndex[FrontCenter] = 2;
1463 device->RealOut.ChannelIndex[LFE] = 3;
1464 device->RealOut.ChannelIndex[BackLeft] = 4;
1465 device->RealOut.ChannelIndex[BackRight] = 5;
1466 device->RealOut.ChannelIndex[SideLeft] = 6;
1467 device->RealOut.ChannelIndex[SideRight] = 7;
1468 break;
1469 case DevFmtAmbi3D:
1470 device->RealOut.ChannelIndex[Aux0] = 0;
1471 if(device->mAmbiOrder > 0)
1473 device->RealOut.ChannelIndex[Aux1] = 1;
1474 device->RealOut.ChannelIndex[Aux2] = 2;
1475 device->RealOut.ChannelIndex[Aux3] = 3;
1477 if(device->mAmbiOrder > 1)
1479 device->RealOut.ChannelIndex[Aux4] = 4;
1480 device->RealOut.ChannelIndex[Aux5] = 5;
1481 device->RealOut.ChannelIndex[Aux6] = 6;
1482 device->RealOut.ChannelIndex[Aux7] = 7;
1483 device->RealOut.ChannelIndex[Aux8] = 8;
1485 if(device->mAmbiOrder > 2)
1487 device->RealOut.ChannelIndex[Aux9] = 9;
1488 device->RealOut.ChannelIndex[Aux10] = 10;
1489 device->RealOut.ChannelIndex[Aux11] = 11;
1490 device->RealOut.ChannelIndex[Aux12] = 12;
1491 device->RealOut.ChannelIndex[Aux13] = 13;
1492 device->RealOut.ChannelIndex[Aux14] = 14;
1493 device->RealOut.ChannelIndex[Aux15] = 15;
1495 break;
1499 /* SetDefaultChannelOrder
1501 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1503 void SetDefaultChannelOrder(ALCdevice *device)
1505 device->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
1507 switch(device->FmtChans)
1509 case DevFmtX51Rear:
1510 device->RealOut.ChannelIndex[FrontLeft] = 0;
1511 device->RealOut.ChannelIndex[FrontRight] = 1;
1512 device->RealOut.ChannelIndex[BackLeft] = 2;
1513 device->RealOut.ChannelIndex[BackRight] = 3;
1514 device->RealOut.ChannelIndex[FrontCenter] = 4;
1515 device->RealOut.ChannelIndex[LFE] = 5;
1516 return;
1517 case DevFmtX71:
1518 device->RealOut.ChannelIndex[FrontLeft] = 0;
1519 device->RealOut.ChannelIndex[FrontRight] = 1;
1520 device->RealOut.ChannelIndex[BackLeft] = 2;
1521 device->RealOut.ChannelIndex[BackRight] = 3;
1522 device->RealOut.ChannelIndex[FrontCenter] = 4;
1523 device->RealOut.ChannelIndex[LFE] = 5;
1524 device->RealOut.ChannelIndex[SideLeft] = 6;
1525 device->RealOut.ChannelIndex[SideRight] = 7;
1526 return;
1528 /* Same as WFX order */
1529 case DevFmtMono:
1530 case DevFmtStereo:
1531 case DevFmtQuad:
1532 case DevFmtX51:
1533 case DevFmtX61:
1534 case DevFmtAmbi3D:
1535 SetDefaultWFXChannelOrder(device);
1536 break;
1541 void ALCcontext::processUpdates()
1543 std::lock_guard<std::mutex> _{mPropLock};
1544 if(mDeferUpdates.exchange(false))
1546 /* Tell the mixer to stop applying updates, then wait for any active
1547 * updating to finish, before providing updates.
1549 mHoldUpdates.store(true, std::memory_order_release);
1550 while((mUpdateCount.load(std::memory_order_acquire)&1) != 0)
1551 std::this_thread::yield();
1553 if(!mPropsClean.test_and_set(std::memory_order_acq_rel))
1554 UpdateContextProps(this);
1555 if(!mListener.PropsClean.test_and_set(std::memory_order_acq_rel))
1556 UpdateListenerProps(this);
1557 UpdateAllEffectSlotProps(this);
1558 UpdateAllSourceProps(this);
1560 /* Now with all updates declared, let the mixer continue applying them
1561 * so they all happen at once.
1563 mHoldUpdates.store(false, std::memory_order_release);
1568 /* alcSetError
1570 * Stores the latest ALC device error
1572 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1574 WARN("Error generated on device %p, code 0x%04x\n", decltype(std::declval<void*>()){device},
1575 errorCode);
1576 if(TrapALCError)
1578 #ifdef _WIN32
1579 /* DebugBreak() will cause an exception if there is no debugger */
1580 if(IsDebuggerPresent())
1581 DebugBreak();
1582 #elif defined(SIGTRAP)
1583 raise(SIGTRAP);
1584 #endif
1587 if(device)
1588 device->LastError.store(errorCode);
1589 else
1590 LastNullDeviceError.store(errorCode);
1594 static std::unique_ptr<Compressor> CreateDeviceLimiter(const ALCdevice *device, const ALfloat threshold)
1596 return CompressorInit(static_cast<ALuint>(device->RealOut.Buffer.size()),
1597 static_cast<float>(device->Frequency), AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, 0.001f,
1598 0.002f, 0.0f, 0.0f, threshold, INFINITY, 0.0f, 0.020f, 0.200f);
1601 /* UpdateClockBase
1603 * Updates the device's base clock time with however many samples have been
1604 * done. This is used so frequency changes on the device don't cause the time
1605 * to jump forward or back. Must not be called while the device is running/
1606 * mixing.
1608 static inline void UpdateClockBase(ALCdevice *device)
1610 IncrementRef(device->MixCount);
1611 device->ClockBase += nanoseconds{seconds{device->SamplesDone}} / device->Frequency;
1612 device->SamplesDone = 0;
1613 IncrementRef(device->MixCount);
1616 /* UpdateDeviceParams
1618 * Updates device parameters according to the attribute list (caller is
1619 * responsible for holding the list lock).
1621 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1623 HrtfRequestMode hrtf_userreq{Hrtf_Default};
1624 HrtfRequestMode hrtf_appreq{Hrtf_Default};
1625 ALCenum gainLimiter{device->LimiterState};
1626 const ALCuint old_sends{device->NumAuxSends};
1627 ALCuint new_sends{device->NumAuxSends};
1628 DevFmtChannels oldChans;
1629 DevFmtType oldType;
1630 ALboolean update_failed;
1631 ALCsizei hrtf_id{-1};
1632 ALCuint oldFreq;
1634 if((!attrList || !attrList[0]) && device->Type == Loopback)
1636 WARN("Missing attributes for loopback device\n");
1637 return ALC_INVALID_VALUE;
1640 // Check for attributes
1641 if(attrList && attrList[0])
1643 ALCenum alayout{AL_NONE};
1644 ALCenum ascale{AL_NONE};
1645 ALCenum schans{AL_NONE};
1646 ALCenum stype{AL_NONE};
1647 ALCsizei attrIdx{0};
1648 ALCuint aorder{0};
1649 ALCuint freq{0u};
1651 ALuint numMono{device->NumMonoSources};
1652 ALuint numStereo{device->NumStereoSources};
1653 ALuint numSends{old_sends};
1655 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1656 while(attrList[attrIdx])
1658 switch(attrList[attrIdx])
1660 case ALC_FORMAT_CHANNELS_SOFT:
1661 schans = attrList[attrIdx + 1];
1662 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1663 break;
1665 case ALC_FORMAT_TYPE_SOFT:
1666 stype = attrList[attrIdx + 1];
1667 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1668 break;
1670 case ALC_FREQUENCY:
1671 freq = static_cast<ALuint>(attrList[attrIdx + 1]);
1672 TRACE_ATTR(ALC_FREQUENCY, freq);
1673 break;
1675 case ALC_AMBISONIC_LAYOUT_SOFT:
1676 alayout = attrList[attrIdx + 1];
1677 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1678 break;
1680 case ALC_AMBISONIC_SCALING_SOFT:
1681 ascale = attrList[attrIdx + 1];
1682 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1683 break;
1685 case ALC_AMBISONIC_ORDER_SOFT:
1686 aorder = static_cast<ALuint>(attrList[attrIdx + 1]);
1687 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1688 break;
1690 case ALC_MONO_SOURCES:
1691 numMono = static_cast<ALuint>(attrList[attrIdx + 1]);
1692 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1693 if(numMono > INT_MAX) numMono = 0;
1694 break;
1696 case ALC_STEREO_SOURCES:
1697 numStereo = static_cast<ALuint>(attrList[attrIdx + 1]);
1698 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1699 if(numStereo > INT_MAX) numStereo = 0;
1700 break;
1702 case ALC_MAX_AUXILIARY_SENDS:
1703 numSends = static_cast<ALuint>(attrList[attrIdx + 1]);
1704 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1705 if(numSends > INT_MAX) numSends = 0;
1706 else numSends = minu(numSends, MAX_SENDS);
1707 break;
1709 case ALC_HRTF_SOFT:
1710 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1711 if(attrList[attrIdx + 1] == ALC_FALSE)
1712 hrtf_appreq = Hrtf_Disable;
1713 else if(attrList[attrIdx + 1] == ALC_TRUE)
1714 hrtf_appreq = Hrtf_Enable;
1715 else
1716 hrtf_appreq = Hrtf_Default;
1717 break;
1719 case ALC_HRTF_ID_SOFT:
1720 hrtf_id = attrList[attrIdx + 1];
1721 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1722 break;
1724 case ALC_OUTPUT_LIMITER_SOFT:
1725 gainLimiter = attrList[attrIdx + 1];
1726 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1727 break;
1729 default:
1730 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1731 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1732 break;
1735 attrIdx += 2;
1737 #undef TRACE_ATTR
1739 const bool loopback{device->Type == Loopback};
1740 if(loopback)
1742 if(!schans || !stype || !freq)
1744 WARN("Missing format for loopback device\n");
1745 return ALC_INVALID_VALUE;
1747 if(!IsValidALCChannels(schans) || !IsValidALCType(stype) || freq < MIN_OUTPUT_RATE)
1748 return ALC_INVALID_VALUE;
1749 if(schans == ALC_BFORMAT3D_SOFT)
1751 if(!alayout || !ascale || !aorder)
1753 WARN("Missing ambisonic info for loopback device\n");
1754 return ALC_INVALID_VALUE;
1756 if(!IsValidAmbiLayout(alayout) || !IsValidAmbiScaling(ascale))
1757 return ALC_INVALID_VALUE;
1758 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1759 return ALC_INVALID_VALUE;
1760 if((alayout == ALC_FUMA_SOFT || ascale == ALC_FUMA_SOFT) && aorder > 3)
1761 return ALC_INVALID_VALUE;
1765 /* If a context is already running on the device, stop playback so the
1766 * device attributes can be updated.
1768 if(device->Flags.get<DeviceRunning>())
1769 device->Backend->stop();
1770 device->Flags.unset<DeviceRunning>();
1772 UpdateClockBase(device);
1774 const char *devname{nullptr};
1775 if(!loopback)
1777 devname = device->DeviceName.c_str();
1779 device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
1780 device->UpdateSize = DEFAULT_UPDATE_SIZE;
1781 device->Frequency = DEFAULT_OUTPUT_RATE;
1783 freq = ConfigValueUInt(devname, nullptr, "frequency").value_or(freq);
1784 if(freq < 1)
1785 device->Flags.unset<FrequencyRequest>();
1786 else
1788 freq = maxu(freq, MIN_OUTPUT_RATE);
1790 device->UpdateSize = (device->UpdateSize*freq + device->Frequency/2) /
1791 device->Frequency;
1792 device->BufferSize = (device->BufferSize*freq + device->Frequency/2) /
1793 device->Frequency;
1795 device->Frequency = freq;
1796 device->Flags.set<FrequencyRequest>();
1799 if(auto persizeopt = ConfigValueUInt(devname, nullptr, "period_size"))
1800 device->UpdateSize = clampu(*persizeopt, 64, 8192);
1802 if(auto peropt = ConfigValueUInt(devname, nullptr, "periods"))
1803 device->BufferSize = device->UpdateSize * clampu(*peropt, 2, 16);
1804 else
1805 device->BufferSize = maxu(device->BufferSize, device->UpdateSize*2);
1807 else
1809 device->Frequency = freq;
1810 device->FmtChans = static_cast<DevFmtChannels>(schans);
1811 device->FmtType = static_cast<DevFmtType>(stype);
1812 if(schans == ALC_BFORMAT3D_SOFT)
1814 device->mAmbiOrder = aorder;
1815 device->mAmbiLayout = static_cast<AmbiLayout>(alayout);
1816 device->mAmbiScale = static_cast<AmbiNorm>(ascale);
1820 if(numMono > INT_MAX-numStereo)
1821 numMono = INT_MAX-numStereo;
1822 numMono += numStereo;
1823 if(auto srcsopt = ConfigValueUInt(devname, nullptr, "sources"))
1825 if(*srcsopt <= 0) numMono = 256;
1826 else numMono = *srcsopt;
1828 else
1829 numMono = maxu(numMono, 256);
1830 numStereo = minu(numStereo, numMono);
1831 numMono -= numStereo;
1832 device->SourcesMax = numMono + numStereo;
1834 device->NumMonoSources = numMono;
1835 device->NumStereoSources = numStereo;
1837 if(auto sendsopt = ConfigValueInt(devname, nullptr, "sends"))
1838 new_sends = minu(numSends, static_cast<ALuint>(clampi(*sendsopt, 0, MAX_SENDS)));
1839 else
1840 new_sends = numSends;
1843 if(device->Flags.get<DeviceRunning>())
1844 return ALC_NO_ERROR;
1846 device->AvgSpeakerDist = 0.0f;
1847 device->Uhj_Encoder = nullptr;
1848 device->AmbiDecoder = nullptr;
1849 device->Bs2b = nullptr;
1850 device->PostProcess = nullptr;
1852 device->Stablizer = nullptr;
1853 device->Limiter = nullptr;
1854 device->ChannelDelay.clear();
1856 device->Dry.AmbiMap.fill(BFChannelConfig{});
1857 device->Dry.Buffer = {};
1858 std::fill(std::begin(device->NumChannelsPerOrder), std::end(device->NumChannelsPerOrder), 0u);
1859 device->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
1860 device->RealOut.Buffer = {};
1861 device->MixBuffer.clear();
1862 device->MixBuffer.shrink_to_fit();
1864 UpdateClockBase(device);
1865 device->FixedLatency = nanoseconds::zero();
1867 device->DitherDepth = 0.0f;
1868 device->DitherSeed = DITHER_RNG_SEED;
1870 /*************************************************************************
1871 * Update device format request if HRTF is requested
1873 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
1874 if(device->Type != Loopback)
1876 if(auto hrtfopt = ConfigValueStr(device->DeviceName.c_str(), nullptr, "hrtf"))
1878 const char *hrtf{hrtfopt->c_str()};
1879 if(al::strcasecmp(hrtf, "true") == 0)
1880 hrtf_userreq = Hrtf_Enable;
1881 else if(al::strcasecmp(hrtf, "false") == 0)
1882 hrtf_userreq = Hrtf_Disable;
1883 else if(al::strcasecmp(hrtf, "auto") != 0)
1884 ERR("Unexpected hrtf value: %s\n", hrtf);
1887 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
1889 HrtfEntry *hrtf{nullptr};
1890 if(device->HrtfList.empty())
1891 device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
1892 if(!device->HrtfList.empty())
1894 if(hrtf_id >= 0 && static_cast<ALuint>(hrtf_id) < device->HrtfList.size())
1895 hrtf = GetLoadedHrtf(device->HrtfList[static_cast<ALuint>(hrtf_id)].hrtf);
1896 else
1897 hrtf = GetLoadedHrtf(device->HrtfList.front().hrtf);
1900 if(hrtf)
1902 device->FmtChans = DevFmtStereo;
1903 device->Frequency = hrtf->sampleRate;
1904 device->Flags.set<ChannelsRequest, FrequencyRequest>();
1905 if(HrtfEntry *oldhrtf{device->mHrtf})
1906 oldhrtf->DecRef();
1907 device->mHrtf = hrtf;
1909 else
1911 hrtf_userreq = Hrtf_Default;
1912 hrtf_appreq = Hrtf_Disable;
1913 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
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 if(device->Backend->reset() == false)
1930 return ALC_INVALID_DEVICE;
1932 catch(std::exception &e) {
1933 ERR("Device reset failed: %s\n", e.what());
1934 return ALC_INVALID_DEVICE;
1937 if(device->FmtChans != oldChans && device->Flags.get<ChannelsRequest>())
1939 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1940 DevFmtChannelsString(device->FmtChans));
1941 device->Flags.unset<ChannelsRequest>();
1943 if(device->FmtType != oldType && device->Flags.get<SampleTypeRequest>())
1945 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1946 DevFmtTypeString(device->FmtType));
1947 device->Flags.unset<SampleTypeRequest>();
1949 if(device->Frequency != oldFreq && device->Flags.get<FrequencyRequest>())
1951 WARN("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1952 device->Flags.unset<FrequencyRequest>();
1955 TRACE("Post-reset: %s, %s, %uhz, %u / %u buffer\n",
1956 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
1957 device->Frequency, device->UpdateSize, device->BufferSize);
1959 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
1961 device->NumAuxSends = new_sends;
1962 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
1963 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
1964 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
1966 /* Enable the stablizer only for formats that have front-left, front-right,
1967 * and front-center outputs.
1969 switch(device->FmtChans)
1971 case DevFmtX51:
1972 case DevFmtX51Rear:
1973 case DevFmtX61:
1974 case DevFmtX71:
1975 if(GetConfigValueBool(device->DeviceName.c_str(), nullptr, "front-stablizer", 0))
1977 auto stablizer = al::make_unique<FrontStablizer>();
1978 /* Initialize band-splitting filters for the front-left and front-
1979 * right channels, with a crossover at 5khz (could be higher).
1981 const ALfloat scale{5000.0f / static_cast<ALfloat>(device->Frequency)};
1983 stablizer->LFilter.init(scale);
1984 stablizer->RFilter = stablizer->LFilter;
1986 device->Stablizer = std::move(stablizer);
1987 /* NOTE: Don't know why this has to be "copied" into a local static
1988 * constexpr variable to avoid a reference on
1989 * FrontStablizer::DelayLength...
1991 static constexpr size_t StablizerDelay{FrontStablizer::DelayLength};
1992 device->FixedLatency += nanoseconds{seconds{StablizerDelay}} / device->Frequency;
1994 break;
1995 case DevFmtMono:
1996 case DevFmtStereo:
1997 case DevFmtQuad:
1998 case DevFmtAmbi3D:
1999 break;
2001 TRACE("Front stablizer %s\n", device->Stablizer ? "enabled" : "disabled");
2003 if(GetConfigValueBool(device->DeviceName.c_str(), nullptr, "dither", 1))
2005 ALint depth{
2006 ConfigValueInt(device->DeviceName.c_str(), nullptr, "dither-depth").value_or(0)};
2007 if(depth <= 0)
2009 switch(device->FmtType)
2011 case DevFmtByte:
2012 case DevFmtUByte:
2013 depth = 8;
2014 break;
2015 case DevFmtShort:
2016 case DevFmtUShort:
2017 depth = 16;
2018 break;
2019 case DevFmtInt:
2020 case DevFmtUInt:
2021 case DevFmtFloat:
2022 break;
2026 if(depth > 0)
2028 depth = clampi(depth, 2, 24);
2029 device->DitherDepth = std::pow(2.0f, static_cast<ALfloat>(depth-1));
2032 if(!(device->DitherDepth > 0.0f))
2033 TRACE("Dithering disabled\n");
2034 else
2035 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device->DitherDepth)+0.5f)+1,
2036 device->DitherDepth);
2038 device->LimiterState = gainLimiter;
2039 if(auto limopt = ConfigValueBool(device->DeviceName.c_str(), nullptr, "output-limiter"))
2040 gainLimiter = *limopt ? ALC_TRUE : ALC_FALSE;
2042 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2043 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2044 * output (where samples must be clamped), and don't for floating-point
2045 * (which can take unclamped samples).
2047 if(gainLimiter == ALC_DONT_CARE_SOFT)
2049 switch(device->FmtType)
2051 case DevFmtByte:
2052 case DevFmtUByte:
2053 case DevFmtShort:
2054 case DevFmtUShort:
2055 case DevFmtInt:
2056 case DevFmtUInt:
2057 gainLimiter = ALC_TRUE;
2058 break;
2059 case DevFmtFloat:
2060 gainLimiter = ALC_FALSE;
2061 break;
2064 if(gainLimiter == ALC_FALSE)
2065 TRACE("Output limiter disabled\n");
2066 else
2068 ALfloat thrshld = 1.0f;
2069 switch(device->FmtType)
2071 case DevFmtByte:
2072 case DevFmtUByte:
2073 thrshld = 127.0f / 128.0f;
2074 break;
2075 case DevFmtShort:
2076 case DevFmtUShort:
2077 thrshld = 32767.0f / 32768.0f;
2078 break;
2079 case DevFmtInt:
2080 case DevFmtUInt:
2081 case DevFmtFloat:
2082 break;
2084 if(device->DitherDepth > 0.0f)
2085 thrshld -= 1.0f / device->DitherDepth;
2087 const float thrshld_dB{std::log10(thrshld) * 20.0f};
2088 auto limiter = CreateDeviceLimiter(device, thrshld_dB);
2089 /* Convert the lookahead from samples to nanosamples to nanoseconds. */
2090 device->FixedLatency += nanoseconds{seconds{limiter->getLookAhead()}} / device->Frequency;
2091 device->Limiter = std::move(limiter);
2092 TRACE("Output limiter enabled, %.4fdB limit\n", thrshld_dB);
2095 TRACE("Fixed device latency: %" PRId64 "ns\n", int64_t{device->FixedLatency.count()});
2097 /* Need to delay returning failure until replacement Send arrays have been
2098 * allocated with the appropriate size.
2100 update_failed = AL_FALSE;
2101 FPUCtl mixer_mode{};
2102 for(ALCcontext *context : *device->mContexts.load())
2104 if(context->mDefaultSlot)
2106 ALeffectslot *slot = context->mDefaultSlot.get();
2107 aluInitEffectPanning(slot, device);
2109 EffectState *state{slot->Effect.State};
2110 state->mOutTarget = device->Dry.Buffer;
2111 if(state->deviceUpdate(device) == AL_FALSE)
2112 update_failed = AL_TRUE;
2113 else
2114 UpdateEffectSlotProps(slot, context);
2117 std::unique_lock<std::mutex> proplock{context->mPropLock};
2118 std::unique_lock<std::mutex> slotlock{context->mEffectSlotLock};
2119 for(auto &sublist : context->mEffectSlotList)
2121 uint64_t usemask = ~sublist.FreeMask;
2122 while(usemask)
2124 ALsizei idx = CTZ64(usemask);
2125 ALeffectslot *slot = sublist.EffectSlots + idx;
2127 usemask &= ~(1_u64 << idx);
2129 aluInitEffectPanning(slot, device);
2131 EffectState *state{slot->Effect.State};
2132 state->mOutTarget = device->Dry.Buffer;
2133 if(state->deviceUpdate(device) == AL_FALSE)
2134 update_failed = AL_TRUE;
2135 else
2136 UpdateEffectSlotProps(slot, context);
2139 slotlock.unlock();
2141 std::unique_lock<std::mutex> srclock{context->mSourceLock};
2142 for(auto &sublist : context->mSourceList)
2144 uint64_t usemask = ~sublist.FreeMask;
2145 while(usemask)
2147 ALsizei idx = CTZ64(usemask);
2148 ALsource *source = sublist.Sources + idx;
2150 usemask &= ~(1_u64 << idx);
2152 if(old_sends != device->NumAuxSends)
2154 if(source->Send.size() > device->NumAuxSends)
2156 auto clear_send = [](ALsource::SendData &send) -> void
2158 if(send.Slot)
2159 DecrementRef(send.Slot->ref);
2160 send.Slot = nullptr;
2162 auto send_begin = source->Send.begin() +
2163 static_cast<ptrdiff_t>(device->NumAuxSends);
2164 std::for_each(send_begin, source->Send.end(), clear_send);
2167 source->Send.resize(device->NumAuxSends,
2168 {nullptr, 1.0f, 1.0f, LOWPASSFREQREF, 1.0f, HIGHPASSFREQREF});
2169 source->Send.shrink_to_fit();
2172 source->PropsClean.clear(std::memory_order_release);
2176 /* Clear any pre-existing voice property structs, in case the number of
2177 * auxiliary sends is changing. Active sources will have updates
2178 * respecified in UpdateAllSourceProps.
2180 ALvoiceProps *vprops{context->mFreeVoiceProps.exchange(nullptr, std::memory_order_acq_rel)};
2181 while(vprops)
2183 ALvoiceProps *next = vprops->next.load(std::memory_order_relaxed);
2184 delete vprops;
2185 vprops = next;
2188 if(device->NumAuxSends < old_sends)
2190 const ALuint num_sends{device->NumAuxSends};
2191 /* Clear extraneous property set sends. */
2192 auto clear_sends = [num_sends](ALvoice &voice) -> void
2194 std::fill(std::begin(voice.mProps.Send)+num_sends, std::end(voice.mProps.Send),
2195 ALvoiceProps::SendData{});
2197 std::fill(voice.mSend.begin()+num_sends, voice.mSend.end(), ALvoice::SendData{});
2198 auto clear_chan_sends = [num_sends](ALvoice::ChannelData &chandata) -> void
2200 std::fill(chandata.mWetParams.begin()+num_sends, chandata.mWetParams.end(),
2201 SendParams{});
2203 std::for_each(voice.mChans.begin(), voice.mChans.end(), clear_chan_sends);
2205 std::for_each(context->mVoices.begin(), context->mVoices.end(), clear_sends);
2207 auto reset_voice = [device](ALvoice &voice) -> void
2209 delete voice.mUpdate.exchange(nullptr, std::memory_order_acq_rel);
2211 /* Force the voice to stopped if it was stopping. */
2212 ALvoice::State vstate{ALvoice::Stopping};
2213 voice.mPlayState.compare_exchange_strong(vstate, ALvoice::Stopped,
2214 std::memory_order_acquire, std::memory_order_acquire);
2215 if(voice.mSourceID.load(std::memory_order_relaxed) == 0u)
2216 return;
2218 if(device->AvgSpeakerDist > 0.0f)
2220 /* Reinitialize the NFC filters for new parameters. */
2221 const ALfloat w1{SPEEDOFSOUNDMETRESPERSEC /
2222 (device->AvgSpeakerDist * static_cast<float>(device->Frequency))};
2223 auto init_nfc = [w1](ALvoice::ChannelData &chandata) -> void
2224 { chandata.mDryParams.NFCtrlFilter.init(w1); };
2225 std::for_each(voice.mChans.begin(), voice.mChans.begin()+voice.mNumChannels,
2226 init_nfc);
2229 std::for_each(context->mVoices.begin(), context->mVoices.end(), reset_voice);
2230 srclock.unlock();
2232 context->mPropsClean.test_and_set(std::memory_order_release);
2233 UpdateContextProps(context);
2234 context->mListener.PropsClean.test_and_set(std::memory_order_release);
2235 UpdateListenerProps(context);
2236 UpdateAllSourceProps(context);
2238 mixer_mode.leave();
2239 if(update_failed)
2240 return ALC_INVALID_DEVICE;
2242 if(!device->Flags.get<DevicePaused>())
2244 if(device->Backend->start() == false)
2245 return ALC_INVALID_DEVICE;
2246 device->Flags.set<DeviceRunning>();
2249 return ALC_NO_ERROR;
2253 ALCdevice::ALCdevice(DeviceType type) : Type{type}, mContexts{&EmptyContextArray}
2257 /* ALCdevice::~ALCdevice
2259 * Frees the device structure, and destroys any objects the app failed to
2260 * delete. Called once there's no more references on the device.
2262 ALCdevice::~ALCdevice()
2264 TRACE("Freeing device %p\n", decltype(std::declval<void*>()){this});
2266 Backend = nullptr;
2268 size_t count{std::accumulate(BufferList.cbegin(), BufferList.cend(), size_t{0u},
2269 [](size_t cur, const BufferSubList &sublist) noexcept -> size_t
2270 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2272 if(count > 0)
2273 WARN("%zu Buffer%s not deleted\n", count, (count==1)?"":"s");
2275 count = std::accumulate(EffectList.cbegin(), EffectList.cend(), size_t{0u},
2276 [](size_t cur, const EffectSubList &sublist) noexcept -> size_t
2277 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2279 if(count > 0)
2280 WARN("%zu Effect%s not deleted\n", count, (count==1)?"":"s");
2282 count = std::accumulate(FilterList.cbegin(), FilterList.cend(), size_t{0u},
2283 [](size_t cur, const FilterSubList &sublist) noexcept -> size_t
2284 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2286 if(count > 0)
2287 WARN("%zu Filter%s not deleted\n", count, (count==1)?"":"s");
2289 if(mHrtf)
2290 mHrtf->DecRef();
2291 mHrtf = nullptr;
2293 auto *oldarray = mContexts.exchange(nullptr, std::memory_order_relaxed);
2294 if(oldarray != &EmptyContextArray) delete oldarray;
2298 /* VerifyDevice
2300 * Checks if the device handle is valid, and returns a new reference if so.
2302 static DeviceRef VerifyDevice(ALCdevice *device)
2304 std::lock_guard<std::recursive_mutex> _{ListLock};
2305 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device);
2306 if(iter != DeviceList.cend() && *iter == device)
2307 return *iter;
2308 return nullptr;
2312 ALCcontext::ALCcontext(al::intrusive_ptr<ALCdevice> device) : mDevice{std::move(device)}
2314 mPropsClean.test_and_set(std::memory_order_relaxed);
2317 ALCcontext::~ALCcontext()
2319 TRACE("Freeing context %p\n", decltype(std::declval<void*>()){this});
2321 size_t count{0};
2322 ALcontextProps *cprops{mUpdate.exchange(nullptr, std::memory_order_relaxed)};
2323 if(cprops)
2325 ++count;
2326 delete cprops;
2328 cprops = mFreeContextProps.exchange(nullptr, std::memory_order_acquire);
2329 while(cprops)
2331 ALcontextProps *next{cprops->next.load(std::memory_order_relaxed)};
2332 delete cprops;
2333 cprops = next;
2334 ++count;
2336 TRACE("Freed %zu context property object%s\n", count, (count==1)?"":"s");
2338 count = std::accumulate(mSourceList.cbegin(), mSourceList.cend(), size_t{0u},
2339 [](size_t cur, const SourceSubList &sublist) noexcept -> size_t
2340 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2342 if(count > 0)
2343 WARN("%zu Source%s not deleted\n", count, (count==1)?"":"s");
2344 mSourceList.clear();
2345 mNumSources = 0;
2347 count = 0;
2348 ALeffectslotProps *eprops{mFreeEffectslotProps.exchange(nullptr, std::memory_order_acquire)};
2349 while(eprops)
2351 ALeffectslotProps *next{eprops->next.load(std::memory_order_relaxed)};
2352 if(eprops->State) eprops->State->release();
2353 delete eprops;
2354 eprops = next;
2355 ++count;
2357 TRACE("Freed %zu AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2359 delete mActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed);
2360 mDefaultSlot = nullptr;
2362 count = std::accumulate(mEffectSlotList.cbegin(), mEffectSlotList.cend(), size_t{0u},
2363 [](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t
2364 { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); }
2366 if(count > 0)
2367 WARN("%zu AuxiliaryEffectSlot%s not deleted\n", count, (count==1)?"":"s");
2368 mEffectSlotList.clear();
2369 mNumEffectSlots = 0;
2371 count = 0;
2372 ALvoiceProps *vprops{mFreeVoiceProps.exchange(nullptr, std::memory_order_acquire)};
2373 while(vprops)
2375 ALvoiceProps *next{vprops->next.load(std::memory_order_relaxed)};
2376 delete vprops;
2377 vprops = next;
2378 ++count;
2380 TRACE("Freed %zu voice property object%s\n", count, (count==1)?"":"s");
2382 mVoices.clear();
2384 count = 0;
2385 ALlistenerProps *lprops{mListener.Params.Update.exchange(nullptr, std::memory_order_relaxed)};
2386 if(lprops)
2388 ++count;
2389 delete lprops;
2391 lprops = mFreeListenerProps.exchange(nullptr, std::memory_order_acquire);
2392 while(lprops)
2394 ALlistenerProps *next{lprops->next.load(std::memory_order_relaxed)};
2395 delete lprops;
2396 lprops = next;
2397 ++count;
2399 TRACE("Freed %zu listener property object%s\n", count, (count==1)?"":"s");
2401 if(mAsyncEvents)
2403 count = 0;
2404 auto evt_vec = mAsyncEvents->getReadVector();
2405 if(evt_vec.first.len > 0)
2407 al::destroy_n(reinterpret_cast<AsyncEvent*>(evt_vec.first.buf), evt_vec.first.len);
2408 count += evt_vec.first.len;
2410 if(evt_vec.second.len > 0)
2412 al::destroy_n(reinterpret_cast<AsyncEvent*>(evt_vec.second.buf), evt_vec.second.len);
2413 count += evt_vec.second.len;
2415 if(count > 0)
2416 TRACE("Destructed %zu orphaned event%s\n", count, (count==1)?"":"s");
2417 mAsyncEvents->readAdvance(count);
2421 void ALCcontext::init()
2423 if(DefaultEffect.type != AL_EFFECT_NULL && mDevice->Type == Playback)
2425 mDefaultSlot = std::unique_ptr<ALeffectslot>{new ALeffectslot{}};
2426 if(InitEffectSlot(mDefaultSlot.get()) == AL_NO_ERROR)
2427 aluInitEffectPanning(mDefaultSlot.get(), mDevice.get());
2428 else
2430 mDefaultSlot = nullptr;
2431 ERR("Failed to initialize the default effect slot\n");
2435 ALeffectslotArray *auxslots;
2436 if(!mDefaultSlot)
2437 auxslots = ALeffectslot::CreatePtrArray(0);
2438 else
2440 auxslots = ALeffectslot::CreatePtrArray(1);
2441 (*auxslots)[0] = mDefaultSlot.get();
2443 mActiveAuxSlots.store(auxslots, std::memory_order_relaxed);
2445 mExtensionList = alExtList;
2448 mListener.Params.Matrix = alu::Matrix::Identity();
2449 mListener.Params.Velocity = alu::Vector{};
2450 mListener.Params.Gain = mListener.Gain;
2451 mListener.Params.MetersPerUnit = mListener.mMetersPerUnit;
2452 mListener.Params.DopplerFactor = mDopplerFactor;
2453 mListener.Params.SpeedOfSound = mSpeedOfSound * mDopplerVelocity;
2454 mListener.Params.SourceDistanceModel = mSourceDistanceModel;
2455 mListener.Params.mDistanceModel = mDistanceModel;
2458 mAsyncEvents = CreateRingBuffer(511, sizeof(AsyncEvent), false);
2459 StartEventThrd(this);
2462 mVoices.reserve(256);
2463 mVoices.resize(64);
2466 bool ALCcontext::deinit()
2468 if(LocalContext.get() == this)
2470 WARN("%p released while current on thread\n", decltype(std::declval<void*>()){this});
2471 LocalContext.set(nullptr);
2472 release();
2475 ALCcontext *origctx{this};
2476 if(GlobalContext.compare_exchange_strong(origctx, nullptr))
2477 release();
2479 bool ret{};
2480 /* First make sure this context exists in the device's list. */
2481 auto *oldarray = mDevice->mContexts.load(std::memory_order_acquire);
2482 if(auto toremove = static_cast<size_t>(std::count(oldarray->begin(), oldarray->end(), this)))
2484 using ContextArray = al::FlexArray<ALCcontext*>;
2485 auto alloc_ctx_array = [](const size_t count) -> ContextArray*
2487 if(count == 0) return &EmptyContextArray;
2488 return ContextArray::Create(count).release();
2490 auto *newarray = alloc_ctx_array(oldarray->size() - toremove);
2492 /* Copy the current/old context handles to the new array, excluding the
2493 * given context.
2495 std::copy_if(oldarray->begin(), oldarray->end(), newarray->begin(),
2496 std::bind(std::not_equal_to<ALCcontext*>{}, _1, this));
2498 /* Store the new context array in the device. Wait for any current mix
2499 * to finish before deleting the old array.
2501 mDevice->mContexts.store(newarray);
2502 if(oldarray != &EmptyContextArray)
2504 while((mDevice->MixCount.load(std::memory_order_acquire)&1))
2505 std::this_thread::yield();
2506 delete oldarray;
2509 ret = !newarray->empty();
2511 else
2512 ret = !oldarray->empty();
2514 StopEventThrd(this);
2516 return ret;
2520 /* VerifyContext
2522 * Checks if the given context is valid, returning a new reference to it if so.
2524 static ContextRef VerifyContext(ALCcontext *context)
2526 std::lock_guard<std::recursive_mutex> _{ListLock};
2527 auto iter = std::lower_bound(ContextList.cbegin(), ContextList.cend(), context);
2528 if(iter != ContextList.cend() && *iter == context)
2529 return *iter;
2530 return nullptr;
2533 /* GetContextRef
2535 * Returns a new reference to the currently active context for this thread.
2537 ContextRef GetContextRef(void)
2539 ALCcontext *context{LocalContext.get()};
2540 if(context)
2541 context->add_ref();
2542 else
2544 std::lock_guard<std::recursive_mutex> _{ListLock};
2545 context = GlobalContext.load(std::memory_order_acquire);
2546 if(context) context->add_ref();
2548 return ContextRef{context};
2552 /************************************************
2553 * Standard ALC functions
2554 ************************************************/
2556 /* alcGetError
2558 * Return last ALC generated error code for the given device
2560 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2561 START_API_FUNC
2563 DeviceRef dev{VerifyDevice(device)};
2564 if(dev) return dev->LastError.exchange(ALC_NO_ERROR);
2565 return LastNullDeviceError.exchange(ALC_NO_ERROR);
2567 END_API_FUNC
2570 /* alcSuspendContext
2572 * Suspends updates for the given context
2574 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2575 START_API_FUNC
2577 if(!SuspendDefers)
2578 return;
2580 ContextRef ctx{VerifyContext(context)};
2581 if(!ctx)
2582 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2583 else
2584 ctx->deferUpdates();
2586 END_API_FUNC
2588 /* alcProcessContext
2590 * Resumes processing updates for the given context
2592 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2593 START_API_FUNC
2595 if(!SuspendDefers)
2596 return;
2598 ContextRef ctx{VerifyContext(context)};
2599 if(!ctx)
2600 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2601 else
2602 ctx->processUpdates();
2604 END_API_FUNC
2607 /* alcGetString
2609 * Returns information about the device, and error strings
2611 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2612 START_API_FUNC
2614 const ALCchar *value = nullptr;
2616 switch(param)
2618 case ALC_NO_ERROR:
2619 value = alcNoError;
2620 break;
2622 case ALC_INVALID_ENUM:
2623 value = alcErrInvalidEnum;
2624 break;
2626 case ALC_INVALID_VALUE:
2627 value = alcErrInvalidValue;
2628 break;
2630 case ALC_INVALID_DEVICE:
2631 value = alcErrInvalidDevice;
2632 break;
2634 case ALC_INVALID_CONTEXT:
2635 value = alcErrInvalidContext;
2636 break;
2638 case ALC_OUT_OF_MEMORY:
2639 value = alcErrOutOfMemory;
2640 break;
2642 case ALC_DEVICE_SPECIFIER:
2643 value = alcDefaultName;
2644 break;
2646 case ALC_ALL_DEVICES_SPECIFIER:
2647 if(DeviceRef dev{VerifyDevice(Device)})
2648 value = dev->DeviceName.c_str();
2649 else
2651 ProbeAllDevicesList();
2652 value = alcAllDevicesList.c_str();
2654 break;
2656 case ALC_CAPTURE_DEVICE_SPECIFIER:
2657 if(DeviceRef dev{VerifyDevice(Device)})
2658 value = dev->DeviceName.c_str();
2659 else
2661 ProbeCaptureDeviceList();
2662 value = alcCaptureDeviceList.c_str();
2664 break;
2666 /* Default devices are always first in the list */
2667 case ALC_DEFAULT_DEVICE_SPECIFIER:
2668 value = alcDefaultName;
2669 break;
2671 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2672 if(alcAllDevicesList.empty())
2673 ProbeAllDevicesList();
2675 /* Copy first entry as default. */
2676 alcDefaultAllDevicesSpecifier = alcAllDevicesList.c_str();
2677 value = alcDefaultAllDevicesSpecifier.c_str();
2678 break;
2680 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2681 if(alcCaptureDeviceList.empty())
2682 ProbeCaptureDeviceList();
2684 /* Copy first entry as default. */
2685 alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList.c_str();
2686 value = alcCaptureDefaultDeviceSpecifier.c_str();
2687 break;
2689 case ALC_EXTENSIONS:
2690 if(VerifyDevice(Device))
2691 value = alcExtensionList;
2692 else
2693 value = alcNoDeviceExtList;
2694 break;
2696 case ALC_HRTF_SPECIFIER_SOFT:
2697 if(DeviceRef dev{VerifyDevice(Device)})
2699 std::lock_guard<std::mutex> _{dev->StateLock};
2700 value = (dev->mHrtf ? dev->HrtfName.c_str() : "");
2702 else
2703 alcSetError(nullptr, ALC_INVALID_DEVICE);
2704 break;
2706 default:
2707 alcSetError(VerifyDevice(Device).get(), ALC_INVALID_ENUM);
2708 break;
2711 return value;
2713 END_API_FUNC
2716 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
2718 if(device->Type == Capture) return 9;
2719 if(device->Type != Loopback) return 29;
2720 if(device->FmtChans == DevFmtAmbi3D)
2721 return 35;
2722 return 29;
2725 static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span<ALCint> values)
2727 size_t i;
2729 if(values.empty())
2731 alcSetError(device, ALC_INVALID_VALUE);
2732 return 0;
2735 if(!device)
2737 switch(param)
2739 case ALC_MAJOR_VERSION:
2740 values[0] = alcMajorVersion;
2741 return 1;
2742 case ALC_MINOR_VERSION:
2743 values[0] = alcMinorVersion;
2744 return 1;
2746 case ALC_ATTRIBUTES_SIZE:
2747 case ALC_ALL_ATTRIBUTES:
2748 case ALC_FREQUENCY:
2749 case ALC_REFRESH:
2750 case ALC_SYNC:
2751 case ALC_MONO_SOURCES:
2752 case ALC_STEREO_SOURCES:
2753 case ALC_CAPTURE_SAMPLES:
2754 case ALC_FORMAT_CHANNELS_SOFT:
2755 case ALC_FORMAT_TYPE_SOFT:
2756 case ALC_AMBISONIC_LAYOUT_SOFT:
2757 case ALC_AMBISONIC_SCALING_SOFT:
2758 case ALC_AMBISONIC_ORDER_SOFT:
2759 case ALC_MAX_AMBISONIC_ORDER_SOFT:
2760 alcSetError(nullptr, ALC_INVALID_DEVICE);
2761 return 0;
2763 default:
2764 alcSetError(nullptr, ALC_INVALID_ENUM);
2765 return 0;
2767 return 0;
2770 if(device->Type == Capture)
2772 switch(param)
2774 case ALC_ATTRIBUTES_SIZE:
2775 values[0] = NumAttrsForDevice(device);
2776 return 1;
2778 case ALC_ALL_ATTRIBUTES:
2779 i = 0;
2780 if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2781 alcSetError(device, ALC_INVALID_VALUE);
2782 else
2784 std::lock_guard<std::mutex> _{device->StateLock};
2785 values[i++] = ALC_MAJOR_VERSION;
2786 values[i++] = alcMajorVersion;
2787 values[i++] = ALC_MINOR_VERSION;
2788 values[i++] = alcMinorVersion;
2789 values[i++] = ALC_CAPTURE_SAMPLES;
2790 values[i++] = static_cast<int>(device->Backend->availableSamples());
2791 values[i++] = ALC_CONNECTED;
2792 values[i++] = device->Connected.load(std::memory_order_relaxed);
2793 values[i++] = 0;
2795 return i;
2797 case ALC_MAJOR_VERSION:
2798 values[0] = alcMajorVersion;
2799 return 1;
2800 case ALC_MINOR_VERSION:
2801 values[0] = alcMinorVersion;
2802 return 1;
2804 case ALC_CAPTURE_SAMPLES:
2806 std::lock_guard<std::mutex> _{device->StateLock};
2807 values[0] = static_cast<int>(device->Backend->availableSamples());
2809 return 1;
2811 case ALC_CONNECTED:
2813 std::lock_guard<std::mutex> _{device->StateLock};
2814 values[0] = device->Connected.load(std::memory_order_acquire);
2816 return 1;
2818 default:
2819 alcSetError(device, ALC_INVALID_ENUM);
2821 return 0;
2824 /* render device */
2825 switch(param)
2827 case ALC_ATTRIBUTES_SIZE:
2828 values[0] = NumAttrsForDevice(device);
2829 return 1;
2831 case ALC_ALL_ATTRIBUTES:
2832 i = 0;
2833 if(values.size() < static_cast<size_t>(NumAttrsForDevice(device)))
2834 alcSetError(device, ALC_INVALID_VALUE);
2835 else
2837 std::lock_guard<std::mutex> _{device->StateLock};
2838 values[i++] = ALC_MAJOR_VERSION;
2839 values[i++] = alcMajorVersion;
2840 values[i++] = ALC_MINOR_VERSION;
2841 values[i++] = alcMinorVersion;
2842 values[i++] = ALC_EFX_MAJOR_VERSION;
2843 values[i++] = alcEFXMajorVersion;
2844 values[i++] = ALC_EFX_MINOR_VERSION;
2845 values[i++] = alcEFXMinorVersion;
2847 values[i++] = ALC_FREQUENCY;
2848 values[i++] = static_cast<int>(device->Frequency);
2849 if(device->Type != Loopback)
2851 values[i++] = ALC_REFRESH;
2852 values[i++] = static_cast<int>(device->Frequency / device->UpdateSize);
2854 values[i++] = ALC_SYNC;
2855 values[i++] = ALC_FALSE;
2857 else
2859 if(device->FmtChans == DevFmtAmbi3D)
2861 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
2862 values[i++] = static_cast<ALCint>(device->mAmbiLayout);
2864 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
2865 values[i++] = static_cast<ALCint>(device->mAmbiScale);
2867 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
2868 values[i++] = static_cast<ALCint>(device->mAmbiOrder);
2871 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2872 values[i++] = device->FmtChans;
2874 values[i++] = ALC_FORMAT_TYPE_SOFT;
2875 values[i++] = device->FmtType;
2878 values[i++] = ALC_MONO_SOURCES;
2879 values[i++] = static_cast<int>(device->NumMonoSources);
2881 values[i++] = ALC_STEREO_SOURCES;
2882 values[i++] = static_cast<int>(device->NumStereoSources);
2884 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2885 values[i++] = static_cast<ALCint>(device->NumAuxSends);
2887 values[i++] = ALC_HRTF_SOFT;
2888 values[i++] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
2890 values[i++] = ALC_HRTF_STATUS_SOFT;
2891 values[i++] = device->HrtfStatus;
2893 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
2894 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
2896 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
2897 values[i++] = MAX_AMBI_ORDER;
2899 values[i++] = 0;
2901 return i;
2903 case ALC_MAJOR_VERSION:
2904 values[0] = alcMajorVersion;
2905 return 1;
2907 case ALC_MINOR_VERSION:
2908 values[0] = alcMinorVersion;
2909 return 1;
2911 case ALC_EFX_MAJOR_VERSION:
2912 values[0] = alcEFXMajorVersion;
2913 return 1;
2915 case ALC_EFX_MINOR_VERSION:
2916 values[0] = alcEFXMinorVersion;
2917 return 1;
2919 case ALC_FREQUENCY:
2920 values[0] = static_cast<int>(device->Frequency);
2921 return 1;
2923 case ALC_REFRESH:
2924 if(device->Type == Loopback)
2926 alcSetError(device, ALC_INVALID_DEVICE);
2927 return 0;
2930 std::lock_guard<std::mutex> _{device->StateLock};
2931 values[0] = static_cast<int>(device->Frequency / device->UpdateSize);
2933 return 1;
2935 case ALC_SYNC:
2936 if(device->Type == Loopback)
2938 alcSetError(device, ALC_INVALID_DEVICE);
2939 return 0;
2941 values[0] = ALC_FALSE;
2942 return 1;
2944 case ALC_FORMAT_CHANNELS_SOFT:
2945 if(device->Type != Loopback)
2947 alcSetError(device, ALC_INVALID_DEVICE);
2948 return 0;
2950 values[0] = device->FmtChans;
2951 return 1;
2953 case ALC_FORMAT_TYPE_SOFT:
2954 if(device->Type != Loopback)
2956 alcSetError(device, ALC_INVALID_DEVICE);
2957 return 0;
2959 values[0] = device->FmtType;
2960 return 1;
2962 case ALC_AMBISONIC_LAYOUT_SOFT:
2963 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
2965 alcSetError(device, ALC_INVALID_DEVICE);
2966 return 0;
2968 values[0] = static_cast<ALCint>(device->mAmbiLayout);
2969 return 1;
2971 case ALC_AMBISONIC_SCALING_SOFT:
2972 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
2974 alcSetError(device, ALC_INVALID_DEVICE);
2975 return 0;
2977 values[0] = static_cast<ALCint>(device->mAmbiScale);
2978 return 1;
2980 case ALC_AMBISONIC_ORDER_SOFT:
2981 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
2983 alcSetError(device, ALC_INVALID_DEVICE);
2984 return 0;
2986 values[0] = static_cast<int>(device->mAmbiOrder);
2987 return 1;
2989 case ALC_MONO_SOURCES:
2990 values[0] = static_cast<int>(device->NumMonoSources);
2991 return 1;
2993 case ALC_STEREO_SOURCES:
2994 values[0] = static_cast<int>(device->NumStereoSources);
2995 return 1;
2997 case ALC_MAX_AUXILIARY_SENDS:
2998 values[0] = static_cast<ALCint>(device->NumAuxSends);
2999 return 1;
3001 case ALC_CONNECTED:
3003 std::lock_guard<std::mutex> _{device->StateLock};
3004 values[0] = device->Connected.load(std::memory_order_acquire);
3006 return 1;
3008 case ALC_HRTF_SOFT:
3009 values[0] = (device->mHrtf ? ALC_TRUE : ALC_FALSE);
3010 return 1;
3012 case ALC_HRTF_STATUS_SOFT:
3013 values[0] = device->HrtfStatus;
3014 return 1;
3016 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3018 std::lock_guard<std::mutex> _{device->StateLock};
3019 device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
3020 values[0] = static_cast<ALCint>(minz(device->HrtfList.size(),
3021 std::numeric_limits<ALCint>::max()));
3023 return 1;
3025 case ALC_OUTPUT_LIMITER_SOFT:
3026 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3027 return 1;
3029 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3030 values[0] = MAX_AMBI_ORDER;
3031 return 1;
3033 default:
3034 alcSetError(device, ALC_INVALID_ENUM);
3036 return 0;
3039 /* alcGetIntegerv
3041 * Returns information about the device and the version of OpenAL
3043 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3044 START_API_FUNC
3046 DeviceRef dev{VerifyDevice(device)};
3047 if(size <= 0 || values == nullptr)
3048 alcSetError(dev.get(), ALC_INVALID_VALUE);
3049 else
3050 GetIntegerv(dev.get(), param, {values, values+size});
3052 END_API_FUNC
3054 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3055 START_API_FUNC
3057 DeviceRef dev{VerifyDevice(device)};
3058 if(size <= 0 || values == nullptr)
3059 alcSetError(dev.get(), ALC_INVALID_VALUE);
3060 else if(!dev || dev->Type == Capture)
3062 auto ivals = al::vector<ALCint>(static_cast<ALuint>(size));
3063 size_t got{GetIntegerv(dev.get(), pname, {ivals.data(), ivals.size()})};
3064 std::copy_n(ivals.begin(), got, values);
3065 return;
3067 /* render device */
3068 switch(pname)
3070 case ALC_ATTRIBUTES_SIZE:
3071 *values = NumAttrsForDevice(dev.get())+4;
3072 break;
3074 case ALC_ALL_ATTRIBUTES:
3075 if(size < NumAttrsForDevice(dev.get())+4)
3076 alcSetError(dev.get(), ALC_INVALID_VALUE);
3077 else
3079 size_t i{0};
3080 std::lock_guard<std::mutex> _{dev->StateLock};
3081 values[i++] = ALC_FREQUENCY;
3082 values[i++] = dev->Frequency;
3084 if(dev->Type != Loopback)
3086 values[i++] = ALC_REFRESH;
3087 values[i++] = dev->Frequency / dev->UpdateSize;
3089 values[i++] = ALC_SYNC;
3090 values[i++] = ALC_FALSE;
3092 else
3094 if(dev->FmtChans == DevFmtAmbi3D)
3096 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3097 values[i++] = static_cast<ALCint64SOFT>(dev->mAmbiLayout);
3099 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3100 values[i++] = static_cast<ALCint64SOFT>(dev->mAmbiScale);
3102 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3103 values[i++] = dev->mAmbiOrder;
3106 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3107 values[i++] = dev->FmtChans;
3109 values[i++] = ALC_FORMAT_TYPE_SOFT;
3110 values[i++] = dev->FmtType;
3113 values[i++] = ALC_MONO_SOURCES;
3114 values[i++] = dev->NumMonoSources;
3116 values[i++] = ALC_STEREO_SOURCES;
3117 values[i++] = dev->NumStereoSources;
3119 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3120 values[i++] = dev->NumAuxSends;
3122 values[i++] = ALC_HRTF_SOFT;
3123 values[i++] = (dev->mHrtf ? ALC_TRUE : ALC_FALSE);
3125 values[i++] = ALC_HRTF_STATUS_SOFT;
3126 values[i++] = dev->HrtfStatus;
3128 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3129 values[i++] = dev->Limiter ? ALC_TRUE : ALC_FALSE;
3131 ClockLatency clock{GetClockLatency(dev.get())};
3132 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3133 values[i++] = clock.ClockTime.count();
3135 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3136 values[i++] = clock.Latency.count();
3138 values[i++] = 0;
3140 break;
3142 case ALC_DEVICE_CLOCK_SOFT:
3143 { std::lock_guard<std::mutex> _{dev->StateLock};
3144 nanoseconds basecount;
3145 ALuint samplecount;
3146 ALuint refcount;
3147 do {
3148 while(((refcount=ReadRef(dev->MixCount))&1) != 0)
3149 std::this_thread::yield();
3150 basecount = dev->ClockBase;
3151 samplecount = dev->SamplesDone;
3152 } while(refcount != ReadRef(dev->MixCount));
3153 basecount += nanoseconds{seconds{samplecount}} / dev->Frequency;
3154 *values = basecount.count();
3156 break;
3158 case ALC_DEVICE_LATENCY_SOFT:
3159 { std::lock_guard<std::mutex> _{dev->StateLock};
3160 ClockLatency clock{GetClockLatency(dev.get())};
3161 *values = clock.Latency.count();
3163 break;
3165 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3166 if(size < 2)
3167 alcSetError(dev.get(), ALC_INVALID_VALUE);
3168 else
3170 std::lock_guard<std::mutex> _{dev->StateLock};
3171 ClockLatency clock{GetClockLatency(dev.get())};
3172 values[0] = clock.ClockTime.count();
3173 values[1] = clock.Latency.count();
3175 break;
3177 default:
3178 auto ivals = al::vector<ALCint>(static_cast<ALuint>(size));
3179 size_t got{GetIntegerv(dev.get(), pname, {ivals.data(), ivals.size()})};
3180 std::copy_n(ivals.begin(), got, values);
3181 break;
3184 END_API_FUNC
3187 /* alcIsExtensionPresent
3189 * Determines if there is support for a particular extension
3191 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3192 START_API_FUNC
3194 DeviceRef dev{VerifyDevice(device)};
3195 if(!extName)
3196 alcSetError(dev.get(), ALC_INVALID_VALUE);
3197 else
3199 size_t len = strlen(extName);
3200 const char *ptr = (dev ? alcExtensionList : alcNoDeviceExtList);
3201 while(ptr && *ptr)
3203 if(al::strncasecmp(ptr, extName, len) == 0 && (ptr[len] == '\0' || isspace(ptr[len])))
3204 return ALC_TRUE;
3206 if((ptr=strchr(ptr, ' ')) != nullptr)
3208 do {
3209 ++ptr;
3210 } while(isspace(*ptr));
3214 return ALC_FALSE;
3216 END_API_FUNC
3219 /* alcGetProcAddress
3221 * Retrieves the function address for a particular extension function
3223 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3224 START_API_FUNC
3226 if(!funcName)
3228 DeviceRef dev{VerifyDevice(device)};
3229 alcSetError(dev.get(), ALC_INVALID_VALUE);
3231 else
3233 for(const auto &func : alcFunctions)
3235 if(strcmp(func.funcName, funcName) == 0)
3236 return func.address;
3239 return nullptr;
3241 END_API_FUNC
3244 /* alcGetEnumValue
3246 * Get the value for a particular ALC enumeration name
3248 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3249 START_API_FUNC
3251 if(!enumName)
3253 DeviceRef dev{VerifyDevice(device)};
3254 alcSetError(dev.get(), ALC_INVALID_VALUE);
3256 else
3258 for(const auto &enm : alcEnumerations)
3260 if(strcmp(enm.enumName, enumName) == 0)
3261 return enm.value;
3264 return 0;
3266 END_API_FUNC
3269 /* alcCreateContext
3271 * Create and attach a context to the given device.
3273 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3274 START_API_FUNC
3276 /* Explicitly hold the list lock while taking the StateLock in case the
3277 * device is asynchronously destroyed, to ensure this new context is
3278 * properly cleaned up after being made.
3280 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3281 DeviceRef dev{VerifyDevice(device)};
3282 if(!dev || dev->Type == Capture || !dev->Connected.load(std::memory_order_relaxed))
3284 listlock.unlock();
3285 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3286 return nullptr;
3288 std::unique_lock<std::mutex> statelock{dev->StateLock};
3289 listlock.unlock();
3291 dev->LastError.store(ALC_NO_ERROR);
3293 ALCenum err{UpdateDeviceParams(dev.get(), attrList)};
3294 if(err != ALC_NO_ERROR)
3296 alcSetError(dev.get(), err);
3297 if(err == ALC_INVALID_DEVICE)
3298 aluHandleDisconnect(dev.get(), "Device update failure");
3299 return nullptr;
3302 ContextRef context{new ALCcontext{dev}};
3303 context->init();
3305 if(auto volopt = ConfigValueFloat(dev->DeviceName.c_str(), nullptr, "volume-adjust"))
3307 const ALfloat valf{*volopt};
3308 if(!std::isfinite(valf))
3309 ERR("volume-adjust must be finite: %f\n", valf);
3310 else
3312 const ALfloat db{clampf(valf, -24.0f, 24.0f)};
3313 if(db != valf)
3314 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3315 context->mGainBoost = std::pow(10.0f, db/20.0f);
3316 TRACE("volume-adjust gain: %f\n", context->mGainBoost);
3319 UpdateListenerProps(context.get());
3322 using ContextArray = al::FlexArray<ALCcontext*>;
3324 /* Allocate a new context array, which holds 1 more than the current/
3325 * old array.
3327 auto *oldarray = device->mContexts.load();
3328 const size_t newcount{oldarray->size()+1};
3329 std::unique_ptr<ContextArray> newarray{ContextArray::Create(newcount)};
3331 /* Copy the current/old context handles to the new array, appending the
3332 * new context.
3334 auto iter = std::copy(oldarray->begin(), oldarray->end(), newarray->begin());
3335 *iter = context.get();
3337 /* Store the new context array in the device. Wait for any current mix
3338 * to finish before deleting the old array.
3340 dev->mContexts.store(newarray.release());
3341 if(oldarray != &EmptyContextArray)
3343 while((dev->MixCount.load(std::memory_order_acquire)&1))
3344 std::this_thread::yield();
3345 delete oldarray;
3348 statelock.unlock();
3351 std::lock_guard<std::recursive_mutex> _{ListLock};
3352 auto iter = std::lower_bound(ContextList.cbegin(), ContextList.cend(), context.get());
3353 ContextList.emplace(iter, context);
3356 if(context->mDefaultSlot)
3358 if(InitializeEffect(context.get(), context->mDefaultSlot.get(), &DefaultEffect) == AL_NO_ERROR)
3359 UpdateEffectSlotProps(context->mDefaultSlot.get(), context.get());
3360 else
3361 ERR("Failed to initialize the default effect\n");
3364 TRACE("Created context %p\n", decltype(std::declval<void*>()){context.get()});
3365 return context.get();
3367 END_API_FUNC
3369 /* alcDestroyContext
3371 * Remove a context from its device
3373 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3374 START_API_FUNC
3376 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3377 auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context);
3378 if(iter == ContextList.end() || *iter != context)
3380 listlock.unlock();
3381 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3382 return;
3384 /* Hold an extra reference to this context so it remains valid until the
3385 * ListLock is released.
3387 ContextRef ctx{std::move(*iter)};
3388 ContextList.erase(iter);
3390 ALCdevice *Device{ctx->mDevice.get()};
3392 std::lock_guard<std::mutex> _{Device->StateLock};
3393 if(!ctx->deinit() && Device->Flags.get<DeviceRunning>())
3395 Device->Backend->stop();
3396 Device->Flags.unset<DeviceRunning>();
3399 END_API_FUNC
3402 /* alcGetCurrentContext
3404 * Returns the currently active context on the calling thread
3406 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3407 START_API_FUNC
3409 ALCcontext *Context{LocalContext.get()};
3410 if(!Context) Context = GlobalContext.load();
3411 return Context;
3413 END_API_FUNC
3415 /* alcGetThreadContext
3417 * Returns the currently active thread-local context
3419 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3420 START_API_FUNC
3421 { return LocalContext.get(); }
3422 END_API_FUNC
3424 /* alcMakeContextCurrent
3426 * Makes the given context the active process-wide context, and removes the
3427 * thread-local context for the calling thread.
3429 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3430 START_API_FUNC
3432 /* context must be valid or nullptr */
3433 ContextRef ctx;
3434 if(context)
3436 ctx = VerifyContext(context);
3437 if(!ctx)
3439 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3440 return ALC_FALSE;
3443 /* Release this reference (if any) to store it in the GlobalContext
3444 * pointer. Take ownership of the reference (if any) that was previously
3445 * stored there.
3447 ctx = ContextRef{GlobalContext.exchange(ctx.release())};
3449 /* Reset (decrement) the previous global reference by replacing it with the
3450 * thread-local context. Take ownership of the thread-local context
3451 * reference (if any), clearing the storage to null.
3453 ctx = ContextRef{LocalContext.get()};
3454 if(ctx) LocalContext.set(nullptr);
3455 /* Reset (decrement) the previous thread-local reference. */
3457 return ALC_TRUE;
3459 END_API_FUNC
3461 /* alcSetThreadContext
3463 * Makes the given context the active context for the current thread
3465 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3466 START_API_FUNC
3468 /* context must be valid or nullptr */
3469 ContextRef ctx;
3470 if(context)
3472 ctx = VerifyContext(context);
3473 if(!ctx)
3475 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3476 return ALC_FALSE;
3479 /* context's reference count is already incremented */
3480 ContextRef old{LocalContext.get()};
3481 LocalContext.set(ctx.release());
3483 return ALC_TRUE;
3485 END_API_FUNC
3488 /* alcGetContextsDevice
3490 * Returns the device that a particular context is attached to
3492 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3493 START_API_FUNC
3495 ContextRef ctx{VerifyContext(Context)};
3496 if(!ctx)
3498 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3499 return nullptr;
3501 return ctx->mDevice.get();
3503 END_API_FUNC
3506 /* alcOpenDevice
3508 * Opens the named device.
3510 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3511 START_API_FUNC
3513 DO_INITCONFIG();
3515 if(!PlaybackFactory)
3517 alcSetError(nullptr, ALC_INVALID_VALUE);
3518 return nullptr;
3521 if(deviceName)
3523 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3524 #ifdef _WIN32
3525 /* Some old Windows apps hardcode these expecting OpenAL to use a
3526 * specific audio API, even when they're not enumerated. Creative's
3527 * router effectively ignores them too.
3529 || al::strcasecmp(deviceName, "DirectSound3D") == 0
3530 || al::strcasecmp(deviceName, "DirectSound") == 0
3531 || al::strcasecmp(deviceName, "MMSYSTEM") == 0
3532 #endif
3533 || al::strcasecmp(deviceName, "openal-soft") == 0)
3534 deviceName = nullptr;
3537 DeviceRef device{new ALCdevice{Playback}};
3539 /* Set output format */
3540 device->FmtChans = DevFmtChannelsDefault;
3541 device->FmtType = DevFmtTypeDefault;
3542 device->Frequency = DEFAULT_OUTPUT_RATE;
3543 device->UpdateSize = DEFAULT_UPDATE_SIZE;
3544 device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
3546 device->SourcesMax = 256;
3547 device->AuxiliaryEffectSlotMax = 64;
3548 device->NumAuxSends = DEFAULT_SENDS;
3550 try {
3551 /* Create the device backend. */
3552 device->Backend = PlaybackFactory->createBackend(device.get(), BackendType::Playback);
3554 /* Find a playback device to open */
3555 ALCenum err{device->Backend->open(deviceName)};
3556 if(err != ALC_NO_ERROR)
3558 alcSetError(nullptr, err);
3559 return nullptr;
3562 catch(al::backend_exception &e) {
3563 WARN("Failed to open playback device: %s\n", e.what());
3564 alcSetError(nullptr, e.errorCode());
3565 return nullptr;
3568 deviceName = device->DeviceName.c_str();
3569 if(auto chanopt = ConfigValueStr(deviceName, nullptr, "channels"))
3571 static constexpr struct ChannelMap {
3572 const char name[16];
3573 DevFmtChannels chans;
3574 ALuint order;
3575 } chanlist[] = {
3576 { "mono", DevFmtMono, 0 },
3577 { "stereo", DevFmtStereo, 0 },
3578 { "quad", DevFmtQuad, 0 },
3579 { "surround51", DevFmtX51, 0 },
3580 { "surround61", DevFmtX61, 0 },
3581 { "surround71", DevFmtX71, 0 },
3582 { "surround51rear", DevFmtX51Rear, 0 },
3583 { "ambi1", DevFmtAmbi3D, 1 },
3584 { "ambi2", DevFmtAmbi3D, 2 },
3585 { "ambi3", DevFmtAmbi3D, 3 },
3588 const ALCchar *fmt{chanopt->c_str()};
3589 auto iter = std::find_if(std::begin(chanlist), std::end(chanlist),
3590 [fmt](const ChannelMap &entry) -> bool
3591 { return al::strcasecmp(entry.name, fmt) == 0; }
3593 if(iter == std::end(chanlist))
3594 ERR("Unsupported channels: %s\n", fmt);
3595 else
3597 device->FmtChans = iter->chans;
3598 device->mAmbiOrder = iter->order;
3599 device->Flags.set<ChannelsRequest>();
3602 if(auto typeopt = ConfigValueStr(deviceName, nullptr, "sample-type"))
3604 static constexpr struct TypeMap {
3605 const char name[16];
3606 DevFmtType type;
3607 } typelist[] = {
3608 { "int8", DevFmtByte },
3609 { "uint8", DevFmtUByte },
3610 { "int16", DevFmtShort },
3611 { "uint16", DevFmtUShort },
3612 { "int32", DevFmtInt },
3613 { "uint32", DevFmtUInt },
3614 { "float32", DevFmtFloat },
3617 const ALCchar *fmt{typeopt->c_str()};
3618 auto iter = std::find_if(std::begin(typelist), std::end(typelist),
3619 [fmt](const TypeMap &entry) -> bool
3620 { return al::strcasecmp(entry.name, fmt) == 0; }
3622 if(iter == std::end(typelist))
3623 ERR("Unsupported sample-type: %s\n", fmt);
3624 else
3626 device->FmtType = iter->type;
3627 device->Flags.set<SampleTypeRequest>();
3631 if(ALuint freq{ConfigValueUInt(deviceName, nullptr, "frequency").value_or(0)})
3633 if(freq < MIN_OUTPUT_RATE)
3635 ERR("%uhz request clamped to %uhz minimum\n", freq, MIN_OUTPUT_RATE);
3636 freq = MIN_OUTPUT_RATE;
3638 device->UpdateSize = (device->UpdateSize*freq + device->Frequency/2) / device->Frequency;
3639 device->BufferSize = (device->BufferSize*freq + device->Frequency/2) / device->Frequency;
3640 device->Frequency = freq;
3641 device->Flags.set<FrequencyRequest>();
3644 if(auto persizeopt = ConfigValueUInt(deviceName, nullptr, "period_size"))
3645 device->UpdateSize = clampu(*persizeopt, 64, 8192);
3647 if(auto peropt = ConfigValueUInt(deviceName, nullptr, "periods"))
3648 device->BufferSize = device->UpdateSize * clampu(*peropt, 2, 16);
3649 else
3650 device->BufferSize = maxu(device->BufferSize, device->UpdateSize*2);
3652 if(auto srcsopt = ConfigValueUInt(deviceName, nullptr, "sources"))
3654 if(*srcsopt > 0) device->SourcesMax = *srcsopt;
3657 if(auto slotsopt = ConfigValueUInt(deviceName, nullptr, "slots"))
3659 if(*slotsopt > 0)
3660 device->AuxiliaryEffectSlotMax = minu(*slotsopt, INT_MAX);
3663 if(auto sendsopt = ConfigValueInt(deviceName, nullptr, "sends"))
3664 device->NumAuxSends = clampu(DEFAULT_SENDS, 0,
3665 static_cast<ALuint>(clampi(*sendsopt, 0, MAX_SENDS)));
3667 device->NumStereoSources = 1;
3668 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3670 if(auto ambiopt = ConfigValueStr(deviceName, nullptr, "ambi-format"))
3672 const ALCchar *fmt{ambiopt->c_str()};
3673 if(al::strcasecmp(fmt, "fuma") == 0)
3675 if(device->mAmbiOrder > 3)
3676 ERR("FuMa is incompatible with %d%s order ambisonics (up to third-order only)\n",
3677 device->mAmbiOrder,
3678 (((device->mAmbiOrder%100)/10) == 1) ? "th" :
3679 ((device->mAmbiOrder%10) == 1) ? "st" :
3680 ((device->mAmbiOrder%10) == 2) ? "nd" :
3681 ((device->mAmbiOrder%10) == 3) ? "rd" : "th");
3682 else
3684 device->mAmbiLayout = AmbiLayout::FuMa;
3685 device->mAmbiScale = AmbiNorm::FuMa;
3688 else if(al::strcasecmp(fmt, "ambix") == 0 || al::strcasecmp(fmt, "acn+sn3d") == 0)
3690 device->mAmbiLayout = AmbiLayout::ACN;
3691 device->mAmbiScale = AmbiNorm::SN3D;
3693 else if(al::strcasecmp(fmt, "acn+n3d") == 0)
3695 device->mAmbiLayout = AmbiLayout::ACN;
3696 device->mAmbiScale = AmbiNorm::N3D;
3698 else
3699 ERR("Unsupported ambi-format: %s\n", fmt);
3703 std::lock_guard<std::recursive_mutex> _{ListLock};
3704 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3705 DeviceList.emplace(iter, device);
3708 TRACE("Created device %p, \"%s\"\n", decltype(std::declval<void*>()){device.get()},
3709 device->DeviceName.c_str());
3710 return device.get();
3712 END_API_FUNC
3714 /* alcCloseDevice
3716 * Closes the given device.
3718 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3719 START_API_FUNC
3721 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3722 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3723 if(iter == DeviceList.end() || *iter != device)
3725 alcSetError(nullptr, ALC_INVALID_DEVICE);
3726 return ALC_FALSE;
3728 if((*iter)->Type == Capture)
3730 alcSetError(iter->get(), ALC_INVALID_DEVICE);
3731 return ALC_FALSE;
3734 /* Erase the device, and any remaining contexts left on it, from their
3735 * respective lists.
3737 DeviceRef dev{std::move(*iter)};
3738 DeviceList.erase(iter);
3740 std::unique_lock<std::mutex> statelock{dev->StateLock};
3741 al::vector<ContextRef> orphanctxs;
3742 for(ALCcontext *ctx : *dev->mContexts.load())
3744 auto ctxiter = std::lower_bound(ContextList.begin(), ContextList.end(), ctx);
3745 if(ctxiter != ContextList.end() && *ctxiter == ctx)
3747 orphanctxs.emplace_back(std::move(*ctxiter));
3748 ContextList.erase(ctxiter);
3751 listlock.unlock();
3753 for(ContextRef &context : orphanctxs)
3755 WARN("Releasing orphaned context %p\n", decltype(std::declval<void*>()){context.get()});
3756 context->deinit();
3758 orphanctxs.clear();
3760 if(dev->Flags.get<DeviceRunning>())
3761 dev->Backend->stop();
3762 dev->Flags.unset<DeviceRunning>();
3764 return ALC_TRUE;
3766 END_API_FUNC
3769 /************************************************
3770 * ALC capture functions
3771 ************************************************/
3772 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3773 START_API_FUNC
3775 DO_INITCONFIG();
3777 if(!CaptureFactory)
3779 alcSetError(nullptr, ALC_INVALID_VALUE);
3780 return nullptr;
3783 if(samples <= 0)
3785 alcSetError(nullptr, ALC_INVALID_VALUE);
3786 return nullptr;
3789 if(deviceName)
3791 if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0
3792 || al::strcasecmp(deviceName, "openal-soft") == 0)
3793 deviceName = nullptr;
3796 DeviceRef device{new ALCdevice{Capture}};
3798 auto decompfmt = DecomposeDevFormat(format);
3799 if(!decompfmt)
3801 alcSetError(nullptr, ALC_INVALID_ENUM);
3802 return nullptr;
3805 device->Frequency = frequency;
3806 device->FmtChans = decompfmt->chans;
3807 device->FmtType = decompfmt->type;
3808 device->Flags.set<FrequencyRequest, ChannelsRequest, SampleTypeRequest>();
3810 device->UpdateSize = static_cast<ALuint>(samples);
3811 device->BufferSize = static_cast<ALuint>(samples);
3813 try {
3814 device->Backend = CaptureFactory->createBackend(device.get(), BackendType::Capture);
3816 TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n",
3817 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
3818 device->Frequency, device->UpdateSize, device->BufferSize);
3819 ALCenum err{device->Backend->open(deviceName)};
3820 if(err != ALC_NO_ERROR)
3822 alcSetError(nullptr, err);
3823 return nullptr;
3826 catch(al::backend_exception &e) {
3827 WARN("Failed to open capture device: %s\n", e.what());
3828 alcSetError(nullptr, e.errorCode());
3829 return nullptr;
3833 std::lock_guard<std::recursive_mutex> _{ListLock};
3834 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
3835 DeviceList.emplace(iter, device);
3838 TRACE("Created capture device %p, \"%s\"\n", decltype(std::declval<void*>()){device.get()},
3839 device->DeviceName.c_str());
3840 return device.get();
3842 END_API_FUNC
3844 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3845 START_API_FUNC
3847 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3848 auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device);
3849 if(iter == DeviceList.end() || *iter != device)
3851 alcSetError(nullptr, ALC_INVALID_DEVICE);
3852 return ALC_FALSE;
3854 if((*iter)->Type != Capture)
3856 alcSetError(iter->get(), ALC_INVALID_DEVICE);
3857 return ALC_FALSE;
3860 DeviceRef dev{std::move(*iter)};
3861 DeviceList.erase(iter);
3862 listlock.unlock();
3864 std::lock_guard<std::mutex> _{dev->StateLock};
3865 if(dev->Flags.get<DeviceRunning>())
3866 dev->Backend->stop();
3867 dev->Flags.unset<DeviceRunning>();
3869 return ALC_TRUE;
3871 END_API_FUNC
3873 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3874 START_API_FUNC
3876 DeviceRef dev{VerifyDevice(device)};
3877 if(!dev || dev->Type != Capture)
3879 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3880 return;
3883 std::lock_guard<std::mutex> _{dev->StateLock};
3884 if(!dev->Connected.load(std::memory_order_acquire))
3885 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3886 else if(!dev->Flags.get<DeviceRunning>())
3888 if(dev->Backend->start())
3889 dev->Flags.set<DeviceRunning>();
3890 else
3892 aluHandleDisconnect(dev.get(), "Device start failure");
3893 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3897 END_API_FUNC
3899 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3900 START_API_FUNC
3902 DeviceRef dev{VerifyDevice(device)};
3903 if(!dev || dev->Type != Capture)
3904 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3905 else
3907 std::lock_guard<std::mutex> _{dev->StateLock};
3908 if(dev->Flags.get<DeviceRunning>())
3909 dev->Backend->stop();
3910 dev->Flags.unset<DeviceRunning>();
3913 END_API_FUNC
3915 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3916 START_API_FUNC
3918 DeviceRef dev{VerifyDevice(device)};
3919 if(!dev || dev->Type != Capture)
3921 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3922 return;
3925 if(samples < 0 || (samples > 0 && buffer == nullptr))
3927 alcSetError(dev.get(), ALC_INVALID_VALUE);
3928 return;
3930 if(samples < 1)
3931 return;
3933 std::lock_guard<std::mutex> _{dev->StateLock};
3934 BackendBase *backend{dev->Backend.get()};
3936 const auto usamples = static_cast<ALCuint>(samples);
3937 if(usamples > backend->availableSamples())
3939 alcSetError(dev.get(), ALC_INVALID_VALUE);
3940 return;
3943 auto *bbuffer = static_cast<al::byte*>(buffer);
3944 if(ALCenum err{backend->captureSamples(bbuffer, usamples)})
3945 alcSetError(dev.get(), err);
3947 END_API_FUNC
3950 /************************************************
3951 * ALC loopback functions
3952 ************************************************/
3954 /* alcLoopbackOpenDeviceSOFT
3956 * Open a loopback device, for manual rendering.
3958 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3959 START_API_FUNC
3961 DO_INITCONFIG();
3963 /* Make sure the device name, if specified, is us. */
3964 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3966 alcSetError(nullptr, ALC_INVALID_VALUE);
3967 return nullptr;
3970 DeviceRef device{new ALCdevice{Loopback}};
3972 device->SourcesMax = 256;
3973 device->AuxiliaryEffectSlotMax = 64;
3974 device->NumAuxSends = DEFAULT_SENDS;
3976 //Set output format
3977 device->BufferSize = 0;
3978 device->UpdateSize = 0;
3980 device->Frequency = DEFAULT_OUTPUT_RATE;
3981 device->FmtChans = DevFmtChannelsDefault;
3982 device->FmtType = DevFmtTypeDefault;
3984 if(auto srcsopt = ConfigValueUInt(nullptr, nullptr, "sources"))
3986 if(*srcsopt > 0) device->SourcesMax = *srcsopt;
3989 if(auto slotsopt = ConfigValueUInt(nullptr, nullptr, "slots"))
3991 if(*slotsopt > 0)
3992 device->AuxiliaryEffectSlotMax = minu(*slotsopt, INT_MAX);
3995 if(auto sendsopt = ConfigValueInt(nullptr, nullptr, "sends"))
3996 device->NumAuxSends = clampu(DEFAULT_SENDS, 0,
3997 static_cast<ALuint>(clampi(*sendsopt, 0, MAX_SENDS)));
3999 device->NumStereoSources = 1;
4000 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4002 try {
4003 device->Backend = LoopbackBackendFactory::getFactory().createBackend(device.get(),
4004 BackendType::Playback);
4006 // Open the "backend"
4007 device->Backend->open("Loopback");
4009 catch(al::backend_exception &e) {
4010 WARN("Failed to open loopback device: %s\n", e.what());
4011 alcSetError(nullptr, e.errorCode());
4012 return nullptr;
4016 std::lock_guard<std::recursive_mutex> _{ListLock};
4017 auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get());
4018 DeviceList.emplace(iter, device);
4021 TRACE("Created loopback device %p\n", decltype(std::declval<void*>()){device.get()});
4022 return device.get();
4024 END_API_FUNC
4026 /* alcIsRenderFormatSupportedSOFT
4028 * Determines if the loopback device supports the given format for rendering.
4030 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4031 START_API_FUNC
4033 DeviceRef dev{VerifyDevice(device)};
4034 if(!dev || dev->Type != Loopback)
4035 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4036 else if(freq <= 0)
4037 alcSetError(dev.get(), ALC_INVALID_VALUE);
4038 else
4040 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4041 return ALC_TRUE;
4044 return ALC_FALSE;
4046 END_API_FUNC
4048 /* alcRenderSamplesSOFT
4050 * Renders some samples into a buffer, using the format last set by the
4051 * attributes given to alcCreateContext.
4053 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4054 START_API_FUNC
4056 DeviceRef dev{VerifyDevice(device)};
4057 if(!dev || dev->Type != Loopback)
4058 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4059 else if(samples < 0 || (samples > 0 && buffer == nullptr))
4060 alcSetError(dev.get(), ALC_INVALID_VALUE);
4061 else
4063 BackendLockGuard _{*dev->Backend};
4064 aluMixData(dev.get(), buffer, static_cast<ALuint>(samples));
4067 END_API_FUNC
4070 /************************************************
4071 * ALC DSP pause/resume functions
4072 ************************************************/
4074 /* alcDevicePauseSOFT
4076 * Pause the DSP to stop audio processing.
4078 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4079 START_API_FUNC
4081 DeviceRef dev{VerifyDevice(device)};
4082 if(!dev || dev->Type != Playback)
4083 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4084 else
4086 std::lock_guard<std::mutex> _{dev->StateLock};
4087 if(dev->Flags.get<DeviceRunning>())
4088 dev->Backend->stop();
4089 dev->Flags.unset<DeviceRunning>();
4090 dev->Flags.set<DevicePaused>();
4093 END_API_FUNC
4095 /* alcDeviceResumeSOFT
4097 * Resume the DSP to restart audio processing.
4099 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4100 START_API_FUNC
4102 DeviceRef dev{VerifyDevice(device)};
4103 if(!dev || dev->Type != Playback)
4105 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4106 return;
4109 std::lock_guard<std::mutex> _{dev->StateLock};
4110 if(!dev->Flags.get<DevicePaused>())
4111 return;
4112 dev->Flags.unset<DevicePaused>();
4113 if(dev->mContexts.load()->empty())
4114 return;
4116 if(dev->Backend->start() == false)
4118 aluHandleDisconnect(dev.get(), "Device start failure");
4119 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4120 return;
4122 dev->Flags.set<DeviceRunning>();
4124 END_API_FUNC
4127 /************************************************
4128 * ALC HRTF functions
4129 ************************************************/
4131 /* alcGetStringiSOFT
4133 * Gets a string parameter at the given index.
4135 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4136 START_API_FUNC
4138 DeviceRef dev{VerifyDevice(device)};
4139 if(!dev || dev->Type == Capture)
4140 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4141 else switch(paramName)
4143 case ALC_HRTF_SPECIFIER_SOFT:
4144 if(index >= 0 && static_cast<size_t>(index) < dev->HrtfList.size())
4145 return dev->HrtfList[static_cast<ALuint>(index)].name.c_str();
4146 alcSetError(dev.get(), ALC_INVALID_VALUE);
4147 break;
4149 default:
4150 alcSetError(dev.get(), ALC_INVALID_ENUM);
4151 break;
4154 return nullptr;
4156 END_API_FUNC
4158 /* alcResetDeviceSOFT
4160 * Resets the given device output, using the specified attribute list.
4162 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4163 START_API_FUNC
4165 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4166 DeviceRef dev{VerifyDevice(device)};
4167 if(!dev || dev->Type == Capture)
4169 listlock.unlock();
4170 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4171 return ALC_FALSE;
4173 std::lock_guard<std::mutex> _{dev->StateLock};
4174 listlock.unlock();
4176 /* Force the backend to stop mixing first since we're resetting. Also reset
4177 * the connected state so lost devices can attempt recover.
4179 if(dev->Flags.get<DeviceRunning>())
4180 dev->Backend->stop();
4181 dev->Flags.unset<DeviceRunning>();
4182 device->Connected.store(true);
4184 ALCenum err{UpdateDeviceParams(dev.get(), attribs)};
4185 if LIKELY(err == ALC_NO_ERROR) return ALC_TRUE;
4187 alcSetError(dev.get(), err);
4188 if(err == ALC_INVALID_DEVICE)
4189 aluHandleDisconnect(dev.get(), "Device start failure");
4190 return ALC_FALSE;
4192 END_API_FUNC