Use a standard string for the enumerated HRTF names
[openal-soft.git] / Alc / alc.cpp
blobf4a641994e3818f9ce85711194a4ef286326ef56
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 = ATOMIC_LOAD(&dev->next, almemory_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 ATOMIC_STORE_SEQ(&context->DeferUpdates, AL_TRUE);
1610 /* ALCcontext_ProcessUpdates
1612 * Resumes update processing after being deferred.
1614 void ALCcontext_ProcessUpdates(ALCcontext *context)
1616 almtx_lock(&context->PropLock);
1617 if(ATOMIC_EXCHANGE_SEQ(&context->DeferUpdates, AL_FALSE))
1619 /* Tell the mixer to stop applying updates, then wait for any active
1620 * updating to finish, before providing updates.
1622 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_TRUE);
1623 while((ATOMIC_LOAD(&context->UpdateCount, almemory_order_acquire)&1) != 0)
1624 althrd_yield();
1626 if(!ATOMIC_EXCHANGE(&context->PropsClean, AL_TRUE, almemory_order_acq_rel))
1627 UpdateContextProps(context);
1628 if(!ATOMIC_EXCHANGE(&context->Listener.PropsClean, AL_TRUE, almemory_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 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_FALSE);
1638 almtx_unlock(&context->PropLock);
1642 /* alcSetError
1644 * Stores the latest ALC device error
1646 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1648 WARN("Error generated on device %p, code 0x%04x\n", device, errorCode);
1649 if(TrapALCError)
1651 #ifdef _WIN32
1652 /* DebugBreak() will cause an exception if there is no debugger */
1653 if(IsDebuggerPresent())
1654 DebugBreak();
1655 #elif defined(SIGTRAP)
1656 raise(SIGTRAP);
1657 #endif
1660 if(device)
1661 ATOMIC_STORE_SEQ(&device->LastError, errorCode);
1662 else
1663 LastNullDeviceError.store(errorCode);
1667 static struct Compressor *CreateDeviceLimiter(const ALCdevice *device, const ALfloat threshold)
1669 return CompressorInit(device->RealOut.NumChannels, device->Frequency,
1670 AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, 0.001f, 0.002f,
1671 0.0f, 0.0f, threshold, INFINITY, 0.0f, 0.020f, 0.200f);
1674 /* UpdateClockBase
1676 * Updates the device's base clock time with however many samples have been
1677 * done. This is used so frequency changes on the device don't cause the time
1678 * to jump forward or back. Must not be called while the device is running/
1679 * mixing.
1681 static inline void UpdateClockBase(ALCdevice *device)
1683 IncrementRef(&device->MixCount);
1684 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1685 device->SamplesDone = 0;
1686 IncrementRef(&device->MixCount);
1689 /* UpdateDeviceParams
1691 * Updates device parameters according to the attribute list (caller is
1692 * responsible for holding the list lock).
1694 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1696 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1697 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1698 ALCenum gainLimiter = device->LimiterState;
1699 const ALsizei old_sends = device->NumAuxSends;
1700 ALsizei new_sends = device->NumAuxSends;
1701 enum DevFmtChannels oldChans;
1702 enum DevFmtType oldType;
1703 ALboolean update_failed;
1704 ALCsizei hrtf_id = -1;
1705 ALCcontext *context;
1706 ALCuint oldFreq;
1707 size_t size;
1708 ALCsizei i;
1709 int val;
1711 // Check for attributes
1712 if(device->Type == Loopback)
1714 ALCsizei numMono, numStereo, numSends;
1715 ALCenum alayout = AL_NONE;
1716 ALCenum ascale = AL_NONE;
1717 ALCenum schans = AL_NONE;
1718 ALCenum stype = AL_NONE;
1719 ALCsizei attrIdx = 0;
1720 ALCsizei aorder = 0;
1721 ALCuint freq = 0;
1723 if(!attrList)
1725 WARN("Missing attributes for loopback device\n");
1726 return ALC_INVALID_VALUE;
1729 numMono = device->NumMonoSources;
1730 numStereo = device->NumStereoSources;
1731 numSends = old_sends;
1733 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1734 while(attrList[attrIdx])
1736 switch(attrList[attrIdx])
1738 case ALC_FORMAT_CHANNELS_SOFT:
1739 schans = attrList[attrIdx + 1];
1740 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1741 if(!IsValidALCChannels(schans))
1742 return ALC_INVALID_VALUE;
1743 break;
1745 case ALC_FORMAT_TYPE_SOFT:
1746 stype = attrList[attrIdx + 1];
1747 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1748 if(!IsValidALCType(stype))
1749 return ALC_INVALID_VALUE;
1750 break;
1752 case ALC_FREQUENCY:
1753 freq = attrList[attrIdx + 1];
1754 TRACE_ATTR(ALC_FREQUENCY, freq);
1755 if(freq < MIN_OUTPUT_RATE)
1756 return ALC_INVALID_VALUE;
1757 break;
1759 case ALC_AMBISONIC_LAYOUT_SOFT:
1760 alayout = attrList[attrIdx + 1];
1761 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1762 if(!IsValidAmbiLayout(alayout))
1763 return ALC_INVALID_VALUE;
1764 break;
1766 case ALC_AMBISONIC_SCALING_SOFT:
1767 ascale = attrList[attrIdx + 1];
1768 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1769 if(!IsValidAmbiScaling(ascale))
1770 return ALC_INVALID_VALUE;
1771 break;
1773 case ALC_AMBISONIC_ORDER_SOFT:
1774 aorder = attrList[attrIdx + 1];
1775 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1776 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1777 return ALC_INVALID_VALUE;
1778 break;
1780 case ALC_MONO_SOURCES:
1781 numMono = attrList[attrIdx + 1];
1782 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1783 numMono = maxi(numMono, 0);
1784 break;
1786 case ALC_STEREO_SOURCES:
1787 numStereo = attrList[attrIdx + 1];
1788 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1789 numStereo = maxi(numStereo, 0);
1790 break;
1792 case ALC_MAX_AUXILIARY_SENDS:
1793 numSends = attrList[attrIdx + 1];
1794 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1795 numSends = clampi(numSends, 0, MAX_SENDS);
1796 break;
1798 case ALC_HRTF_SOFT:
1799 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1800 if(attrList[attrIdx + 1] == ALC_FALSE)
1801 hrtf_appreq = Hrtf_Disable;
1802 else if(attrList[attrIdx + 1] == ALC_TRUE)
1803 hrtf_appreq = Hrtf_Enable;
1804 else
1805 hrtf_appreq = Hrtf_Default;
1806 break;
1808 case ALC_HRTF_ID_SOFT:
1809 hrtf_id = attrList[attrIdx + 1];
1810 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1811 break;
1813 case ALC_OUTPUT_LIMITER_SOFT:
1814 gainLimiter = attrList[attrIdx + 1];
1815 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1816 break;
1818 default:
1819 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList[attrIdx],
1820 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1821 break;
1824 attrIdx += 2;
1826 #undef TRACE_ATTR
1828 if(!schans || !stype || !freq)
1830 WARN("Missing format for loopback device\n");
1831 return ALC_INVALID_VALUE;
1833 if(schans == ALC_BFORMAT3D_SOFT && (!alayout || !ascale || !aorder))
1835 WARN("Missing ambisonic info for loopback device\n");
1836 return ALC_INVALID_VALUE;
1839 if((device->Flags&DEVICE_RUNNING))
1840 V0(device->Backend,stop)();
1841 device->Flags &= ~DEVICE_RUNNING;
1843 UpdateClockBase(device);
1845 device->Frequency = freq;
1846 device->FmtChans = static_cast<enum DevFmtChannels>(schans);
1847 device->FmtType = static_cast<enum DevFmtType>(stype);
1848 if(schans == ALC_BFORMAT3D_SOFT)
1850 device->mAmbiOrder = aorder;
1851 device->mAmbiLayout = static_cast<enum AmbiLayout>(alayout);
1852 device->mAmbiScale = static_cast<enum AmbiNorm>(ascale);
1855 if(numMono > INT_MAX-numStereo)
1856 numMono = INT_MAX-numStereo;
1857 numMono += numStereo;
1858 if(ConfigValueInt(nullptr, nullptr, "sources", &numMono))
1860 if(numMono <= 0)
1861 numMono = 256;
1863 else
1864 numMono = maxi(numMono, 256);
1865 numStereo = mini(numStereo, numMono);
1866 numMono -= numStereo;
1867 device->SourcesMax = numMono + numStereo;
1869 device->NumMonoSources = numMono;
1870 device->NumStereoSources = numStereo;
1872 if(ConfigValueInt(nullptr, nullptr, "sends", &new_sends))
1873 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1874 else
1875 new_sends = numSends;
1877 else if(attrList && attrList[0])
1879 ALCsizei numMono, numStereo, numSends;
1880 ALCsizei attrIdx = 0;
1881 ALCuint freq;
1883 /* If a context is already running on the device, stop playback so the
1884 * device attributes can be updated. */
1885 if((device->Flags&DEVICE_RUNNING))
1886 V0(device->Backend,stop)();
1887 device->Flags &= ~DEVICE_RUNNING;
1889 UpdateClockBase(device);
1891 freq = device->Frequency;
1892 numMono = device->NumMonoSources;
1893 numStereo = device->NumStereoSources;
1894 numSends = old_sends;
1896 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1897 while(attrList[attrIdx])
1899 switch(attrList[attrIdx])
1901 case ALC_FREQUENCY:
1902 freq = attrList[attrIdx + 1];
1903 TRACE_ATTR(ALC_FREQUENCY, freq);
1904 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1905 break;
1907 case ALC_MONO_SOURCES:
1908 numMono = attrList[attrIdx + 1];
1909 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1910 numMono = maxi(numMono, 0);
1911 break;
1913 case ALC_STEREO_SOURCES:
1914 numStereo = attrList[attrIdx + 1];
1915 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1916 numStereo = maxi(numStereo, 0);
1917 break;
1919 case ALC_MAX_AUXILIARY_SENDS:
1920 numSends = attrList[attrIdx + 1];
1921 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1922 numSends = clampi(numSends, 0, MAX_SENDS);
1923 break;
1925 case ALC_HRTF_SOFT:
1926 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1927 if(attrList[attrIdx + 1] == ALC_FALSE)
1928 hrtf_appreq = Hrtf_Disable;
1929 else if(attrList[attrIdx + 1] == ALC_TRUE)
1930 hrtf_appreq = Hrtf_Enable;
1931 else
1932 hrtf_appreq = Hrtf_Default;
1933 break;
1935 case ALC_HRTF_ID_SOFT:
1936 hrtf_id = attrList[attrIdx + 1];
1937 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1938 break;
1940 case ALC_OUTPUT_LIMITER_SOFT:
1941 gainLimiter = attrList[attrIdx + 1];
1942 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1943 break;
1945 default:
1946 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1947 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1948 break;
1951 attrIdx += 2;
1953 #undef TRACE_ATTR
1955 ConfigValueUInt(device->DeviceName.c_str(), nullptr, "frequency", &freq);
1956 freq = maxu(freq, MIN_OUTPUT_RATE);
1958 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1959 device->Frequency;
1960 /* SSE and Neon do best with the update size being a multiple of 4 */
1961 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1962 device->UpdateSize = (device->UpdateSize+3)&~3;
1964 device->Frequency = freq;
1966 if(numMono > INT_MAX-numStereo)
1967 numMono = INT_MAX-numStereo;
1968 numMono += numStereo;
1969 if(ConfigValueInt(device->DeviceName.c_str(), nullptr, "sources", &numMono))
1971 if(numMono <= 0)
1972 numMono = 256;
1974 else
1975 numMono = maxi(numMono, 256);
1976 numStereo = mini(numStereo, numMono);
1977 numMono -= numStereo;
1978 device->SourcesMax = numMono + numStereo;
1980 device->NumMonoSources = numMono;
1981 device->NumStereoSources = numStereo;
1983 if(ConfigValueInt(device->DeviceName.c_str(), nullptr, "sends", &new_sends))
1984 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1985 else
1986 new_sends = numSends;
1989 if((device->Flags&DEVICE_RUNNING))
1990 return ALC_NO_ERROR;
1992 al_free(device->Uhj_Encoder);
1993 device->Uhj_Encoder = nullptr;
1995 al_free(device->Bs2b);
1996 device->Bs2b = nullptr;
1998 al_free(device->ChannelDelay[0].Buffer);
1999 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2001 device->ChannelDelay[i].Length = 0;
2002 device->ChannelDelay[i].Buffer = nullptr;
2005 al_free(device->Dry.Buffer);
2006 device->Dry.Buffer = nullptr;
2007 device->Dry.NumChannels = 0;
2008 device->FOAOut.Buffer = nullptr;
2009 device->FOAOut.NumChannels = 0;
2010 device->RealOut.Buffer = nullptr;
2011 device->RealOut.NumChannels = 0;
2013 UpdateClockBase(device);
2014 device->FixedLatency = 0;
2016 device->DitherSeed = DITHER_RNG_SEED;
2018 /*************************************************************************
2019 * Update device format request if HRTF is requested
2021 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
2022 if(device->Type != Loopback)
2024 const char *hrtf;
2025 if(ConfigValueStr(device->DeviceName.c_str(), nullptr, "hrtf", &hrtf))
2027 if(strcasecmp(hrtf, "true") == 0)
2028 hrtf_userreq = Hrtf_Enable;
2029 else if(strcasecmp(hrtf, "false") == 0)
2030 hrtf_userreq = Hrtf_Disable;
2031 else if(strcasecmp(hrtf, "auto") != 0)
2032 ERR("Unexpected hrtf value: %s\n", hrtf);
2035 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
2037 struct Hrtf *hrtf = nullptr;
2038 if(device->HrtfList.empty())
2039 device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
2040 if(!device->HrtfList.empty())
2042 if(hrtf_id >= 0 && (size_t)hrtf_id < device->HrtfList.size())
2043 hrtf = GetLoadedHrtf(device->HrtfList[hrtf_id].hrtf);
2044 else
2045 hrtf = GetLoadedHrtf(device->HrtfList.front().hrtf);
2048 if(hrtf)
2050 device->FmtChans = DevFmtStereo;
2051 device->Frequency = hrtf->sampleRate;
2052 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
2053 if(device->HrtfHandle)
2054 Hrtf_DecRef(device->HrtfHandle);
2055 device->HrtfHandle = hrtf;
2057 else
2059 hrtf_userreq = Hrtf_Default;
2060 hrtf_appreq = Hrtf_Disable;
2061 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2066 oldFreq = device->Frequency;
2067 oldChans = device->FmtChans;
2068 oldType = device->FmtType;
2070 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2071 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
2072 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
2073 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
2074 device->UpdateSize, device->NumUpdates
2077 if(V0(device->Backend,reset)() == ALC_FALSE)
2078 return ALC_INVALID_DEVICE;
2080 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
2082 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2083 DevFmtChannelsString(device->FmtChans));
2084 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2086 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2088 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2089 DevFmtTypeString(device->FmtType));
2090 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2092 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2094 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2095 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2098 if((device->UpdateSize&3) != 0)
2100 if((CPUCapFlags&CPU_CAP_SSE))
2101 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2102 if((CPUCapFlags&CPU_CAP_NEON))
2103 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2106 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2107 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2108 device->Frequency, device->UpdateSize, device->NumUpdates
2111 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2112 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device->Dry.NumChannels,
2113 device->FOAOut.NumChannels, device->RealOut.NumChannels);
2115 /* Allocate extra channels for any post-filter output. */
2116 size = (device->Dry.NumChannels + device->FOAOut.NumChannels +
2117 device->RealOut.NumChannels)*sizeof(device->Dry.Buffer[0]);
2119 TRACE("Allocating " SZFMT " channels, " SZFMT " bytes\n", size/sizeof(device->Dry.Buffer[0]), size);
2120 device->Dry.Buffer = static_cast<float(*)[BUFFERSIZE]>(al_calloc(16, size));
2121 if(!device->Dry.Buffer)
2123 ERR("Failed to allocate " SZFMT " bytes for mix buffer\n", size);
2124 return ALC_INVALID_DEVICE;
2127 if(device->RealOut.NumChannels != 0)
2128 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels +
2129 device->FOAOut.NumChannels;
2130 else
2132 device->RealOut.Buffer = device->Dry.Buffer;
2133 device->RealOut.NumChannels = device->Dry.NumChannels;
2136 if(device->FOAOut.NumChannels != 0)
2137 device->FOAOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2138 else
2140 device->FOAOut.Buffer = device->Dry.Buffer;
2141 device->FOAOut.NumChannels = device->Dry.NumChannels;
2144 device->NumAuxSends = new_sends;
2145 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2146 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
2147 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
2149 device->DitherDepth = 0.0f;
2150 if(GetConfigValueBool(device->DeviceName.c_str(), nullptr, "dither", 1))
2152 ALint depth = 0;
2153 ConfigValueInt(device->DeviceName.c_str(), nullptr, "dither-depth", &depth);
2154 if(depth <= 0)
2156 switch(device->FmtType)
2158 case DevFmtByte:
2159 case DevFmtUByte:
2160 depth = 8;
2161 break;
2162 case DevFmtShort:
2163 case DevFmtUShort:
2164 depth = 16;
2165 break;
2166 case DevFmtInt:
2167 case DevFmtUInt:
2168 case DevFmtFloat:
2169 break;
2173 if(depth > 0)
2175 depth = clampi(depth, 2, 24);
2176 device->DitherDepth = std::pow(2.0f, (ALfloat)(depth-1));
2179 if(!(device->DitherDepth > 0.0f))
2180 TRACE("Dithering disabled\n");
2181 else
2182 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device->DitherDepth)+0.5f)+1,
2183 device->DitherDepth);
2185 device->LimiterState = gainLimiter;
2186 if(ConfigValueBool(device->DeviceName.c_str(), nullptr, "output-limiter", &val))
2187 gainLimiter = val ? ALC_TRUE : ALC_FALSE;
2189 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2190 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2191 * output (where samples must be clamped), and don't for floating-point
2192 * (which can take unclamped samples).
2194 if(gainLimiter == ALC_DONT_CARE_SOFT)
2196 switch(device->FmtType)
2198 case DevFmtByte:
2199 case DevFmtUByte:
2200 case DevFmtShort:
2201 case DevFmtUShort:
2202 case DevFmtInt:
2203 case DevFmtUInt:
2204 gainLimiter = ALC_TRUE;
2205 break;
2206 case DevFmtFloat:
2207 gainLimiter = ALC_FALSE;
2208 break;
2211 if(gainLimiter != ALC_FALSE)
2213 ALfloat thrshld = 1.0f;
2214 switch(device->FmtType)
2216 case DevFmtByte:
2217 case DevFmtUByte:
2218 thrshld = 127.0f / 128.0f;
2219 break;
2220 case DevFmtShort:
2221 case DevFmtUShort:
2222 thrshld = 32767.0f / 32768.0f;
2223 break;
2224 case DevFmtInt:
2225 case DevFmtUInt:
2226 case DevFmtFloat:
2227 break;
2229 if(device->DitherDepth > 0.0f)
2230 thrshld -= 1.0f / device->DitherDepth;
2232 al_free(device->Limiter);
2233 device->Limiter = CreateDeviceLimiter(device, std::log10(thrshld) * 20.0f);
2234 device->FixedLatency += (ALuint)(GetCompressorLookAhead(device->Limiter) *
2235 DEVICE_CLOCK_RES / device->Frequency);
2237 else
2239 al_free(device->Limiter);
2240 device->Limiter = nullptr;
2242 TRACE("Output limiter %s\n", device->Limiter ? "enabled" : "disabled");
2244 aluSelectPostProcess(device);
2246 TRACE("Fixed device latency: %uns\n", device->FixedLatency);
2248 /* Need to delay returning failure until replacement Send arrays have been
2249 * allocated with the appropriate size.
2251 update_failed = AL_FALSE;
2252 START_MIXER_MODE();
2253 context = ATOMIC_LOAD_SEQ(&device->ContextList);
2254 while(context)
2256 struct ALvoiceProps *vprops;
2257 ALsizei pos;
2259 if(context->DefaultSlot)
2261 ALeffectslot *slot = context->DefaultSlot;
2262 ALeffectState *state = slot->Effect.State;
2264 state->OutBuffer = device->Dry.Buffer;
2265 state->OutChannels = device->Dry.NumChannels;
2266 if(V(state,deviceUpdate)(device) == AL_FALSE)
2267 update_failed = AL_TRUE;
2268 else
2269 UpdateEffectSlotProps(slot, context);
2272 almtx_lock(&context->PropLock);
2273 almtx_lock(&context->EffectSlotLock);
2274 for(auto &slot : context->EffectSlotList)
2276 ALeffectState *state = slot->Effect.State;
2278 state->OutBuffer = device->Dry.Buffer;
2279 state->OutChannels = device->Dry.NumChannels;
2280 if(V(state,deviceUpdate)(device) == AL_FALSE)
2281 update_failed = AL_TRUE;
2282 else
2283 UpdateEffectSlotProps(slot, context);
2285 almtx_unlock(&context->EffectSlotLock);
2287 almtx_lock(&context->SourceLock);
2288 for(auto &sublist : context->SourceList)
2290 uint64_t usemask = ~sublist.FreeMask;
2291 while(usemask)
2293 ALsizei idx = CTZ64(usemask);
2294 ALsource *source = sublist.Sources + idx;
2296 usemask &= ~(U64(1) << idx);
2298 if(old_sends != device->NumAuxSends)
2300 ALvoid *sends = al_calloc(16, device->NumAuxSends*sizeof(source->Send[0]));
2301 ALsizei s;
2303 memcpy(sends, source->Send,
2304 mini(device->NumAuxSends, old_sends)*sizeof(source->Send[0])
2306 for(s = device->NumAuxSends;s < old_sends;s++)
2308 if(source->Send[s].Slot)
2309 DecrementRef(&source->Send[s].Slot->ref);
2310 source->Send[s].Slot = nullptr;
2312 al_free(source->Send);
2313 source->Send = static_cast<decltype(source->Send)>(sends);
2314 for(s = old_sends;s < device->NumAuxSends;s++)
2316 source->Send[s].Slot = nullptr;
2317 source->Send[s].Gain = 1.0f;
2318 source->Send[s].GainHF = 1.0f;
2319 source->Send[s].HFReference = LOWPASSFREQREF;
2320 source->Send[s].GainLF = 1.0f;
2321 source->Send[s].LFReference = HIGHPASSFREQREF;
2325 ATOMIC_STORE(&source->PropsClean, AL_FALSE, almemory_order_release);
2329 /* Clear any pre-existing voice property structs, in case the number of
2330 * auxiliary sends is changing. Active sources will have updates
2331 * respecified in UpdateAllSourceProps.
2333 vprops = ATOMIC_EXCHANGE(&context->FreeVoiceProps, static_cast<ALvoiceProps*>(nullptr),
2334 almemory_order_acq_rel);
2335 while(vprops)
2337 struct ALvoiceProps *next = ATOMIC_LOAD(&vprops->next, almemory_order_relaxed);
2338 al_free(vprops);
2339 vprops = next;
2342 AllocateVoices(context, context->MaxVoices, old_sends);
2343 for(pos = 0;pos < context->VoiceCount;pos++)
2345 ALvoice *voice = context->Voices[pos];
2347 al_free(ATOMIC_EXCHANGE(&voice->Update, static_cast<ALvoiceProps*>(nullptr),
2348 almemory_order_acq_rel));
2350 if(ATOMIC_LOAD(&voice->Source, almemory_order_acquire) == nullptr)
2351 continue;
2353 if(device->AvgSpeakerDist > 0.0f)
2355 /* Reinitialize the NFC filters for new parameters. */
2356 ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
2357 (device->AvgSpeakerDist * device->Frequency);
2358 for(i = 0;i < voice->NumChannels;i++)
2359 NfcFilterCreate(&voice->Direct.Params[i].NFCtrlFilter, 0.0f, w1);
2362 almtx_unlock(&context->SourceLock);
2364 ATOMIC_STORE(&context->PropsClean, AL_TRUE, almemory_order_release);
2365 UpdateContextProps(context);
2366 ATOMIC_STORE(&context->Listener.PropsClean, AL_TRUE, almemory_order_release);
2367 UpdateListenerProps(context);
2368 UpdateAllSourceProps(context);
2369 almtx_unlock(&context->PropLock);
2371 context = ATOMIC_LOAD(&context->next, almemory_order_relaxed);
2373 END_MIXER_MODE();
2374 if(update_failed)
2375 return ALC_INVALID_DEVICE;
2377 if(!(device->Flags&DEVICE_PAUSED))
2379 if(V0(device->Backend,start)() == ALC_FALSE)
2380 return ALC_INVALID_DEVICE;
2381 device->Flags |= DEVICE_RUNNING;
2384 return ALC_NO_ERROR;
2388 ALCdevice_struct::ALCdevice_struct(DeviceType type)
2389 : Type{type}
2391 VECTOR_INIT(BufferList);
2392 almtx_init(&BufferLock, almtx_plain);
2394 VECTOR_INIT(EffectList);
2395 almtx_init(&EffectLock, almtx_plain);
2397 VECTOR_INIT(FilterList);
2398 almtx_init(&FilterLock, almtx_plain);
2400 almtx_init(&BackendLock, almtx_plain);
2403 /* ALCdevice_struct::~ALCdevice_struct
2405 * Frees the device structure, and destroys any objects the app failed to
2406 * delete. Called once there's no more references on the device.
2408 ALCdevice_struct::~ALCdevice_struct()
2410 TRACE("%p\n", this);
2412 if(Backend)
2413 DELETE_OBJ(Backend);
2414 Backend = nullptr;
2416 almtx_destroy(&BackendLock);
2418 ReleaseALBuffers(this);
2419 #define FREE_BUFFERSUBLIST(x) al_free((x)->Buffers)
2420 VECTOR_FOR_EACH(BufferSubList, BufferList, FREE_BUFFERSUBLIST);
2421 #undef FREE_BUFFERSUBLIST
2422 VECTOR_DEINIT(BufferList);
2423 almtx_destroy(&BufferLock);
2425 ReleaseALEffects(this);
2426 #define FREE_EFFECTSUBLIST(x) al_free((x)->Effects)
2427 VECTOR_FOR_EACH(EffectSubList, EffectList, FREE_EFFECTSUBLIST);
2428 #undef FREE_EFFECTSUBLIST
2429 VECTOR_DEINIT(EffectList);
2430 almtx_destroy(&EffectLock);
2432 ReleaseALFilters(this);
2433 #define FREE_FILTERSUBLIST(x) al_free((x)->Filters)
2434 VECTOR_FOR_EACH(FilterSubList, FilterList, FREE_FILTERSUBLIST);
2435 #undef FREE_FILTERSUBLIST
2436 VECTOR_DEINIT(FilterList);
2437 almtx_destroy(&FilterLock);
2439 HrtfList.clear();
2440 if(HrtfHandle)
2441 Hrtf_DecRef(HrtfHandle);
2442 HrtfHandle = nullptr;
2443 al_free(Hrtf);
2444 Hrtf = nullptr;
2446 al_free(Bs2b);
2447 Bs2b = nullptr;
2449 al_free(Uhj_Encoder);
2450 Uhj_Encoder = nullptr;
2452 bformatdec_free(&AmbiDecoder);
2453 ambiup_free(&AmbiUp);
2455 al_free(Stablizer);
2456 Stablizer = nullptr;
2458 al_free(Limiter);
2459 Limiter = nullptr;
2461 al_free(ChannelDelay[0].Buffer);
2462 for(ALsizei i{0};i < MAX_OUTPUT_CHANNELS;i++)
2464 ChannelDelay[i].Gain = 1.0f;
2465 ChannelDelay[i].Length = 0;
2466 ChannelDelay[i].Buffer = nullptr;
2469 al_free(Dry.Buffer);
2470 Dry.Buffer = nullptr;
2471 Dry.NumChannels = 0;
2472 FOAOut.Buffer = nullptr;
2473 FOAOut.NumChannels = 0;
2474 RealOut.Buffer = nullptr;
2475 RealOut.NumChannels = 0;
2479 void ALCdevice_IncRef(ALCdevice *device)
2481 uint ref;
2482 ref = IncrementRef(&device->ref);
2483 TRACEREF("%p increasing refcount to %u\n", device, ref);
2486 void ALCdevice_DecRef(ALCdevice *device)
2488 uint ref;
2489 ref = DecrementRef(&device->ref);
2490 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2491 if(ref == 0) delete device;
2494 /* VerifyDevice
2496 * Checks if the device handle is valid, and increments its ref count if so.
2498 static ALCboolean VerifyDevice(ALCdevice **device)
2500 std::lock_guard<std::recursive_mutex> _{ListLock};
2501 ALCdevice *tmpDevice{DeviceList.load()};
2502 while(tmpDevice)
2504 if(tmpDevice == *device)
2506 ALCdevice_IncRef(tmpDevice);
2507 return ALC_TRUE;
2509 tmpDevice = ATOMIC_LOAD(&tmpDevice->next, almemory_order_relaxed);
2512 *device = nullptr;
2513 return ALC_FALSE;
2517 /* InitContext
2519 * Initializes context fields
2521 static ALvoid InitContext(ALCcontext *Context)
2523 ALlistener &listener = Context->Listener;
2524 struct ALeffectslotArray *auxslots;
2526 //Validate Context
2527 almtx_init(&Context->PropLock, almtx_plain);
2528 almtx_init(&Context->SourceLock, almtx_plain);
2529 almtx_init(&Context->EffectSlotLock, almtx_plain);
2531 if(Context->DefaultSlot)
2533 auxslots = static_cast<ALeffectslotArray*>(al_calloc(DEF_ALIGN,
2534 FAM_SIZE(struct ALeffectslotArray, slot, 1)));
2535 auxslots->count = 1;
2536 auxslots->slot[0] = Context->DefaultSlot;
2538 else
2540 auxslots = static_cast<ALeffectslotArray*>(al_calloc(DEF_ALIGN,
2541 sizeof(struct ALeffectslotArray)));
2542 auxslots->count = 0;
2544 ATOMIC_INIT(&Context->ActiveAuxSlots, auxslots);
2546 //Set globals
2547 Context->mDistanceModel = DistanceModel::Default;
2548 Context->SourceDistanceModel = AL_FALSE;
2549 Context->DopplerFactor = 1.0f;
2550 Context->DopplerVelocity = 1.0f;
2551 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2552 Context->MetersPerUnit = AL_DEFAULT_METERS_PER_UNIT;
2553 ATOMIC_INIT(&Context->PropsClean, AL_TRUE);
2554 ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
2555 alsem_init(&Context->EventSem, 0);
2556 almtx_init(&Context->EventCbLock, almtx_plain);
2558 Context->ExtensionList = alExtList;
2561 listener.Params.Matrix = aluMatrixf::Identity;
2562 aluVectorSet(&listener.Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2563 listener.Params.Gain = listener.Gain;
2564 listener.Params.MetersPerUnit = Context->MetersPerUnit;
2565 listener.Params.DopplerFactor = Context->DopplerFactor;
2566 listener.Params.SpeedOfSound = Context->SpeedOfSound * Context->DopplerVelocity;
2567 listener.Params.ReverbSpeedOfSound = listener.Params.SpeedOfSound *
2568 listener.Params.MetersPerUnit;
2569 listener.Params.SourceDistanceModel = Context->SourceDistanceModel;
2570 listener.Params.mDistanceModel = Context->mDistanceModel;
2573 Context->AsyncEvents = ll_ringbuffer_create(63, sizeof(AsyncEvent), false);
2574 StartEventThrd(Context);
2578 /* ALCcontext_struct::~ALCcontext_struct()
2580 * Cleans up the context, and destroys any remaining objects the app failed to
2581 * delete. Called once there's no more references on the context.
2583 ALCcontext_struct::~ALCcontext_struct()
2585 TRACE("%p\n", this);
2587 struct ALcontextProps *cprops{Update.load(std::memory_order_relaxed)};
2588 if(cprops)
2590 TRACE("Freed unapplied context update %p\n", cprops);
2591 al_free(cprops);
2593 size_t count{0};
2594 cprops = FreeContextProps.load(std::memory_order_acquire);
2595 while(cprops)
2597 struct ALcontextProps *next{cprops->next.load(std::memory_order_relaxed)};
2598 al_free(cprops);
2599 cprops = next;
2600 ++count;
2602 TRACE("Freed " SZFMT " context property object%s\n", count, (count==1)?"":"s");
2604 delete DefaultSlot;
2605 DefaultSlot = nullptr;
2607 al_free(ActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed));
2609 ReleaseALSources(this);
2610 std::for_each(SourceList.begin(), SourceList.end(),
2611 [](const SourceSubList &entry) noexcept -> void
2612 { al_free(entry.Sources); }
2614 SourceList.clear();
2615 NumSources = 0;
2616 almtx_destroy(&SourceLock);
2618 count = 0;
2619 struct ALeffectslotProps *eprops{FreeEffectslotProps.load(std::memory_order_acquire)};
2620 while(eprops)
2622 struct ALeffectslotProps *next{eprops->next.load(std::memory_order_relaxed)};
2623 if(eprops->State) ALeffectState_DecRef(eprops->State);
2624 al_free(eprops);
2625 eprops = next;
2626 ++count;
2628 TRACE("Freed " SZFMT " AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2630 ReleaseALAuxiliaryEffectSlots(this);
2631 EffectSlotList.clear();
2632 almtx_destroy(&EffectSlotLock);
2634 count = 0;
2635 struct ALvoiceProps *vprops{FreeVoiceProps.load(std::memory_order_acquire)};
2636 while(vprops)
2638 struct ALvoiceProps *next{vprops->next.load(std::memory_order_relaxed)};
2639 al_free(vprops);
2640 vprops = next;
2641 ++count;
2643 TRACE("Freed " SZFMT " voice property object%s\n", count, (count==1)?"":"s");
2645 for(ALsizei i{0};i < VoiceCount;i++)
2646 DeinitVoice(Voices[i]);
2647 al_free(Voices);
2648 Voices = nullptr;
2649 VoiceCount = 0;
2650 MaxVoices = 0;
2652 struct ALlistenerProps *lprops{Listener.Update.load(std::memory_order_relaxed)};
2653 if(lprops)
2655 TRACE("Freed unapplied listener update %p\n", lprops);
2656 al_free(lprops);
2658 count = 0;
2659 lprops = FreeListenerProps.load(std::memory_order_acquire);
2660 while(lprops)
2662 struct ALlistenerProps *next{lprops->next.load(std::memory_order_relaxed)};
2663 al_free(lprops);
2664 lprops = next;
2665 ++count;
2667 TRACE("Freed " SZFMT " listener property object%s\n", count, (count==1)?"":"s");
2669 almtx_destroy(&EventCbLock);
2670 alsem_destroy(&EventSem);
2672 ll_ringbuffer_free(AsyncEvents);
2673 AsyncEvents = nullptr;
2675 almtx_destroy(&PropLock);
2677 ALCdevice_DecRef(Device);
2680 /* ReleaseContext
2682 * Removes the context reference from the given device and removes it from
2683 * being current on the running thread or globally. Returns true if other
2684 * contexts still exist on the device.
2686 static bool ReleaseContext(ALCcontext *context, ALCdevice *device)
2688 ALCcontext *origctx, *newhead;
2689 bool ret = true;
2691 if(LocalContext.get() == context)
2693 WARN("%p released while current on thread\n", context);
2694 LocalContext.set(nullptr);
2695 ALCcontext_DecRef(context);
2698 origctx = context;
2699 if(GlobalContext.compare_exchange_strong(origctx, nullptr))
2700 ALCcontext_DecRef(context);
2702 V0(device->Backend,lock)();
2703 origctx = context;
2704 newhead = ATOMIC_LOAD(&context->next, almemory_order_relaxed);
2705 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(&device->ContextList, &origctx, newhead))
2707 ALCcontext *list;
2708 do {
2709 /* origctx is what the desired context failed to match. Try
2710 * swapping out the next one in the list.
2712 list = origctx;
2713 origctx = context;
2714 } while(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(&list->next, &origctx, newhead));
2716 else
2717 ret = !!newhead;
2718 V0(device->Backend,unlock)();
2720 /* Make sure the context is finished and no longer processing in the mixer
2721 * before sending the message queue kill event. The backend's lock does
2722 * this, although waiting for a non-odd mix count would work too.
2725 StopEventThrd(context);
2727 ALCcontext_DecRef(context);
2728 return ret;
2731 static void ALCcontext_IncRef(ALCcontext *context)
2733 uint ref = IncrementRef(&context->ref);
2734 TRACEREF("%p increasing refcount to %u\n", context, ref);
2737 void ALCcontext_DecRef(ALCcontext *context)
2739 uint ref = DecrementRef(&context->ref);
2740 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2741 if(ref == 0) delete context;
2744 static void ReleaseThreadCtx(ALCcontext *context)
2746 uint ref = DecrementRef(&context->ref);
2747 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2748 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2751 /* VerifyContext
2753 * Checks that the given context is valid, and increments its reference count.
2755 static ALCboolean VerifyContext(ALCcontext **context)
2757 std::lock_guard<std::recursive_mutex> _{ListLock};
2758 ALCdevice *dev{DeviceList.load()};
2759 while(dev)
2761 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList, almemory_order_acquire);
2762 while(ctx)
2764 if(ctx == *context)
2766 ALCcontext_IncRef(ctx);
2767 return ALC_TRUE;
2769 ctx = ATOMIC_LOAD(&ctx->next, almemory_order_relaxed);
2771 dev = ATOMIC_LOAD(&dev->next, almemory_order_relaxed);
2774 *context = nullptr;
2775 return ALC_FALSE;
2779 /* GetContextRef
2781 * Returns the currently active context for this thread, and adds a reference
2782 * without locking it.
2784 ALCcontext *GetContextRef(void)
2786 ALCcontext *context{LocalContext.get()};
2787 if(context)
2788 ALCcontext_IncRef(context);
2789 else
2791 std::lock_guard<std::recursive_mutex> _{ListLock};
2792 context = GlobalContext.load(std::memory_order_acquire);
2793 if(context) ALCcontext_IncRef(context);
2796 return context;
2800 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
2802 ALCdevice *device = context->Device;
2803 ALsizei num_sends = device->NumAuxSends;
2804 struct ALvoiceProps *props;
2805 size_t sizeof_props;
2806 size_t sizeof_voice;
2807 ALvoice **voices;
2808 ALvoice *voice;
2809 ALsizei v = 0;
2810 size_t size;
2812 if(num_voices == context->MaxVoices && num_sends == old_sends)
2813 return;
2815 /* Allocate the voice pointers, voices, and the voices' stored source
2816 * property set (including the dynamically-sized Send[] array) in one
2817 * chunk.
2819 sizeof_voice = RoundUp(FAM_SIZE(ALvoice, Send, num_sends), 16);
2820 sizeof_props = RoundUp(FAM_SIZE(struct ALvoiceProps, Send, num_sends), 16);
2821 size = sizeof(ALvoice*) + sizeof_voice + sizeof_props;
2823 voices = static_cast<ALvoice**>(al_calloc(16, RoundUp(size*num_voices, 16)));
2824 /* The voice and property objects are stored interleaved since they're
2825 * paired together.
2827 voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
2828 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2830 if(context->Voices)
2832 const ALsizei v_count = mini(context->VoiceCount, num_voices);
2833 const ALsizei s_count = mini(old_sends, num_sends);
2835 for(;v < v_count;v++)
2837 ALvoice *old_voice = context->Voices[v];
2838 ALsizei i;
2840 /* Copy the old voice data and source property set to the new
2841 * storage.
2843 memcpy(voice, old_voice, sizeof(*voice));
2844 for(i = 0;i < s_count;i++)
2845 voice->Send[i] = old_voice->Send[i];
2847 memcpy(props, old_voice->Props, sizeof(*props));
2848 for(i = 0;i < s_count;i++)
2849 props->Send[i] = old_voice->Props->Send[i];
2851 /* Set this voice's property set pointer and voice reference. */
2852 voice->Props = props;
2853 voices[v] = voice;
2855 /* Increment pointers to the next storage space. */
2856 voice = (ALvoice*)((char*)props + sizeof_props);
2857 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2859 /* Deinit any left over voices that weren't copied over to the new
2860 * array. NOTE: If this does anything, v equals num_voices and
2861 * num_voices is less than VoiceCount, so the following loop won't do
2862 * anything.
2864 for(;v < context->VoiceCount;v++)
2865 DeinitVoice(context->Voices[v]);
2867 /* Finish setting the voices' property set pointers and references. */
2868 for(;v < num_voices;v++)
2870 ATOMIC_INIT(&voice->Update, static_cast<ALvoiceProps*>(nullptr));
2872 voice->Props = props;
2873 voices[v] = voice;
2875 voice = (ALvoice*)((char*)props + sizeof_props);
2876 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2879 al_free(context->Voices);
2880 context->Voices = voices;
2881 context->MaxVoices = num_voices;
2882 context->VoiceCount = mini(context->VoiceCount, num_voices);
2886 /************************************************
2887 * Standard ALC functions
2888 ************************************************/
2890 /* alcGetError
2892 * Return last ALC generated error code for the given device
2894 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2896 ALCenum errorCode;
2898 if(VerifyDevice(&device))
2900 errorCode = ATOMIC_EXCHANGE_SEQ(&device->LastError, ALC_NO_ERROR);
2901 ALCdevice_DecRef(device);
2903 else
2904 errorCode = LastNullDeviceError.exchange(ALC_NO_ERROR);
2906 return errorCode;
2910 /* alcSuspendContext
2912 * Suspends updates for the given context
2914 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2916 if(!SuspendDefers)
2917 return;
2919 if(!VerifyContext(&context))
2920 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2921 else
2923 ALCcontext_DeferUpdates(context);
2924 ALCcontext_DecRef(context);
2928 /* alcProcessContext
2930 * Resumes processing updates for the given context
2932 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2934 if(!SuspendDefers)
2935 return;
2937 if(!VerifyContext(&context))
2938 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2939 else
2941 ALCcontext_ProcessUpdates(context);
2942 ALCcontext_DecRef(context);
2947 /* alcGetString
2949 * Returns information about the device, and error strings
2951 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2953 const ALCchar *value = nullptr;
2955 switch(param)
2957 case ALC_NO_ERROR:
2958 value = alcNoError;
2959 break;
2961 case ALC_INVALID_ENUM:
2962 value = alcErrInvalidEnum;
2963 break;
2965 case ALC_INVALID_VALUE:
2966 value = alcErrInvalidValue;
2967 break;
2969 case ALC_INVALID_DEVICE:
2970 value = alcErrInvalidDevice;
2971 break;
2973 case ALC_INVALID_CONTEXT:
2974 value = alcErrInvalidContext;
2975 break;
2977 case ALC_OUT_OF_MEMORY:
2978 value = alcErrOutOfMemory;
2979 break;
2981 case ALC_DEVICE_SPECIFIER:
2982 value = alcDefaultName;
2983 break;
2985 case ALC_ALL_DEVICES_SPECIFIER:
2986 if(VerifyDevice(&Device))
2988 value = Device->DeviceName.c_str();
2989 ALCdevice_DecRef(Device);
2991 else
2993 ProbeAllDevicesList();
2994 value = alcAllDevicesList.c_str();
2996 break;
2998 case ALC_CAPTURE_DEVICE_SPECIFIER:
2999 if(VerifyDevice(&Device))
3001 value = Device->DeviceName.c_str();
3002 ALCdevice_DecRef(Device);
3004 else
3006 ProbeCaptureDeviceList();
3007 value = alcCaptureDeviceList.c_str();
3009 break;
3011 /* Default devices are always first in the list */
3012 case ALC_DEFAULT_DEVICE_SPECIFIER:
3013 value = alcDefaultName;
3014 break;
3016 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
3017 if(alcAllDevicesList.empty())
3018 ProbeAllDevicesList();
3020 /* Copy first entry as default. */
3021 alcDefaultAllDevicesSpecifier = alcAllDevicesList.c_str();
3022 value = alcDefaultAllDevicesSpecifier.c_str();
3023 break;
3025 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
3026 if(alcCaptureDeviceList.empty())
3027 ProbeCaptureDeviceList();
3029 /* Copy first entry as default. */
3030 alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList.c_str();
3031 value = alcCaptureDefaultDeviceSpecifier.c_str();
3032 break;
3034 case ALC_EXTENSIONS:
3035 if(!VerifyDevice(&Device))
3036 value = alcNoDeviceExtList;
3037 else
3039 value = alcExtensionList;
3040 ALCdevice_DecRef(Device);
3042 break;
3044 case ALC_HRTF_SPECIFIER_SOFT:
3045 if(!VerifyDevice(&Device))
3046 alcSetError(nullptr, ALC_INVALID_DEVICE);
3047 else
3049 almtx_lock(&Device->BackendLock);
3050 value = (Device->HrtfHandle ? Device->HrtfName.c_str() : "");
3051 almtx_unlock(&Device->BackendLock);
3052 ALCdevice_DecRef(Device);
3054 break;
3056 default:
3057 VerifyDevice(&Device);
3058 alcSetError(Device, ALC_INVALID_ENUM);
3059 if(Device) ALCdevice_DecRef(Device);
3060 break;
3063 return value;
3067 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
3069 if(device->Type == Capture) return 9;
3070 if(device->Type != Loopback) return 29;
3071 if(device->FmtChans == DevFmtAmbi3D)
3072 return 35;
3073 return 29;
3076 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3078 ALCsizei i;
3080 if(size <= 0 || values == nullptr)
3082 alcSetError(device, ALC_INVALID_VALUE);
3083 return 0;
3086 if(!device)
3088 switch(param)
3090 case ALC_MAJOR_VERSION:
3091 values[0] = alcMajorVersion;
3092 return 1;
3093 case ALC_MINOR_VERSION:
3094 values[0] = alcMinorVersion;
3095 return 1;
3097 case ALC_ATTRIBUTES_SIZE:
3098 case ALC_ALL_ATTRIBUTES:
3099 case ALC_FREQUENCY:
3100 case ALC_REFRESH:
3101 case ALC_SYNC:
3102 case ALC_MONO_SOURCES:
3103 case ALC_STEREO_SOURCES:
3104 case ALC_CAPTURE_SAMPLES:
3105 case ALC_FORMAT_CHANNELS_SOFT:
3106 case ALC_FORMAT_TYPE_SOFT:
3107 case ALC_AMBISONIC_LAYOUT_SOFT:
3108 case ALC_AMBISONIC_SCALING_SOFT:
3109 case ALC_AMBISONIC_ORDER_SOFT:
3110 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3111 alcSetError(nullptr, ALC_INVALID_DEVICE);
3112 return 0;
3114 default:
3115 alcSetError(nullptr, ALC_INVALID_ENUM);
3116 return 0;
3118 return 0;
3121 if(device->Type == Capture)
3123 switch(param)
3125 case ALC_ATTRIBUTES_SIZE:
3126 values[0] = NumAttrsForDevice(device);
3127 return 1;
3129 case ALC_ALL_ATTRIBUTES:
3130 if(size < NumAttrsForDevice(device))
3132 alcSetError(device, ALC_INVALID_VALUE);
3133 return 0;
3136 i = 0;
3137 almtx_lock(&device->BackendLock);
3138 values[i++] = ALC_MAJOR_VERSION;
3139 values[i++] = alcMajorVersion;
3140 values[i++] = ALC_MINOR_VERSION;
3141 values[i++] = alcMinorVersion;
3142 values[i++] = ALC_CAPTURE_SAMPLES;
3143 values[i++] = V0(device->Backend,availableSamples)();
3144 values[i++] = ALC_CONNECTED;
3145 values[i++] = ATOMIC_LOAD(&device->Connected, almemory_order_relaxed);
3146 almtx_unlock(&device->BackendLock);
3148 values[i++] = 0;
3149 return i;
3151 case ALC_MAJOR_VERSION:
3152 values[0] = alcMajorVersion;
3153 return 1;
3154 case ALC_MINOR_VERSION:
3155 values[0] = alcMinorVersion;
3156 return 1;
3158 case ALC_CAPTURE_SAMPLES:
3159 almtx_lock(&device->BackendLock);
3160 values[0] = V0(device->Backend,availableSamples)();
3161 almtx_unlock(&device->BackendLock);
3162 return 1;
3164 case ALC_CONNECTED:
3165 values[0] = ATOMIC_LOAD(&device->Connected, almemory_order_acquire);
3166 return 1;
3168 default:
3169 alcSetError(device, ALC_INVALID_ENUM);
3170 return 0;
3172 return 0;
3175 /* render device */
3176 switch(param)
3178 case ALC_ATTRIBUTES_SIZE:
3179 values[0] = NumAttrsForDevice(device);
3180 return 1;
3182 case ALC_ALL_ATTRIBUTES:
3183 if(size < NumAttrsForDevice(device))
3185 alcSetError(device, ALC_INVALID_VALUE);
3186 return 0;
3189 i = 0;
3190 almtx_lock(&device->BackendLock);
3191 values[i++] = ALC_MAJOR_VERSION;
3192 values[i++] = alcMajorVersion;
3193 values[i++] = ALC_MINOR_VERSION;
3194 values[i++] = alcMinorVersion;
3195 values[i++] = ALC_EFX_MAJOR_VERSION;
3196 values[i++] = alcEFXMajorVersion;
3197 values[i++] = ALC_EFX_MINOR_VERSION;
3198 values[i++] = alcEFXMinorVersion;
3200 values[i++] = ALC_FREQUENCY;
3201 values[i++] = device->Frequency;
3202 if(device->Type != Loopback)
3204 values[i++] = ALC_REFRESH;
3205 values[i++] = device->Frequency / device->UpdateSize;
3207 values[i++] = ALC_SYNC;
3208 values[i++] = ALC_FALSE;
3210 else
3212 if(device->FmtChans == DevFmtAmbi3D)
3214 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3215 values[i++] = device->mAmbiLayout;
3217 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3218 values[i++] = device->mAmbiScale;
3220 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3221 values[i++] = device->mAmbiOrder;
3224 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3225 values[i++] = device->FmtChans;
3227 values[i++] = ALC_FORMAT_TYPE_SOFT;
3228 values[i++] = device->FmtType;
3231 values[i++] = ALC_MONO_SOURCES;
3232 values[i++] = device->NumMonoSources;
3234 values[i++] = ALC_STEREO_SOURCES;
3235 values[i++] = device->NumStereoSources;
3237 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3238 values[i++] = device->NumAuxSends;
3240 values[i++] = ALC_HRTF_SOFT;
3241 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3243 values[i++] = ALC_HRTF_STATUS_SOFT;
3244 values[i++] = device->HrtfStatus;
3246 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3247 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3249 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
3250 values[i++] = MAX_AMBI_ORDER;
3251 almtx_unlock(&device->BackendLock);
3253 values[i++] = 0;
3254 return i;
3256 case ALC_MAJOR_VERSION:
3257 values[0] = alcMajorVersion;
3258 return 1;
3260 case ALC_MINOR_VERSION:
3261 values[0] = alcMinorVersion;
3262 return 1;
3264 case ALC_EFX_MAJOR_VERSION:
3265 values[0] = alcEFXMajorVersion;
3266 return 1;
3268 case ALC_EFX_MINOR_VERSION:
3269 values[0] = alcEFXMinorVersion;
3270 return 1;
3272 case ALC_FREQUENCY:
3273 values[0] = device->Frequency;
3274 return 1;
3276 case ALC_REFRESH:
3277 if(device->Type == Loopback)
3279 alcSetError(device, ALC_INVALID_DEVICE);
3280 return 0;
3282 almtx_lock(&device->BackendLock);
3283 values[0] = device->Frequency / device->UpdateSize;
3284 almtx_unlock(&device->BackendLock);
3285 return 1;
3287 case ALC_SYNC:
3288 if(device->Type == Loopback)
3290 alcSetError(device, ALC_INVALID_DEVICE);
3291 return 0;
3293 values[0] = ALC_FALSE;
3294 return 1;
3296 case ALC_FORMAT_CHANNELS_SOFT:
3297 if(device->Type != Loopback)
3299 alcSetError(device, ALC_INVALID_DEVICE);
3300 return 0;
3302 values[0] = device->FmtChans;
3303 return 1;
3305 case ALC_FORMAT_TYPE_SOFT:
3306 if(device->Type != Loopback)
3308 alcSetError(device, ALC_INVALID_DEVICE);
3309 return 0;
3311 values[0] = device->FmtType;
3312 return 1;
3314 case ALC_AMBISONIC_LAYOUT_SOFT:
3315 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3317 alcSetError(device, ALC_INVALID_DEVICE);
3318 return 0;
3320 values[0] = device->mAmbiLayout;
3321 return 1;
3323 case ALC_AMBISONIC_SCALING_SOFT:
3324 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3326 alcSetError(device, ALC_INVALID_DEVICE);
3327 return 0;
3329 values[0] = device->mAmbiScale;
3330 return 1;
3332 case ALC_AMBISONIC_ORDER_SOFT:
3333 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3335 alcSetError(device, ALC_INVALID_DEVICE);
3336 return 0;
3338 values[0] = device->mAmbiOrder;
3339 return 1;
3341 case ALC_MONO_SOURCES:
3342 values[0] = device->NumMonoSources;
3343 return 1;
3345 case ALC_STEREO_SOURCES:
3346 values[0] = device->NumStereoSources;
3347 return 1;
3349 case ALC_MAX_AUXILIARY_SENDS:
3350 values[0] = device->NumAuxSends;
3351 return 1;
3353 case ALC_CONNECTED:
3354 values[0] = ATOMIC_LOAD(&device->Connected, almemory_order_acquire);
3355 return 1;
3357 case ALC_HRTF_SOFT:
3358 values[0] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3359 return 1;
3361 case ALC_HRTF_STATUS_SOFT:
3362 values[0] = device->HrtfStatus;
3363 return 1;
3365 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3366 almtx_lock(&device->BackendLock);
3367 device->HrtfList.clear();
3368 device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
3369 values[0] = (ALCint)device->HrtfList.size();
3370 almtx_unlock(&device->BackendLock);
3371 return 1;
3373 case ALC_OUTPUT_LIMITER_SOFT:
3374 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3375 return 1;
3377 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3378 values[0] = MAX_AMBI_ORDER;
3379 return 1;
3381 default:
3382 alcSetError(device, ALC_INVALID_ENUM);
3383 return 0;
3385 return 0;
3388 /* alcGetIntegerv
3390 * Returns information about the device and the version of OpenAL
3392 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3394 VerifyDevice(&device);
3395 if(size <= 0 || values == nullptr)
3396 alcSetError(device, ALC_INVALID_VALUE);
3397 else
3398 GetIntegerv(device, param, size, values);
3399 if(device) ALCdevice_DecRef(device);
3402 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3404 ALsizei i;
3406 VerifyDevice(&device);
3407 if(size <= 0 || values == nullptr)
3408 alcSetError(device, ALC_INVALID_VALUE);
3409 else if(!device || device->Type == Capture)
3411 std::vector<ALCint> ivals(size);
3412 size = GetIntegerv(device, pname, size, ivals.data());
3413 for(i = 0;i < size;i++)
3414 values[i] = ivals[i];
3416 else /* render device */
3418 ClockLatency clock;
3419 ALuint64 basecount;
3420 ALuint samplecount;
3421 ALuint refcount;
3423 switch(pname)
3425 case ALC_ATTRIBUTES_SIZE:
3426 *values = NumAttrsForDevice(device)+4;
3427 break;
3429 case ALC_ALL_ATTRIBUTES:
3430 if(size < NumAttrsForDevice(device)+4)
3431 alcSetError(device, ALC_INVALID_VALUE);
3432 else
3434 i = 0;
3435 almtx_lock(&device->BackendLock);
3436 values[i++] = ALC_FREQUENCY;
3437 values[i++] = device->Frequency;
3439 if(device->Type != Loopback)
3441 values[i++] = ALC_REFRESH;
3442 values[i++] = device->Frequency / device->UpdateSize;
3444 values[i++] = ALC_SYNC;
3445 values[i++] = ALC_FALSE;
3447 else
3449 if(device->FmtChans == DevFmtAmbi3D)
3451 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3452 values[i++] = device->mAmbiLayout;
3454 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3455 values[i++] = device->mAmbiScale;
3457 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3458 values[i++] = device->mAmbiOrder;
3461 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3462 values[i++] = device->FmtChans;
3464 values[i++] = ALC_FORMAT_TYPE_SOFT;
3465 values[i++] = device->FmtType;
3468 values[i++] = ALC_MONO_SOURCES;
3469 values[i++] = device->NumMonoSources;
3471 values[i++] = ALC_STEREO_SOURCES;
3472 values[i++] = device->NumStereoSources;
3474 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3475 values[i++] = device->NumAuxSends;
3477 values[i++] = ALC_HRTF_SOFT;
3478 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3480 values[i++] = ALC_HRTF_STATUS_SOFT;
3481 values[i++] = device->HrtfStatus;
3483 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3484 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3486 clock = GetClockLatency(device);
3487 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3488 values[i++] = clock.ClockTime;
3490 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3491 values[i++] = clock.Latency;
3492 almtx_unlock(&device->BackendLock);
3494 values[i++] = 0;
3496 break;
3498 case ALC_DEVICE_CLOCK_SOFT:
3499 almtx_lock(&device->BackendLock);
3500 do {
3501 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3502 althrd_yield();
3503 basecount = device->ClockBase;
3504 samplecount = device->SamplesDone;
3505 } while(refcount != ReadRef(&device->MixCount));
3506 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3507 almtx_unlock(&device->BackendLock);
3508 break;
3510 case ALC_DEVICE_LATENCY_SOFT:
3511 almtx_lock(&device->BackendLock);
3512 clock = GetClockLatency(device);
3513 almtx_unlock(&device->BackendLock);
3514 *values = clock.Latency;
3515 break;
3517 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3518 if(size < 2)
3519 alcSetError(device, ALC_INVALID_VALUE);
3520 else
3522 almtx_lock(&device->BackendLock);
3523 clock = GetClockLatency(device);
3524 almtx_unlock(&device->BackendLock);
3525 values[0] = clock.ClockTime;
3526 values[1] = clock.Latency;
3528 break;
3530 default:
3531 std::vector<ALCint> ivals(size);
3532 size = GetIntegerv(device, pname, size, ivals.data());
3533 for(i = 0;i < size;i++)
3534 values[i] = ivals[i];
3535 break;
3538 if(device)
3539 ALCdevice_DecRef(device);
3543 /* alcIsExtensionPresent
3545 * Determines if there is support for a particular extension
3547 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3549 ALCboolean bResult = ALC_FALSE;
3551 VerifyDevice(&device);
3553 if(!extName)
3554 alcSetError(device, ALC_INVALID_VALUE);
3555 else
3557 size_t len = strlen(extName);
3558 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3559 while(ptr && *ptr)
3561 if(strncasecmp(ptr, extName, len) == 0 &&
3562 (ptr[len] == '\0' || isspace(ptr[len])))
3564 bResult = ALC_TRUE;
3565 break;
3567 if((ptr=strchr(ptr, ' ')) != nullptr)
3569 do {
3570 ++ptr;
3571 } while(isspace(*ptr));
3575 if(device)
3576 ALCdevice_DecRef(device);
3577 return bResult;
3581 /* alcGetProcAddress
3583 * Retrieves the function address for a particular extension function
3585 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3587 ALCvoid *ptr = nullptr;
3589 if(!funcName)
3591 VerifyDevice(&device);
3592 alcSetError(device, ALC_INVALID_VALUE);
3593 if(device) ALCdevice_DecRef(device);
3595 else
3597 size_t i = 0;
3598 for(i = 0;i < COUNTOF(alcFunctions);i++)
3600 if(strcmp(alcFunctions[i].funcName, funcName) == 0)
3602 ptr = alcFunctions[i].address;
3603 break;
3608 return ptr;
3612 /* alcGetEnumValue
3614 * Get the value for a particular ALC enumeration name
3616 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3618 ALCenum val = 0;
3620 if(!enumName)
3622 VerifyDevice(&device);
3623 alcSetError(device, ALC_INVALID_VALUE);
3624 if(device) ALCdevice_DecRef(device);
3626 else
3628 size_t i = 0;
3629 for(i = 0;i < COUNTOF(alcEnumerations);i++)
3631 if(strcmp(alcEnumerations[i].enumName, enumName) == 0)
3633 val = alcEnumerations[i].value;
3634 break;
3639 return val;
3643 /* alcCreateContext
3645 * Create and attach a context to the given device.
3647 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3649 ALCcontext *ALContext;
3650 ALfloat valf;
3651 ALCenum err;
3653 /* Explicitly hold the list lock while taking the BackendLock in case the
3654 * device is asynchronously destropyed, to ensure this new context is
3655 * properly cleaned up after being made.
3657 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3658 if(!VerifyDevice(&device) || device->Type == Capture ||
3659 !ATOMIC_LOAD(&device->Connected, almemory_order_relaxed))
3661 listlock.unlock();
3662 alcSetError(device, ALC_INVALID_DEVICE);
3663 if(device) ALCdevice_DecRef(device);
3664 return nullptr;
3666 almtx_lock(&device->BackendLock);
3667 listlock.unlock();
3669 ATOMIC_STORE_SEQ(&device->LastError, ALC_NO_ERROR);
3671 ALContext = new ALCcontext{device};
3672 ALCdevice_IncRef(ALContext->Device);
3674 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3676 almtx_unlock(&device->BackendLock);
3678 delete ALContext;
3679 ALContext = nullptr;
3681 alcSetError(device, err);
3682 if(err == ALC_INVALID_DEVICE)
3684 V0(device->Backend,lock)();
3685 aluHandleDisconnect(device, "Device update failure");
3686 V0(device->Backend,unlock)();
3688 ALCdevice_DecRef(device);
3689 return nullptr;
3691 AllocateVoices(ALContext, 256, device->NumAuxSends);
3693 if(DefaultEffect.type != AL_EFFECT_NULL && device->Type == Playback)
3695 ALContext->DefaultSlot = new ALeffectslot{};
3696 if(InitEffectSlot(ALContext->DefaultSlot) == AL_NO_ERROR)
3697 aluInitEffectPanning(ALContext->DefaultSlot);
3698 else
3700 delete ALContext->DefaultSlot;
3701 ALContext->DefaultSlot = nullptr;
3702 ERR("Failed to initialize the default effect slot\n");
3706 InitContext(ALContext);
3708 if(ConfigValueFloat(device->DeviceName.c_str(), nullptr, "volume-adjust", &valf))
3710 if(!std::isfinite(valf))
3711 ERR("volume-adjust must be finite: %f\n", valf);
3712 else
3714 ALfloat db = clampf(valf, -24.0f, 24.0f);
3715 if(db != valf)
3716 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3717 ALContext->GainBoost = std::pow(10.0f, db/20.0f);
3718 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3721 UpdateListenerProps(ALContext);
3724 ALCcontext *head = ATOMIC_LOAD_SEQ(&device->ContextList);
3725 do {
3726 ATOMIC_STORE(&ALContext->next, head, almemory_order_relaxed);
3727 } while(ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(&device->ContextList, &head,
3728 ALContext) == 0);
3730 almtx_unlock(&device->BackendLock);
3732 if(ALContext->DefaultSlot)
3734 if(InitializeEffect(ALContext, ALContext->DefaultSlot, &DefaultEffect) == AL_NO_ERROR)
3735 UpdateEffectSlotProps(ALContext->DefaultSlot, ALContext);
3736 else
3737 ERR("Failed to initialize the default effect\n");
3740 ALCdevice_DecRef(device);
3742 TRACE("Created context %p\n", ALContext);
3743 return ALContext;
3746 /* alcDestroyContext
3748 * Remove a context from its device
3750 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3752 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3753 if(!VerifyContext(&context))
3755 listlock.unlock();
3756 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3757 return;
3760 ALCdevice* Device{context->Device};
3761 if(Device)
3763 almtx_lock(&Device->BackendLock);
3764 if(!ReleaseContext(context, Device))
3766 V0(Device->Backend,stop)();
3767 Device->Flags &= ~DEVICE_RUNNING;
3769 almtx_unlock(&Device->BackendLock);
3771 listlock.unlock();
3773 ALCcontext_DecRef(context);
3777 /* alcGetCurrentContext
3779 * Returns the currently active context on the calling thread
3781 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3783 ALCcontext *Context{LocalContext.get()};
3784 if(!Context) Context = GlobalContext.load();
3785 return Context;
3788 /* alcGetThreadContext
3790 * Returns the currently active thread-local context
3792 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3794 return LocalContext.get();
3798 /* alcMakeContextCurrent
3800 * Makes the given context the active process-wide context, and removes the
3801 * thread-local context for the calling thread.
3803 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3805 /* context must be valid or nullptr */
3806 if(context && !VerifyContext(&context))
3808 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3809 return ALC_FALSE;
3811 /* context's reference count is already incremented */
3812 context = GlobalContext.exchange(context);
3813 if(context) ALCcontext_DecRef(context);
3815 if((context=LocalContext.get()) != nullptr)
3817 LocalContext.set(nullptr);
3818 ALCcontext_DecRef(context);
3821 return ALC_TRUE;
3824 /* alcSetThreadContext
3826 * Makes the given context the active context for the current thread
3828 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3830 /* context must be valid or nullptr */
3831 if(context && !VerifyContext(&context))
3833 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3834 return ALC_FALSE;
3836 /* context's reference count is already incremented */
3837 ALCcontext *old{LocalContext.get()};
3838 LocalContext.set(context);
3839 if(old) ALCcontext_DecRef(old);
3841 return ALC_TRUE;
3845 /* alcGetContextsDevice
3847 * Returns the device that a particular context is attached to
3849 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3851 if(!VerifyContext(&Context))
3853 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3854 return nullptr;
3856 ALCdevice *Device{Context->Device};
3857 ALCcontext_DecRef(Context);
3859 return Device;
3863 /* alcOpenDevice
3865 * Opens the named device.
3867 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3869 DO_INITCONFIG();
3871 if(!PlaybackBackend.name)
3873 alcSetError(nullptr, ALC_INVALID_VALUE);
3874 return nullptr;
3877 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
3878 #ifdef _WIN32
3879 /* Some old Windows apps hardcode these expecting OpenAL to use a
3880 * specific audio API, even when they're not enumerated. Creative's
3881 * router effectively ignores them too.
3883 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
3884 || strcasecmp(deviceName, "MMSYSTEM") == 0
3885 #endif
3887 deviceName = nullptr;
3889 auto device = new ALCdevice{Playback};
3891 //Set output format
3892 device->FmtChans = DevFmtChannelsDefault;
3893 device->FmtType = DevFmtTypeDefault;
3894 device->Frequency = DEFAULT_OUTPUT_RATE;
3895 device->IsHeadphones = AL_FALSE;
3896 device->mAmbiLayout = AmbiLayout_Default;
3897 device->mAmbiScale = AmbiNorm_Default;
3898 device->LimiterState = ALC_TRUE;
3899 device->NumUpdates = 3;
3900 device->UpdateSize = 1024;
3902 device->SourcesMax = 256;
3903 device->AuxiliaryEffectSlotMax = 64;
3904 device->NumAuxSends = DEFAULT_SENDS;
3906 const ALCchar *fmt{};
3907 if(ConfigValueStr(deviceName, nullptr, "channels", &fmt))
3909 static constexpr struct ChannelMap {
3910 const char name[16];
3911 enum DevFmtChannels chans;
3912 ALsizei order;
3913 } chanlist[] = {
3914 { "mono", DevFmtMono, 0 },
3915 { "stereo", DevFmtStereo, 0 },
3916 { "quad", DevFmtQuad, 0 },
3917 { "surround51", DevFmtX51, 0 },
3918 { "surround61", DevFmtX61, 0 },
3919 { "surround71", DevFmtX71, 0 },
3920 { "surround51rear", DevFmtX51Rear, 0 },
3921 { "ambi1", DevFmtAmbi3D, 1 },
3922 { "ambi2", DevFmtAmbi3D, 2 },
3923 { "ambi3", DevFmtAmbi3D, 3 },
3926 auto iter = std::find_if(std::begin(chanlist), std::end(chanlist),
3927 [fmt](const ChannelMap &entry) -> bool
3928 { return strcasecmp(entry.name, fmt) == 0; }
3930 if(iter == std::end(chanlist))
3931 ERR("Unsupported channels: %s\n", fmt);
3932 else
3934 device->FmtChans = iter->chans;
3935 device->mAmbiOrder = iter->order;
3936 device->Flags |= DEVICE_CHANNELS_REQUEST;
3939 if(ConfigValueStr(deviceName, nullptr, "sample-type", &fmt))
3941 static constexpr struct TypeMap {
3942 const char name[16];
3943 enum DevFmtType type;
3944 } typelist[] = {
3945 { "int8", DevFmtByte },
3946 { "uint8", DevFmtUByte },
3947 { "int16", DevFmtShort },
3948 { "uint16", DevFmtUShort },
3949 { "int32", DevFmtInt },
3950 { "uint32", DevFmtUInt },
3951 { "float32", DevFmtFloat },
3954 auto iter = std::find_if(std::begin(typelist), std::end(typelist),
3955 [fmt](const TypeMap &entry) -> bool
3956 { return strcasecmp(entry.name, fmt) == 0; }
3958 if(iter == std::end(typelist))
3959 ERR("Unsupported sample-type: %s\n", fmt);
3960 else
3962 device->FmtType = iter->type;
3963 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3967 if(ConfigValueUInt(deviceName, nullptr, "frequency", &device->Frequency))
3969 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3970 if(device->Frequency < MIN_OUTPUT_RATE)
3971 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3972 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3975 ConfigValueUInt(deviceName, nullptr, "periods", &device->NumUpdates);
3976 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3978 ConfigValueUInt(deviceName, nullptr, "period_size", &device->UpdateSize);
3979 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3980 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
3981 device->UpdateSize = (device->UpdateSize+3)&~3;
3983 ConfigValueUInt(deviceName, nullptr, "sources", &device->SourcesMax);
3984 if(device->SourcesMax == 0) device->SourcesMax = 256;
3986 ConfigValueUInt(deviceName, nullptr, "slots", &device->AuxiliaryEffectSlotMax);
3987 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
3988 else device->AuxiliaryEffectSlotMax = minu(device->AuxiliaryEffectSlotMax, INT_MAX);
3990 if(ConfigValueInt(deviceName, nullptr, "sends", &device->NumAuxSends))
3991 device->NumAuxSends = clampi(
3992 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
3995 device->NumStereoSources = 1;
3996 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3998 device->Backend = PlaybackBackend.getFactory().createBackend(device, ALCbackend_Playback);
3999 if(!device->Backend)
4001 delete device;
4002 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
4003 return nullptr;
4006 // Find a playback device to open
4007 ALCenum err{V(device->Backend,open)(deviceName)};
4008 if(err != ALC_NO_ERROR)
4010 delete device;
4011 alcSetError(nullptr, err);
4012 return nullptr;
4015 if(ConfigValueStr(device->DeviceName.c_str(), nullptr, "ambi-format", &fmt))
4017 if(strcasecmp(fmt, "fuma") == 0)
4019 device->mAmbiLayout = AmbiLayout_FuMa;
4020 device->mAmbiScale = AmbiNorm_FuMa;
4022 else if(strcasecmp(fmt, "acn+sn3d") == 0)
4024 device->mAmbiLayout = AmbiLayout_ACN;
4025 device->mAmbiScale = AmbiNorm_SN3D;
4027 else if(strcasecmp(fmt, "acn+n3d") == 0)
4029 device->mAmbiLayout = AmbiLayout_ACN;
4030 device->mAmbiScale = AmbiNorm_N3D;
4032 else
4033 ERR("Unsupported ambi-format: %s\n", fmt);
4037 ALCdevice *head{DeviceList.load()};
4038 do {
4039 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4040 } while(!DeviceList.compare_exchange_weak(head, device));
4043 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName.c_str());
4044 return device;
4047 /* alcCloseDevice
4049 * Closes the given device.
4051 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
4053 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4054 ALCdevice *iter{DeviceList.load()};
4055 do {
4056 if(iter == device)
4057 break;
4058 iter = ATOMIC_LOAD(&iter->next, almemory_order_relaxed);
4059 } while(iter != nullptr);
4060 if(!iter || iter->Type == Capture)
4062 alcSetError(iter, ALC_INVALID_DEVICE);
4063 return ALC_FALSE;
4065 almtx_lock(&device->BackendLock);
4067 ALCdevice *origdev{device};
4068 ALCdevice *nextdev{ATOMIC_LOAD(&device->next, almemory_order_relaxed)};
4069 if(!DeviceList.compare_exchange_strong(origdev, nextdev))
4071 ALCdevice *list;
4072 do {
4073 list = origdev;
4074 origdev = device;
4075 } while(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(&list->next, &origdev, nextdev));
4077 listlock.unlock();
4079 ALCcontext *ctx{ATOMIC_LOAD_SEQ(&device->ContextList)};
4080 while(ctx != nullptr)
4082 ALCcontext *next = ATOMIC_LOAD(&ctx->next, almemory_order_relaxed);
4083 WARN("Releasing context %p\n", ctx);
4084 ReleaseContext(ctx, device);
4085 ctx = next;
4087 if((device->Flags&DEVICE_RUNNING))
4088 V0(device->Backend,stop)();
4089 device->Flags &= ~DEVICE_RUNNING;
4090 almtx_unlock(&device->BackendLock);
4092 ALCdevice_DecRef(device);
4094 return ALC_TRUE;
4098 /************************************************
4099 * ALC capture functions
4100 ************************************************/
4101 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
4103 DO_INITCONFIG();
4105 if(!CaptureBackend.name)
4107 alcSetError(nullptr, ALC_INVALID_VALUE);
4108 return nullptr;
4111 if(samples <= 0)
4113 alcSetError(nullptr, ALC_INVALID_VALUE);
4114 return nullptr;
4117 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
4118 deviceName = nullptr;
4120 auto device = new ALCdevice{Capture};
4122 device->Frequency = frequency;
4123 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4125 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
4127 delete device;
4128 alcSetError(nullptr, ALC_INVALID_ENUM);
4129 return nullptr;
4131 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
4132 device->IsHeadphones = AL_FALSE;
4133 device->mAmbiOrder = 0;
4134 device->mAmbiLayout = AmbiLayout_Default;
4135 device->mAmbiScale = AmbiNorm_Default;
4137 device->UpdateSize = samples;
4138 device->NumUpdates = 1;
4140 device->Backend = CaptureBackend.getFactory().createBackend(device, ALCbackend_Capture);
4141 if(!device->Backend)
4143 delete device;
4144 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
4145 return nullptr;
4148 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4149 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
4150 device->Frequency, device->UpdateSize, device->NumUpdates
4152 ALCenum err{V(device->Backend,open)(deviceName)};
4153 if(err != ALC_NO_ERROR)
4155 delete device;
4156 alcSetError(nullptr, err);
4157 return nullptr;
4161 ALCdevice *head{DeviceList.load()};
4162 do {
4163 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4164 } while(!DeviceList.compare_exchange_weak(head, device));
4167 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName.c_str());
4168 return device;
4171 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
4173 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4175 ALCdevice *iter{DeviceList.load()};
4176 do {
4177 if(iter == device)
4178 break;
4179 iter = ATOMIC_LOAD(&iter->next, almemory_order_relaxed);
4180 } while(iter != nullptr);
4181 if(!iter || iter->Type != Capture)
4183 alcSetError(iter, ALC_INVALID_DEVICE);
4184 return ALC_FALSE;
4187 ALCdevice *origdev{device};
4188 ALCdevice *nextdev{ATOMIC_LOAD(&device->next, almemory_order_relaxed)};
4189 if(!DeviceList.compare_exchange_strong(origdev, nextdev))
4191 ALCdevice *list;
4192 do {
4193 list = origdev;
4194 origdev = device;
4195 } while(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(&list->next, &origdev, nextdev));
4197 listlock.unlock();
4199 almtx_lock(&device->BackendLock);
4200 if((device->Flags&DEVICE_RUNNING))
4201 V0(device->Backend,stop)();
4202 device->Flags &= ~DEVICE_RUNNING;
4203 almtx_unlock(&device->BackendLock);
4205 ALCdevice_DecRef(device);
4207 return ALC_TRUE;
4210 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
4212 if(!VerifyDevice(&device) || device->Type != Capture)
4213 alcSetError(device, ALC_INVALID_DEVICE);
4214 else
4216 almtx_lock(&device->BackendLock);
4217 if(!ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
4218 alcSetError(device, ALC_INVALID_DEVICE);
4219 else if(!(device->Flags&DEVICE_RUNNING))
4221 if(V0(device->Backend,start)())
4222 device->Flags |= DEVICE_RUNNING;
4223 else
4225 aluHandleDisconnect(device, "Device start failure");
4226 alcSetError(device, ALC_INVALID_DEVICE);
4229 almtx_unlock(&device->BackendLock);
4232 if(device) ALCdevice_DecRef(device);
4235 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
4237 if(!VerifyDevice(&device) || device->Type != Capture)
4238 alcSetError(device, ALC_INVALID_DEVICE);
4239 else
4241 almtx_lock(&device->BackendLock);
4242 if((device->Flags&DEVICE_RUNNING))
4243 V0(device->Backend,stop)();
4244 device->Flags &= ~DEVICE_RUNNING;
4245 almtx_unlock(&device->BackendLock);
4248 if(device) ALCdevice_DecRef(device);
4251 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4253 if(!VerifyDevice(&device) || device->Type != Capture)
4254 alcSetError(device, ALC_INVALID_DEVICE);
4255 else
4257 ALCenum err = ALC_INVALID_VALUE;
4259 almtx_lock(&device->BackendLock);
4260 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
4261 err = V(device->Backend,captureSamples)(buffer, samples);
4262 almtx_unlock(&device->BackendLock);
4264 if(err != ALC_NO_ERROR)
4265 alcSetError(device, err);
4267 if(device) ALCdevice_DecRef(device);
4271 /************************************************
4272 * ALC loopback functions
4273 ************************************************/
4275 /* alcLoopbackOpenDeviceSOFT
4277 * Open a loopback device, for manual rendering.
4279 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
4281 DO_INITCONFIG();
4283 /* Make sure the device name, if specified, is us. */
4284 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
4286 alcSetError(nullptr, ALC_INVALID_VALUE);
4287 return nullptr;
4290 auto device = new ALCdevice{Loopback};
4292 device->SourcesMax = 256;
4293 device->AuxiliaryEffectSlotMax = 64;
4294 device->NumAuxSends = DEFAULT_SENDS;
4296 //Set output format
4297 device->NumUpdates = 0;
4298 device->UpdateSize = 0;
4300 device->Frequency = DEFAULT_OUTPUT_RATE;
4301 device->FmtChans = DevFmtChannelsDefault;
4302 device->FmtType = DevFmtTypeDefault;
4303 device->IsHeadphones = AL_FALSE;
4304 device->mAmbiLayout = AmbiLayout_Default;
4305 device->mAmbiScale = AmbiNorm_Default;
4307 ConfigValueUInt(nullptr, nullptr, "sources", &device->SourcesMax);
4308 if(device->SourcesMax == 0) device->SourcesMax = 256;
4310 ConfigValueUInt(nullptr, nullptr, "slots", &device->AuxiliaryEffectSlotMax);
4311 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4312 else device->AuxiliaryEffectSlotMax = minu(device->AuxiliaryEffectSlotMax, INT_MAX);
4314 if(ConfigValueInt(nullptr, nullptr, "sends", &device->NumAuxSends))
4315 device->NumAuxSends = clampi(
4316 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4319 device->NumStereoSources = 1;
4320 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4322 device->Backend = LoopbackBackendFactory::getFactory().createBackend(
4323 device, ALCbackend_Loopback);
4324 if(!device->Backend)
4326 al_free(device);
4327 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
4328 return nullptr;
4331 // Open the "backend"
4332 V(device->Backend,open)("Loopback");
4335 ALCdevice *head{DeviceList.load()};
4336 do {
4337 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4338 } while(!DeviceList.compare_exchange_weak(head, device));
4341 TRACE("Created device %p\n", device);
4342 return device;
4345 /* alcIsRenderFormatSupportedSOFT
4347 * Determines if the loopback device supports the given format for rendering.
4349 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4351 ALCboolean ret{ALC_FALSE};
4353 if(!VerifyDevice(&device) || device->Type != Loopback)
4354 alcSetError(device, ALC_INVALID_DEVICE);
4355 else if(freq <= 0)
4356 alcSetError(device, ALC_INVALID_VALUE);
4357 else
4359 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4360 ret = ALC_TRUE;
4362 if(device) ALCdevice_DecRef(device);
4364 return ret;
4367 /* alcRenderSamplesSOFT
4369 * Renders some samples into a buffer, using the format last set by the
4370 * attributes given to alcCreateContext.
4372 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4374 if(!VerifyDevice(&device) || device->Type != Loopback)
4375 alcSetError(device, ALC_INVALID_DEVICE);
4376 else if(samples < 0 || (samples > 0 && buffer == nullptr))
4377 alcSetError(device, ALC_INVALID_VALUE);
4378 else
4380 V0(device->Backend,lock)();
4381 aluMixData(device, buffer, samples);
4382 V0(device->Backend,unlock)();
4384 if(device) ALCdevice_DecRef(device);
4388 /************************************************
4389 * ALC DSP pause/resume functions
4390 ************************************************/
4392 /* alcDevicePauseSOFT
4394 * Pause the DSP to stop audio processing.
4396 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4398 if(!VerifyDevice(&device) || device->Type != Playback)
4399 alcSetError(device, ALC_INVALID_DEVICE);
4400 else
4402 almtx_lock(&device->BackendLock);
4403 if((device->Flags&DEVICE_RUNNING))
4404 V0(device->Backend,stop)();
4405 device->Flags &= ~DEVICE_RUNNING;
4406 device->Flags |= DEVICE_PAUSED;
4407 almtx_unlock(&device->BackendLock);
4409 if(device) ALCdevice_DecRef(device);
4412 /* alcDeviceResumeSOFT
4414 * Resume the DSP to restart audio processing.
4416 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4418 if(!VerifyDevice(&device) || device->Type != Playback)
4419 alcSetError(device, ALC_INVALID_DEVICE);
4420 else
4422 almtx_lock(&device->BackendLock);
4423 if((device->Flags&DEVICE_PAUSED))
4425 device->Flags &= ~DEVICE_PAUSED;
4426 if(ATOMIC_LOAD_SEQ(&device->ContextList) != nullptr)
4428 if(V0(device->Backend,start)() != ALC_FALSE)
4429 device->Flags |= DEVICE_RUNNING;
4430 else
4432 V0(device->Backend,lock)();
4433 aluHandleDisconnect(device, "Device start failure");
4434 V0(device->Backend,unlock)();
4435 alcSetError(device, ALC_INVALID_DEVICE);
4439 almtx_unlock(&device->BackendLock);
4441 if(device) ALCdevice_DecRef(device);
4445 /************************************************
4446 * ALC HRTF functions
4447 ************************************************/
4449 /* alcGetStringiSOFT
4451 * Gets a string parameter at the given index.
4453 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4455 const ALCchar *str{nullptr};
4457 if(!VerifyDevice(&device) || device->Type == Capture)
4458 alcSetError(device, ALC_INVALID_DEVICE);
4459 else switch(paramName)
4461 case ALC_HRTF_SPECIFIER_SOFT:
4462 if(index >= 0 && (size_t)index < device->HrtfList.size())
4463 str = device->HrtfList[index].name.c_str();
4464 else
4465 alcSetError(device, ALC_INVALID_VALUE);
4466 break;
4468 default:
4469 alcSetError(device, ALC_INVALID_ENUM);
4470 break;
4472 if(device) ALCdevice_DecRef(device);
4474 return str;
4477 /* alcResetDeviceSOFT
4479 * Resets the given device output, using the specified attribute list.
4481 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4483 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4484 if(!VerifyDevice(&device) || device->Type == Capture ||
4485 !ATOMIC_LOAD(&device->Connected, almemory_order_relaxed))
4487 listlock.unlock();
4488 alcSetError(device, ALC_INVALID_DEVICE);
4489 if(device) ALCdevice_DecRef(device);
4490 return ALC_FALSE;
4492 almtx_lock(&device->BackendLock);
4493 listlock.unlock();
4495 ALCenum err{UpdateDeviceParams(device, attribs)};
4496 almtx_unlock(&device->BackendLock);
4498 if(err != ALC_NO_ERROR)
4500 alcSetError(device, err);
4501 if(err == ALC_INVALID_DEVICE)
4503 V0(device->Backend,lock)();
4504 aluHandleDisconnect(device, "Device start failure");
4505 V0(device->Backend,unlock)();
4507 ALCdevice_DecRef(device);
4508 return ALC_FALSE;
4510 ALCdevice_DecRef(device);
4512 return ALC_TRUE;