Avoid using ATOMIC macros
[openal-soft.git] / Alc / alc.cpp
blob5c46b950107469024619ca0102451100a5eccc4f
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 <stdlib.h>
26 #include <stdio.h>
27 #include <memory.h>
28 #include <ctype.h>
29 #include <signal.h>
31 #include <cmath>
32 #include <atomic>
33 #include <mutex>
34 #include <thread>
35 #include <vector>
36 #include <string>
37 #include <algorithm>
39 #include "alMain.h"
40 #include "alcontext.h"
41 #include "alSource.h"
42 #include "alListener.h"
43 #include "alSource.h"
44 #include "alBuffer.h"
45 #include "alFilter.h"
46 #include "alEffect.h"
47 #include "alAuxEffectSlot.h"
48 #include "alError.h"
49 #include "mastering.h"
50 #include "bformatdec.h"
51 #include "alu.h"
52 #include "alconfig.h"
53 #include "ringbuffer.h"
55 #include "fpu_modes.h"
56 #include "cpu_caps.h"
57 #include "compat.h"
58 #include "threads.h"
59 #include "almalloc.h"
61 #include "backends/base.h"
62 #include "backends/null.h"
63 #include "backends/loopback.h"
64 #ifdef HAVE_JACK
65 #include "backends/jack.h"
66 #endif
67 #ifdef HAVE_PULSEAUDIO
68 #include "backends/pulseaudio.h"
69 #endif
70 #ifdef HAVE_ALSA
71 #include "backends/alsa.h"
72 #endif
73 #ifdef HAVE_WASAPI
74 #include "backends/wasapi.h"
75 #endif
76 #ifdef HAVE_COREAUDIO
77 #include "backends/coreaudio.h"
78 #endif
79 #ifdef HAVE_OPENSL
80 #include "backends/opensl.h"
81 #endif
82 #ifdef HAVE_SOLARIS
83 #include "backends/solaris.h"
84 #endif
85 #ifdef HAVE_SNDIO
86 #include "backends/sndio.h"
87 #endif
88 #ifdef HAVE_OSS
89 #include "backends/oss.h"
90 #endif
91 #ifdef HAVE_QSA
92 #include "backends/qsa.h"
93 #endif
94 #ifdef HAVE_DSOUND
95 #include "backends/dsound.h"
96 #endif
97 #ifdef HAVE_WINMM
98 #include "backends/winmm.h"
99 #endif
100 #ifdef HAVE_PORTAUDIO
101 #include "backends/portaudio.h"
102 #endif
103 #ifdef HAVE_SDL2
104 #include "backends/sdl2.h"
105 #endif
106 #ifdef HAVE_WAVE
107 #include "backends/wave.h"
108 #endif
111 namespace {
113 /************************************************
114 * Backends
115 ************************************************/
116 struct BackendInfo {
117 const char *name;
118 BackendFactory& (*getFactory)(void);
121 struct BackendInfo BackendList[] = {
122 #ifdef HAVE_JACK
123 { "jack", JackBackendFactory::getFactory },
124 #endif
125 #ifdef HAVE_PULSEAUDIO
126 { "pulse", PulseBackendFactory::getFactory },
127 #endif
128 #ifdef HAVE_ALSA
129 { "alsa", AlsaBackendFactory::getFactory },
130 #endif
131 #ifdef HAVE_WASAPI
132 { "wasapi", WasapiBackendFactory::getFactory },
133 #endif
134 #ifdef HAVE_COREAUDIO
135 { "core", CoreAudioBackendFactory::getFactory },
136 #endif
137 #ifdef HAVE_OPENSL
138 { "opensl", OSLBackendFactory::getFactory },
139 #endif
140 #ifdef HAVE_SOLARIS
141 { "solaris", SolarisBackendFactory::getFactory },
142 #endif
143 #ifdef HAVE_SNDIO
144 { "sndio", SndIOBackendFactory::getFactory },
145 #endif
146 #ifdef HAVE_OSS
147 { "oss", OSSBackendFactory::getFactory },
148 #endif
149 #ifdef HAVE_QSA
150 { "qsa", QSABackendFactory::getFactory },
151 #endif
152 #ifdef HAVE_DSOUND
153 { "dsound", DSoundBackendFactory::getFactory },
154 #endif
155 #ifdef HAVE_WINMM
156 { "winmm", WinMMBackendFactory::getFactory },
157 #endif
158 #ifdef HAVE_PORTAUDIO
159 { "port", PortBackendFactory::getFactory },
160 #endif
161 #ifdef HAVE_SDL2
162 { "sdl2", SDL2BackendFactory::getFactory },
163 #endif
165 { "null", NullBackendFactory::getFactory },
166 #ifdef HAVE_WAVE
167 { "wave", WaveBackendFactory::getFactory },
168 #endif
170 ALsizei BackendListSize = COUNTOF(BackendList);
172 struct BackendInfo PlaybackBackend;
173 struct BackendInfo CaptureBackend;
176 /************************************************
177 * Functions, enums, and errors
178 ************************************************/
179 #define DECL(x) { #x, (ALCvoid*)(x) }
180 constexpr struct {
181 const ALCchar *funcName;
182 ALCvoid *address;
183 } alcFunctions[] = {
184 DECL(alcCreateContext),
185 DECL(alcMakeContextCurrent),
186 DECL(alcProcessContext),
187 DECL(alcSuspendContext),
188 DECL(alcDestroyContext),
189 DECL(alcGetCurrentContext),
190 DECL(alcGetContextsDevice),
191 DECL(alcOpenDevice),
192 DECL(alcCloseDevice),
193 DECL(alcGetError),
194 DECL(alcIsExtensionPresent),
195 DECL(alcGetProcAddress),
196 DECL(alcGetEnumValue),
197 DECL(alcGetString),
198 DECL(alcGetIntegerv),
199 DECL(alcCaptureOpenDevice),
200 DECL(alcCaptureCloseDevice),
201 DECL(alcCaptureStart),
202 DECL(alcCaptureStop),
203 DECL(alcCaptureSamples),
205 DECL(alcSetThreadContext),
206 DECL(alcGetThreadContext),
208 DECL(alcLoopbackOpenDeviceSOFT),
209 DECL(alcIsRenderFormatSupportedSOFT),
210 DECL(alcRenderSamplesSOFT),
212 DECL(alcDevicePauseSOFT),
213 DECL(alcDeviceResumeSOFT),
215 DECL(alcGetStringiSOFT),
216 DECL(alcResetDeviceSOFT),
218 DECL(alcGetInteger64vSOFT),
220 DECL(alEnable),
221 DECL(alDisable),
222 DECL(alIsEnabled),
223 DECL(alGetString),
224 DECL(alGetBooleanv),
225 DECL(alGetIntegerv),
226 DECL(alGetFloatv),
227 DECL(alGetDoublev),
228 DECL(alGetBoolean),
229 DECL(alGetInteger),
230 DECL(alGetFloat),
231 DECL(alGetDouble),
232 DECL(alGetError),
233 DECL(alIsExtensionPresent),
234 DECL(alGetProcAddress),
235 DECL(alGetEnumValue),
236 DECL(alListenerf),
237 DECL(alListener3f),
238 DECL(alListenerfv),
239 DECL(alListeneri),
240 DECL(alListener3i),
241 DECL(alListeneriv),
242 DECL(alGetListenerf),
243 DECL(alGetListener3f),
244 DECL(alGetListenerfv),
245 DECL(alGetListeneri),
246 DECL(alGetListener3i),
247 DECL(alGetListeneriv),
248 DECL(alGenSources),
249 DECL(alDeleteSources),
250 DECL(alIsSource),
251 DECL(alSourcef),
252 DECL(alSource3f),
253 DECL(alSourcefv),
254 DECL(alSourcei),
255 DECL(alSource3i),
256 DECL(alSourceiv),
257 DECL(alGetSourcef),
258 DECL(alGetSource3f),
259 DECL(alGetSourcefv),
260 DECL(alGetSourcei),
261 DECL(alGetSource3i),
262 DECL(alGetSourceiv),
263 DECL(alSourcePlayv),
264 DECL(alSourceStopv),
265 DECL(alSourceRewindv),
266 DECL(alSourcePausev),
267 DECL(alSourcePlay),
268 DECL(alSourceStop),
269 DECL(alSourceRewind),
270 DECL(alSourcePause),
271 DECL(alSourceQueueBuffers),
272 DECL(alSourceUnqueueBuffers),
273 DECL(alGenBuffers),
274 DECL(alDeleteBuffers),
275 DECL(alIsBuffer),
276 DECL(alBufferData),
277 DECL(alBufferf),
278 DECL(alBuffer3f),
279 DECL(alBufferfv),
280 DECL(alBufferi),
281 DECL(alBuffer3i),
282 DECL(alBufferiv),
283 DECL(alGetBufferf),
284 DECL(alGetBuffer3f),
285 DECL(alGetBufferfv),
286 DECL(alGetBufferi),
287 DECL(alGetBuffer3i),
288 DECL(alGetBufferiv),
289 DECL(alDopplerFactor),
290 DECL(alDopplerVelocity),
291 DECL(alSpeedOfSound),
292 DECL(alDistanceModel),
294 DECL(alGenFilters),
295 DECL(alDeleteFilters),
296 DECL(alIsFilter),
297 DECL(alFilteri),
298 DECL(alFilteriv),
299 DECL(alFilterf),
300 DECL(alFilterfv),
301 DECL(alGetFilteri),
302 DECL(alGetFilteriv),
303 DECL(alGetFilterf),
304 DECL(alGetFilterfv),
305 DECL(alGenEffects),
306 DECL(alDeleteEffects),
307 DECL(alIsEffect),
308 DECL(alEffecti),
309 DECL(alEffectiv),
310 DECL(alEffectf),
311 DECL(alEffectfv),
312 DECL(alGetEffecti),
313 DECL(alGetEffectiv),
314 DECL(alGetEffectf),
315 DECL(alGetEffectfv),
316 DECL(alGenAuxiliaryEffectSlots),
317 DECL(alDeleteAuxiliaryEffectSlots),
318 DECL(alIsAuxiliaryEffectSlot),
319 DECL(alAuxiliaryEffectSloti),
320 DECL(alAuxiliaryEffectSlotiv),
321 DECL(alAuxiliaryEffectSlotf),
322 DECL(alAuxiliaryEffectSlotfv),
323 DECL(alGetAuxiliaryEffectSloti),
324 DECL(alGetAuxiliaryEffectSlotiv),
325 DECL(alGetAuxiliaryEffectSlotf),
326 DECL(alGetAuxiliaryEffectSlotfv),
328 DECL(alDeferUpdatesSOFT),
329 DECL(alProcessUpdatesSOFT),
331 DECL(alSourcedSOFT),
332 DECL(alSource3dSOFT),
333 DECL(alSourcedvSOFT),
334 DECL(alGetSourcedSOFT),
335 DECL(alGetSource3dSOFT),
336 DECL(alGetSourcedvSOFT),
337 DECL(alSourcei64SOFT),
338 DECL(alSource3i64SOFT),
339 DECL(alSourcei64vSOFT),
340 DECL(alGetSourcei64SOFT),
341 DECL(alGetSource3i64SOFT),
342 DECL(alGetSourcei64vSOFT),
344 DECL(alGetStringiSOFT),
346 DECL(alBufferStorageSOFT),
347 DECL(alMapBufferSOFT),
348 DECL(alUnmapBufferSOFT),
349 DECL(alFlushMappedBufferSOFT),
351 DECL(alEventControlSOFT),
352 DECL(alEventCallbackSOFT),
353 DECL(alGetPointerSOFT),
354 DECL(alGetPointervSOFT),
356 #undef DECL
358 #define DECL(x) { #x, (x) }
359 constexpr struct {
360 const ALCchar *enumName;
361 ALCenum value;
362 } alcEnumerations[] = {
363 DECL(ALC_INVALID),
364 DECL(ALC_FALSE),
365 DECL(ALC_TRUE),
367 DECL(ALC_MAJOR_VERSION),
368 DECL(ALC_MINOR_VERSION),
369 DECL(ALC_ATTRIBUTES_SIZE),
370 DECL(ALC_ALL_ATTRIBUTES),
371 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
372 DECL(ALC_DEVICE_SPECIFIER),
373 DECL(ALC_ALL_DEVICES_SPECIFIER),
374 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
375 DECL(ALC_EXTENSIONS),
376 DECL(ALC_FREQUENCY),
377 DECL(ALC_REFRESH),
378 DECL(ALC_SYNC),
379 DECL(ALC_MONO_SOURCES),
380 DECL(ALC_STEREO_SOURCES),
381 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
382 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
383 DECL(ALC_CAPTURE_SAMPLES),
384 DECL(ALC_CONNECTED),
386 DECL(ALC_EFX_MAJOR_VERSION),
387 DECL(ALC_EFX_MINOR_VERSION),
388 DECL(ALC_MAX_AUXILIARY_SENDS),
390 DECL(ALC_FORMAT_CHANNELS_SOFT),
391 DECL(ALC_FORMAT_TYPE_SOFT),
393 DECL(ALC_MONO_SOFT),
394 DECL(ALC_STEREO_SOFT),
395 DECL(ALC_QUAD_SOFT),
396 DECL(ALC_5POINT1_SOFT),
397 DECL(ALC_6POINT1_SOFT),
398 DECL(ALC_7POINT1_SOFT),
399 DECL(ALC_BFORMAT3D_SOFT),
401 DECL(ALC_BYTE_SOFT),
402 DECL(ALC_UNSIGNED_BYTE_SOFT),
403 DECL(ALC_SHORT_SOFT),
404 DECL(ALC_UNSIGNED_SHORT_SOFT),
405 DECL(ALC_INT_SOFT),
406 DECL(ALC_UNSIGNED_INT_SOFT),
407 DECL(ALC_FLOAT_SOFT),
409 DECL(ALC_HRTF_SOFT),
410 DECL(ALC_DONT_CARE_SOFT),
411 DECL(ALC_HRTF_STATUS_SOFT),
412 DECL(ALC_HRTF_DISABLED_SOFT),
413 DECL(ALC_HRTF_ENABLED_SOFT),
414 DECL(ALC_HRTF_DENIED_SOFT),
415 DECL(ALC_HRTF_REQUIRED_SOFT),
416 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
417 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
418 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
419 DECL(ALC_HRTF_SPECIFIER_SOFT),
420 DECL(ALC_HRTF_ID_SOFT),
422 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
423 DECL(ALC_AMBISONIC_SCALING_SOFT),
424 DECL(ALC_AMBISONIC_ORDER_SOFT),
425 DECL(ALC_ACN_SOFT),
426 DECL(ALC_FUMA_SOFT),
427 DECL(ALC_N3D_SOFT),
428 DECL(ALC_SN3D_SOFT),
430 DECL(ALC_OUTPUT_LIMITER_SOFT),
432 DECL(ALC_NO_ERROR),
433 DECL(ALC_INVALID_DEVICE),
434 DECL(ALC_INVALID_CONTEXT),
435 DECL(ALC_INVALID_ENUM),
436 DECL(ALC_INVALID_VALUE),
437 DECL(ALC_OUT_OF_MEMORY),
440 DECL(AL_INVALID),
441 DECL(AL_NONE),
442 DECL(AL_FALSE),
443 DECL(AL_TRUE),
445 DECL(AL_SOURCE_RELATIVE),
446 DECL(AL_CONE_INNER_ANGLE),
447 DECL(AL_CONE_OUTER_ANGLE),
448 DECL(AL_PITCH),
449 DECL(AL_POSITION),
450 DECL(AL_DIRECTION),
451 DECL(AL_VELOCITY),
452 DECL(AL_LOOPING),
453 DECL(AL_BUFFER),
454 DECL(AL_GAIN),
455 DECL(AL_MIN_GAIN),
456 DECL(AL_MAX_GAIN),
457 DECL(AL_ORIENTATION),
458 DECL(AL_REFERENCE_DISTANCE),
459 DECL(AL_ROLLOFF_FACTOR),
460 DECL(AL_CONE_OUTER_GAIN),
461 DECL(AL_MAX_DISTANCE),
462 DECL(AL_SEC_OFFSET),
463 DECL(AL_SAMPLE_OFFSET),
464 DECL(AL_BYTE_OFFSET),
465 DECL(AL_SOURCE_TYPE),
466 DECL(AL_STATIC),
467 DECL(AL_STREAMING),
468 DECL(AL_UNDETERMINED),
469 DECL(AL_METERS_PER_UNIT),
470 DECL(AL_LOOP_POINTS_SOFT),
471 DECL(AL_DIRECT_CHANNELS_SOFT),
473 DECL(AL_DIRECT_FILTER),
474 DECL(AL_AUXILIARY_SEND_FILTER),
475 DECL(AL_AIR_ABSORPTION_FACTOR),
476 DECL(AL_ROOM_ROLLOFF_FACTOR),
477 DECL(AL_CONE_OUTER_GAINHF),
478 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
479 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
480 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
482 DECL(AL_SOURCE_STATE),
483 DECL(AL_INITIAL),
484 DECL(AL_PLAYING),
485 DECL(AL_PAUSED),
486 DECL(AL_STOPPED),
488 DECL(AL_BUFFERS_QUEUED),
489 DECL(AL_BUFFERS_PROCESSED),
491 DECL(AL_FORMAT_MONO8),
492 DECL(AL_FORMAT_MONO16),
493 DECL(AL_FORMAT_MONO_FLOAT32),
494 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
495 DECL(AL_FORMAT_STEREO8),
496 DECL(AL_FORMAT_STEREO16),
497 DECL(AL_FORMAT_STEREO_FLOAT32),
498 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
499 DECL(AL_FORMAT_MONO_IMA4),
500 DECL(AL_FORMAT_STEREO_IMA4),
501 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
502 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
503 DECL(AL_FORMAT_QUAD8_LOKI),
504 DECL(AL_FORMAT_QUAD16_LOKI),
505 DECL(AL_FORMAT_QUAD8),
506 DECL(AL_FORMAT_QUAD16),
507 DECL(AL_FORMAT_QUAD32),
508 DECL(AL_FORMAT_51CHN8),
509 DECL(AL_FORMAT_51CHN16),
510 DECL(AL_FORMAT_51CHN32),
511 DECL(AL_FORMAT_61CHN8),
512 DECL(AL_FORMAT_61CHN16),
513 DECL(AL_FORMAT_61CHN32),
514 DECL(AL_FORMAT_71CHN8),
515 DECL(AL_FORMAT_71CHN16),
516 DECL(AL_FORMAT_71CHN32),
517 DECL(AL_FORMAT_REAR8),
518 DECL(AL_FORMAT_REAR16),
519 DECL(AL_FORMAT_REAR32),
520 DECL(AL_FORMAT_MONO_MULAW),
521 DECL(AL_FORMAT_MONO_MULAW_EXT),
522 DECL(AL_FORMAT_STEREO_MULAW),
523 DECL(AL_FORMAT_STEREO_MULAW_EXT),
524 DECL(AL_FORMAT_QUAD_MULAW),
525 DECL(AL_FORMAT_51CHN_MULAW),
526 DECL(AL_FORMAT_61CHN_MULAW),
527 DECL(AL_FORMAT_71CHN_MULAW),
528 DECL(AL_FORMAT_REAR_MULAW),
529 DECL(AL_FORMAT_MONO_ALAW_EXT),
530 DECL(AL_FORMAT_STEREO_ALAW_EXT),
532 DECL(AL_FORMAT_BFORMAT2D_8),
533 DECL(AL_FORMAT_BFORMAT2D_16),
534 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
535 DECL(AL_FORMAT_BFORMAT2D_MULAW),
536 DECL(AL_FORMAT_BFORMAT3D_8),
537 DECL(AL_FORMAT_BFORMAT3D_16),
538 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
539 DECL(AL_FORMAT_BFORMAT3D_MULAW),
541 DECL(AL_FREQUENCY),
542 DECL(AL_BITS),
543 DECL(AL_CHANNELS),
544 DECL(AL_SIZE),
545 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
546 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
548 DECL(AL_SOURCE_RADIUS),
550 DECL(AL_STEREO_ANGLES),
552 DECL(AL_UNUSED),
553 DECL(AL_PENDING),
554 DECL(AL_PROCESSED),
556 DECL(AL_NO_ERROR),
557 DECL(AL_INVALID_NAME),
558 DECL(AL_INVALID_ENUM),
559 DECL(AL_INVALID_VALUE),
560 DECL(AL_INVALID_OPERATION),
561 DECL(AL_OUT_OF_MEMORY),
563 DECL(AL_VENDOR),
564 DECL(AL_VERSION),
565 DECL(AL_RENDERER),
566 DECL(AL_EXTENSIONS),
568 DECL(AL_DOPPLER_FACTOR),
569 DECL(AL_DOPPLER_VELOCITY),
570 DECL(AL_DISTANCE_MODEL),
571 DECL(AL_SPEED_OF_SOUND),
572 DECL(AL_SOURCE_DISTANCE_MODEL),
573 DECL(AL_DEFERRED_UPDATES_SOFT),
574 DECL(AL_GAIN_LIMIT_SOFT),
576 DECL(AL_INVERSE_DISTANCE),
577 DECL(AL_INVERSE_DISTANCE_CLAMPED),
578 DECL(AL_LINEAR_DISTANCE),
579 DECL(AL_LINEAR_DISTANCE_CLAMPED),
580 DECL(AL_EXPONENT_DISTANCE),
581 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
583 DECL(AL_FILTER_TYPE),
584 DECL(AL_FILTER_NULL),
585 DECL(AL_FILTER_LOWPASS),
586 DECL(AL_FILTER_HIGHPASS),
587 DECL(AL_FILTER_BANDPASS),
589 DECL(AL_LOWPASS_GAIN),
590 DECL(AL_LOWPASS_GAINHF),
592 DECL(AL_HIGHPASS_GAIN),
593 DECL(AL_HIGHPASS_GAINLF),
595 DECL(AL_BANDPASS_GAIN),
596 DECL(AL_BANDPASS_GAINHF),
597 DECL(AL_BANDPASS_GAINLF),
599 DECL(AL_EFFECT_TYPE),
600 DECL(AL_EFFECT_NULL),
601 DECL(AL_EFFECT_REVERB),
602 DECL(AL_EFFECT_EAXREVERB),
603 DECL(AL_EFFECT_CHORUS),
604 DECL(AL_EFFECT_DISTORTION),
605 DECL(AL_EFFECT_ECHO),
606 DECL(AL_EFFECT_FLANGER),
607 DECL(AL_EFFECT_PITCH_SHIFTER),
608 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
609 #if 0
610 DECL(AL_EFFECT_VOCAL_MORPHER),
611 #endif
612 DECL(AL_EFFECT_RING_MODULATOR),
613 DECL(AL_EFFECT_AUTOWAH),
614 DECL(AL_EFFECT_COMPRESSOR),
615 DECL(AL_EFFECT_EQUALIZER),
616 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
617 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
619 DECL(AL_EFFECTSLOT_EFFECT),
620 DECL(AL_EFFECTSLOT_GAIN),
621 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
622 DECL(AL_EFFECTSLOT_NULL),
624 DECL(AL_EAXREVERB_DENSITY),
625 DECL(AL_EAXREVERB_DIFFUSION),
626 DECL(AL_EAXREVERB_GAIN),
627 DECL(AL_EAXREVERB_GAINHF),
628 DECL(AL_EAXREVERB_GAINLF),
629 DECL(AL_EAXREVERB_DECAY_TIME),
630 DECL(AL_EAXREVERB_DECAY_HFRATIO),
631 DECL(AL_EAXREVERB_DECAY_LFRATIO),
632 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
633 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
634 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
635 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
636 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
637 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
638 DECL(AL_EAXREVERB_ECHO_TIME),
639 DECL(AL_EAXREVERB_ECHO_DEPTH),
640 DECL(AL_EAXREVERB_MODULATION_TIME),
641 DECL(AL_EAXREVERB_MODULATION_DEPTH),
642 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
643 DECL(AL_EAXREVERB_HFREFERENCE),
644 DECL(AL_EAXREVERB_LFREFERENCE),
645 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
646 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
648 DECL(AL_REVERB_DENSITY),
649 DECL(AL_REVERB_DIFFUSION),
650 DECL(AL_REVERB_GAIN),
651 DECL(AL_REVERB_GAINHF),
652 DECL(AL_REVERB_DECAY_TIME),
653 DECL(AL_REVERB_DECAY_HFRATIO),
654 DECL(AL_REVERB_REFLECTIONS_GAIN),
655 DECL(AL_REVERB_REFLECTIONS_DELAY),
656 DECL(AL_REVERB_LATE_REVERB_GAIN),
657 DECL(AL_REVERB_LATE_REVERB_DELAY),
658 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
659 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
660 DECL(AL_REVERB_DECAY_HFLIMIT),
662 DECL(AL_CHORUS_WAVEFORM),
663 DECL(AL_CHORUS_PHASE),
664 DECL(AL_CHORUS_RATE),
665 DECL(AL_CHORUS_DEPTH),
666 DECL(AL_CHORUS_FEEDBACK),
667 DECL(AL_CHORUS_DELAY),
669 DECL(AL_DISTORTION_EDGE),
670 DECL(AL_DISTORTION_GAIN),
671 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
672 DECL(AL_DISTORTION_EQCENTER),
673 DECL(AL_DISTORTION_EQBANDWIDTH),
675 DECL(AL_ECHO_DELAY),
676 DECL(AL_ECHO_LRDELAY),
677 DECL(AL_ECHO_DAMPING),
678 DECL(AL_ECHO_FEEDBACK),
679 DECL(AL_ECHO_SPREAD),
681 DECL(AL_FLANGER_WAVEFORM),
682 DECL(AL_FLANGER_PHASE),
683 DECL(AL_FLANGER_RATE),
684 DECL(AL_FLANGER_DEPTH),
685 DECL(AL_FLANGER_FEEDBACK),
686 DECL(AL_FLANGER_DELAY),
688 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY),
689 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION),
690 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION),
692 DECL(AL_RING_MODULATOR_FREQUENCY),
693 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
694 DECL(AL_RING_MODULATOR_WAVEFORM),
696 DECL(AL_PITCH_SHIFTER_COARSE_TUNE),
697 DECL(AL_PITCH_SHIFTER_FINE_TUNE),
699 DECL(AL_COMPRESSOR_ONOFF),
701 DECL(AL_EQUALIZER_LOW_GAIN),
702 DECL(AL_EQUALIZER_LOW_CUTOFF),
703 DECL(AL_EQUALIZER_MID1_GAIN),
704 DECL(AL_EQUALIZER_MID1_CENTER),
705 DECL(AL_EQUALIZER_MID1_WIDTH),
706 DECL(AL_EQUALIZER_MID2_GAIN),
707 DECL(AL_EQUALIZER_MID2_CENTER),
708 DECL(AL_EQUALIZER_MID2_WIDTH),
709 DECL(AL_EQUALIZER_HIGH_GAIN),
710 DECL(AL_EQUALIZER_HIGH_CUTOFF),
712 DECL(AL_DEDICATED_GAIN),
714 DECL(AL_AUTOWAH_ATTACK_TIME),
715 DECL(AL_AUTOWAH_RELEASE_TIME),
716 DECL(AL_AUTOWAH_RESONANCE),
717 DECL(AL_AUTOWAH_PEAK_GAIN),
719 DECL(AL_NUM_RESAMPLERS_SOFT),
720 DECL(AL_DEFAULT_RESAMPLER_SOFT),
721 DECL(AL_SOURCE_RESAMPLER_SOFT),
722 DECL(AL_RESAMPLER_NAME_SOFT),
724 DECL(AL_SOURCE_SPATIALIZE_SOFT),
725 DECL(AL_AUTO_SOFT),
727 DECL(AL_MAP_READ_BIT_SOFT),
728 DECL(AL_MAP_WRITE_BIT_SOFT),
729 DECL(AL_MAP_PERSISTENT_BIT_SOFT),
730 DECL(AL_PRESERVE_DATA_BIT_SOFT),
732 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT),
733 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT),
734 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT),
735 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT),
736 DECL(AL_EVENT_TYPE_ERROR_SOFT),
737 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT),
738 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT),
740 #undef DECL
742 constexpr ALCchar alcNoError[] = "No Error";
743 constexpr ALCchar alcErrInvalidDevice[] = "Invalid Device";
744 constexpr ALCchar alcErrInvalidContext[] = "Invalid Context";
745 constexpr ALCchar alcErrInvalidEnum[] = "Invalid Enum";
746 constexpr ALCchar alcErrInvalidValue[] = "Invalid Value";
747 constexpr ALCchar alcErrOutOfMemory[] = "Out of Memory";
750 /************************************************
751 * Global variables
752 ************************************************/
754 /* Enumerated device names */
755 constexpr ALCchar alcDefaultName[] = "OpenAL Soft\0";
757 std::string alcAllDevicesList;
758 std::string alcCaptureDeviceList;
760 /* Default is always the first in the list */
761 std::string alcDefaultAllDevicesSpecifier;
762 std::string alcCaptureDefaultDeviceSpecifier;
764 /* Default context extensions */
765 constexpr ALchar alExtList[] =
766 "AL_EXT_ALAW "
767 "AL_EXT_BFORMAT "
768 "AL_EXT_DOUBLE "
769 "AL_EXT_EXPONENT_DISTANCE "
770 "AL_EXT_FLOAT32 "
771 "AL_EXT_IMA4 "
772 "AL_EXT_LINEAR_DISTANCE "
773 "AL_EXT_MCFORMATS "
774 "AL_EXT_MULAW "
775 "AL_EXT_MULAW_BFORMAT "
776 "AL_EXT_MULAW_MCFORMATS "
777 "AL_EXT_OFFSET "
778 "AL_EXT_source_distance_model "
779 "AL_EXT_SOURCE_RADIUS "
780 "AL_EXT_STEREO_ANGLES "
781 "AL_LOKI_quadriphonic "
782 "AL_SOFT_block_alignment "
783 "AL_SOFT_deferred_updates "
784 "AL_SOFT_direct_channels "
785 "AL_SOFTX_events "
786 "AL_SOFTX_filter_gain_ex "
787 "AL_SOFT_gain_clamp_ex "
788 "AL_SOFT_loop_points "
789 "AL_SOFTX_map_buffer "
790 "AL_SOFT_MSADPCM "
791 "AL_SOFT_source_latency "
792 "AL_SOFT_source_length "
793 "AL_SOFT_source_resampler "
794 "AL_SOFT_source_spatialize";
796 std::atomic<ALCenum> LastNullDeviceError{ALC_NO_ERROR};
798 /* Thread-local current context */
799 std::atomic<void(*)(ALCcontext*)> ThreadCtxProc{nullptr};
800 class ThreadCtx {
801 ALCcontext *ctx{nullptr};
803 public:
804 ~ThreadCtx()
806 auto destruct = ThreadCtxProc.load();
807 if(destruct && ctx)
808 destruct(ctx);
809 ctx = nullptr;
812 ALCcontext *get() const noexcept { return ctx; }
813 void set(ALCcontext *ctx_) noexcept { ctx = ctx_; }
815 thread_local ThreadCtx LocalContext;
816 /* Process-wide current context */
817 std::atomic<ALCcontext*> GlobalContext{nullptr};
819 /* Flag to trap ALC device errors */
820 bool TrapALCError{false};
822 /* One-time configuration init control */
823 std::once_flag alc_config_once{};
825 /* Default effect that applies to sources that don't have an effect on send 0 */
826 ALeffect DefaultEffect;
828 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
829 * updates.
831 bool SuspendDefers{true};
834 /************************************************
835 * ALC information
836 ************************************************/
837 constexpr ALCchar alcNoDeviceExtList[] =
838 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
839 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
840 constexpr ALCchar alcExtensionList[] =
841 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
842 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
843 "ALC_EXT_thread_local_context ALC_SOFT_device_clock ALC_SOFT_HRTF "
844 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
845 constexpr ALCint alcMajorVersion = 1;
846 constexpr ALCint alcMinorVersion = 1;
848 constexpr ALCint alcEFXMajorVersion = 1;
849 constexpr ALCint alcEFXMinorVersion = 0;
852 /************************************************
853 * Device lists
854 ************************************************/
855 std::atomic<ALCdevice*> DeviceList{nullptr};
857 std::recursive_mutex ListLock;
859 } // namespace
861 /* Mixing thread piority level */
862 ALint RTPrioLevel;
864 FILE *LogFile;
865 #ifdef _DEBUG
866 enum LogLevel LogLevel = LogWarning;
867 #else
868 enum LogLevel LogLevel = LogError;
869 #endif
871 /************************************************
872 * Library initialization
873 ************************************************/
874 #if defined(_WIN32)
875 static void alc_init(void);
876 static void alc_deinit(void);
877 static void alc_deinit_safe(void);
879 #ifndef AL_LIBTYPE_STATIC
880 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
882 switch(reason)
884 case DLL_PROCESS_ATTACH:
885 /* Pin the DLL so we won't get unloaded until the process terminates */
886 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
887 (WCHAR*)hModule, &hModule);
888 alc_init();
889 break;
891 case DLL_PROCESS_DETACH:
892 if(!lpReserved)
893 alc_deinit();
894 else
895 alc_deinit_safe();
896 break;
898 return TRUE;
900 #elif defined(_MSC_VER)
901 #pragma section(".CRT$XCU",read)
902 static void alc_constructor(void);
903 static void alc_destructor(void);
904 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
906 static void alc_constructor(void)
908 atexit(alc_destructor);
909 alc_init();
912 static void alc_destructor(void)
914 alc_deinit();
916 #elif defined(HAVE_GCC_DESTRUCTOR)
917 static void alc_init(void) __attribute__((constructor));
918 static void alc_deinit(void) __attribute__((destructor));
919 #else
920 #error "No static initialization available on this platform!"
921 #endif
923 #elif defined(HAVE_GCC_DESTRUCTOR)
925 static void alc_init(void) __attribute__((constructor));
926 static void alc_deinit(void) __attribute__((destructor));
928 #else
929 #error "No global initialization available on this platform!"
930 #endif
932 static void ReleaseThreadCtx(ALCcontext *ctx);
933 static void alc_init(void)
935 LogFile = stderr;
937 const char *str{getenv("__ALSOFT_HALF_ANGLE_CONES")};
938 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
939 ConeScale *= 0.5f;
941 str = getenv("__ALSOFT_REVERSE_Z");
942 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
943 ZScale *= -1.0f;
945 str = getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
946 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
947 OverrideReverbSpeedOfSound = AL_TRUE;
949 ThreadCtxProc = ReleaseThreadCtx;
952 static void alc_initconfig(void)
954 const char *devs, *str;
955 int capfilter;
956 float valf;
957 int i, n;
959 str = getenv("ALSOFT_LOGLEVEL");
960 if(str)
962 long lvl = strtol(str, nullptr, 0);
963 if(lvl >= NoLog && lvl <= LogRef)
964 LogLevel = static_cast<enum LogLevel>(lvl);
967 str = getenv("ALSOFT_LOGFILE");
968 if(str && str[0])
970 #ifdef _WIN32
971 std::wstring wname{utf8_to_wstr(str)};
972 FILE *logfile = _wfopen(wname.c_str(), L"wt");
973 #else
974 FILE *logfile = fopen(str, "wt");
975 #endif
976 if(logfile) LogFile = logfile;
977 else ERR("Failed to open log file '%s'\n", str);
980 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION,
981 ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH);
983 std::string names;
984 if(BackendListSize > 0)
985 names += BackendList[0].name;
986 for(i = 1;i < BackendListSize;i++)
988 names += ", ";
989 names += BackendList[i].name;
991 TRACE("Supported backends: %s\n", names.c_str());
993 ReadALConfig();
995 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
996 if(str && *str)
998 if(strcasecmp(str, "ignore") == 0)
1000 SuspendDefers = false;
1001 TRACE("Selected context suspend behavior, \"ignore\"\n");
1003 else
1004 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
1007 capfilter = 0;
1008 #if defined(HAVE_SSE4_1)
1009 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
1010 #elif defined(HAVE_SSE3)
1011 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
1012 #elif defined(HAVE_SSE2)
1013 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
1014 #elif defined(HAVE_SSE)
1015 capfilter |= CPU_CAP_SSE;
1016 #endif
1017 #ifdef HAVE_NEON
1018 capfilter |= CPU_CAP_NEON;
1019 #endif
1020 if(ConfigValueStr(nullptr, nullptr, "disable-cpu-exts", &str))
1022 if(strcasecmp(str, "all") == 0)
1023 capfilter = 0;
1024 else
1026 size_t len;
1027 const char *next = str;
1029 do {
1030 str = next;
1031 while(isspace(str[0]))
1032 str++;
1033 next = strchr(str, ',');
1035 if(!str[0] || str[0] == ',')
1036 continue;
1038 len = (next ? ((size_t)(next-str)) : strlen(str));
1039 while(len > 0 && isspace(str[len-1]))
1040 len--;
1041 if(len == 3 && strncasecmp(str, "sse", len) == 0)
1042 capfilter &= ~CPU_CAP_SSE;
1043 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
1044 capfilter &= ~CPU_CAP_SSE2;
1045 else if(len == 4 && strncasecmp(str, "sse3", len) == 0)
1046 capfilter &= ~CPU_CAP_SSE3;
1047 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
1048 capfilter &= ~CPU_CAP_SSE4_1;
1049 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
1050 capfilter &= ~CPU_CAP_NEON;
1051 else
1052 WARN("Invalid CPU extension \"%s\"\n", str);
1053 } while(next++);
1056 FillCPUCaps(capfilter);
1058 #ifdef _WIN32
1059 RTPrioLevel = 1;
1060 #else
1061 RTPrioLevel = 0;
1062 #endif
1063 ConfigValueInt(nullptr, nullptr, "rt-prio", &RTPrioLevel);
1065 aluInit();
1066 aluInitMixer();
1068 str = getenv("ALSOFT_TRAP_ERROR");
1069 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
1071 TrapALError = AL_TRUE;
1072 TrapALCError = true;
1074 else
1076 str = getenv("ALSOFT_TRAP_AL_ERROR");
1077 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
1078 TrapALError = AL_TRUE;
1079 TrapALError = GetConfigValueBool(nullptr, nullptr, "trap-al-error", TrapALError);
1081 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1082 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
1083 TrapALCError = true;
1084 TrapALCError = !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", TrapALCError);
1087 if(ConfigValueFloat(nullptr, "reverb", "boost", &valf))
1088 ReverbBoost *= std::pow(10.0f, valf / 20.0f);
1090 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1091 ConfigValueStr(nullptr, nullptr, "drivers", &devs))
1093 int n;
1094 size_t len;
1095 const char *next = devs;
1096 int endlist, delitem;
1098 i = 0;
1099 do {
1100 devs = next;
1101 while(isspace(devs[0]))
1102 devs++;
1103 next = strchr(devs, ',');
1105 delitem = (devs[0] == '-');
1106 if(devs[0] == '-') devs++;
1108 if(!devs[0] || devs[0] == ',')
1110 endlist = 0;
1111 continue;
1113 endlist = 1;
1115 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1116 while(len > 0 && isspace(devs[len-1]))
1117 len--;
1118 #ifdef HAVE_WASAPI
1119 /* HACK: For backwards compatibility, convert backend references of
1120 * mmdevapi to wasapi. This should eventually be removed.
1122 if(len == 8 && strncmp(devs, "mmdevapi", len) == 0)
1124 devs = "wasapi";
1125 len = 6;
1127 #endif
1128 for(n = i;n < BackendListSize;n++)
1130 if(len == strlen(BackendList[n].name) &&
1131 strncmp(BackendList[n].name, devs, len) == 0)
1133 if(delitem)
1135 for(;n+1 < BackendListSize;n++)
1136 BackendList[n] = BackendList[n+1];
1137 BackendListSize--;
1139 else
1141 struct BackendInfo Bkp = BackendList[n];
1142 for(;n > i;n--)
1143 BackendList[n] = BackendList[n-1];
1144 BackendList[n] = Bkp;
1146 i++;
1148 break;
1151 } while(next++);
1153 if(endlist)
1154 BackendListSize = i;
1157 for(n = i = 0;i < BackendListSize && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1159 BackendList[n] = BackendList[i];
1161 BackendFactory &factory = BackendList[n].getFactory();
1162 if(!factory.init())
1164 WARN("Failed to initialize backend \"%s\"\n", BackendList[n].name);
1165 continue;
1168 TRACE("Initialized backend \"%s\"\n", BackendList[n].name);
1169 if(!PlaybackBackend.name && factory.querySupport(ALCbackend_Playback))
1171 PlaybackBackend = BackendList[n];
1172 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1174 if(!CaptureBackend.name && factory.querySupport(ALCbackend_Capture))
1176 CaptureBackend = BackendList[n];
1177 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1179 n++;
1181 BackendListSize = n;
1183 LoopbackBackendFactory::getFactory().init();
1185 if(!PlaybackBackend.name)
1186 WARN("No playback backend available!\n");
1187 if(!CaptureBackend.name)
1188 WARN("No capture backend available!\n");
1190 if(ConfigValueStr(nullptr, nullptr, "excludefx", &str))
1192 size_t len;
1193 const char *next = str;
1195 do {
1196 str = next;
1197 next = strchr(str, ',');
1199 if(!str[0] || next == str)
1200 continue;
1202 len = (next ? ((size_t)(next-str)) : strlen(str));
1203 for(n = 0;n < EFFECTLIST_SIZE;n++)
1205 if(len == strlen(EffectList[n].name) &&
1206 strncmp(EffectList[n].name, str, len) == 0)
1207 DisabledEffects[EffectList[n].type] = AL_TRUE;
1209 } while(next++);
1212 InitEffect(&DefaultEffect);
1213 str = getenv("ALSOFT_DEFAULT_REVERB");
1214 if((str && str[0]) || ConfigValueStr(nullptr, nullptr, "default-reverb", &str))
1215 LoadReverbPreset(str, &DefaultEffect);
1217 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1220 /************************************************
1221 * Library deinitialization
1222 ************************************************/
1223 static void alc_cleanup(void)
1225 alcAllDevicesList.clear();
1226 alcCaptureDeviceList.clear();
1228 alcDefaultAllDevicesSpecifier.clear();
1229 alcCaptureDefaultDeviceSpecifier.clear();
1231 if(ALCdevice *dev{DeviceList.exchange(nullptr)})
1233 ALCuint num = 0;
1234 do {
1235 num++;
1236 dev = dev->next.load(std::memory_order_relaxed);
1237 } while(dev != nullptr);
1238 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1242 static void alc_deinit_safe(void)
1244 alc_cleanup();
1246 FreeHrtfs();
1247 FreeALConfig();
1249 ThreadCtxProc = nullptr;
1251 if(LogFile != stderr)
1252 fclose(LogFile);
1253 LogFile = nullptr;
1256 static void alc_deinit(void)
1258 int i;
1260 alc_cleanup();
1262 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1263 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1265 for(i = 0;i < BackendListSize;i++)
1266 BackendList[i].getFactory().deinit();
1268 LoopbackBackendFactory::getFactory().deinit();
1270 alc_deinit_safe();
1274 /************************************************
1275 * Device enumeration
1276 ************************************************/
1277 static void ProbeDevices(std::string *list, struct BackendInfo *backendinfo, enum DevProbe type)
1279 DO_INITCONFIG();
1281 std::lock_guard<std::recursive_mutex> _{ListLock};
1282 list->clear();
1283 if(backendinfo->getFactory)
1284 backendinfo->getFactory().probe(type, list);
1286 static void ProbeAllDevicesList(void)
1287 { ProbeDevices(&alcAllDevicesList, &PlaybackBackend, ALL_DEVICE_PROBE); }
1288 static void ProbeCaptureDeviceList(void)
1289 { ProbeDevices(&alcCaptureDeviceList, &CaptureBackend, CAPTURE_DEVICE_PROBE); }
1292 /************************************************
1293 * Device format information
1294 ************************************************/
1295 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1297 switch(type)
1299 case DevFmtByte: return "Signed Byte";
1300 case DevFmtUByte: return "Unsigned Byte";
1301 case DevFmtShort: return "Signed Short";
1302 case DevFmtUShort: return "Unsigned Short";
1303 case DevFmtInt: return "Signed Int";
1304 case DevFmtUInt: return "Unsigned Int";
1305 case DevFmtFloat: return "Float";
1307 return "(unknown type)";
1309 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1311 switch(chans)
1313 case DevFmtMono: return "Mono";
1314 case DevFmtStereo: return "Stereo";
1315 case DevFmtQuad: return "Quadraphonic";
1316 case DevFmtX51: return "5.1 Surround";
1317 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1318 case DevFmtX61: return "6.1 Surround";
1319 case DevFmtX71: return "7.1 Surround";
1320 case DevFmtAmbi3D: return "Ambisonic 3D";
1322 return "(unknown channels)";
1325 ALsizei BytesFromDevFmt(enum DevFmtType type)
1327 switch(type)
1329 case DevFmtByte: return sizeof(ALbyte);
1330 case DevFmtUByte: return sizeof(ALubyte);
1331 case DevFmtShort: return sizeof(ALshort);
1332 case DevFmtUShort: return sizeof(ALushort);
1333 case DevFmtInt: return sizeof(ALint);
1334 case DevFmtUInt: return sizeof(ALuint);
1335 case DevFmtFloat: return sizeof(ALfloat);
1337 return 0;
1339 ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans, ALsizei ambiorder)
1341 switch(chans)
1343 case DevFmtMono: return 1;
1344 case DevFmtStereo: return 2;
1345 case DevFmtQuad: return 4;
1346 case DevFmtX51: return 6;
1347 case DevFmtX51Rear: return 6;
1348 case DevFmtX61: return 7;
1349 case DevFmtX71: return 8;
1350 case DevFmtAmbi3D: return (ambiorder >= 3) ? 16 :
1351 (ambiorder == 2) ? 9 :
1352 (ambiorder == 1) ? 4 : 1;
1354 return 0;
1357 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1358 enum DevFmtType *type)
1360 static const struct {
1361 ALenum format;
1362 enum DevFmtChannels channels;
1363 enum DevFmtType type;
1364 } list[] = {
1365 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1366 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1367 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1369 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1370 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1371 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1373 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1374 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1375 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1377 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1378 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1379 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1381 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1382 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1383 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1385 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1386 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1387 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1389 ALuint i;
1391 for(i = 0;i < COUNTOF(list);i++)
1393 if(list[i].format == format)
1395 *chans = list[i].channels;
1396 *type = list[i].type;
1397 return AL_TRUE;
1401 return AL_FALSE;
1404 static ALCboolean IsValidALCType(ALCenum type)
1406 switch(type)
1408 case ALC_BYTE_SOFT:
1409 case ALC_UNSIGNED_BYTE_SOFT:
1410 case ALC_SHORT_SOFT:
1411 case ALC_UNSIGNED_SHORT_SOFT:
1412 case ALC_INT_SOFT:
1413 case ALC_UNSIGNED_INT_SOFT:
1414 case ALC_FLOAT_SOFT:
1415 return ALC_TRUE;
1417 return ALC_FALSE;
1420 static ALCboolean IsValidALCChannels(ALCenum channels)
1422 switch(channels)
1424 case ALC_MONO_SOFT:
1425 case ALC_STEREO_SOFT:
1426 case ALC_QUAD_SOFT:
1427 case ALC_5POINT1_SOFT:
1428 case ALC_6POINT1_SOFT:
1429 case ALC_7POINT1_SOFT:
1430 case ALC_BFORMAT3D_SOFT:
1431 return ALC_TRUE;
1433 return ALC_FALSE;
1436 static ALCboolean IsValidAmbiLayout(ALCenum layout)
1438 switch(layout)
1440 case ALC_ACN_SOFT:
1441 case ALC_FUMA_SOFT:
1442 return ALC_TRUE;
1444 return ALC_FALSE;
1447 static ALCboolean IsValidAmbiScaling(ALCenum scaling)
1449 switch(scaling)
1451 case ALC_N3D_SOFT:
1452 case ALC_SN3D_SOFT:
1453 case ALC_FUMA_SOFT:
1454 return ALC_TRUE;
1456 return ALC_FALSE;
1459 /************************************************
1460 * Miscellaneous ALC helpers
1461 ************************************************/
1463 /* SetDefaultWFXChannelOrder
1465 * Sets the default channel order used by WaveFormatEx.
1467 void SetDefaultWFXChannelOrder(ALCdevice *device)
1469 ALsizei i;
1471 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1472 device->RealOut.ChannelName[i] = InvalidChannel;
1474 switch(device->FmtChans)
1476 case DevFmtMono:
1477 device->RealOut.ChannelName[0] = FrontCenter;
1478 break;
1479 case DevFmtStereo:
1480 device->RealOut.ChannelName[0] = FrontLeft;
1481 device->RealOut.ChannelName[1] = FrontRight;
1482 break;
1483 case DevFmtQuad:
1484 device->RealOut.ChannelName[0] = FrontLeft;
1485 device->RealOut.ChannelName[1] = FrontRight;
1486 device->RealOut.ChannelName[2] = BackLeft;
1487 device->RealOut.ChannelName[3] = BackRight;
1488 break;
1489 case DevFmtX51:
1490 device->RealOut.ChannelName[0] = FrontLeft;
1491 device->RealOut.ChannelName[1] = FrontRight;
1492 device->RealOut.ChannelName[2] = FrontCenter;
1493 device->RealOut.ChannelName[3] = LFE;
1494 device->RealOut.ChannelName[4] = SideLeft;
1495 device->RealOut.ChannelName[5] = SideRight;
1496 break;
1497 case DevFmtX51Rear:
1498 device->RealOut.ChannelName[0] = FrontLeft;
1499 device->RealOut.ChannelName[1] = FrontRight;
1500 device->RealOut.ChannelName[2] = FrontCenter;
1501 device->RealOut.ChannelName[3] = LFE;
1502 device->RealOut.ChannelName[4] = BackLeft;
1503 device->RealOut.ChannelName[5] = BackRight;
1504 break;
1505 case DevFmtX61:
1506 device->RealOut.ChannelName[0] = FrontLeft;
1507 device->RealOut.ChannelName[1] = FrontRight;
1508 device->RealOut.ChannelName[2] = FrontCenter;
1509 device->RealOut.ChannelName[3] = LFE;
1510 device->RealOut.ChannelName[4] = BackCenter;
1511 device->RealOut.ChannelName[5] = SideLeft;
1512 device->RealOut.ChannelName[6] = SideRight;
1513 break;
1514 case DevFmtX71:
1515 device->RealOut.ChannelName[0] = FrontLeft;
1516 device->RealOut.ChannelName[1] = FrontRight;
1517 device->RealOut.ChannelName[2] = FrontCenter;
1518 device->RealOut.ChannelName[3] = LFE;
1519 device->RealOut.ChannelName[4] = BackLeft;
1520 device->RealOut.ChannelName[5] = BackRight;
1521 device->RealOut.ChannelName[6] = SideLeft;
1522 device->RealOut.ChannelName[7] = SideRight;
1523 break;
1524 case DevFmtAmbi3D:
1525 device->RealOut.ChannelName[0] = Aux0;
1526 if(device->mAmbiOrder > 0)
1528 device->RealOut.ChannelName[1] = Aux1;
1529 device->RealOut.ChannelName[2] = Aux2;
1530 device->RealOut.ChannelName[3] = Aux3;
1532 if(device->mAmbiOrder > 1)
1534 device->RealOut.ChannelName[4] = Aux4;
1535 device->RealOut.ChannelName[5] = Aux5;
1536 device->RealOut.ChannelName[6] = Aux6;
1537 device->RealOut.ChannelName[7] = Aux7;
1538 device->RealOut.ChannelName[8] = Aux8;
1540 if(device->mAmbiOrder > 2)
1542 device->RealOut.ChannelName[9] = Aux9;
1543 device->RealOut.ChannelName[10] = Aux10;
1544 device->RealOut.ChannelName[11] = Aux11;
1545 device->RealOut.ChannelName[12] = Aux12;
1546 device->RealOut.ChannelName[13] = Aux13;
1547 device->RealOut.ChannelName[14] = Aux14;
1548 device->RealOut.ChannelName[15] = Aux15;
1550 break;
1554 /* SetDefaultChannelOrder
1556 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1558 void SetDefaultChannelOrder(ALCdevice *device)
1560 ALsizei i;
1562 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1563 device->RealOut.ChannelName[i] = InvalidChannel;
1565 switch(device->FmtChans)
1567 case DevFmtX51Rear:
1568 device->RealOut.ChannelName[0] = FrontLeft;
1569 device->RealOut.ChannelName[1] = FrontRight;
1570 device->RealOut.ChannelName[2] = BackLeft;
1571 device->RealOut.ChannelName[3] = BackRight;
1572 device->RealOut.ChannelName[4] = FrontCenter;
1573 device->RealOut.ChannelName[5] = LFE;
1574 return;
1575 case DevFmtX71:
1576 device->RealOut.ChannelName[0] = FrontLeft;
1577 device->RealOut.ChannelName[1] = FrontRight;
1578 device->RealOut.ChannelName[2] = BackLeft;
1579 device->RealOut.ChannelName[3] = BackRight;
1580 device->RealOut.ChannelName[4] = FrontCenter;
1581 device->RealOut.ChannelName[5] = LFE;
1582 device->RealOut.ChannelName[6] = SideLeft;
1583 device->RealOut.ChannelName[7] = SideRight;
1584 return;
1586 /* Same as WFX order */
1587 case DevFmtMono:
1588 case DevFmtStereo:
1589 case DevFmtQuad:
1590 case DevFmtX51:
1591 case DevFmtX61:
1592 case DevFmtAmbi3D:
1593 SetDefaultWFXChannelOrder(device);
1594 break;
1599 /* ALCcontext_DeferUpdates
1601 * Defers/suspends updates for the given context's listener and sources. This
1602 * does *NOT* stop mixing, but rather prevents certain property changes from
1603 * taking effect.
1605 void ALCcontext_DeferUpdates(ALCcontext *context)
1607 context->DeferUpdates.store(true);
1610 /* ALCcontext_ProcessUpdates
1612 * Resumes update processing after being deferred.
1614 void ALCcontext_ProcessUpdates(ALCcontext *context)
1616 std::lock_guard<almtx_t> _{context->PropLock};
1617 if(context->DeferUpdates.exchange(false))
1619 /* Tell the mixer to stop applying updates, then wait for any active
1620 * updating to finish, before providing updates.
1622 context->HoldUpdates.store(AL_TRUE);
1623 while((context->UpdateCount.load(std::memory_order_acquire)&1) != 0)
1624 althrd_yield();
1626 if(!context->PropsClean.test_and_set(std::memory_order_acq_rel))
1627 UpdateContextProps(context);
1628 if(!context->Listener.PropsClean.test_and_set(std::memory_order_acq_rel))
1629 UpdateListenerProps(context);
1630 UpdateAllEffectSlotProps(context);
1631 UpdateAllSourceProps(context);
1633 /* Now with all updates declared, let the mixer continue applying them
1634 * so they all happen at once.
1636 context->HoldUpdates.store(AL_FALSE);
1641 /* alcSetError
1643 * Stores the latest ALC device error
1645 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1647 WARN("Error generated on device %p, code 0x%04x\n", device, errorCode);
1648 if(TrapALCError)
1650 #ifdef _WIN32
1651 /* DebugBreak() will cause an exception if there is no debugger */
1652 if(IsDebuggerPresent())
1653 DebugBreak();
1654 #elif defined(SIGTRAP)
1655 raise(SIGTRAP);
1656 #endif
1659 if(device)
1660 device->LastError.store(errorCode);
1661 else
1662 LastNullDeviceError.store(errorCode);
1666 static struct Compressor *CreateDeviceLimiter(const ALCdevice *device, const ALfloat threshold)
1668 return CompressorInit(device->RealOut.NumChannels, device->Frequency,
1669 AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, 0.001f, 0.002f,
1670 0.0f, 0.0f, threshold, INFINITY, 0.0f, 0.020f, 0.200f);
1673 /* UpdateClockBase
1675 * Updates the device's base clock time with however many samples have been
1676 * done. This is used so frequency changes on the device don't cause the time
1677 * to jump forward or back. Must not be called while the device is running/
1678 * mixing.
1680 static inline void UpdateClockBase(ALCdevice *device)
1682 IncrementRef(&device->MixCount);
1683 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1684 device->SamplesDone = 0;
1685 IncrementRef(&device->MixCount);
1688 /* UpdateDeviceParams
1690 * Updates device parameters according to the attribute list (caller is
1691 * responsible for holding the list lock).
1693 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1695 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1696 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1697 ALCenum gainLimiter = device->LimiterState;
1698 const ALsizei old_sends = device->NumAuxSends;
1699 ALsizei new_sends = device->NumAuxSends;
1700 enum DevFmtChannels oldChans;
1701 enum DevFmtType oldType;
1702 ALboolean update_failed;
1703 ALCsizei hrtf_id = -1;
1704 ALCcontext *context;
1705 ALCuint oldFreq;
1706 ALCsizei i;
1707 int val;
1709 // Check for attributes
1710 if(device->Type == Loopback)
1712 ALCsizei numMono, numStereo, numSends;
1713 ALCenum alayout = AL_NONE;
1714 ALCenum ascale = AL_NONE;
1715 ALCenum schans = AL_NONE;
1716 ALCenum stype = AL_NONE;
1717 ALCsizei attrIdx = 0;
1718 ALCsizei aorder = 0;
1719 ALCuint freq = 0;
1721 if(!attrList)
1723 WARN("Missing attributes for loopback device\n");
1724 return ALC_INVALID_VALUE;
1727 numMono = device->NumMonoSources;
1728 numStereo = device->NumStereoSources;
1729 numSends = old_sends;
1731 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1732 while(attrList[attrIdx])
1734 switch(attrList[attrIdx])
1736 case ALC_FORMAT_CHANNELS_SOFT:
1737 schans = attrList[attrIdx + 1];
1738 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1739 if(!IsValidALCChannels(schans))
1740 return ALC_INVALID_VALUE;
1741 break;
1743 case ALC_FORMAT_TYPE_SOFT:
1744 stype = attrList[attrIdx + 1];
1745 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1746 if(!IsValidALCType(stype))
1747 return ALC_INVALID_VALUE;
1748 break;
1750 case ALC_FREQUENCY:
1751 freq = attrList[attrIdx + 1];
1752 TRACE_ATTR(ALC_FREQUENCY, freq);
1753 if(freq < MIN_OUTPUT_RATE)
1754 return ALC_INVALID_VALUE;
1755 break;
1757 case ALC_AMBISONIC_LAYOUT_SOFT:
1758 alayout = attrList[attrIdx + 1];
1759 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1760 if(!IsValidAmbiLayout(alayout))
1761 return ALC_INVALID_VALUE;
1762 break;
1764 case ALC_AMBISONIC_SCALING_SOFT:
1765 ascale = attrList[attrIdx + 1];
1766 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1767 if(!IsValidAmbiScaling(ascale))
1768 return ALC_INVALID_VALUE;
1769 break;
1771 case ALC_AMBISONIC_ORDER_SOFT:
1772 aorder = attrList[attrIdx + 1];
1773 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1774 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1775 return ALC_INVALID_VALUE;
1776 break;
1778 case ALC_MONO_SOURCES:
1779 numMono = attrList[attrIdx + 1];
1780 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1781 numMono = maxi(numMono, 0);
1782 break;
1784 case ALC_STEREO_SOURCES:
1785 numStereo = attrList[attrIdx + 1];
1786 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1787 numStereo = maxi(numStereo, 0);
1788 break;
1790 case ALC_MAX_AUXILIARY_SENDS:
1791 numSends = attrList[attrIdx + 1];
1792 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1793 numSends = clampi(numSends, 0, MAX_SENDS);
1794 break;
1796 case ALC_HRTF_SOFT:
1797 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1798 if(attrList[attrIdx + 1] == ALC_FALSE)
1799 hrtf_appreq = Hrtf_Disable;
1800 else if(attrList[attrIdx + 1] == ALC_TRUE)
1801 hrtf_appreq = Hrtf_Enable;
1802 else
1803 hrtf_appreq = Hrtf_Default;
1804 break;
1806 case ALC_HRTF_ID_SOFT:
1807 hrtf_id = attrList[attrIdx + 1];
1808 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1809 break;
1811 case ALC_OUTPUT_LIMITER_SOFT:
1812 gainLimiter = attrList[attrIdx + 1];
1813 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1814 break;
1816 default:
1817 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList[attrIdx],
1818 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1819 break;
1822 attrIdx += 2;
1824 #undef TRACE_ATTR
1826 if(!schans || !stype || !freq)
1828 WARN("Missing format for loopback device\n");
1829 return ALC_INVALID_VALUE;
1831 if(schans == ALC_BFORMAT3D_SOFT && (!alayout || !ascale || !aorder))
1833 WARN("Missing ambisonic info for loopback device\n");
1834 return ALC_INVALID_VALUE;
1837 if((device->Flags&DEVICE_RUNNING))
1838 V0(device->Backend,stop)();
1839 device->Flags &= ~DEVICE_RUNNING;
1841 UpdateClockBase(device);
1843 device->Frequency = freq;
1844 device->FmtChans = static_cast<enum DevFmtChannels>(schans);
1845 device->FmtType = static_cast<enum DevFmtType>(stype);
1846 if(schans == ALC_BFORMAT3D_SOFT)
1848 device->mAmbiOrder = aorder;
1849 device->mAmbiLayout = static_cast<AmbiLayout>(alayout);
1850 device->mAmbiScale = static_cast<AmbiNorm>(ascale);
1853 if(numMono > INT_MAX-numStereo)
1854 numMono = INT_MAX-numStereo;
1855 numMono += numStereo;
1856 if(ConfigValueInt(nullptr, nullptr, "sources", &numMono))
1858 if(numMono <= 0)
1859 numMono = 256;
1861 else
1862 numMono = maxi(numMono, 256);
1863 numStereo = mini(numStereo, numMono);
1864 numMono -= numStereo;
1865 device->SourcesMax = numMono + numStereo;
1867 device->NumMonoSources = numMono;
1868 device->NumStereoSources = numStereo;
1870 if(ConfigValueInt(nullptr, nullptr, "sends", &new_sends))
1871 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1872 else
1873 new_sends = numSends;
1875 else if(attrList && attrList[0])
1877 ALCsizei numMono, numStereo, numSends;
1878 ALCsizei attrIdx = 0;
1879 ALCuint freq;
1881 /* If a context is already running on the device, stop playback so the
1882 * device attributes can be updated. */
1883 if((device->Flags&DEVICE_RUNNING))
1884 V0(device->Backend,stop)();
1885 device->Flags &= ~DEVICE_RUNNING;
1887 UpdateClockBase(device);
1889 freq = device->Frequency;
1890 numMono = device->NumMonoSources;
1891 numStereo = device->NumStereoSources;
1892 numSends = old_sends;
1894 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1895 while(attrList[attrIdx])
1897 switch(attrList[attrIdx])
1899 case ALC_FREQUENCY:
1900 freq = attrList[attrIdx + 1];
1901 TRACE_ATTR(ALC_FREQUENCY, freq);
1902 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1903 break;
1905 case ALC_MONO_SOURCES:
1906 numMono = attrList[attrIdx + 1];
1907 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1908 numMono = maxi(numMono, 0);
1909 break;
1911 case ALC_STEREO_SOURCES:
1912 numStereo = attrList[attrIdx + 1];
1913 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1914 numStereo = maxi(numStereo, 0);
1915 break;
1917 case ALC_MAX_AUXILIARY_SENDS:
1918 numSends = attrList[attrIdx + 1];
1919 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1920 numSends = clampi(numSends, 0, MAX_SENDS);
1921 break;
1923 case ALC_HRTF_SOFT:
1924 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1925 if(attrList[attrIdx + 1] == ALC_FALSE)
1926 hrtf_appreq = Hrtf_Disable;
1927 else if(attrList[attrIdx + 1] == ALC_TRUE)
1928 hrtf_appreq = Hrtf_Enable;
1929 else
1930 hrtf_appreq = Hrtf_Default;
1931 break;
1933 case ALC_HRTF_ID_SOFT:
1934 hrtf_id = attrList[attrIdx + 1];
1935 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1936 break;
1938 case ALC_OUTPUT_LIMITER_SOFT:
1939 gainLimiter = attrList[attrIdx + 1];
1940 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1941 break;
1943 default:
1944 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1945 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1946 break;
1949 attrIdx += 2;
1951 #undef TRACE_ATTR
1953 ConfigValueUInt(device->DeviceName.c_str(), nullptr, "frequency", &freq);
1954 freq = maxu(freq, MIN_OUTPUT_RATE);
1956 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1957 device->Frequency;
1958 /* SSE and Neon do best with the update size being a multiple of 4 */
1959 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1960 device->UpdateSize = (device->UpdateSize+3)&~3;
1962 device->Frequency = freq;
1964 if(numMono > INT_MAX-numStereo)
1965 numMono = INT_MAX-numStereo;
1966 numMono += numStereo;
1967 if(ConfigValueInt(device->DeviceName.c_str(), nullptr, "sources", &numMono))
1969 if(numMono <= 0)
1970 numMono = 256;
1972 else
1973 numMono = maxi(numMono, 256);
1974 numStereo = mini(numStereo, numMono);
1975 numMono -= numStereo;
1976 device->SourcesMax = numMono + numStereo;
1978 device->NumMonoSources = numMono;
1979 device->NumStereoSources = numStereo;
1981 if(ConfigValueInt(device->DeviceName.c_str(), nullptr, "sends", &new_sends))
1982 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1983 else
1984 new_sends = numSends;
1987 if((device->Flags&DEVICE_RUNNING))
1988 return ALC_NO_ERROR;
1990 al_free(device->Uhj_Encoder);
1991 device->Uhj_Encoder = nullptr;
1993 al_free(device->Bs2b);
1994 device->Bs2b = nullptr;
1996 device->ChannelDelay.clear();
1997 device->ChannelDelay.shrink_to_fit();
1999 device->Dry.Buffer = nullptr;
2000 device->Dry.NumChannels = 0;
2001 device->FOAOut.Buffer = nullptr;
2002 device->FOAOut.NumChannels = 0;
2003 device->RealOut.Buffer = nullptr;
2004 device->RealOut.NumChannels = 0;
2005 device->MixBuffer.clear();
2006 device->MixBuffer.shrink_to_fit();
2008 UpdateClockBase(device);
2009 device->FixedLatency = 0;
2011 device->DitherSeed = DITHER_RNG_SEED;
2013 /*************************************************************************
2014 * Update device format request if HRTF is requested
2016 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
2017 if(device->Type != Loopback)
2019 const char *hrtf;
2020 if(ConfigValueStr(device->DeviceName.c_str(), nullptr, "hrtf", &hrtf))
2022 if(strcasecmp(hrtf, "true") == 0)
2023 hrtf_userreq = Hrtf_Enable;
2024 else if(strcasecmp(hrtf, "false") == 0)
2025 hrtf_userreq = Hrtf_Disable;
2026 else if(strcasecmp(hrtf, "auto") != 0)
2027 ERR("Unexpected hrtf value: %s\n", hrtf);
2030 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
2032 struct Hrtf *hrtf = nullptr;
2033 if(device->HrtfList.empty())
2034 device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
2035 if(!device->HrtfList.empty())
2037 if(hrtf_id >= 0 && (size_t)hrtf_id < device->HrtfList.size())
2038 hrtf = GetLoadedHrtf(device->HrtfList[hrtf_id].hrtf);
2039 else
2040 hrtf = GetLoadedHrtf(device->HrtfList.front().hrtf);
2043 if(hrtf)
2045 device->FmtChans = DevFmtStereo;
2046 device->Frequency = hrtf->sampleRate;
2047 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
2048 if(device->HrtfHandle)
2049 Hrtf_DecRef(device->HrtfHandle);
2050 device->HrtfHandle = hrtf;
2052 else
2054 hrtf_userreq = Hrtf_Default;
2055 hrtf_appreq = Hrtf_Disable;
2056 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2061 oldFreq = device->Frequency;
2062 oldChans = device->FmtChans;
2063 oldType = device->FmtType;
2065 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2066 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
2067 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
2068 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
2069 device->UpdateSize, device->NumUpdates
2072 if(V0(device->Backend,reset)() == ALC_FALSE)
2073 return ALC_INVALID_DEVICE;
2075 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
2077 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2078 DevFmtChannelsString(device->FmtChans));
2079 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2081 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2083 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2084 DevFmtTypeString(device->FmtType));
2085 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2087 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2089 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2090 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2093 if((device->UpdateSize&3) != 0)
2095 if((CPUCapFlags&CPU_CAP_SSE))
2096 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2097 if((CPUCapFlags&CPU_CAP_NEON))
2098 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2101 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2102 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2103 device->Frequency, device->UpdateSize, device->NumUpdates
2106 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2107 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device->Dry.NumChannels,
2108 device->FOAOut.NumChannels, device->RealOut.NumChannels);
2110 /* Allocate extra channels for any post-filter output. */
2111 ALsizei num_chans{device->Dry.NumChannels + device->FOAOut.NumChannels +
2112 device->RealOut.NumChannels};
2114 TRACE("Allocating %d channels, " SZFMT " bytes\n", num_chans,
2115 num_chans*sizeof(device->MixBuffer[0]));
2116 device->MixBuffer.resize(num_chans);
2118 device->Dry.Buffer = &reinterpret_cast<ALfloat(&)[BUFFERSIZE]>(device->MixBuffer[0]);
2119 if(device->RealOut.NumChannels != 0)
2120 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels +
2121 device->FOAOut.NumChannels;
2122 else
2124 device->RealOut.Buffer = device->Dry.Buffer;
2125 device->RealOut.NumChannels = device->Dry.NumChannels;
2128 if(device->FOAOut.NumChannels != 0)
2129 device->FOAOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2130 else
2132 device->FOAOut.Buffer = device->Dry.Buffer;
2133 device->FOAOut.NumChannels = device->Dry.NumChannels;
2136 device->NumAuxSends = new_sends;
2137 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2138 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
2139 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
2141 device->DitherDepth = 0.0f;
2142 if(GetConfigValueBool(device->DeviceName.c_str(), nullptr, "dither", 1))
2144 ALint depth = 0;
2145 ConfigValueInt(device->DeviceName.c_str(), nullptr, "dither-depth", &depth);
2146 if(depth <= 0)
2148 switch(device->FmtType)
2150 case DevFmtByte:
2151 case DevFmtUByte:
2152 depth = 8;
2153 break;
2154 case DevFmtShort:
2155 case DevFmtUShort:
2156 depth = 16;
2157 break;
2158 case DevFmtInt:
2159 case DevFmtUInt:
2160 case DevFmtFloat:
2161 break;
2165 if(depth > 0)
2167 depth = clampi(depth, 2, 24);
2168 device->DitherDepth = std::pow(2.0f, (ALfloat)(depth-1));
2171 if(!(device->DitherDepth > 0.0f))
2172 TRACE("Dithering disabled\n");
2173 else
2174 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device->DitherDepth)+0.5f)+1,
2175 device->DitherDepth);
2177 device->LimiterState = gainLimiter;
2178 if(ConfigValueBool(device->DeviceName.c_str(), nullptr, "output-limiter", &val))
2179 gainLimiter = val ? ALC_TRUE : ALC_FALSE;
2181 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2182 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2183 * output (where samples must be clamped), and don't for floating-point
2184 * (which can take unclamped samples).
2186 if(gainLimiter == ALC_DONT_CARE_SOFT)
2188 switch(device->FmtType)
2190 case DevFmtByte:
2191 case DevFmtUByte:
2192 case DevFmtShort:
2193 case DevFmtUShort:
2194 case DevFmtInt:
2195 case DevFmtUInt:
2196 gainLimiter = ALC_TRUE;
2197 break;
2198 case DevFmtFloat:
2199 gainLimiter = ALC_FALSE;
2200 break;
2203 if(gainLimiter != ALC_FALSE)
2205 ALfloat thrshld = 1.0f;
2206 switch(device->FmtType)
2208 case DevFmtByte:
2209 case DevFmtUByte:
2210 thrshld = 127.0f / 128.0f;
2211 break;
2212 case DevFmtShort:
2213 case DevFmtUShort:
2214 thrshld = 32767.0f / 32768.0f;
2215 break;
2216 case DevFmtInt:
2217 case DevFmtUInt:
2218 case DevFmtFloat:
2219 break;
2221 if(device->DitherDepth > 0.0f)
2222 thrshld -= 1.0f / device->DitherDepth;
2224 al_free(device->Limiter);
2225 device->Limiter = CreateDeviceLimiter(device, std::log10(thrshld) * 20.0f);
2226 device->FixedLatency += (ALuint)(GetCompressorLookAhead(device->Limiter) *
2227 DEVICE_CLOCK_RES / device->Frequency);
2229 else
2231 al_free(device->Limiter);
2232 device->Limiter = nullptr;
2234 TRACE("Output limiter %s\n", device->Limiter ? "enabled" : "disabled");
2236 aluSelectPostProcess(device);
2238 TRACE("Fixed device latency: %uns\n", device->FixedLatency);
2240 /* Need to delay returning failure until replacement Send arrays have been
2241 * allocated with the appropriate size.
2243 update_failed = AL_FALSE;
2244 START_MIXER_MODE();
2245 context = device->ContextList.load();
2246 while(context)
2248 struct ALvoiceProps *vprops;
2249 ALsizei pos;
2251 if(context->DefaultSlot)
2253 ALeffectslot *slot = context->DefaultSlot.get();
2254 EffectState *state = slot->Effect.State;
2256 state->mOutBuffer = device->Dry.Buffer;
2257 state->mOutChannels = device->Dry.NumChannels;
2258 if(state->deviceUpdate(device) == AL_FALSE)
2259 update_failed = AL_TRUE;
2260 else
2261 UpdateEffectSlotProps(slot, context);
2264 std::unique_lock<almtx_t> proplock{context->PropLock};
2265 std::unique_lock<almtx_t> slotlock{context->EffectSlotLock};
2266 for(auto &slot : context->EffectSlotList)
2268 EffectState *state = slot->Effect.State;
2270 state->mOutBuffer = device->Dry.Buffer;
2271 state->mOutChannels = device->Dry.NumChannels;
2272 if(state->deviceUpdate(device) == AL_FALSE)
2273 update_failed = AL_TRUE;
2274 else
2275 UpdateEffectSlotProps(slot.get(), context);
2277 slotlock.unlock();
2279 std::unique_lock<almtx_t> srclock{context->SourceLock};
2280 for(auto &sublist : context->SourceList)
2282 uint64_t usemask = ~sublist.FreeMask;
2283 while(usemask)
2285 ALsizei idx = CTZ64(usemask);
2286 ALsource *source = sublist.Sources + idx;
2288 usemask &= ~(U64(1) << idx);
2290 if(old_sends != device->NumAuxSends)
2292 ALsizei s;
2293 for(s = device->NumAuxSends;s < old_sends;s++)
2295 if(source->Send[s].Slot)
2296 DecrementRef(&source->Send[s].Slot->ref);
2297 source->Send[s].Slot = nullptr;
2299 source->Send.resize(device->NumAuxSends);
2300 source->Send.shrink_to_fit();
2301 for(s = old_sends;s < device->NumAuxSends;s++)
2303 source->Send[s].Slot = nullptr;
2304 source->Send[s].Gain = 1.0f;
2305 source->Send[s].GainHF = 1.0f;
2306 source->Send[s].HFReference = LOWPASSFREQREF;
2307 source->Send[s].GainLF = 1.0f;
2308 source->Send[s].LFReference = HIGHPASSFREQREF;
2312 source->PropsClean.clear(std::memory_order_release);
2316 /* Clear any pre-existing voice property structs, in case the number of
2317 * auxiliary sends is changing. Active sources will have updates
2318 * respecified in UpdateAllSourceProps.
2320 vprops = context->FreeVoiceProps.exchange(nullptr, std::memory_order_acq_rel);
2321 while(vprops)
2323 struct ALvoiceProps *next = vprops->next.load(std::memory_order_relaxed);
2324 al_free(vprops);
2325 vprops = next;
2328 AllocateVoices(context, context->MaxVoices, old_sends);
2329 for(pos = 0;pos < context->VoiceCount;pos++)
2331 ALvoice *voice = context->Voices[pos];
2333 al_free(voice->Update.exchange(nullptr, std::memory_order_acq_rel));
2335 if(voice->Source.load(std::memory_order_acquire) == nullptr)
2336 continue;
2338 if(device->AvgSpeakerDist > 0.0f)
2340 /* Reinitialize the NFC filters for new parameters. */
2341 ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
2342 (device->AvgSpeakerDist * device->Frequency);
2343 for(i = 0;i < voice->NumChannels;i++)
2344 NfcFilterCreate(&voice->Direct.Params[i].NFCtrlFilter, 0.0f, w1);
2347 srclock.unlock();
2349 context->PropsClean.test_and_set(std::memory_order_release);
2350 UpdateContextProps(context);
2351 context->Listener.PropsClean.test_and_set(std::memory_order_release);
2352 UpdateListenerProps(context);
2353 UpdateAllSourceProps(context);
2355 context = context->next.load(std::memory_order_relaxed);
2357 END_MIXER_MODE();
2358 if(update_failed)
2359 return ALC_INVALID_DEVICE;
2361 if(!(device->Flags&DEVICE_PAUSED))
2363 if(V0(device->Backend,start)() == ALC_FALSE)
2364 return ALC_INVALID_DEVICE;
2365 device->Flags |= DEVICE_RUNNING;
2368 return ALC_NO_ERROR;
2372 ALCdevice_struct::ALCdevice_struct(DeviceType type)
2373 : Type{type}
2375 almtx_init(&BufferLock, almtx_plain);
2376 almtx_init(&EffectLock, almtx_plain);
2377 almtx_init(&FilterLock, almtx_plain);
2379 almtx_init(&BackendLock, almtx_plain);
2382 /* ALCdevice_struct::~ALCdevice_struct
2384 * Frees the device structure, and destroys any objects the app failed to
2385 * delete. Called once there's no more references on the device.
2387 ALCdevice_struct::~ALCdevice_struct()
2389 TRACE("%p\n", this);
2391 if(Backend)
2392 DELETE_OBJ(Backend);
2393 Backend = nullptr;
2395 almtx_destroy(&BackendLock);
2397 ReleaseALBuffers(this);
2398 std::for_each(BufferList.begin(), BufferList.end(),
2399 [](BufferSubList &entry) noexcept -> void
2400 { al_free(entry.Buffers); }
2402 BufferList.clear();
2403 almtx_destroy(&BufferLock);
2405 ReleaseALEffects(this);
2406 std::for_each(EffectList.begin(), EffectList.end(),
2407 [](EffectSubList &entry) noexcept -> void
2408 { al_free(entry.Effects); }
2410 EffectList.clear();
2411 almtx_destroy(&EffectLock);
2413 ReleaseALFilters(this);
2414 std::for_each(FilterList.begin(), FilterList.end(),
2415 [](FilterSubList &entry) noexcept -> void
2416 { al_free(entry.Filters); }
2418 FilterList.clear();
2419 almtx_destroy(&FilterLock);
2421 HrtfList.clear();
2422 if(HrtfHandle)
2423 Hrtf_DecRef(HrtfHandle);
2424 HrtfHandle = nullptr;
2425 al_free(Hrtf);
2426 Hrtf = nullptr;
2428 al_free(Bs2b);
2429 Bs2b = nullptr;
2431 al_free(Uhj_Encoder);
2432 Uhj_Encoder = nullptr;
2434 bformatdec_free(&AmbiDecoder);
2435 ambiup_free(&AmbiUp);
2437 al_free(Stablizer);
2438 Stablizer = nullptr;
2440 al_free(Limiter);
2441 Limiter = nullptr;
2445 void ALCdevice_IncRef(ALCdevice *device)
2447 auto ref = IncrementRef(&device->ref);
2448 TRACEREF("%p increasing refcount to %u\n", device, ref);
2451 void ALCdevice_DecRef(ALCdevice *device)
2453 auto ref = DecrementRef(&device->ref);
2454 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2455 if(ref == 0) delete device;
2458 /* VerifyDevice
2460 * Checks if the device handle is valid, and increments its ref count if so.
2462 static ALCboolean VerifyDevice(ALCdevice **device)
2464 std::lock_guard<std::recursive_mutex> _{ListLock};
2465 ALCdevice *tmpDevice{DeviceList.load()};
2466 while(tmpDevice)
2468 if(tmpDevice == *device)
2470 ALCdevice_IncRef(tmpDevice);
2471 return ALC_TRUE;
2473 tmpDevice = tmpDevice->next.load(std::memory_order_relaxed);
2476 *device = nullptr;
2477 return ALC_FALSE;
2481 ALCcontext_struct::ALCcontext_struct(ALCdevice *device)
2482 : Device{device}
2486 /* InitContext
2488 * Initializes context fields
2490 static ALvoid InitContext(ALCcontext *Context)
2492 ALlistener &listener = Context->Listener;
2493 struct ALeffectslotArray *auxslots;
2495 //Validate Context
2496 almtx_init(&Context->PropLock, almtx_plain);
2497 almtx_init(&Context->SourceLock, almtx_plain);
2498 almtx_init(&Context->EffectSlotLock, almtx_plain);
2500 if(Context->DefaultSlot)
2502 auxslots = static_cast<ALeffectslotArray*>(al_calloc(DEF_ALIGN,
2503 FAM_SIZE(struct ALeffectslotArray, slot, 1)));
2504 auxslots->count = 1;
2505 auxslots->slot[0] = Context->DefaultSlot.get();
2507 else
2509 auxslots = static_cast<ALeffectslotArray*>(al_calloc(DEF_ALIGN,
2510 sizeof(struct ALeffectslotArray)));
2511 auxslots->count = 0;
2513 ATOMIC_INIT(&Context->ActiveAuxSlots, auxslots);
2515 //Set globals
2516 Context->mDistanceModel = DistanceModel::Default;
2517 Context->SourceDistanceModel = AL_FALSE;
2518 Context->DopplerFactor = 1.0f;
2519 Context->DopplerVelocity = 1.0f;
2520 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2521 Context->MetersPerUnit = AL_DEFAULT_METERS_PER_UNIT;
2522 alsem_init(&Context->EventSem, 0);
2524 Context->ExtensionList = alExtList;
2527 listener.Params.Matrix = aluMatrixf::Identity;
2528 aluVectorSet(&listener.Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2529 listener.Params.Gain = listener.Gain;
2530 listener.Params.MetersPerUnit = Context->MetersPerUnit;
2531 listener.Params.DopplerFactor = Context->DopplerFactor;
2532 listener.Params.SpeedOfSound = Context->SpeedOfSound * Context->DopplerVelocity;
2533 listener.Params.ReverbSpeedOfSound = listener.Params.SpeedOfSound *
2534 listener.Params.MetersPerUnit;
2535 listener.Params.SourceDistanceModel = Context->SourceDistanceModel;
2536 listener.Params.mDistanceModel = Context->mDistanceModel;
2539 Context->AsyncEvents = ll_ringbuffer_create(63, sizeof(AsyncEvent), false);
2540 StartEventThrd(Context);
2544 /* ALCcontext_struct::~ALCcontext_struct()
2546 * Cleans up the context, and destroys any remaining objects the app failed to
2547 * delete. Called once there's no more references on the context.
2549 ALCcontext_struct::~ALCcontext_struct()
2551 TRACE("%p\n", this);
2553 struct ALcontextProps *cprops{Update.load(std::memory_order_relaxed)};
2554 if(cprops)
2556 TRACE("Freed unapplied context update %p\n", cprops);
2557 al_free(cprops);
2559 size_t count{0};
2560 cprops = FreeContextProps.load(std::memory_order_acquire);
2561 while(cprops)
2563 struct ALcontextProps *next{cprops->next.load(std::memory_order_relaxed)};
2564 al_free(cprops);
2565 cprops = next;
2566 ++count;
2568 TRACE("Freed " SZFMT " context property object%s\n", count, (count==1)?"":"s");
2570 al_free(ActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed));
2571 DefaultSlot = nullptr;
2573 ReleaseALSources(this);
2574 std::for_each(SourceList.begin(), SourceList.end(),
2575 [](const SourceSubList &entry) noexcept -> void
2576 { al_free(entry.Sources); }
2578 SourceList.clear();
2579 NumSources = 0;
2580 almtx_destroy(&SourceLock);
2582 count = 0;
2583 struct ALeffectslotProps *eprops{FreeEffectslotProps.load(std::memory_order_acquire)};
2584 while(eprops)
2586 struct ALeffectslotProps *next{eprops->next.load(std::memory_order_relaxed)};
2587 if(eprops->State) eprops->State->DecRef();
2588 al_free(eprops);
2589 eprops = next;
2590 ++count;
2592 TRACE("Freed " SZFMT " AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2594 ReleaseALAuxiliaryEffectSlots(this);
2595 EffectSlotList.clear();
2596 almtx_destroy(&EffectSlotLock);
2598 count = 0;
2599 struct ALvoiceProps *vprops{FreeVoiceProps.load(std::memory_order_acquire)};
2600 while(vprops)
2602 struct ALvoiceProps *next{vprops->next.load(std::memory_order_relaxed)};
2603 al_free(vprops);
2604 vprops = next;
2605 ++count;
2607 TRACE("Freed " SZFMT " voice property object%s\n", count, (count==1)?"":"s");
2609 for(ALsizei i{0};i < VoiceCount;i++)
2610 DeinitVoice(Voices[i]);
2611 al_free(Voices);
2612 Voices = nullptr;
2613 VoiceCount = 0;
2614 MaxVoices = 0;
2616 struct ALlistenerProps *lprops{Listener.Update.load(std::memory_order_relaxed)};
2617 if(lprops)
2619 TRACE("Freed unapplied listener update %p\n", lprops);
2620 al_free(lprops);
2622 count = 0;
2623 lprops = FreeListenerProps.load(std::memory_order_acquire);
2624 while(lprops)
2626 struct ALlistenerProps *next{lprops->next.load(std::memory_order_relaxed)};
2627 al_free(lprops);
2628 lprops = next;
2629 ++count;
2631 TRACE("Freed " SZFMT " listener property object%s\n", count, (count==1)?"":"s");
2633 alsem_destroy(&EventSem);
2635 ll_ringbuffer_free(AsyncEvents);
2636 AsyncEvents = nullptr;
2638 almtx_destroy(&PropLock);
2640 ALCdevice_DecRef(Device);
2643 /* ReleaseContext
2645 * Removes the context reference from the given device and removes it from
2646 * being current on the running thread or globally. Returns true if other
2647 * contexts still exist on the device.
2649 static bool ReleaseContext(ALCcontext *context, ALCdevice *device)
2651 ALCcontext *origctx, *newhead;
2652 bool ret = true;
2654 if(LocalContext.get() == context)
2656 WARN("%p released while current on thread\n", context);
2657 LocalContext.set(nullptr);
2658 ALCcontext_DecRef(context);
2661 origctx = context;
2662 if(GlobalContext.compare_exchange_strong(origctx, nullptr))
2663 ALCcontext_DecRef(context);
2665 V0(device->Backend,lock)();
2666 origctx = context;
2667 newhead = context->next.load(std::memory_order_relaxed);
2668 if(!device->ContextList.compare_exchange_strong(origctx, newhead))
2670 ALCcontext *list;
2671 do {
2672 /* origctx is what the desired context failed to match. Try
2673 * swapping out the next one in the list.
2675 list = origctx;
2676 origctx = context;
2677 } while(!list->next.compare_exchange_strong(origctx, newhead));
2679 else
2680 ret = !!newhead;
2681 V0(device->Backend,unlock)();
2683 /* Make sure the context is finished and no longer processing in the mixer
2684 * before sending the message queue kill event. The backend's lock does
2685 * this, although waiting for a non-odd mix count would work too.
2688 StopEventThrd(context);
2690 ALCcontext_DecRef(context);
2691 return ret;
2694 static void ALCcontext_IncRef(ALCcontext *context)
2696 auto ref = IncrementRef(&context->ref);
2697 TRACEREF("%p increasing refcount to %u\n", context, ref);
2700 void ALCcontext_DecRef(ALCcontext *context)
2702 auto ref = DecrementRef(&context->ref);
2703 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2704 if(ref == 0) delete context;
2707 static void ReleaseThreadCtx(ALCcontext *context)
2709 auto ref = DecrementRef(&context->ref);
2710 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2711 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2714 /* VerifyContext
2716 * Checks if the given context is valid, returning a new reference to it if so.
2718 static ContextRef VerifyContext(ALCcontext *context)
2720 std::lock_guard<std::recursive_mutex> _{ListLock};
2721 ALCdevice *dev{DeviceList.load()};
2722 while(dev)
2724 ALCcontext *ctx = dev->ContextList.load(std::memory_order_acquire);
2725 while(ctx)
2727 if(ctx == context)
2729 ALCcontext_IncRef(ctx);
2730 return ContextRef{ctx};
2732 ctx = ctx->next.load(std::memory_order_relaxed);
2734 dev = dev->next.load(std::memory_order_relaxed);
2737 return ContextRef{};
2741 /* GetContextRef
2743 * Returns the currently active context for this thread, and adds a reference
2744 * without locking it.
2746 ALCcontext *GetContextRef(void)
2748 ALCcontext *context{LocalContext.get()};
2749 if(context)
2750 ALCcontext_IncRef(context);
2751 else
2753 std::lock_guard<std::recursive_mutex> _{ListLock};
2754 context = GlobalContext.load(std::memory_order_acquire);
2755 if(context) ALCcontext_IncRef(context);
2758 return context;
2762 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
2764 ALCdevice *device = context->Device;
2765 ALsizei num_sends = device->NumAuxSends;
2766 struct ALvoiceProps *props;
2767 size_t sizeof_props;
2768 size_t sizeof_voice;
2769 ALvoice **voices;
2770 ALvoice *voice;
2771 ALsizei v = 0;
2772 size_t size;
2774 if(num_voices == context->MaxVoices && num_sends == old_sends)
2775 return;
2777 /* Allocate the voice pointers, voices, and the voices' stored source
2778 * property set (including the dynamically-sized Send[] array) in one
2779 * chunk.
2781 sizeof_voice = RoundUp(FAM_SIZE(ALvoice, Send, num_sends), 16);
2782 sizeof_props = RoundUp(FAM_SIZE(struct ALvoiceProps, Send, num_sends), 16);
2783 size = sizeof(ALvoice*) + sizeof_voice + sizeof_props;
2785 voices = static_cast<ALvoice**>(al_calloc(16, RoundUp(size*num_voices, 16)));
2786 /* The voice and property objects are stored interleaved since they're
2787 * paired together.
2789 voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
2790 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2792 if(context->Voices)
2794 const ALsizei v_count = mini(context->VoiceCount, num_voices);
2795 const ALsizei s_count = mini(old_sends, num_sends);
2797 for(;v < v_count;v++)
2799 ALvoice *old_voice = context->Voices[v];
2800 ALsizei i;
2802 /* Copy the old voice data and source property set to the new
2803 * storage.
2805 memcpy(voice, old_voice, sizeof(*voice));
2806 for(i = 0;i < s_count;i++)
2807 voice->Send[i] = old_voice->Send[i];
2809 memcpy(props, old_voice->Props, sizeof(*props));
2810 for(i = 0;i < s_count;i++)
2811 props->Send[i] = old_voice->Props->Send[i];
2813 /* Set this voice's property set pointer and voice reference. */
2814 voice->Props = props;
2815 voices[v] = voice;
2817 /* Increment pointers to the next storage space. */
2818 voice = (ALvoice*)((char*)props + sizeof_props);
2819 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2821 /* Deinit any left over voices that weren't copied over to the new
2822 * array. NOTE: If this does anything, v equals num_voices and
2823 * num_voices is less than VoiceCount, so the following loop won't do
2824 * anything.
2826 for(;v < context->VoiceCount;v++)
2827 DeinitVoice(context->Voices[v]);
2829 /* Finish setting the voices' property set pointers and references. */
2830 for(;v < num_voices;v++)
2832 ATOMIC_INIT(&voice->Update, static_cast<ALvoiceProps*>(nullptr));
2834 voice->Props = props;
2835 voices[v] = voice;
2837 voice = (ALvoice*)((char*)props + sizeof_props);
2838 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2841 al_free(context->Voices);
2842 context->Voices = voices;
2843 context->MaxVoices = num_voices;
2844 context->VoiceCount = mini(context->VoiceCount, num_voices);
2848 /************************************************
2849 * Standard ALC functions
2850 ************************************************/
2852 /* alcGetError
2854 * Return last ALC generated error code for the given device
2856 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2858 ALCenum errorCode;
2860 if(VerifyDevice(&device))
2862 errorCode = device->LastError.exchange(ALC_NO_ERROR);
2863 ALCdevice_DecRef(device);
2865 else
2866 errorCode = LastNullDeviceError.exchange(ALC_NO_ERROR);
2868 return errorCode;
2872 /* alcSuspendContext
2874 * Suspends updates for the given context
2876 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2878 if(!SuspendDefers)
2879 return;
2881 ContextRef ctx{VerifyContext(context)};
2882 if(!ctx)
2883 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2884 else
2885 ALCcontext_DeferUpdates(ctx.get());
2888 /* alcProcessContext
2890 * Resumes processing updates for the given context
2892 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2894 if(!SuspendDefers)
2895 return;
2897 ContextRef ctx{VerifyContext(context)};
2898 if(!ctx)
2899 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2900 else
2901 ALCcontext_ProcessUpdates(ctx.get());
2905 /* alcGetString
2907 * Returns information about the device, and error strings
2909 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2911 const ALCchar *value = nullptr;
2913 switch(param)
2915 case ALC_NO_ERROR:
2916 value = alcNoError;
2917 break;
2919 case ALC_INVALID_ENUM:
2920 value = alcErrInvalidEnum;
2921 break;
2923 case ALC_INVALID_VALUE:
2924 value = alcErrInvalidValue;
2925 break;
2927 case ALC_INVALID_DEVICE:
2928 value = alcErrInvalidDevice;
2929 break;
2931 case ALC_INVALID_CONTEXT:
2932 value = alcErrInvalidContext;
2933 break;
2935 case ALC_OUT_OF_MEMORY:
2936 value = alcErrOutOfMemory;
2937 break;
2939 case ALC_DEVICE_SPECIFIER:
2940 value = alcDefaultName;
2941 break;
2943 case ALC_ALL_DEVICES_SPECIFIER:
2944 if(VerifyDevice(&Device))
2946 value = Device->DeviceName.c_str();
2947 ALCdevice_DecRef(Device);
2949 else
2951 ProbeAllDevicesList();
2952 value = alcAllDevicesList.c_str();
2954 break;
2956 case ALC_CAPTURE_DEVICE_SPECIFIER:
2957 if(VerifyDevice(&Device))
2959 value = Device->DeviceName.c_str();
2960 ALCdevice_DecRef(Device);
2962 else
2964 ProbeCaptureDeviceList();
2965 value = alcCaptureDeviceList.c_str();
2967 break;
2969 /* Default devices are always first in the list */
2970 case ALC_DEFAULT_DEVICE_SPECIFIER:
2971 value = alcDefaultName;
2972 break;
2974 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2975 if(alcAllDevicesList.empty())
2976 ProbeAllDevicesList();
2978 /* Copy first entry as default. */
2979 alcDefaultAllDevicesSpecifier = alcAllDevicesList.c_str();
2980 value = alcDefaultAllDevicesSpecifier.c_str();
2981 break;
2983 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2984 if(alcCaptureDeviceList.empty())
2985 ProbeCaptureDeviceList();
2987 /* Copy first entry as default. */
2988 alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList.c_str();
2989 value = alcCaptureDefaultDeviceSpecifier.c_str();
2990 break;
2992 case ALC_EXTENSIONS:
2993 if(!VerifyDevice(&Device))
2994 value = alcNoDeviceExtList;
2995 else
2997 value = alcExtensionList;
2998 ALCdevice_DecRef(Device);
3000 break;
3002 case ALC_HRTF_SPECIFIER_SOFT:
3003 if(!VerifyDevice(&Device))
3004 alcSetError(nullptr, ALC_INVALID_DEVICE);
3005 else
3007 { std::lock_guard<almtx_t> _{Device->BackendLock};
3008 value = (Device->HrtfHandle ? Device->HrtfName.c_str() : "");
3010 ALCdevice_DecRef(Device);
3012 break;
3014 default:
3015 VerifyDevice(&Device);
3016 alcSetError(Device, ALC_INVALID_ENUM);
3017 if(Device) ALCdevice_DecRef(Device);
3018 break;
3021 return value;
3025 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
3027 if(device->Type == Capture) return 9;
3028 if(device->Type != Loopback) return 29;
3029 if(device->FmtChans == DevFmtAmbi3D)
3030 return 35;
3031 return 29;
3034 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3036 ALCsizei i;
3038 if(size <= 0 || values == nullptr)
3040 alcSetError(device, ALC_INVALID_VALUE);
3041 return 0;
3044 if(!device)
3046 switch(param)
3048 case ALC_MAJOR_VERSION:
3049 values[0] = alcMajorVersion;
3050 return 1;
3051 case ALC_MINOR_VERSION:
3052 values[0] = alcMinorVersion;
3053 return 1;
3055 case ALC_ATTRIBUTES_SIZE:
3056 case ALC_ALL_ATTRIBUTES:
3057 case ALC_FREQUENCY:
3058 case ALC_REFRESH:
3059 case ALC_SYNC:
3060 case ALC_MONO_SOURCES:
3061 case ALC_STEREO_SOURCES:
3062 case ALC_CAPTURE_SAMPLES:
3063 case ALC_FORMAT_CHANNELS_SOFT:
3064 case ALC_FORMAT_TYPE_SOFT:
3065 case ALC_AMBISONIC_LAYOUT_SOFT:
3066 case ALC_AMBISONIC_SCALING_SOFT:
3067 case ALC_AMBISONIC_ORDER_SOFT:
3068 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3069 alcSetError(nullptr, ALC_INVALID_DEVICE);
3070 return 0;
3072 default:
3073 alcSetError(nullptr, ALC_INVALID_ENUM);
3074 return 0;
3076 return 0;
3079 if(device->Type == Capture)
3081 switch(param)
3083 case ALC_ATTRIBUTES_SIZE:
3084 values[0] = NumAttrsForDevice(device);
3085 return 1;
3087 case ALC_ALL_ATTRIBUTES:
3088 i = 0;
3089 if(size < NumAttrsForDevice(device))
3090 alcSetError(device, ALC_INVALID_VALUE);
3091 else
3093 std::lock_guard<almtx_t> _{device->BackendLock};
3094 values[i++] = ALC_MAJOR_VERSION;
3095 values[i++] = alcMajorVersion;
3096 values[i++] = ALC_MINOR_VERSION;
3097 values[i++] = alcMinorVersion;
3098 values[i++] = ALC_CAPTURE_SAMPLES;
3099 values[i++] = V0(device->Backend,availableSamples)();
3100 values[i++] = ALC_CONNECTED;
3101 values[i++] = device->Connected.load(std::memory_order_relaxed);
3102 values[i++] = 0;
3104 return i;
3106 case ALC_MAJOR_VERSION:
3107 values[0] = alcMajorVersion;
3108 return 1;
3109 case ALC_MINOR_VERSION:
3110 values[0] = alcMinorVersion;
3111 return 1;
3113 case ALC_CAPTURE_SAMPLES:
3114 { std::lock_guard<almtx_t> _{device->BackendLock};
3115 values[0] = V0(device->Backend,availableSamples)();
3117 return 1;
3119 case ALC_CONNECTED:
3120 values[0] = device->Connected.load(std::memory_order_acquire);
3121 return 1;
3123 default:
3124 alcSetError(device, ALC_INVALID_ENUM);
3125 return 0;
3127 return 0;
3130 /* render device */
3131 switch(param)
3133 case ALC_ATTRIBUTES_SIZE:
3134 values[0] = NumAttrsForDevice(device);
3135 return 1;
3137 case ALC_ALL_ATTRIBUTES:
3138 i = 0;
3139 if(size < NumAttrsForDevice(device))
3140 alcSetError(device, ALC_INVALID_VALUE);
3141 else
3143 std::lock_guard<almtx_t> _{device->BackendLock};
3144 values[i++] = ALC_MAJOR_VERSION;
3145 values[i++] = alcMajorVersion;
3146 values[i++] = ALC_MINOR_VERSION;
3147 values[i++] = alcMinorVersion;
3148 values[i++] = ALC_EFX_MAJOR_VERSION;
3149 values[i++] = alcEFXMajorVersion;
3150 values[i++] = ALC_EFX_MINOR_VERSION;
3151 values[i++] = alcEFXMinorVersion;
3153 values[i++] = ALC_FREQUENCY;
3154 values[i++] = device->Frequency;
3155 if(device->Type != Loopback)
3157 values[i++] = ALC_REFRESH;
3158 values[i++] = device->Frequency / device->UpdateSize;
3160 values[i++] = ALC_SYNC;
3161 values[i++] = ALC_FALSE;
3163 else
3165 if(device->FmtChans == DevFmtAmbi3D)
3167 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3168 values[i++] = static_cast<ALCint>(device->mAmbiLayout);
3170 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3171 values[i++] = static_cast<ALCint>(device->mAmbiScale);
3173 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3174 values[i++] = device->mAmbiOrder;
3177 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3178 values[i++] = device->FmtChans;
3180 values[i++] = ALC_FORMAT_TYPE_SOFT;
3181 values[i++] = device->FmtType;
3184 values[i++] = ALC_MONO_SOURCES;
3185 values[i++] = device->NumMonoSources;
3187 values[i++] = ALC_STEREO_SOURCES;
3188 values[i++] = device->NumStereoSources;
3190 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3191 values[i++] = device->NumAuxSends;
3193 values[i++] = ALC_HRTF_SOFT;
3194 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3196 values[i++] = ALC_HRTF_STATUS_SOFT;
3197 values[i++] = device->HrtfStatus;
3199 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3200 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3202 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
3203 values[i++] = MAX_AMBI_ORDER;
3205 values[i++] = 0;
3207 return i;
3209 case ALC_MAJOR_VERSION:
3210 values[0] = alcMajorVersion;
3211 return 1;
3213 case ALC_MINOR_VERSION:
3214 values[0] = alcMinorVersion;
3215 return 1;
3217 case ALC_EFX_MAJOR_VERSION:
3218 values[0] = alcEFXMajorVersion;
3219 return 1;
3221 case ALC_EFX_MINOR_VERSION:
3222 values[0] = alcEFXMinorVersion;
3223 return 1;
3225 case ALC_FREQUENCY:
3226 values[0] = device->Frequency;
3227 return 1;
3229 case ALC_REFRESH:
3230 if(device->Type == Loopback)
3232 alcSetError(device, ALC_INVALID_DEVICE);
3233 return 0;
3235 { std::lock_guard<almtx_t> _{device->BackendLock};
3236 values[0] = device->Frequency / device->UpdateSize;
3238 return 1;
3240 case ALC_SYNC:
3241 if(device->Type == Loopback)
3243 alcSetError(device, ALC_INVALID_DEVICE);
3244 return 0;
3246 values[0] = ALC_FALSE;
3247 return 1;
3249 case ALC_FORMAT_CHANNELS_SOFT:
3250 if(device->Type != Loopback)
3252 alcSetError(device, ALC_INVALID_DEVICE);
3253 return 0;
3255 values[0] = device->FmtChans;
3256 return 1;
3258 case ALC_FORMAT_TYPE_SOFT:
3259 if(device->Type != Loopback)
3261 alcSetError(device, ALC_INVALID_DEVICE);
3262 return 0;
3264 values[0] = device->FmtType;
3265 return 1;
3267 case ALC_AMBISONIC_LAYOUT_SOFT:
3268 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3270 alcSetError(device, ALC_INVALID_DEVICE);
3271 return 0;
3273 values[0] = static_cast<ALCint>(device->mAmbiLayout);
3274 return 1;
3276 case ALC_AMBISONIC_SCALING_SOFT:
3277 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3279 alcSetError(device, ALC_INVALID_DEVICE);
3280 return 0;
3282 values[0] = static_cast<ALCint>(device->mAmbiScale);
3283 return 1;
3285 case ALC_AMBISONIC_ORDER_SOFT:
3286 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3288 alcSetError(device, ALC_INVALID_DEVICE);
3289 return 0;
3291 values[0] = device->mAmbiOrder;
3292 return 1;
3294 case ALC_MONO_SOURCES:
3295 values[0] = device->NumMonoSources;
3296 return 1;
3298 case ALC_STEREO_SOURCES:
3299 values[0] = device->NumStereoSources;
3300 return 1;
3302 case ALC_MAX_AUXILIARY_SENDS:
3303 values[0] = device->NumAuxSends;
3304 return 1;
3306 case ALC_CONNECTED:
3307 values[0] = device->Connected.load(std::memory_order_acquire);
3308 return 1;
3310 case ALC_HRTF_SOFT:
3311 values[0] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3312 return 1;
3314 case ALC_HRTF_STATUS_SOFT:
3315 values[0] = device->HrtfStatus;
3316 return 1;
3318 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3319 { std::lock_guard<almtx_t> _{device->BackendLock};
3320 device->HrtfList.clear();
3321 device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
3322 values[0] = (ALCint)device->HrtfList.size();
3324 return 1;
3326 case ALC_OUTPUT_LIMITER_SOFT:
3327 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3328 return 1;
3330 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3331 values[0] = MAX_AMBI_ORDER;
3332 return 1;
3334 default:
3335 alcSetError(device, ALC_INVALID_ENUM);
3336 return 0;
3338 return 0;
3341 /* alcGetIntegerv
3343 * Returns information about the device and the version of OpenAL
3345 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3347 VerifyDevice(&device);
3348 if(size <= 0 || values == nullptr)
3349 alcSetError(device, ALC_INVALID_VALUE);
3350 else
3351 GetIntegerv(device, param, size, values);
3352 if(device) ALCdevice_DecRef(device);
3355 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3357 VerifyDevice(&device);
3358 if(size <= 0 || values == nullptr)
3359 alcSetError(device, ALC_INVALID_VALUE);
3360 else if(!device || device->Type == Capture)
3362 std::vector<ALCint> ivals(size);
3363 size = GetIntegerv(device, pname, size, ivals.data());
3364 std::copy(ivals.begin(), ivals.begin()+size, values);
3366 else /* render device */
3368 switch(pname)
3370 case ALC_ATTRIBUTES_SIZE:
3371 *values = NumAttrsForDevice(device)+4;
3372 break;
3374 case ALC_ALL_ATTRIBUTES:
3375 if(size < NumAttrsForDevice(device)+4)
3376 alcSetError(device, ALC_INVALID_VALUE);
3377 else
3379 ALsizei i{0};
3380 std::lock_guard<almtx_t> _{device->BackendLock};
3381 values[i++] = ALC_FREQUENCY;
3382 values[i++] = device->Frequency;
3384 if(device->Type != Loopback)
3386 values[i++] = ALC_REFRESH;
3387 values[i++] = device->Frequency / device->UpdateSize;
3389 values[i++] = ALC_SYNC;
3390 values[i++] = ALC_FALSE;
3392 else
3394 if(device->FmtChans == DevFmtAmbi3D)
3396 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3397 values[i++] = static_cast<ALCint64SOFT>(device->mAmbiLayout);
3399 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3400 values[i++] = static_cast<ALCint64SOFT>(device->mAmbiScale);
3402 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3403 values[i++] = device->mAmbiOrder;
3406 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3407 values[i++] = device->FmtChans;
3409 values[i++] = ALC_FORMAT_TYPE_SOFT;
3410 values[i++] = device->FmtType;
3413 values[i++] = ALC_MONO_SOURCES;
3414 values[i++] = device->NumMonoSources;
3416 values[i++] = ALC_STEREO_SOURCES;
3417 values[i++] = device->NumStereoSources;
3419 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3420 values[i++] = device->NumAuxSends;
3422 values[i++] = ALC_HRTF_SOFT;
3423 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3425 values[i++] = ALC_HRTF_STATUS_SOFT;
3426 values[i++] = device->HrtfStatus;
3428 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3429 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3431 ClockLatency clock{GetClockLatency(device)};
3432 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3433 values[i++] = clock.ClockTime;
3435 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3436 values[i++] = clock.Latency;
3438 values[i++] = 0;
3440 break;
3442 case ALC_DEVICE_CLOCK_SOFT:
3443 { std::lock_guard<almtx_t> _{device->BackendLock};
3444 ALuint64 basecount;
3445 ALuint samplecount;
3446 ALuint refcount;
3447 do {
3448 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3449 althrd_yield();
3450 basecount = device->ClockBase;
3451 samplecount = device->SamplesDone;
3452 } while(refcount != ReadRef(&device->MixCount));
3453 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3455 break;
3457 case ALC_DEVICE_LATENCY_SOFT:
3458 { std::lock_guard<almtx_t> _{device->BackendLock};
3459 ClockLatency clock{GetClockLatency(device)};
3460 *values = clock.Latency;
3462 break;
3464 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3465 if(size < 2)
3466 alcSetError(device, ALC_INVALID_VALUE);
3467 else
3469 std::lock_guard<almtx_t> _{device->BackendLock};
3470 ClockLatency clock{GetClockLatency(device)};
3471 values[0] = clock.ClockTime;
3472 values[1] = clock.Latency;
3474 break;
3476 default:
3477 std::vector<ALCint> ivals(size);
3478 size = GetIntegerv(device, pname, size, ivals.data());
3479 std::copy(ivals.begin(), ivals.begin()+size, values);
3480 break;
3483 if(device)
3484 ALCdevice_DecRef(device);
3488 /* alcIsExtensionPresent
3490 * Determines if there is support for a particular extension
3492 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3494 ALCboolean bResult = ALC_FALSE;
3496 VerifyDevice(&device);
3498 if(!extName)
3499 alcSetError(device, ALC_INVALID_VALUE);
3500 else
3502 size_t len = strlen(extName);
3503 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3504 while(ptr && *ptr)
3506 if(strncasecmp(ptr, extName, len) == 0 &&
3507 (ptr[len] == '\0' || isspace(ptr[len])))
3509 bResult = ALC_TRUE;
3510 break;
3512 if((ptr=strchr(ptr, ' ')) != nullptr)
3514 do {
3515 ++ptr;
3516 } while(isspace(*ptr));
3520 if(device)
3521 ALCdevice_DecRef(device);
3522 return bResult;
3526 /* alcGetProcAddress
3528 * Retrieves the function address for a particular extension function
3530 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3532 ALCvoid *ptr = nullptr;
3534 if(!funcName)
3536 VerifyDevice(&device);
3537 alcSetError(device, ALC_INVALID_VALUE);
3538 if(device) ALCdevice_DecRef(device);
3540 else
3542 size_t i = 0;
3543 for(i = 0;i < COUNTOF(alcFunctions);i++)
3545 if(strcmp(alcFunctions[i].funcName, funcName) == 0)
3547 ptr = alcFunctions[i].address;
3548 break;
3553 return ptr;
3557 /* alcGetEnumValue
3559 * Get the value for a particular ALC enumeration name
3561 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3563 ALCenum val = 0;
3565 if(!enumName)
3567 VerifyDevice(&device);
3568 alcSetError(device, ALC_INVALID_VALUE);
3569 if(device) ALCdevice_DecRef(device);
3571 else
3573 size_t i = 0;
3574 for(i = 0;i < COUNTOF(alcEnumerations);i++)
3576 if(strcmp(alcEnumerations[i].enumName, enumName) == 0)
3578 val = alcEnumerations[i].value;
3579 break;
3584 return val;
3588 /* alcCreateContext
3590 * Create and attach a context to the given device.
3592 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3594 ALCcontext *ALContext;
3595 ALfloat valf;
3596 ALCenum err;
3598 /* Explicitly hold the list lock while taking the BackendLock in case the
3599 * device is asynchronously destropyed, to ensure this new context is
3600 * properly cleaned up after being made.
3602 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3603 if(!VerifyDevice(&device) || device->Type == Capture ||
3604 !device->Connected.load(std::memory_order_relaxed))
3606 listlock.unlock();
3607 alcSetError(device, ALC_INVALID_DEVICE);
3608 if(device) ALCdevice_DecRef(device);
3609 return nullptr;
3611 std::unique_lock<almtx_t> backlock{device->BackendLock};
3612 listlock.unlock();
3614 device->LastError.store(ALC_NO_ERROR);
3616 ALContext = new ALCcontext{device};
3617 ALCdevice_IncRef(ALContext->Device);
3619 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3621 backlock.unlock();
3623 delete ALContext;
3624 ALContext = nullptr;
3626 alcSetError(device, err);
3627 if(err == ALC_INVALID_DEVICE)
3629 V0(device->Backend,lock)();
3630 aluHandleDisconnect(device, "Device update failure");
3631 V0(device->Backend,unlock)();
3633 ALCdevice_DecRef(device);
3634 return nullptr;
3636 AllocateVoices(ALContext, 256, device->NumAuxSends);
3638 if(DefaultEffect.type != AL_EFFECT_NULL && device->Type == Playback)
3640 ALContext->DefaultSlot.reset(new ALeffectslot{});
3641 if(InitEffectSlot(ALContext->DefaultSlot.get()) == AL_NO_ERROR)
3642 aluInitEffectPanning(ALContext->DefaultSlot.get());
3643 else
3645 ALContext->DefaultSlot = nullptr;
3646 ERR("Failed to initialize the default effect slot\n");
3650 InitContext(ALContext);
3652 if(ConfigValueFloat(device->DeviceName.c_str(), nullptr, "volume-adjust", &valf))
3654 if(!std::isfinite(valf))
3655 ERR("volume-adjust must be finite: %f\n", valf);
3656 else
3658 ALfloat db = clampf(valf, -24.0f, 24.0f);
3659 if(db != valf)
3660 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3661 ALContext->GainBoost = std::pow(10.0f, db/20.0f);
3662 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3665 UpdateListenerProps(ALContext);
3668 ALCcontext *head = device->ContextList.load();
3669 do {
3670 ALContext->next.store(head, std::memory_order_relaxed);
3671 } while(!device->ContextList.compare_exchange_weak(head, ALContext));
3673 backlock.unlock();
3675 if(ALContext->DefaultSlot)
3677 if(InitializeEffect(ALContext, ALContext->DefaultSlot.get(), &DefaultEffect) == AL_NO_ERROR)
3678 UpdateEffectSlotProps(ALContext->DefaultSlot.get(), ALContext);
3679 else
3680 ERR("Failed to initialize the default effect\n");
3683 ALCdevice_DecRef(device);
3685 TRACE("Created context %p\n", ALContext);
3686 return ALContext;
3689 /* alcDestroyContext
3691 * Remove a context from its device
3693 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3695 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3696 ContextRef ctx{VerifyContext(context)};
3697 if(!ctx)
3699 listlock.unlock();
3700 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3701 return;
3704 ALCdevice* Device{ctx->Device};
3705 if(Device)
3707 std::lock_guard<almtx_t> _{Device->BackendLock};
3708 if(!ReleaseContext(ctx.get(), Device))
3710 V0(Device->Backend,stop)();
3711 Device->Flags &= ~DEVICE_RUNNING;
3714 listlock.unlock();
3718 /* alcGetCurrentContext
3720 * Returns the currently active context on the calling thread
3722 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3724 ALCcontext *Context{LocalContext.get()};
3725 if(!Context) Context = GlobalContext.load();
3726 return Context;
3729 /* alcGetThreadContext
3731 * Returns the currently active thread-local context
3733 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3735 return LocalContext.get();
3739 /* alcMakeContextCurrent
3741 * Makes the given context the active process-wide context, and removes the
3742 * thread-local context for the calling thread.
3744 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3746 /* context must be valid or nullptr */
3747 ContextRef ctx;
3748 if(context)
3750 ctx = VerifyContext(context);
3751 if(!ctx)
3753 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3754 return ALC_FALSE;
3757 /* Release this reference (if any) to store it in the GlobalContext
3758 * pointer. Take ownership of the reference (if any) that was previously
3759 * stored there.
3761 ctx = ContextRef{GlobalContext.exchange(ctx.release())};
3763 /* Reset (decrement) the previous global reference by replacing it with the
3764 * thread-local context. Take ownership of the thread-local context
3765 * reference (if any), clearing the storage to null.
3767 ctx = ContextRef{LocalContext.get()};
3768 if(ctx) LocalContext.set(nullptr);
3769 /* Reset (decrement) the previous thread-local reference. */
3771 return ALC_TRUE;
3774 /* alcSetThreadContext
3776 * Makes the given context the active context for the current thread
3778 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3780 /* context must be valid or nullptr */
3781 ContextRef ctx;
3782 if(context)
3784 ctx = VerifyContext(context);
3785 if(!ctx)
3787 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3788 return ALC_FALSE;
3791 /* context's reference count is already incremented */
3792 ContextRef old{LocalContext.get()};
3793 LocalContext.set(ctx.release());
3795 return ALC_TRUE;
3799 /* alcGetContextsDevice
3801 * Returns the device that a particular context is attached to
3803 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3805 ContextRef ctx{VerifyContext(Context)};
3806 if(!ctx)
3808 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3809 return nullptr;
3811 return ctx->Device;
3815 /* alcOpenDevice
3817 * Opens the named device.
3819 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3821 DO_INITCONFIG();
3823 if(!PlaybackBackend.name)
3825 alcSetError(nullptr, ALC_INVALID_VALUE);
3826 return nullptr;
3829 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
3830 #ifdef _WIN32
3831 /* Some old Windows apps hardcode these expecting OpenAL to use a
3832 * specific audio API, even when they're not enumerated. Creative's
3833 * router effectively ignores them too.
3835 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
3836 || strcasecmp(deviceName, "MMSYSTEM") == 0
3837 #endif
3839 deviceName = nullptr;
3841 auto device = new ALCdevice{Playback};
3843 //Set output format
3844 device->FmtChans = DevFmtChannelsDefault;
3845 device->FmtType = DevFmtTypeDefault;
3846 device->Frequency = DEFAULT_OUTPUT_RATE;
3847 device->LimiterState = ALC_TRUE;
3848 device->NumUpdates = 3;
3849 device->UpdateSize = 1024;
3851 device->SourcesMax = 256;
3852 device->AuxiliaryEffectSlotMax = 64;
3853 device->NumAuxSends = DEFAULT_SENDS;
3855 const ALCchar *fmt{};
3856 if(ConfigValueStr(deviceName, nullptr, "channels", &fmt))
3858 static constexpr struct ChannelMap {
3859 const char name[16];
3860 enum DevFmtChannels chans;
3861 ALsizei order;
3862 } chanlist[] = {
3863 { "mono", DevFmtMono, 0 },
3864 { "stereo", DevFmtStereo, 0 },
3865 { "quad", DevFmtQuad, 0 },
3866 { "surround51", DevFmtX51, 0 },
3867 { "surround61", DevFmtX61, 0 },
3868 { "surround71", DevFmtX71, 0 },
3869 { "surround51rear", DevFmtX51Rear, 0 },
3870 { "ambi1", DevFmtAmbi3D, 1 },
3871 { "ambi2", DevFmtAmbi3D, 2 },
3872 { "ambi3", DevFmtAmbi3D, 3 },
3875 auto iter = std::find_if(std::begin(chanlist), std::end(chanlist),
3876 [fmt](const ChannelMap &entry) -> bool
3877 { return strcasecmp(entry.name, fmt) == 0; }
3879 if(iter == std::end(chanlist))
3880 ERR("Unsupported channels: %s\n", fmt);
3881 else
3883 device->FmtChans = iter->chans;
3884 device->mAmbiOrder = iter->order;
3885 device->Flags |= DEVICE_CHANNELS_REQUEST;
3888 if(ConfigValueStr(deviceName, nullptr, "sample-type", &fmt))
3890 static constexpr struct TypeMap {
3891 const char name[16];
3892 enum DevFmtType type;
3893 } typelist[] = {
3894 { "int8", DevFmtByte },
3895 { "uint8", DevFmtUByte },
3896 { "int16", DevFmtShort },
3897 { "uint16", DevFmtUShort },
3898 { "int32", DevFmtInt },
3899 { "uint32", DevFmtUInt },
3900 { "float32", DevFmtFloat },
3903 auto iter = std::find_if(std::begin(typelist), std::end(typelist),
3904 [fmt](const TypeMap &entry) -> bool
3905 { return strcasecmp(entry.name, fmt) == 0; }
3907 if(iter == std::end(typelist))
3908 ERR("Unsupported sample-type: %s\n", fmt);
3909 else
3911 device->FmtType = iter->type;
3912 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3916 if(ConfigValueUInt(deviceName, nullptr, "frequency", &device->Frequency))
3918 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3919 if(device->Frequency < MIN_OUTPUT_RATE)
3920 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3921 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3924 ConfigValueUInt(deviceName, nullptr, "periods", &device->NumUpdates);
3925 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3927 ConfigValueUInt(deviceName, nullptr, "period_size", &device->UpdateSize);
3928 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3929 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
3930 device->UpdateSize = (device->UpdateSize+3)&~3;
3932 ConfigValueUInt(deviceName, nullptr, "sources", &device->SourcesMax);
3933 if(device->SourcesMax == 0) device->SourcesMax = 256;
3935 ConfigValueUInt(deviceName, nullptr, "slots", &device->AuxiliaryEffectSlotMax);
3936 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
3937 else device->AuxiliaryEffectSlotMax = minu(device->AuxiliaryEffectSlotMax, INT_MAX);
3939 if(ConfigValueInt(deviceName, nullptr, "sends", &device->NumAuxSends))
3940 device->NumAuxSends = clampi(
3941 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
3944 device->NumStereoSources = 1;
3945 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3947 device->Backend = PlaybackBackend.getFactory().createBackend(device, ALCbackend_Playback);
3948 if(!device->Backend)
3950 delete device;
3951 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
3952 return nullptr;
3955 // Find a playback device to open
3956 ALCenum err{V(device->Backend,open)(deviceName)};
3957 if(err != ALC_NO_ERROR)
3959 delete device;
3960 alcSetError(nullptr, err);
3961 return nullptr;
3964 if(ConfigValueStr(device->DeviceName.c_str(), nullptr, "ambi-format", &fmt))
3966 if(strcasecmp(fmt, "fuma") == 0)
3968 device->mAmbiLayout = AmbiLayout::FuMa;
3969 device->mAmbiScale = AmbiNorm::FuMa;
3971 else if(strcasecmp(fmt, "acn+sn3d") == 0)
3973 device->mAmbiLayout = AmbiLayout::ACN;
3974 device->mAmbiScale = AmbiNorm::SN3D;
3976 else if(strcasecmp(fmt, "acn+n3d") == 0)
3978 device->mAmbiLayout = AmbiLayout::ACN;
3979 device->mAmbiScale = AmbiNorm::N3D;
3981 else
3982 ERR("Unsupported ambi-format: %s\n", fmt);
3986 ALCdevice *head{DeviceList.load()};
3987 do {
3988 device->next.store(head, std::memory_order_relaxed);
3989 } while(!DeviceList.compare_exchange_weak(head, device));
3992 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName.c_str());
3993 return device;
3996 /* alcCloseDevice
3998 * Closes the given device.
4000 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
4002 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4003 ALCdevice *iter{DeviceList.load()};
4004 do {
4005 if(iter == device)
4006 break;
4007 iter = iter->next.load(std::memory_order_relaxed);
4008 } while(iter != nullptr);
4009 if(!iter || iter->Type == Capture)
4011 alcSetError(iter, ALC_INVALID_DEVICE);
4012 return ALC_FALSE;
4014 std::unique_lock<almtx_t> backlock{device->BackendLock};
4016 ALCdevice *origdev{device};
4017 ALCdevice *nextdev{device->next.load(std::memory_order_relaxed)};
4018 if(!DeviceList.compare_exchange_strong(origdev, nextdev))
4020 ALCdevice *list;
4021 do {
4022 list = origdev;
4023 origdev = device;
4024 } while(!list->next.compare_exchange_strong(origdev, nextdev));
4026 listlock.unlock();
4028 ALCcontext *ctx{device->ContextList.load()};
4029 while(ctx != nullptr)
4031 ALCcontext *next = ctx->next.load(std::memory_order_relaxed);
4032 WARN("Releasing context %p\n", ctx);
4033 ReleaseContext(ctx, device);
4034 ctx = next;
4036 if((device->Flags&DEVICE_RUNNING))
4037 V0(device->Backend,stop)();
4038 device->Flags &= ~DEVICE_RUNNING;
4039 backlock.unlock();
4041 ALCdevice_DecRef(device);
4043 return ALC_TRUE;
4047 /************************************************
4048 * ALC capture functions
4049 ************************************************/
4050 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
4052 DO_INITCONFIG();
4054 if(!CaptureBackend.name)
4056 alcSetError(nullptr, ALC_INVALID_VALUE);
4057 return nullptr;
4060 if(samples <= 0)
4062 alcSetError(nullptr, ALC_INVALID_VALUE);
4063 return nullptr;
4066 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
4067 deviceName = nullptr;
4069 auto device = new ALCdevice{Capture};
4071 device->Frequency = frequency;
4072 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4074 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
4076 delete device;
4077 alcSetError(nullptr, ALC_INVALID_ENUM);
4078 return nullptr;
4080 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
4082 device->UpdateSize = samples;
4083 device->NumUpdates = 1;
4085 device->Backend = CaptureBackend.getFactory().createBackend(device, ALCbackend_Capture);
4086 if(!device->Backend)
4088 delete device;
4089 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
4090 return nullptr;
4093 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4094 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
4095 device->Frequency, device->UpdateSize, device->NumUpdates
4097 ALCenum err{V(device->Backend,open)(deviceName)};
4098 if(err != ALC_NO_ERROR)
4100 delete device;
4101 alcSetError(nullptr, err);
4102 return nullptr;
4106 ALCdevice *head{DeviceList.load()};
4107 do {
4108 device->next.store(head, std::memory_order_relaxed);
4109 } while(!DeviceList.compare_exchange_weak(head, device));
4112 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName.c_str());
4113 return device;
4116 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
4118 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4120 ALCdevice *iter{DeviceList.load()};
4121 do {
4122 if(iter == device)
4123 break;
4124 iter = iter->next.load(std::memory_order_relaxed);
4125 } while(iter != nullptr);
4126 if(!iter || iter->Type != Capture)
4128 alcSetError(iter, ALC_INVALID_DEVICE);
4129 return ALC_FALSE;
4132 ALCdevice *origdev{device};
4133 ALCdevice *nextdev{device->next.load(std::memory_order_relaxed)};
4134 if(!DeviceList.compare_exchange_strong(origdev, nextdev))
4136 ALCdevice *list;
4137 do {
4138 list = origdev;
4139 origdev = device;
4140 } while(!list->next.compare_exchange_strong(origdev, nextdev));
4142 listlock.unlock();
4144 { std::lock_guard<almtx_t> _{device->BackendLock};
4145 if((device->Flags&DEVICE_RUNNING))
4146 V0(device->Backend,stop)();
4147 device->Flags &= ~DEVICE_RUNNING;
4150 ALCdevice_DecRef(device);
4152 return ALC_TRUE;
4155 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
4157 if(!VerifyDevice(&device) || device->Type != Capture)
4158 alcSetError(device, ALC_INVALID_DEVICE);
4159 else
4161 std::lock_guard<almtx_t> _{device->BackendLock};
4162 if(!device->Connected.load(std::memory_order_acquire))
4163 alcSetError(device, ALC_INVALID_DEVICE);
4164 else if(!(device->Flags&DEVICE_RUNNING))
4166 if(V0(device->Backend,start)())
4167 device->Flags |= DEVICE_RUNNING;
4168 else
4170 aluHandleDisconnect(device, "Device start failure");
4171 alcSetError(device, ALC_INVALID_DEVICE);
4176 if(device) ALCdevice_DecRef(device);
4179 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
4181 if(!VerifyDevice(&device) || device->Type != Capture)
4182 alcSetError(device, ALC_INVALID_DEVICE);
4183 else
4185 std::lock_guard<almtx_t> _{device->BackendLock};
4186 if((device->Flags&DEVICE_RUNNING))
4187 V0(device->Backend,stop)();
4188 device->Flags &= ~DEVICE_RUNNING;
4191 if(device) ALCdevice_DecRef(device);
4194 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4196 if(!VerifyDevice(&device) || device->Type != Capture)
4197 alcSetError(device, ALC_INVALID_DEVICE);
4198 else
4200 ALCenum err = ALC_INVALID_VALUE;
4201 { std::lock_guard<almtx_t> _{device->BackendLock};
4202 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
4203 err = V(device->Backend,captureSamples)(buffer, samples);
4205 if(err != ALC_NO_ERROR)
4206 alcSetError(device, err);
4208 if(device) ALCdevice_DecRef(device);
4212 /************************************************
4213 * ALC loopback functions
4214 ************************************************/
4216 /* alcLoopbackOpenDeviceSOFT
4218 * Open a loopback device, for manual rendering.
4220 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
4222 DO_INITCONFIG();
4224 /* Make sure the device name, if specified, is us. */
4225 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
4227 alcSetError(nullptr, ALC_INVALID_VALUE);
4228 return nullptr;
4231 auto device = new ALCdevice{Loopback};
4233 device->SourcesMax = 256;
4234 device->AuxiliaryEffectSlotMax = 64;
4235 device->NumAuxSends = DEFAULT_SENDS;
4237 //Set output format
4238 device->NumUpdates = 0;
4239 device->UpdateSize = 0;
4241 device->Frequency = DEFAULT_OUTPUT_RATE;
4242 device->FmtChans = DevFmtChannelsDefault;
4243 device->FmtType = DevFmtTypeDefault;
4245 ConfigValueUInt(nullptr, nullptr, "sources", &device->SourcesMax);
4246 if(device->SourcesMax == 0) device->SourcesMax = 256;
4248 ConfigValueUInt(nullptr, nullptr, "slots", &device->AuxiliaryEffectSlotMax);
4249 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4250 else device->AuxiliaryEffectSlotMax = minu(device->AuxiliaryEffectSlotMax, INT_MAX);
4252 if(ConfigValueInt(nullptr, nullptr, "sends", &device->NumAuxSends))
4253 device->NumAuxSends = clampi(
4254 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4257 device->NumStereoSources = 1;
4258 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4260 device->Backend = LoopbackBackendFactory::getFactory().createBackend(
4261 device, ALCbackend_Loopback);
4262 if(!device->Backend)
4264 al_free(device);
4265 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
4266 return nullptr;
4269 // Open the "backend"
4270 V(device->Backend,open)("Loopback");
4273 ALCdevice *head{DeviceList.load()};
4274 do {
4275 device->next.store(head, std::memory_order_relaxed);
4276 } while(!DeviceList.compare_exchange_weak(head, device));
4279 TRACE("Created device %p\n", device);
4280 return device;
4283 /* alcIsRenderFormatSupportedSOFT
4285 * Determines if the loopback device supports the given format for rendering.
4287 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4289 ALCboolean ret{ALC_FALSE};
4291 if(!VerifyDevice(&device) || device->Type != Loopback)
4292 alcSetError(device, ALC_INVALID_DEVICE);
4293 else if(freq <= 0)
4294 alcSetError(device, ALC_INVALID_VALUE);
4295 else
4297 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4298 ret = ALC_TRUE;
4300 if(device) ALCdevice_DecRef(device);
4302 return ret;
4305 /* alcRenderSamplesSOFT
4307 * Renders some samples into a buffer, using the format last set by the
4308 * attributes given to alcCreateContext.
4310 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4312 if(!VerifyDevice(&device) || device->Type != Loopback)
4313 alcSetError(device, ALC_INVALID_DEVICE);
4314 else if(samples < 0 || (samples > 0 && buffer == nullptr))
4315 alcSetError(device, ALC_INVALID_VALUE);
4316 else
4318 V0(device->Backend,lock)();
4319 aluMixData(device, buffer, samples);
4320 V0(device->Backend,unlock)();
4322 if(device) ALCdevice_DecRef(device);
4326 /************************************************
4327 * ALC DSP pause/resume functions
4328 ************************************************/
4330 /* alcDevicePauseSOFT
4332 * Pause the DSP to stop audio processing.
4334 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4336 if(!VerifyDevice(&device) || device->Type != Playback)
4337 alcSetError(device, ALC_INVALID_DEVICE);
4338 else
4340 std::lock_guard<almtx_t> _{device->BackendLock};
4341 if((device->Flags&DEVICE_RUNNING))
4342 V0(device->Backend,stop)();
4343 device->Flags &= ~DEVICE_RUNNING;
4344 device->Flags |= DEVICE_PAUSED;
4346 if(device) ALCdevice_DecRef(device);
4349 /* alcDeviceResumeSOFT
4351 * Resume the DSP to restart audio processing.
4353 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4355 if(!VerifyDevice(&device) || device->Type != Playback)
4356 alcSetError(device, ALC_INVALID_DEVICE);
4357 else
4359 std::lock_guard<almtx_t> _{device->BackendLock};
4360 if((device->Flags&DEVICE_PAUSED))
4362 device->Flags &= ~DEVICE_PAUSED;
4363 if(device->ContextList.load() != nullptr)
4365 if(V0(device->Backend,start)() != ALC_FALSE)
4366 device->Flags |= DEVICE_RUNNING;
4367 else
4369 V0(device->Backend,lock)();
4370 aluHandleDisconnect(device, "Device start failure");
4371 V0(device->Backend,unlock)();
4372 alcSetError(device, ALC_INVALID_DEVICE);
4377 if(device) ALCdevice_DecRef(device);
4381 /************************************************
4382 * ALC HRTF functions
4383 ************************************************/
4385 /* alcGetStringiSOFT
4387 * Gets a string parameter at the given index.
4389 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4391 const ALCchar *str{nullptr};
4393 if(!VerifyDevice(&device) || device->Type == Capture)
4394 alcSetError(device, ALC_INVALID_DEVICE);
4395 else switch(paramName)
4397 case ALC_HRTF_SPECIFIER_SOFT:
4398 if(index >= 0 && (size_t)index < device->HrtfList.size())
4399 str = device->HrtfList[index].name.c_str();
4400 else
4401 alcSetError(device, ALC_INVALID_VALUE);
4402 break;
4404 default:
4405 alcSetError(device, ALC_INVALID_ENUM);
4406 break;
4408 if(device) ALCdevice_DecRef(device);
4410 return str;
4413 /* alcResetDeviceSOFT
4415 * Resets the given device output, using the specified attribute list.
4417 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4419 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4420 if(!VerifyDevice(&device) || device->Type == Capture ||
4421 !device->Connected.load(std::memory_order_relaxed))
4423 listlock.unlock();
4424 alcSetError(device, ALC_INVALID_DEVICE);
4425 if(device) ALCdevice_DecRef(device);
4426 return ALC_FALSE;
4428 std::unique_lock<almtx_t> backlock{device->BackendLock};
4429 listlock.unlock();
4431 ALCenum err{UpdateDeviceParams(device, attribs)};
4432 backlock.unlock();
4434 if(err != ALC_NO_ERROR)
4436 alcSetError(device, err);
4437 if(err == ALC_INVALID_DEVICE)
4439 V0(device->Backend,lock)();
4440 aluHandleDisconnect(device, "Device start failure");
4441 V0(device->Backend,unlock)();
4443 ALCdevice_DecRef(device);
4444 return ALC_FALSE;
4446 ALCdevice_DecRef(device);
4448 return ALC_TRUE;