Use proper inheritence for the effect state objects
[openal-soft.git] / Alc / alc.cpp
blob56a581fd86f94d586362fba42e42bd37d0881179
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(context->DeferUpdates.exchange(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(!context->PropsClean.exchange(AL_TRUE, std::memory_order_acq_rel))
1627 UpdateContextProps(context);
1628 if(!context->Listener.PropsClean.exchange(AL_TRUE, std::memory_order_acq_rel))
1629 UpdateListenerProps(context);
1630 UpdateAllEffectSlotProps(context);
1631 UpdateAllSourceProps(context);
1633 /* Now with all updates declared, let the mixer continue applying them
1634 * so they all happen at once.
1636 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 ALCsizei i;
1708 int val;
1710 // Check for attributes
1711 if(device->Type == Loopback)
1713 ALCsizei numMono, numStereo, numSends;
1714 ALCenum alayout = AL_NONE;
1715 ALCenum ascale = AL_NONE;
1716 ALCenum schans = AL_NONE;
1717 ALCenum stype = AL_NONE;
1718 ALCsizei attrIdx = 0;
1719 ALCsizei aorder = 0;
1720 ALCuint freq = 0;
1722 if(!attrList)
1724 WARN("Missing attributes for loopback device\n");
1725 return ALC_INVALID_VALUE;
1728 numMono = device->NumMonoSources;
1729 numStereo = device->NumStereoSources;
1730 numSends = old_sends;
1732 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1733 while(attrList[attrIdx])
1735 switch(attrList[attrIdx])
1737 case ALC_FORMAT_CHANNELS_SOFT:
1738 schans = attrList[attrIdx + 1];
1739 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1740 if(!IsValidALCChannels(schans))
1741 return ALC_INVALID_VALUE;
1742 break;
1744 case ALC_FORMAT_TYPE_SOFT:
1745 stype = attrList[attrIdx + 1];
1746 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1747 if(!IsValidALCType(stype))
1748 return ALC_INVALID_VALUE;
1749 break;
1751 case ALC_FREQUENCY:
1752 freq = attrList[attrIdx + 1];
1753 TRACE_ATTR(ALC_FREQUENCY, freq);
1754 if(freq < MIN_OUTPUT_RATE)
1755 return ALC_INVALID_VALUE;
1756 break;
1758 case ALC_AMBISONIC_LAYOUT_SOFT:
1759 alayout = attrList[attrIdx + 1];
1760 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1761 if(!IsValidAmbiLayout(alayout))
1762 return ALC_INVALID_VALUE;
1763 break;
1765 case ALC_AMBISONIC_SCALING_SOFT:
1766 ascale = attrList[attrIdx + 1];
1767 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1768 if(!IsValidAmbiScaling(ascale))
1769 return ALC_INVALID_VALUE;
1770 break;
1772 case ALC_AMBISONIC_ORDER_SOFT:
1773 aorder = attrList[attrIdx + 1];
1774 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1775 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1776 return ALC_INVALID_VALUE;
1777 break;
1779 case ALC_MONO_SOURCES:
1780 numMono = attrList[attrIdx + 1];
1781 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1782 numMono = maxi(numMono, 0);
1783 break;
1785 case ALC_STEREO_SOURCES:
1786 numStereo = attrList[attrIdx + 1];
1787 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1788 numStereo = maxi(numStereo, 0);
1789 break;
1791 case ALC_MAX_AUXILIARY_SENDS:
1792 numSends = attrList[attrIdx + 1];
1793 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1794 numSends = clampi(numSends, 0, MAX_SENDS);
1795 break;
1797 case ALC_HRTF_SOFT:
1798 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1799 if(attrList[attrIdx + 1] == ALC_FALSE)
1800 hrtf_appreq = Hrtf_Disable;
1801 else if(attrList[attrIdx + 1] == ALC_TRUE)
1802 hrtf_appreq = Hrtf_Enable;
1803 else
1804 hrtf_appreq = Hrtf_Default;
1805 break;
1807 case ALC_HRTF_ID_SOFT:
1808 hrtf_id = attrList[attrIdx + 1];
1809 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1810 break;
1812 case ALC_OUTPUT_LIMITER_SOFT:
1813 gainLimiter = attrList[attrIdx + 1];
1814 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1815 break;
1817 default:
1818 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList[attrIdx],
1819 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1820 break;
1823 attrIdx += 2;
1825 #undef TRACE_ATTR
1827 if(!schans || !stype || !freq)
1829 WARN("Missing format for loopback device\n");
1830 return ALC_INVALID_VALUE;
1832 if(schans == ALC_BFORMAT3D_SOFT && (!alayout || !ascale || !aorder))
1834 WARN("Missing ambisonic info for loopback device\n");
1835 return ALC_INVALID_VALUE;
1838 if((device->Flags&DEVICE_RUNNING))
1839 V0(device->Backend,stop)();
1840 device->Flags &= ~DEVICE_RUNNING;
1842 UpdateClockBase(device);
1844 device->Frequency = freq;
1845 device->FmtChans = static_cast<enum DevFmtChannels>(schans);
1846 device->FmtType = static_cast<enum DevFmtType>(stype);
1847 if(schans == ALC_BFORMAT3D_SOFT)
1849 device->mAmbiOrder = aorder;
1850 device->mAmbiLayout = static_cast<enum AmbiLayout>(alayout);
1851 device->mAmbiScale = static_cast<enum AmbiNorm>(ascale);
1854 if(numMono > INT_MAX-numStereo)
1855 numMono = INT_MAX-numStereo;
1856 numMono += numStereo;
1857 if(ConfigValueInt(nullptr, nullptr, "sources", &numMono))
1859 if(numMono <= 0)
1860 numMono = 256;
1862 else
1863 numMono = maxi(numMono, 256);
1864 numStereo = mini(numStereo, numMono);
1865 numMono -= numStereo;
1866 device->SourcesMax = numMono + numStereo;
1868 device->NumMonoSources = numMono;
1869 device->NumStereoSources = numStereo;
1871 if(ConfigValueInt(nullptr, nullptr, "sends", &new_sends))
1872 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1873 else
1874 new_sends = numSends;
1876 else if(attrList && attrList[0])
1878 ALCsizei numMono, numStereo, numSends;
1879 ALCsizei attrIdx = 0;
1880 ALCuint freq;
1882 /* If a context is already running on the device, stop playback so the
1883 * device attributes can be updated. */
1884 if((device->Flags&DEVICE_RUNNING))
1885 V0(device->Backend,stop)();
1886 device->Flags &= ~DEVICE_RUNNING;
1888 UpdateClockBase(device);
1890 freq = device->Frequency;
1891 numMono = device->NumMonoSources;
1892 numStereo = device->NumStereoSources;
1893 numSends = old_sends;
1895 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1896 while(attrList[attrIdx])
1898 switch(attrList[attrIdx])
1900 case ALC_FREQUENCY:
1901 freq = attrList[attrIdx + 1];
1902 TRACE_ATTR(ALC_FREQUENCY, freq);
1903 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1904 break;
1906 case ALC_MONO_SOURCES:
1907 numMono = attrList[attrIdx + 1];
1908 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1909 numMono = maxi(numMono, 0);
1910 break;
1912 case ALC_STEREO_SOURCES:
1913 numStereo = attrList[attrIdx + 1];
1914 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1915 numStereo = maxi(numStereo, 0);
1916 break;
1918 case ALC_MAX_AUXILIARY_SENDS:
1919 numSends = attrList[attrIdx + 1];
1920 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1921 numSends = clampi(numSends, 0, MAX_SENDS);
1922 break;
1924 case ALC_HRTF_SOFT:
1925 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1926 if(attrList[attrIdx + 1] == ALC_FALSE)
1927 hrtf_appreq = Hrtf_Disable;
1928 else if(attrList[attrIdx + 1] == ALC_TRUE)
1929 hrtf_appreq = Hrtf_Enable;
1930 else
1931 hrtf_appreq = Hrtf_Default;
1932 break;
1934 case ALC_HRTF_ID_SOFT:
1935 hrtf_id = attrList[attrIdx + 1];
1936 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1937 break;
1939 case ALC_OUTPUT_LIMITER_SOFT:
1940 gainLimiter = attrList[attrIdx + 1];
1941 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1942 break;
1944 default:
1945 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1946 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1947 break;
1950 attrIdx += 2;
1952 #undef TRACE_ATTR
1954 ConfigValueUInt(device->DeviceName.c_str(), nullptr, "frequency", &freq);
1955 freq = maxu(freq, MIN_OUTPUT_RATE);
1957 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1958 device->Frequency;
1959 /* SSE and Neon do best with the update size being a multiple of 4 */
1960 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1961 device->UpdateSize = (device->UpdateSize+3)&~3;
1963 device->Frequency = freq;
1965 if(numMono > INT_MAX-numStereo)
1966 numMono = INT_MAX-numStereo;
1967 numMono += numStereo;
1968 if(ConfigValueInt(device->DeviceName.c_str(), nullptr, "sources", &numMono))
1970 if(numMono <= 0)
1971 numMono = 256;
1973 else
1974 numMono = maxi(numMono, 256);
1975 numStereo = mini(numStereo, numMono);
1976 numMono -= numStereo;
1977 device->SourcesMax = numMono + numStereo;
1979 device->NumMonoSources = numMono;
1980 device->NumStereoSources = numStereo;
1982 if(ConfigValueInt(device->DeviceName.c_str(), nullptr, "sends", &new_sends))
1983 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1984 else
1985 new_sends = numSends;
1988 if((device->Flags&DEVICE_RUNNING))
1989 return ALC_NO_ERROR;
1991 al_free(device->Uhj_Encoder);
1992 device->Uhj_Encoder = nullptr;
1994 al_free(device->Bs2b);
1995 device->Bs2b = nullptr;
1997 al_free(device->ChannelDelay[0].Buffer);
1998 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2000 device->ChannelDelay[i].Length = 0;
2001 device->ChannelDelay[i].Buffer = nullptr;
2004 device->Dry.Buffer = nullptr;
2005 device->Dry.NumChannels = 0;
2006 device->FOAOut.Buffer = nullptr;
2007 device->FOAOut.NumChannels = 0;
2008 device->RealOut.Buffer = nullptr;
2009 device->RealOut.NumChannels = 0;
2010 device->MixBuffer.clear();
2011 device->MixBuffer.shrink_to_fit();
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 ALsizei num_chans{device->Dry.NumChannels + device->FOAOut.NumChannels +
2117 device->RealOut.NumChannels};
2119 TRACE("Allocating %d channels, " SZFMT " bytes\n", num_chans,
2120 num_chans*sizeof(device->MixBuffer[0]));
2121 device->MixBuffer.resize(num_chans);
2123 device->Dry.Buffer = &reinterpret_cast<ALfloat(&)[BUFFERSIZE]>(device->MixBuffer[0]);
2124 if(device->RealOut.NumChannels != 0)
2125 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels +
2126 device->FOAOut.NumChannels;
2127 else
2129 device->RealOut.Buffer = device->Dry.Buffer;
2130 device->RealOut.NumChannels = device->Dry.NumChannels;
2133 if(device->FOAOut.NumChannels != 0)
2134 device->FOAOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2135 else
2137 device->FOAOut.Buffer = device->Dry.Buffer;
2138 device->FOAOut.NumChannels = device->Dry.NumChannels;
2141 device->NumAuxSends = new_sends;
2142 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2143 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
2144 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
2146 device->DitherDepth = 0.0f;
2147 if(GetConfigValueBool(device->DeviceName.c_str(), nullptr, "dither", 1))
2149 ALint depth = 0;
2150 ConfigValueInt(device->DeviceName.c_str(), nullptr, "dither-depth", &depth);
2151 if(depth <= 0)
2153 switch(device->FmtType)
2155 case DevFmtByte:
2156 case DevFmtUByte:
2157 depth = 8;
2158 break;
2159 case DevFmtShort:
2160 case DevFmtUShort:
2161 depth = 16;
2162 break;
2163 case DevFmtInt:
2164 case DevFmtUInt:
2165 case DevFmtFloat:
2166 break;
2170 if(depth > 0)
2172 depth = clampi(depth, 2, 24);
2173 device->DitherDepth = std::pow(2.0f, (ALfloat)(depth-1));
2176 if(!(device->DitherDepth > 0.0f))
2177 TRACE("Dithering disabled\n");
2178 else
2179 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device->DitherDepth)+0.5f)+1,
2180 device->DitherDepth);
2182 device->LimiterState = gainLimiter;
2183 if(ConfigValueBool(device->DeviceName.c_str(), nullptr, "output-limiter", &val))
2184 gainLimiter = val ? ALC_TRUE : ALC_FALSE;
2186 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2187 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2188 * output (where samples must be clamped), and don't for floating-point
2189 * (which can take unclamped samples).
2191 if(gainLimiter == ALC_DONT_CARE_SOFT)
2193 switch(device->FmtType)
2195 case DevFmtByte:
2196 case DevFmtUByte:
2197 case DevFmtShort:
2198 case DevFmtUShort:
2199 case DevFmtInt:
2200 case DevFmtUInt:
2201 gainLimiter = ALC_TRUE;
2202 break;
2203 case DevFmtFloat:
2204 gainLimiter = ALC_FALSE;
2205 break;
2208 if(gainLimiter != ALC_FALSE)
2210 ALfloat thrshld = 1.0f;
2211 switch(device->FmtType)
2213 case DevFmtByte:
2214 case DevFmtUByte:
2215 thrshld = 127.0f / 128.0f;
2216 break;
2217 case DevFmtShort:
2218 case DevFmtUShort:
2219 thrshld = 32767.0f / 32768.0f;
2220 break;
2221 case DevFmtInt:
2222 case DevFmtUInt:
2223 case DevFmtFloat:
2224 break;
2226 if(device->DitherDepth > 0.0f)
2227 thrshld -= 1.0f / device->DitherDepth;
2229 al_free(device->Limiter);
2230 device->Limiter = CreateDeviceLimiter(device, std::log10(thrshld) * 20.0f);
2231 device->FixedLatency += (ALuint)(GetCompressorLookAhead(device->Limiter) *
2232 DEVICE_CLOCK_RES / device->Frequency);
2234 else
2236 al_free(device->Limiter);
2237 device->Limiter = nullptr;
2239 TRACE("Output limiter %s\n", device->Limiter ? "enabled" : "disabled");
2241 aluSelectPostProcess(device);
2243 TRACE("Fixed device latency: %uns\n", device->FixedLatency);
2245 /* Need to delay returning failure until replacement Send arrays have been
2246 * allocated with the appropriate size.
2248 update_failed = AL_FALSE;
2249 START_MIXER_MODE();
2250 context = ATOMIC_LOAD_SEQ(&device->ContextList);
2251 while(context)
2253 struct ALvoiceProps *vprops;
2254 ALsizei pos;
2256 if(context->DefaultSlot)
2258 ALeffectslot *slot = context->DefaultSlot;
2259 EffectState *state = slot->Effect.State;
2261 state->mOutBuffer = device->Dry.Buffer;
2262 state->mOutChannels = device->Dry.NumChannels;
2263 if(state->deviceUpdate(device) == AL_FALSE)
2264 update_failed = AL_TRUE;
2265 else
2266 UpdateEffectSlotProps(slot, context);
2269 almtx_lock(&context->PropLock);
2270 almtx_lock(&context->EffectSlotLock);
2271 for(auto &slot : context->EffectSlotList)
2273 EffectState *state = slot->Effect.State;
2275 state->mOutBuffer = device->Dry.Buffer;
2276 state->mOutChannels = device->Dry.NumChannels;
2277 if(state->deviceUpdate(device) == AL_FALSE)
2278 update_failed = AL_TRUE;
2279 else
2280 UpdateEffectSlotProps(slot, context);
2282 almtx_unlock(&context->EffectSlotLock);
2284 almtx_lock(&context->SourceLock);
2285 for(auto &sublist : context->SourceList)
2287 uint64_t usemask = ~sublist.FreeMask;
2288 while(usemask)
2290 ALsizei idx = CTZ64(usemask);
2291 ALsource *source = sublist.Sources + idx;
2293 usemask &= ~(U64(1) << idx);
2295 if(old_sends != device->NumAuxSends)
2297 ALvoid *sends = al_calloc(16, device->NumAuxSends*sizeof(source->Send[0]));
2298 ALsizei s;
2300 memcpy(sends, source->Send,
2301 mini(device->NumAuxSends, old_sends)*sizeof(source->Send[0])
2303 for(s = device->NumAuxSends;s < old_sends;s++)
2305 if(source->Send[s].Slot)
2306 DecrementRef(&source->Send[s].Slot->ref);
2307 source->Send[s].Slot = nullptr;
2309 al_free(source->Send);
2310 source->Send = static_cast<decltype(source->Send)>(sends);
2311 for(s = old_sends;s < device->NumAuxSends;s++)
2313 source->Send[s].Slot = nullptr;
2314 source->Send[s].Gain = 1.0f;
2315 source->Send[s].GainHF = 1.0f;
2316 source->Send[s].HFReference = LOWPASSFREQREF;
2317 source->Send[s].GainLF = 1.0f;
2318 source->Send[s].LFReference = HIGHPASSFREQREF;
2322 ATOMIC_STORE(&source->PropsClean, AL_FALSE, almemory_order_release);
2326 /* Clear any pre-existing voice property structs, in case the number of
2327 * auxiliary sends is changing. Active sources will have updates
2328 * respecified in UpdateAllSourceProps.
2330 vprops = context->FreeVoiceProps.exchange(nullptr, std::memory_order_acq_rel);
2331 while(vprops)
2333 struct ALvoiceProps *next = vprops->next.load(std::memory_order_relaxed);
2334 al_free(vprops);
2335 vprops = next;
2338 AllocateVoices(context, context->MaxVoices, old_sends);
2339 for(pos = 0;pos < context->VoiceCount;pos++)
2341 ALvoice *voice = context->Voices[pos];
2343 al_free(voice->Update.exchange(nullptr, std::memory_order_acq_rel));
2345 if(voice->Source.load(std::memory_order_acquire) == nullptr)
2346 continue;
2348 if(device->AvgSpeakerDist > 0.0f)
2350 /* Reinitialize the NFC filters for new parameters. */
2351 ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
2352 (device->AvgSpeakerDist * device->Frequency);
2353 for(i = 0;i < voice->NumChannels;i++)
2354 NfcFilterCreate(&voice->Direct.Params[i].NFCtrlFilter, 0.0f, w1);
2357 almtx_unlock(&context->SourceLock);
2359 ATOMIC_STORE(&context->PropsClean, AL_TRUE, almemory_order_release);
2360 UpdateContextProps(context);
2361 ATOMIC_STORE(&context->Listener.PropsClean, AL_TRUE, almemory_order_release);
2362 UpdateListenerProps(context);
2363 UpdateAllSourceProps(context);
2364 almtx_unlock(&context->PropLock);
2366 context = ATOMIC_LOAD(&context->next, almemory_order_relaxed);
2368 END_MIXER_MODE();
2369 if(update_failed)
2370 return ALC_INVALID_DEVICE;
2372 if(!(device->Flags&DEVICE_PAUSED))
2374 if(V0(device->Backend,start)() == ALC_FALSE)
2375 return ALC_INVALID_DEVICE;
2376 device->Flags |= DEVICE_RUNNING;
2379 return ALC_NO_ERROR;
2383 ALCdevice_struct::ALCdevice_struct(DeviceType type)
2384 : Type{type}
2386 almtx_init(&BufferLock, almtx_plain);
2387 almtx_init(&EffectLock, almtx_plain);
2388 almtx_init(&FilterLock, almtx_plain);
2390 almtx_init(&BackendLock, almtx_plain);
2393 /* ALCdevice_struct::~ALCdevice_struct
2395 * Frees the device structure, and destroys any objects the app failed to
2396 * delete. Called once there's no more references on the device.
2398 ALCdevice_struct::~ALCdevice_struct()
2400 TRACE("%p\n", this);
2402 if(Backend)
2403 DELETE_OBJ(Backend);
2404 Backend = nullptr;
2406 almtx_destroy(&BackendLock);
2408 ReleaseALBuffers(this);
2409 std::for_each(BufferList.begin(), BufferList.end(),
2410 [](BufferSubList &entry) noexcept -> void
2411 { al_free(entry.Buffers); }
2413 BufferList.clear();
2414 almtx_destroy(&BufferLock);
2416 ReleaseALEffects(this);
2417 std::for_each(EffectList.begin(), EffectList.end(),
2418 [](EffectSubList &entry) noexcept -> void
2419 { al_free(entry.Effects); }
2421 EffectList.clear();
2422 almtx_destroy(&EffectLock);
2424 ReleaseALFilters(this);
2425 std::for_each(FilterList.begin(), FilterList.end(),
2426 [](FilterSubList &entry) noexcept -> void
2427 { al_free(entry.Filters); }
2429 FilterList.clear();
2430 almtx_destroy(&FilterLock);
2432 HrtfList.clear();
2433 if(HrtfHandle)
2434 Hrtf_DecRef(HrtfHandle);
2435 HrtfHandle = nullptr;
2436 al_free(Hrtf);
2437 Hrtf = nullptr;
2439 al_free(Bs2b);
2440 Bs2b = nullptr;
2442 al_free(Uhj_Encoder);
2443 Uhj_Encoder = nullptr;
2445 bformatdec_free(&AmbiDecoder);
2446 ambiup_free(&AmbiUp);
2448 al_free(Stablizer);
2449 Stablizer = nullptr;
2451 al_free(Limiter);
2452 Limiter = nullptr;
2454 al_free(ChannelDelay[0].Buffer);
2455 for(ALsizei i{0};i < MAX_OUTPUT_CHANNELS;i++)
2457 ChannelDelay[i].Gain = 1.0f;
2458 ChannelDelay[i].Length = 0;
2459 ChannelDelay[i].Buffer = nullptr;
2464 void ALCdevice_IncRef(ALCdevice *device)
2466 auto ref = IncrementRef(&device->ref);
2467 TRACEREF("%p increasing refcount to %u\n", device, ref);
2470 void ALCdevice_DecRef(ALCdevice *device)
2472 auto ref = DecrementRef(&device->ref);
2473 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2474 if(ref == 0) delete device;
2477 /* VerifyDevice
2479 * Checks if the device handle is valid, and increments its ref count if so.
2481 static ALCboolean VerifyDevice(ALCdevice **device)
2483 std::lock_guard<std::recursive_mutex> _{ListLock};
2484 ALCdevice *tmpDevice{DeviceList.load()};
2485 while(tmpDevice)
2487 if(tmpDevice == *device)
2489 ALCdevice_IncRef(tmpDevice);
2490 return ALC_TRUE;
2492 tmpDevice = ATOMIC_LOAD(&tmpDevice->next, almemory_order_relaxed);
2495 *device = nullptr;
2496 return ALC_FALSE;
2500 /* InitContext
2502 * Initializes context fields
2504 static ALvoid InitContext(ALCcontext *Context)
2506 ALlistener &listener = Context->Listener;
2507 struct ALeffectslotArray *auxslots;
2509 //Validate Context
2510 almtx_init(&Context->PropLock, almtx_plain);
2511 almtx_init(&Context->SourceLock, almtx_plain);
2512 almtx_init(&Context->EffectSlotLock, almtx_plain);
2514 if(Context->DefaultSlot)
2516 auxslots = static_cast<ALeffectslotArray*>(al_calloc(DEF_ALIGN,
2517 FAM_SIZE(struct ALeffectslotArray, slot, 1)));
2518 auxslots->count = 1;
2519 auxslots->slot[0] = Context->DefaultSlot;
2521 else
2523 auxslots = static_cast<ALeffectslotArray*>(al_calloc(DEF_ALIGN,
2524 sizeof(struct ALeffectslotArray)));
2525 auxslots->count = 0;
2527 ATOMIC_INIT(&Context->ActiveAuxSlots, auxslots);
2529 //Set globals
2530 Context->mDistanceModel = DistanceModel::Default;
2531 Context->SourceDistanceModel = AL_FALSE;
2532 Context->DopplerFactor = 1.0f;
2533 Context->DopplerVelocity = 1.0f;
2534 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2535 Context->MetersPerUnit = AL_DEFAULT_METERS_PER_UNIT;
2536 ATOMIC_INIT(&Context->PropsClean, AL_TRUE);
2537 ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
2538 alsem_init(&Context->EventSem, 0);
2539 almtx_init(&Context->EventCbLock, almtx_plain);
2541 Context->ExtensionList = alExtList;
2544 listener.Params.Matrix = aluMatrixf::Identity;
2545 aluVectorSet(&listener.Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2546 listener.Params.Gain = listener.Gain;
2547 listener.Params.MetersPerUnit = Context->MetersPerUnit;
2548 listener.Params.DopplerFactor = Context->DopplerFactor;
2549 listener.Params.SpeedOfSound = Context->SpeedOfSound * Context->DopplerVelocity;
2550 listener.Params.ReverbSpeedOfSound = listener.Params.SpeedOfSound *
2551 listener.Params.MetersPerUnit;
2552 listener.Params.SourceDistanceModel = Context->SourceDistanceModel;
2553 listener.Params.mDistanceModel = Context->mDistanceModel;
2556 Context->AsyncEvents = ll_ringbuffer_create(63, sizeof(AsyncEvent), false);
2557 StartEventThrd(Context);
2561 /* ALCcontext_struct::~ALCcontext_struct()
2563 * Cleans up the context, and destroys any remaining objects the app failed to
2564 * delete. Called once there's no more references on the context.
2566 ALCcontext_struct::~ALCcontext_struct()
2568 TRACE("%p\n", this);
2570 struct ALcontextProps *cprops{Update.load(std::memory_order_relaxed)};
2571 if(cprops)
2573 TRACE("Freed unapplied context update %p\n", cprops);
2574 al_free(cprops);
2576 size_t count{0};
2577 cprops = FreeContextProps.load(std::memory_order_acquire);
2578 while(cprops)
2580 struct ALcontextProps *next{cprops->next.load(std::memory_order_relaxed)};
2581 al_free(cprops);
2582 cprops = next;
2583 ++count;
2585 TRACE("Freed " SZFMT " context property object%s\n", count, (count==1)?"":"s");
2587 delete DefaultSlot;
2588 DefaultSlot = nullptr;
2590 al_free(ActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed));
2592 ReleaseALSources(this);
2593 std::for_each(SourceList.begin(), SourceList.end(),
2594 [](const SourceSubList &entry) noexcept -> void
2595 { al_free(entry.Sources); }
2597 SourceList.clear();
2598 NumSources = 0;
2599 almtx_destroy(&SourceLock);
2601 count = 0;
2602 struct ALeffectslotProps *eprops{FreeEffectslotProps.load(std::memory_order_acquire)};
2603 while(eprops)
2605 struct ALeffectslotProps *next{eprops->next.load(std::memory_order_relaxed)};
2606 if(eprops->State) eprops->State->DecRef();
2607 al_free(eprops);
2608 eprops = next;
2609 ++count;
2611 TRACE("Freed " SZFMT " AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2613 ReleaseALAuxiliaryEffectSlots(this);
2614 EffectSlotList.clear();
2615 almtx_destroy(&EffectSlotLock);
2617 count = 0;
2618 struct ALvoiceProps *vprops{FreeVoiceProps.load(std::memory_order_acquire)};
2619 while(vprops)
2621 struct ALvoiceProps *next{vprops->next.load(std::memory_order_relaxed)};
2622 al_free(vprops);
2623 vprops = next;
2624 ++count;
2626 TRACE("Freed " SZFMT " voice property object%s\n", count, (count==1)?"":"s");
2628 for(ALsizei i{0};i < VoiceCount;i++)
2629 DeinitVoice(Voices[i]);
2630 al_free(Voices);
2631 Voices = nullptr;
2632 VoiceCount = 0;
2633 MaxVoices = 0;
2635 struct ALlistenerProps *lprops{Listener.Update.load(std::memory_order_relaxed)};
2636 if(lprops)
2638 TRACE("Freed unapplied listener update %p\n", lprops);
2639 al_free(lprops);
2641 count = 0;
2642 lprops = FreeListenerProps.load(std::memory_order_acquire);
2643 while(lprops)
2645 struct ALlistenerProps *next{lprops->next.load(std::memory_order_relaxed)};
2646 al_free(lprops);
2647 lprops = next;
2648 ++count;
2650 TRACE("Freed " SZFMT " listener property object%s\n", count, (count==1)?"":"s");
2652 almtx_destroy(&EventCbLock);
2653 alsem_destroy(&EventSem);
2655 ll_ringbuffer_free(AsyncEvents);
2656 AsyncEvents = nullptr;
2658 almtx_destroy(&PropLock);
2660 ALCdevice_DecRef(Device);
2663 /* ReleaseContext
2665 * Removes the context reference from the given device and removes it from
2666 * being current on the running thread or globally. Returns true if other
2667 * contexts still exist on the device.
2669 static bool ReleaseContext(ALCcontext *context, ALCdevice *device)
2671 ALCcontext *origctx, *newhead;
2672 bool ret = true;
2674 if(LocalContext.get() == context)
2676 WARN("%p released while current on thread\n", context);
2677 LocalContext.set(nullptr);
2678 ALCcontext_DecRef(context);
2681 origctx = context;
2682 if(GlobalContext.compare_exchange_strong(origctx, nullptr))
2683 ALCcontext_DecRef(context);
2685 V0(device->Backend,lock)();
2686 origctx = context;
2687 newhead = ATOMIC_LOAD(&context->next, almemory_order_relaxed);
2688 if(!device->ContextList.compare_exchange_strong(origctx, newhead))
2690 ALCcontext *list;
2691 do {
2692 /* origctx is what the desired context failed to match. Try
2693 * swapping out the next one in the list.
2695 list = origctx;
2696 origctx = context;
2697 } while(!list->next.compare_exchange_strong(origctx, newhead));
2699 else
2700 ret = !!newhead;
2701 V0(device->Backend,unlock)();
2703 /* Make sure the context is finished and no longer processing in the mixer
2704 * before sending the message queue kill event. The backend's lock does
2705 * this, although waiting for a non-odd mix count would work too.
2708 StopEventThrd(context);
2710 ALCcontext_DecRef(context);
2711 return ret;
2714 static void ALCcontext_IncRef(ALCcontext *context)
2716 auto ref = IncrementRef(&context->ref);
2717 TRACEREF("%p increasing refcount to %u\n", context, ref);
2720 void ALCcontext_DecRef(ALCcontext *context)
2722 auto ref = DecrementRef(&context->ref);
2723 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2724 if(ref == 0) delete context;
2727 static void ReleaseThreadCtx(ALCcontext *context)
2729 auto ref = DecrementRef(&context->ref);
2730 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2731 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2734 /* VerifyContext
2736 * Checks that the given context is valid, and increments its reference count.
2738 static ALCboolean VerifyContext(ALCcontext **context)
2740 std::lock_guard<std::recursive_mutex> _{ListLock};
2741 ALCdevice *dev{DeviceList.load()};
2742 while(dev)
2744 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList, almemory_order_acquire);
2745 while(ctx)
2747 if(ctx == *context)
2749 ALCcontext_IncRef(ctx);
2750 return ALC_TRUE;
2752 ctx = ATOMIC_LOAD(&ctx->next, almemory_order_relaxed);
2754 dev = ATOMIC_LOAD(&dev->next, almemory_order_relaxed);
2757 *context = nullptr;
2758 return ALC_FALSE;
2762 /* GetContextRef
2764 * Returns the currently active context for this thread, and adds a reference
2765 * without locking it.
2767 ALCcontext *GetContextRef(void)
2769 ALCcontext *context{LocalContext.get()};
2770 if(context)
2771 ALCcontext_IncRef(context);
2772 else
2774 std::lock_guard<std::recursive_mutex> _{ListLock};
2775 context = GlobalContext.load(std::memory_order_acquire);
2776 if(context) ALCcontext_IncRef(context);
2779 return context;
2783 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
2785 ALCdevice *device = context->Device;
2786 ALsizei num_sends = device->NumAuxSends;
2787 struct ALvoiceProps *props;
2788 size_t sizeof_props;
2789 size_t sizeof_voice;
2790 ALvoice **voices;
2791 ALvoice *voice;
2792 ALsizei v = 0;
2793 size_t size;
2795 if(num_voices == context->MaxVoices && num_sends == old_sends)
2796 return;
2798 /* Allocate the voice pointers, voices, and the voices' stored source
2799 * property set (including the dynamically-sized Send[] array) in one
2800 * chunk.
2802 sizeof_voice = RoundUp(FAM_SIZE(ALvoice, Send, num_sends), 16);
2803 sizeof_props = RoundUp(FAM_SIZE(struct ALvoiceProps, Send, num_sends), 16);
2804 size = sizeof(ALvoice*) + sizeof_voice + sizeof_props;
2806 voices = static_cast<ALvoice**>(al_calloc(16, RoundUp(size*num_voices, 16)));
2807 /* The voice and property objects are stored interleaved since they're
2808 * paired together.
2810 voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
2811 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2813 if(context->Voices)
2815 const ALsizei v_count = mini(context->VoiceCount, num_voices);
2816 const ALsizei s_count = mini(old_sends, num_sends);
2818 for(;v < v_count;v++)
2820 ALvoice *old_voice = context->Voices[v];
2821 ALsizei i;
2823 /* Copy the old voice data and source property set to the new
2824 * storage.
2826 memcpy(voice, old_voice, sizeof(*voice));
2827 for(i = 0;i < s_count;i++)
2828 voice->Send[i] = old_voice->Send[i];
2830 memcpy(props, old_voice->Props, sizeof(*props));
2831 for(i = 0;i < s_count;i++)
2832 props->Send[i] = old_voice->Props->Send[i];
2834 /* Set this voice's property set pointer and voice reference. */
2835 voice->Props = props;
2836 voices[v] = voice;
2838 /* Increment pointers to the next storage space. */
2839 voice = (ALvoice*)((char*)props + sizeof_props);
2840 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2842 /* Deinit any left over voices that weren't copied over to the new
2843 * array. NOTE: If this does anything, v equals num_voices and
2844 * num_voices is less than VoiceCount, so the following loop won't do
2845 * anything.
2847 for(;v < context->VoiceCount;v++)
2848 DeinitVoice(context->Voices[v]);
2850 /* Finish setting the voices' property set pointers and references. */
2851 for(;v < num_voices;v++)
2853 ATOMIC_INIT(&voice->Update, static_cast<ALvoiceProps*>(nullptr));
2855 voice->Props = props;
2856 voices[v] = voice;
2858 voice = (ALvoice*)((char*)props + sizeof_props);
2859 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2862 al_free(context->Voices);
2863 context->Voices = voices;
2864 context->MaxVoices = num_voices;
2865 context->VoiceCount = mini(context->VoiceCount, num_voices);
2869 /************************************************
2870 * Standard ALC functions
2871 ************************************************/
2873 /* alcGetError
2875 * Return last ALC generated error code for the given device
2877 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2879 ALCenum errorCode;
2881 if(VerifyDevice(&device))
2883 errorCode = device->LastError.exchange(ALC_NO_ERROR);
2884 ALCdevice_DecRef(device);
2886 else
2887 errorCode = LastNullDeviceError.exchange(ALC_NO_ERROR);
2889 return errorCode;
2893 /* alcSuspendContext
2895 * Suspends updates for the given context
2897 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2899 if(!SuspendDefers)
2900 return;
2902 if(!VerifyContext(&context))
2903 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2904 else
2906 ALCcontext_DeferUpdates(context);
2907 ALCcontext_DecRef(context);
2911 /* alcProcessContext
2913 * Resumes processing updates for the given context
2915 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2917 if(!SuspendDefers)
2918 return;
2920 if(!VerifyContext(&context))
2921 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2922 else
2924 ALCcontext_ProcessUpdates(context);
2925 ALCcontext_DecRef(context);
2930 /* alcGetString
2932 * Returns information about the device, and error strings
2934 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2936 const ALCchar *value = nullptr;
2938 switch(param)
2940 case ALC_NO_ERROR:
2941 value = alcNoError;
2942 break;
2944 case ALC_INVALID_ENUM:
2945 value = alcErrInvalidEnum;
2946 break;
2948 case ALC_INVALID_VALUE:
2949 value = alcErrInvalidValue;
2950 break;
2952 case ALC_INVALID_DEVICE:
2953 value = alcErrInvalidDevice;
2954 break;
2956 case ALC_INVALID_CONTEXT:
2957 value = alcErrInvalidContext;
2958 break;
2960 case ALC_OUT_OF_MEMORY:
2961 value = alcErrOutOfMemory;
2962 break;
2964 case ALC_DEVICE_SPECIFIER:
2965 value = alcDefaultName;
2966 break;
2968 case ALC_ALL_DEVICES_SPECIFIER:
2969 if(VerifyDevice(&Device))
2971 value = Device->DeviceName.c_str();
2972 ALCdevice_DecRef(Device);
2974 else
2976 ProbeAllDevicesList();
2977 value = alcAllDevicesList.c_str();
2979 break;
2981 case ALC_CAPTURE_DEVICE_SPECIFIER:
2982 if(VerifyDevice(&Device))
2984 value = Device->DeviceName.c_str();
2985 ALCdevice_DecRef(Device);
2987 else
2989 ProbeCaptureDeviceList();
2990 value = alcCaptureDeviceList.c_str();
2992 break;
2994 /* Default devices are always first in the list */
2995 case ALC_DEFAULT_DEVICE_SPECIFIER:
2996 value = alcDefaultName;
2997 break;
2999 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
3000 if(alcAllDevicesList.empty())
3001 ProbeAllDevicesList();
3003 /* Copy first entry as default. */
3004 alcDefaultAllDevicesSpecifier = alcAllDevicesList.c_str();
3005 value = alcDefaultAllDevicesSpecifier.c_str();
3006 break;
3008 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
3009 if(alcCaptureDeviceList.empty())
3010 ProbeCaptureDeviceList();
3012 /* Copy first entry as default. */
3013 alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList.c_str();
3014 value = alcCaptureDefaultDeviceSpecifier.c_str();
3015 break;
3017 case ALC_EXTENSIONS:
3018 if(!VerifyDevice(&Device))
3019 value = alcNoDeviceExtList;
3020 else
3022 value = alcExtensionList;
3023 ALCdevice_DecRef(Device);
3025 break;
3027 case ALC_HRTF_SPECIFIER_SOFT:
3028 if(!VerifyDevice(&Device))
3029 alcSetError(nullptr, ALC_INVALID_DEVICE);
3030 else
3032 almtx_lock(&Device->BackendLock);
3033 value = (Device->HrtfHandle ? Device->HrtfName.c_str() : "");
3034 almtx_unlock(&Device->BackendLock);
3035 ALCdevice_DecRef(Device);
3037 break;
3039 default:
3040 VerifyDevice(&Device);
3041 alcSetError(Device, ALC_INVALID_ENUM);
3042 if(Device) ALCdevice_DecRef(Device);
3043 break;
3046 return value;
3050 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
3052 if(device->Type == Capture) return 9;
3053 if(device->Type != Loopback) return 29;
3054 if(device->FmtChans == DevFmtAmbi3D)
3055 return 35;
3056 return 29;
3059 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3061 ALCsizei i;
3063 if(size <= 0 || values == nullptr)
3065 alcSetError(device, ALC_INVALID_VALUE);
3066 return 0;
3069 if(!device)
3071 switch(param)
3073 case ALC_MAJOR_VERSION:
3074 values[0] = alcMajorVersion;
3075 return 1;
3076 case ALC_MINOR_VERSION:
3077 values[0] = alcMinorVersion;
3078 return 1;
3080 case ALC_ATTRIBUTES_SIZE:
3081 case ALC_ALL_ATTRIBUTES:
3082 case ALC_FREQUENCY:
3083 case ALC_REFRESH:
3084 case ALC_SYNC:
3085 case ALC_MONO_SOURCES:
3086 case ALC_STEREO_SOURCES:
3087 case ALC_CAPTURE_SAMPLES:
3088 case ALC_FORMAT_CHANNELS_SOFT:
3089 case ALC_FORMAT_TYPE_SOFT:
3090 case ALC_AMBISONIC_LAYOUT_SOFT:
3091 case ALC_AMBISONIC_SCALING_SOFT:
3092 case ALC_AMBISONIC_ORDER_SOFT:
3093 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3094 alcSetError(nullptr, ALC_INVALID_DEVICE);
3095 return 0;
3097 default:
3098 alcSetError(nullptr, ALC_INVALID_ENUM);
3099 return 0;
3101 return 0;
3104 if(device->Type == Capture)
3106 switch(param)
3108 case ALC_ATTRIBUTES_SIZE:
3109 values[0] = NumAttrsForDevice(device);
3110 return 1;
3112 case ALC_ALL_ATTRIBUTES:
3113 if(size < NumAttrsForDevice(device))
3115 alcSetError(device, ALC_INVALID_VALUE);
3116 return 0;
3119 i = 0;
3120 almtx_lock(&device->BackendLock);
3121 values[i++] = ALC_MAJOR_VERSION;
3122 values[i++] = alcMajorVersion;
3123 values[i++] = ALC_MINOR_VERSION;
3124 values[i++] = alcMinorVersion;
3125 values[i++] = ALC_CAPTURE_SAMPLES;
3126 values[i++] = V0(device->Backend,availableSamples)();
3127 values[i++] = ALC_CONNECTED;
3128 values[i++] = ATOMIC_LOAD(&device->Connected, almemory_order_relaxed);
3129 almtx_unlock(&device->BackendLock);
3131 values[i++] = 0;
3132 return i;
3134 case ALC_MAJOR_VERSION:
3135 values[0] = alcMajorVersion;
3136 return 1;
3137 case ALC_MINOR_VERSION:
3138 values[0] = alcMinorVersion;
3139 return 1;
3141 case ALC_CAPTURE_SAMPLES:
3142 almtx_lock(&device->BackendLock);
3143 values[0] = V0(device->Backend,availableSamples)();
3144 almtx_unlock(&device->BackendLock);
3145 return 1;
3147 case ALC_CONNECTED:
3148 values[0] = ATOMIC_LOAD(&device->Connected, almemory_order_acquire);
3149 return 1;
3151 default:
3152 alcSetError(device, ALC_INVALID_ENUM);
3153 return 0;
3155 return 0;
3158 /* render device */
3159 switch(param)
3161 case ALC_ATTRIBUTES_SIZE:
3162 values[0] = NumAttrsForDevice(device);
3163 return 1;
3165 case ALC_ALL_ATTRIBUTES:
3166 if(size < NumAttrsForDevice(device))
3168 alcSetError(device, ALC_INVALID_VALUE);
3169 return 0;
3172 i = 0;
3173 almtx_lock(&device->BackendLock);
3174 values[i++] = ALC_MAJOR_VERSION;
3175 values[i++] = alcMajorVersion;
3176 values[i++] = ALC_MINOR_VERSION;
3177 values[i++] = alcMinorVersion;
3178 values[i++] = ALC_EFX_MAJOR_VERSION;
3179 values[i++] = alcEFXMajorVersion;
3180 values[i++] = ALC_EFX_MINOR_VERSION;
3181 values[i++] = alcEFXMinorVersion;
3183 values[i++] = ALC_FREQUENCY;
3184 values[i++] = device->Frequency;
3185 if(device->Type != Loopback)
3187 values[i++] = ALC_REFRESH;
3188 values[i++] = device->Frequency / device->UpdateSize;
3190 values[i++] = ALC_SYNC;
3191 values[i++] = ALC_FALSE;
3193 else
3195 if(device->FmtChans == DevFmtAmbi3D)
3197 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3198 values[i++] = device->mAmbiLayout;
3200 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3201 values[i++] = device->mAmbiScale;
3203 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3204 values[i++] = device->mAmbiOrder;
3207 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3208 values[i++] = device->FmtChans;
3210 values[i++] = ALC_FORMAT_TYPE_SOFT;
3211 values[i++] = device->FmtType;
3214 values[i++] = ALC_MONO_SOURCES;
3215 values[i++] = device->NumMonoSources;
3217 values[i++] = ALC_STEREO_SOURCES;
3218 values[i++] = device->NumStereoSources;
3220 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3221 values[i++] = device->NumAuxSends;
3223 values[i++] = ALC_HRTF_SOFT;
3224 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3226 values[i++] = ALC_HRTF_STATUS_SOFT;
3227 values[i++] = device->HrtfStatus;
3229 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3230 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3232 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
3233 values[i++] = MAX_AMBI_ORDER;
3234 almtx_unlock(&device->BackendLock);
3236 values[i++] = 0;
3237 return i;
3239 case ALC_MAJOR_VERSION:
3240 values[0] = alcMajorVersion;
3241 return 1;
3243 case ALC_MINOR_VERSION:
3244 values[0] = alcMinorVersion;
3245 return 1;
3247 case ALC_EFX_MAJOR_VERSION:
3248 values[0] = alcEFXMajorVersion;
3249 return 1;
3251 case ALC_EFX_MINOR_VERSION:
3252 values[0] = alcEFXMinorVersion;
3253 return 1;
3255 case ALC_FREQUENCY:
3256 values[0] = device->Frequency;
3257 return 1;
3259 case ALC_REFRESH:
3260 if(device->Type == Loopback)
3262 alcSetError(device, ALC_INVALID_DEVICE);
3263 return 0;
3265 almtx_lock(&device->BackendLock);
3266 values[0] = device->Frequency / device->UpdateSize;
3267 almtx_unlock(&device->BackendLock);
3268 return 1;
3270 case ALC_SYNC:
3271 if(device->Type == Loopback)
3273 alcSetError(device, ALC_INVALID_DEVICE);
3274 return 0;
3276 values[0] = ALC_FALSE;
3277 return 1;
3279 case ALC_FORMAT_CHANNELS_SOFT:
3280 if(device->Type != Loopback)
3282 alcSetError(device, ALC_INVALID_DEVICE);
3283 return 0;
3285 values[0] = device->FmtChans;
3286 return 1;
3288 case ALC_FORMAT_TYPE_SOFT:
3289 if(device->Type != Loopback)
3291 alcSetError(device, ALC_INVALID_DEVICE);
3292 return 0;
3294 values[0] = device->FmtType;
3295 return 1;
3297 case ALC_AMBISONIC_LAYOUT_SOFT:
3298 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3300 alcSetError(device, ALC_INVALID_DEVICE);
3301 return 0;
3303 values[0] = device->mAmbiLayout;
3304 return 1;
3306 case ALC_AMBISONIC_SCALING_SOFT:
3307 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3309 alcSetError(device, ALC_INVALID_DEVICE);
3310 return 0;
3312 values[0] = device->mAmbiScale;
3313 return 1;
3315 case ALC_AMBISONIC_ORDER_SOFT:
3316 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3318 alcSetError(device, ALC_INVALID_DEVICE);
3319 return 0;
3321 values[0] = device->mAmbiOrder;
3322 return 1;
3324 case ALC_MONO_SOURCES:
3325 values[0] = device->NumMonoSources;
3326 return 1;
3328 case ALC_STEREO_SOURCES:
3329 values[0] = device->NumStereoSources;
3330 return 1;
3332 case ALC_MAX_AUXILIARY_SENDS:
3333 values[0] = device->NumAuxSends;
3334 return 1;
3336 case ALC_CONNECTED:
3337 values[0] = ATOMIC_LOAD(&device->Connected, almemory_order_acquire);
3338 return 1;
3340 case ALC_HRTF_SOFT:
3341 values[0] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3342 return 1;
3344 case ALC_HRTF_STATUS_SOFT:
3345 values[0] = device->HrtfStatus;
3346 return 1;
3348 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3349 almtx_lock(&device->BackendLock);
3350 device->HrtfList.clear();
3351 device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
3352 values[0] = (ALCint)device->HrtfList.size();
3353 almtx_unlock(&device->BackendLock);
3354 return 1;
3356 case ALC_OUTPUT_LIMITER_SOFT:
3357 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3358 return 1;
3360 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3361 values[0] = MAX_AMBI_ORDER;
3362 return 1;
3364 default:
3365 alcSetError(device, ALC_INVALID_ENUM);
3366 return 0;
3368 return 0;
3371 /* alcGetIntegerv
3373 * Returns information about the device and the version of OpenAL
3375 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3377 VerifyDevice(&device);
3378 if(size <= 0 || values == nullptr)
3379 alcSetError(device, ALC_INVALID_VALUE);
3380 else
3381 GetIntegerv(device, param, size, values);
3382 if(device) ALCdevice_DecRef(device);
3385 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3387 ALsizei i;
3389 VerifyDevice(&device);
3390 if(size <= 0 || values == nullptr)
3391 alcSetError(device, ALC_INVALID_VALUE);
3392 else if(!device || device->Type == Capture)
3394 std::vector<ALCint> ivals(size);
3395 size = GetIntegerv(device, pname, size, ivals.data());
3396 for(i = 0;i < size;i++)
3397 values[i] = ivals[i];
3399 else /* render device */
3401 ClockLatency clock;
3402 ALuint64 basecount;
3403 ALuint samplecount;
3404 ALuint refcount;
3406 switch(pname)
3408 case ALC_ATTRIBUTES_SIZE:
3409 *values = NumAttrsForDevice(device)+4;
3410 break;
3412 case ALC_ALL_ATTRIBUTES:
3413 if(size < NumAttrsForDevice(device)+4)
3414 alcSetError(device, ALC_INVALID_VALUE);
3415 else
3417 i = 0;
3418 almtx_lock(&device->BackendLock);
3419 values[i++] = ALC_FREQUENCY;
3420 values[i++] = device->Frequency;
3422 if(device->Type != Loopback)
3424 values[i++] = ALC_REFRESH;
3425 values[i++] = device->Frequency / device->UpdateSize;
3427 values[i++] = ALC_SYNC;
3428 values[i++] = ALC_FALSE;
3430 else
3432 if(device->FmtChans == DevFmtAmbi3D)
3434 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3435 values[i++] = device->mAmbiLayout;
3437 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3438 values[i++] = device->mAmbiScale;
3440 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3441 values[i++] = device->mAmbiOrder;
3444 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3445 values[i++] = device->FmtChans;
3447 values[i++] = ALC_FORMAT_TYPE_SOFT;
3448 values[i++] = device->FmtType;
3451 values[i++] = ALC_MONO_SOURCES;
3452 values[i++] = device->NumMonoSources;
3454 values[i++] = ALC_STEREO_SOURCES;
3455 values[i++] = device->NumStereoSources;
3457 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3458 values[i++] = device->NumAuxSends;
3460 values[i++] = ALC_HRTF_SOFT;
3461 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3463 values[i++] = ALC_HRTF_STATUS_SOFT;
3464 values[i++] = device->HrtfStatus;
3466 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3467 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3469 clock = GetClockLatency(device);
3470 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3471 values[i++] = clock.ClockTime;
3473 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3474 values[i++] = clock.Latency;
3475 almtx_unlock(&device->BackendLock);
3477 values[i++] = 0;
3479 break;
3481 case ALC_DEVICE_CLOCK_SOFT:
3482 almtx_lock(&device->BackendLock);
3483 do {
3484 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3485 althrd_yield();
3486 basecount = device->ClockBase;
3487 samplecount = device->SamplesDone;
3488 } while(refcount != ReadRef(&device->MixCount));
3489 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3490 almtx_unlock(&device->BackendLock);
3491 break;
3493 case ALC_DEVICE_LATENCY_SOFT:
3494 almtx_lock(&device->BackendLock);
3495 clock = GetClockLatency(device);
3496 almtx_unlock(&device->BackendLock);
3497 *values = clock.Latency;
3498 break;
3500 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3501 if(size < 2)
3502 alcSetError(device, ALC_INVALID_VALUE);
3503 else
3505 almtx_lock(&device->BackendLock);
3506 clock = GetClockLatency(device);
3507 almtx_unlock(&device->BackendLock);
3508 values[0] = clock.ClockTime;
3509 values[1] = clock.Latency;
3511 break;
3513 default:
3514 std::vector<ALCint> ivals(size);
3515 size = GetIntegerv(device, pname, size, ivals.data());
3516 for(i = 0;i < size;i++)
3517 values[i] = ivals[i];
3518 break;
3521 if(device)
3522 ALCdevice_DecRef(device);
3526 /* alcIsExtensionPresent
3528 * Determines if there is support for a particular extension
3530 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3532 ALCboolean bResult = ALC_FALSE;
3534 VerifyDevice(&device);
3536 if(!extName)
3537 alcSetError(device, ALC_INVALID_VALUE);
3538 else
3540 size_t len = strlen(extName);
3541 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3542 while(ptr && *ptr)
3544 if(strncasecmp(ptr, extName, len) == 0 &&
3545 (ptr[len] == '\0' || isspace(ptr[len])))
3547 bResult = ALC_TRUE;
3548 break;
3550 if((ptr=strchr(ptr, ' ')) != nullptr)
3552 do {
3553 ++ptr;
3554 } while(isspace(*ptr));
3558 if(device)
3559 ALCdevice_DecRef(device);
3560 return bResult;
3564 /* alcGetProcAddress
3566 * Retrieves the function address for a particular extension function
3568 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3570 ALCvoid *ptr = nullptr;
3572 if(!funcName)
3574 VerifyDevice(&device);
3575 alcSetError(device, ALC_INVALID_VALUE);
3576 if(device) ALCdevice_DecRef(device);
3578 else
3580 size_t i = 0;
3581 for(i = 0;i < COUNTOF(alcFunctions);i++)
3583 if(strcmp(alcFunctions[i].funcName, funcName) == 0)
3585 ptr = alcFunctions[i].address;
3586 break;
3591 return ptr;
3595 /* alcGetEnumValue
3597 * Get the value for a particular ALC enumeration name
3599 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3601 ALCenum val = 0;
3603 if(!enumName)
3605 VerifyDevice(&device);
3606 alcSetError(device, ALC_INVALID_VALUE);
3607 if(device) ALCdevice_DecRef(device);
3609 else
3611 size_t i = 0;
3612 for(i = 0;i < COUNTOF(alcEnumerations);i++)
3614 if(strcmp(alcEnumerations[i].enumName, enumName) == 0)
3616 val = alcEnumerations[i].value;
3617 break;
3622 return val;
3626 /* alcCreateContext
3628 * Create and attach a context to the given device.
3630 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3632 ALCcontext *ALContext;
3633 ALfloat valf;
3634 ALCenum err;
3636 /* Explicitly hold the list lock while taking the BackendLock in case the
3637 * device is asynchronously destropyed, to ensure this new context is
3638 * properly cleaned up after being made.
3640 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3641 if(!VerifyDevice(&device) || device->Type == Capture ||
3642 !ATOMIC_LOAD(&device->Connected, almemory_order_relaxed))
3644 listlock.unlock();
3645 alcSetError(device, ALC_INVALID_DEVICE);
3646 if(device) ALCdevice_DecRef(device);
3647 return nullptr;
3649 almtx_lock(&device->BackendLock);
3650 listlock.unlock();
3652 ATOMIC_STORE_SEQ(&device->LastError, ALC_NO_ERROR);
3654 ALContext = new ALCcontext{device};
3655 ALCdevice_IncRef(ALContext->Device);
3657 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3659 almtx_unlock(&device->BackendLock);
3661 delete ALContext;
3662 ALContext = nullptr;
3664 alcSetError(device, err);
3665 if(err == ALC_INVALID_DEVICE)
3667 V0(device->Backend,lock)();
3668 aluHandleDisconnect(device, "Device update failure");
3669 V0(device->Backend,unlock)();
3671 ALCdevice_DecRef(device);
3672 return nullptr;
3674 AllocateVoices(ALContext, 256, device->NumAuxSends);
3676 if(DefaultEffect.type != AL_EFFECT_NULL && device->Type == Playback)
3678 ALContext->DefaultSlot = new ALeffectslot{};
3679 if(InitEffectSlot(ALContext->DefaultSlot) == AL_NO_ERROR)
3680 aluInitEffectPanning(ALContext->DefaultSlot);
3681 else
3683 delete ALContext->DefaultSlot;
3684 ALContext->DefaultSlot = nullptr;
3685 ERR("Failed to initialize the default effect slot\n");
3689 InitContext(ALContext);
3691 if(ConfigValueFloat(device->DeviceName.c_str(), nullptr, "volume-adjust", &valf))
3693 if(!std::isfinite(valf))
3694 ERR("volume-adjust must be finite: %f\n", valf);
3695 else
3697 ALfloat db = clampf(valf, -24.0f, 24.0f);
3698 if(db != valf)
3699 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3700 ALContext->GainBoost = std::pow(10.0f, db/20.0f);
3701 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3704 UpdateListenerProps(ALContext);
3707 ALCcontext *head = ATOMIC_LOAD_SEQ(&device->ContextList);
3708 do {
3709 ATOMIC_STORE(&ALContext->next, head, almemory_order_relaxed);
3710 } while(!device->ContextList.compare_exchange_weak(head, ALContext));
3712 almtx_unlock(&device->BackendLock);
3714 if(ALContext->DefaultSlot)
3716 if(InitializeEffect(ALContext, ALContext->DefaultSlot, &DefaultEffect) == AL_NO_ERROR)
3717 UpdateEffectSlotProps(ALContext->DefaultSlot, ALContext);
3718 else
3719 ERR("Failed to initialize the default effect\n");
3722 ALCdevice_DecRef(device);
3724 TRACE("Created context %p\n", ALContext);
3725 return ALContext;
3728 /* alcDestroyContext
3730 * Remove a context from its device
3732 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3734 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3735 if(!VerifyContext(&context))
3737 listlock.unlock();
3738 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3739 return;
3742 ALCdevice* Device{context->Device};
3743 if(Device)
3745 almtx_lock(&Device->BackendLock);
3746 if(!ReleaseContext(context, Device))
3748 V0(Device->Backend,stop)();
3749 Device->Flags &= ~DEVICE_RUNNING;
3751 almtx_unlock(&Device->BackendLock);
3753 listlock.unlock();
3755 ALCcontext_DecRef(context);
3759 /* alcGetCurrentContext
3761 * Returns the currently active context on the calling thread
3763 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3765 ALCcontext *Context{LocalContext.get()};
3766 if(!Context) Context = GlobalContext.load();
3767 return Context;
3770 /* alcGetThreadContext
3772 * Returns the currently active thread-local context
3774 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3776 return LocalContext.get();
3780 /* alcMakeContextCurrent
3782 * Makes the given context the active process-wide context, and removes the
3783 * thread-local context for the calling thread.
3785 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3787 /* context must be valid or nullptr */
3788 if(context && !VerifyContext(&context))
3790 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3791 return ALC_FALSE;
3793 /* context's reference count is already incremented */
3794 context = GlobalContext.exchange(context);
3795 if(context) ALCcontext_DecRef(context);
3797 if((context=LocalContext.get()) != nullptr)
3799 LocalContext.set(nullptr);
3800 ALCcontext_DecRef(context);
3803 return ALC_TRUE;
3806 /* alcSetThreadContext
3808 * Makes the given context the active context for the current thread
3810 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3812 /* context must be valid or nullptr */
3813 if(context && !VerifyContext(&context))
3815 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3816 return ALC_FALSE;
3818 /* context's reference count is already incremented */
3819 ALCcontext *old{LocalContext.get()};
3820 LocalContext.set(context);
3821 if(old) ALCcontext_DecRef(old);
3823 return ALC_TRUE;
3827 /* alcGetContextsDevice
3829 * Returns the device that a particular context is attached to
3831 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3833 if(!VerifyContext(&Context))
3835 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3836 return nullptr;
3838 ALCdevice *Device{Context->Device};
3839 ALCcontext_DecRef(Context);
3841 return Device;
3845 /* alcOpenDevice
3847 * Opens the named device.
3849 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3851 DO_INITCONFIG();
3853 if(!PlaybackBackend.name)
3855 alcSetError(nullptr, ALC_INVALID_VALUE);
3856 return nullptr;
3859 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
3860 #ifdef _WIN32
3861 /* Some old Windows apps hardcode these expecting OpenAL to use a
3862 * specific audio API, even when they're not enumerated. Creative's
3863 * router effectively ignores them too.
3865 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
3866 || strcasecmp(deviceName, "MMSYSTEM") == 0
3867 #endif
3869 deviceName = nullptr;
3871 auto device = new ALCdevice{Playback};
3873 //Set output format
3874 device->FmtChans = DevFmtChannelsDefault;
3875 device->FmtType = DevFmtTypeDefault;
3876 device->Frequency = DEFAULT_OUTPUT_RATE;
3877 device->IsHeadphones = AL_FALSE;
3878 device->mAmbiLayout = AmbiLayout_Default;
3879 device->mAmbiScale = AmbiNorm_Default;
3880 device->LimiterState = ALC_TRUE;
3881 device->NumUpdates = 3;
3882 device->UpdateSize = 1024;
3884 device->SourcesMax = 256;
3885 device->AuxiliaryEffectSlotMax = 64;
3886 device->NumAuxSends = DEFAULT_SENDS;
3888 const ALCchar *fmt{};
3889 if(ConfigValueStr(deviceName, nullptr, "channels", &fmt))
3891 static constexpr struct ChannelMap {
3892 const char name[16];
3893 enum DevFmtChannels chans;
3894 ALsizei order;
3895 } chanlist[] = {
3896 { "mono", DevFmtMono, 0 },
3897 { "stereo", DevFmtStereo, 0 },
3898 { "quad", DevFmtQuad, 0 },
3899 { "surround51", DevFmtX51, 0 },
3900 { "surround61", DevFmtX61, 0 },
3901 { "surround71", DevFmtX71, 0 },
3902 { "surround51rear", DevFmtX51Rear, 0 },
3903 { "ambi1", DevFmtAmbi3D, 1 },
3904 { "ambi2", DevFmtAmbi3D, 2 },
3905 { "ambi3", DevFmtAmbi3D, 3 },
3908 auto iter = std::find_if(std::begin(chanlist), std::end(chanlist),
3909 [fmt](const ChannelMap &entry) -> bool
3910 { return strcasecmp(entry.name, fmt) == 0; }
3912 if(iter == std::end(chanlist))
3913 ERR("Unsupported channels: %s\n", fmt);
3914 else
3916 device->FmtChans = iter->chans;
3917 device->mAmbiOrder = iter->order;
3918 device->Flags |= DEVICE_CHANNELS_REQUEST;
3921 if(ConfigValueStr(deviceName, nullptr, "sample-type", &fmt))
3923 static constexpr struct TypeMap {
3924 const char name[16];
3925 enum DevFmtType type;
3926 } typelist[] = {
3927 { "int8", DevFmtByte },
3928 { "uint8", DevFmtUByte },
3929 { "int16", DevFmtShort },
3930 { "uint16", DevFmtUShort },
3931 { "int32", DevFmtInt },
3932 { "uint32", DevFmtUInt },
3933 { "float32", DevFmtFloat },
3936 auto iter = std::find_if(std::begin(typelist), std::end(typelist),
3937 [fmt](const TypeMap &entry) -> bool
3938 { return strcasecmp(entry.name, fmt) == 0; }
3940 if(iter == std::end(typelist))
3941 ERR("Unsupported sample-type: %s\n", fmt);
3942 else
3944 device->FmtType = iter->type;
3945 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3949 if(ConfigValueUInt(deviceName, nullptr, "frequency", &device->Frequency))
3951 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3952 if(device->Frequency < MIN_OUTPUT_RATE)
3953 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3954 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3957 ConfigValueUInt(deviceName, nullptr, "periods", &device->NumUpdates);
3958 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3960 ConfigValueUInt(deviceName, nullptr, "period_size", &device->UpdateSize);
3961 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3962 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
3963 device->UpdateSize = (device->UpdateSize+3)&~3;
3965 ConfigValueUInt(deviceName, nullptr, "sources", &device->SourcesMax);
3966 if(device->SourcesMax == 0) device->SourcesMax = 256;
3968 ConfigValueUInt(deviceName, nullptr, "slots", &device->AuxiliaryEffectSlotMax);
3969 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
3970 else device->AuxiliaryEffectSlotMax = minu(device->AuxiliaryEffectSlotMax, INT_MAX);
3972 if(ConfigValueInt(deviceName, nullptr, "sends", &device->NumAuxSends))
3973 device->NumAuxSends = clampi(
3974 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
3977 device->NumStereoSources = 1;
3978 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3980 device->Backend = PlaybackBackend.getFactory().createBackend(device, ALCbackend_Playback);
3981 if(!device->Backend)
3983 delete device;
3984 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
3985 return nullptr;
3988 // Find a playback device to open
3989 ALCenum err{V(device->Backend,open)(deviceName)};
3990 if(err != ALC_NO_ERROR)
3992 delete device;
3993 alcSetError(nullptr, err);
3994 return nullptr;
3997 if(ConfigValueStr(device->DeviceName.c_str(), nullptr, "ambi-format", &fmt))
3999 if(strcasecmp(fmt, "fuma") == 0)
4001 device->mAmbiLayout = AmbiLayout_FuMa;
4002 device->mAmbiScale = AmbiNorm_FuMa;
4004 else if(strcasecmp(fmt, "acn+sn3d") == 0)
4006 device->mAmbiLayout = AmbiLayout_ACN;
4007 device->mAmbiScale = AmbiNorm_SN3D;
4009 else if(strcasecmp(fmt, "acn+n3d") == 0)
4011 device->mAmbiLayout = AmbiLayout_ACN;
4012 device->mAmbiScale = AmbiNorm_N3D;
4014 else
4015 ERR("Unsupported ambi-format: %s\n", fmt);
4019 ALCdevice *head{DeviceList.load()};
4020 do {
4021 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4022 } while(!DeviceList.compare_exchange_weak(head, device));
4025 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName.c_str());
4026 return device;
4029 /* alcCloseDevice
4031 * Closes the given device.
4033 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
4035 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4036 ALCdevice *iter{DeviceList.load()};
4037 do {
4038 if(iter == device)
4039 break;
4040 iter = ATOMIC_LOAD(&iter->next, almemory_order_relaxed);
4041 } while(iter != nullptr);
4042 if(!iter || iter->Type == Capture)
4044 alcSetError(iter, ALC_INVALID_DEVICE);
4045 return ALC_FALSE;
4047 almtx_lock(&device->BackendLock);
4049 ALCdevice *origdev{device};
4050 ALCdevice *nextdev{ATOMIC_LOAD(&device->next, almemory_order_relaxed)};
4051 if(!DeviceList.compare_exchange_strong(origdev, nextdev))
4053 ALCdevice *list;
4054 do {
4055 list = origdev;
4056 origdev = device;
4057 } while(!list->next.compare_exchange_strong(origdev, nextdev));
4059 listlock.unlock();
4061 ALCcontext *ctx{ATOMIC_LOAD_SEQ(&device->ContextList)};
4062 while(ctx != nullptr)
4064 ALCcontext *next = ATOMIC_LOAD(&ctx->next, almemory_order_relaxed);
4065 WARN("Releasing context %p\n", ctx);
4066 ReleaseContext(ctx, device);
4067 ctx = next;
4069 if((device->Flags&DEVICE_RUNNING))
4070 V0(device->Backend,stop)();
4071 device->Flags &= ~DEVICE_RUNNING;
4072 almtx_unlock(&device->BackendLock);
4074 ALCdevice_DecRef(device);
4076 return ALC_TRUE;
4080 /************************************************
4081 * ALC capture functions
4082 ************************************************/
4083 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
4085 DO_INITCONFIG();
4087 if(!CaptureBackend.name)
4089 alcSetError(nullptr, ALC_INVALID_VALUE);
4090 return nullptr;
4093 if(samples <= 0)
4095 alcSetError(nullptr, ALC_INVALID_VALUE);
4096 return nullptr;
4099 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
4100 deviceName = nullptr;
4102 auto device = new ALCdevice{Capture};
4104 device->Frequency = frequency;
4105 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4107 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
4109 delete device;
4110 alcSetError(nullptr, ALC_INVALID_ENUM);
4111 return nullptr;
4113 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
4114 device->IsHeadphones = AL_FALSE;
4115 device->mAmbiOrder = 0;
4116 device->mAmbiLayout = AmbiLayout_Default;
4117 device->mAmbiScale = AmbiNorm_Default;
4119 device->UpdateSize = samples;
4120 device->NumUpdates = 1;
4122 device->Backend = CaptureBackend.getFactory().createBackend(device, ALCbackend_Capture);
4123 if(!device->Backend)
4125 delete device;
4126 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
4127 return nullptr;
4130 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4131 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
4132 device->Frequency, device->UpdateSize, device->NumUpdates
4134 ALCenum err{V(device->Backend,open)(deviceName)};
4135 if(err != ALC_NO_ERROR)
4137 delete device;
4138 alcSetError(nullptr, err);
4139 return nullptr;
4143 ALCdevice *head{DeviceList.load()};
4144 do {
4145 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4146 } while(!DeviceList.compare_exchange_weak(head, device));
4149 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName.c_str());
4150 return device;
4153 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
4155 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4157 ALCdevice *iter{DeviceList.load()};
4158 do {
4159 if(iter == device)
4160 break;
4161 iter = ATOMIC_LOAD(&iter->next, almemory_order_relaxed);
4162 } while(iter != nullptr);
4163 if(!iter || iter->Type != Capture)
4165 alcSetError(iter, ALC_INVALID_DEVICE);
4166 return ALC_FALSE;
4169 ALCdevice *origdev{device};
4170 ALCdevice *nextdev{ATOMIC_LOAD(&device->next, almemory_order_relaxed)};
4171 if(!DeviceList.compare_exchange_strong(origdev, nextdev))
4173 ALCdevice *list;
4174 do {
4175 list = origdev;
4176 origdev = device;
4177 } while(!list->next.compare_exchange_strong(origdev, nextdev));
4179 listlock.unlock();
4181 almtx_lock(&device->BackendLock);
4182 if((device->Flags&DEVICE_RUNNING))
4183 V0(device->Backend,stop)();
4184 device->Flags &= ~DEVICE_RUNNING;
4185 almtx_unlock(&device->BackendLock);
4187 ALCdevice_DecRef(device);
4189 return ALC_TRUE;
4192 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
4194 if(!VerifyDevice(&device) || device->Type != Capture)
4195 alcSetError(device, ALC_INVALID_DEVICE);
4196 else
4198 almtx_lock(&device->BackendLock);
4199 if(!ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
4200 alcSetError(device, ALC_INVALID_DEVICE);
4201 else if(!(device->Flags&DEVICE_RUNNING))
4203 if(V0(device->Backend,start)())
4204 device->Flags |= DEVICE_RUNNING;
4205 else
4207 aluHandleDisconnect(device, "Device start failure");
4208 alcSetError(device, ALC_INVALID_DEVICE);
4211 almtx_unlock(&device->BackendLock);
4214 if(device) ALCdevice_DecRef(device);
4217 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
4219 if(!VerifyDevice(&device) || device->Type != Capture)
4220 alcSetError(device, ALC_INVALID_DEVICE);
4221 else
4223 almtx_lock(&device->BackendLock);
4224 if((device->Flags&DEVICE_RUNNING))
4225 V0(device->Backend,stop)();
4226 device->Flags &= ~DEVICE_RUNNING;
4227 almtx_unlock(&device->BackendLock);
4230 if(device) ALCdevice_DecRef(device);
4233 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4235 if(!VerifyDevice(&device) || device->Type != Capture)
4236 alcSetError(device, ALC_INVALID_DEVICE);
4237 else
4239 ALCenum err = ALC_INVALID_VALUE;
4241 almtx_lock(&device->BackendLock);
4242 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
4243 err = V(device->Backend,captureSamples)(buffer, samples);
4244 almtx_unlock(&device->BackendLock);
4246 if(err != ALC_NO_ERROR)
4247 alcSetError(device, err);
4249 if(device) ALCdevice_DecRef(device);
4253 /************************************************
4254 * ALC loopback functions
4255 ************************************************/
4257 /* alcLoopbackOpenDeviceSOFT
4259 * Open a loopback device, for manual rendering.
4261 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
4263 DO_INITCONFIG();
4265 /* Make sure the device name, if specified, is us. */
4266 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
4268 alcSetError(nullptr, ALC_INVALID_VALUE);
4269 return nullptr;
4272 auto device = new ALCdevice{Loopback};
4274 device->SourcesMax = 256;
4275 device->AuxiliaryEffectSlotMax = 64;
4276 device->NumAuxSends = DEFAULT_SENDS;
4278 //Set output format
4279 device->NumUpdates = 0;
4280 device->UpdateSize = 0;
4282 device->Frequency = DEFAULT_OUTPUT_RATE;
4283 device->FmtChans = DevFmtChannelsDefault;
4284 device->FmtType = DevFmtTypeDefault;
4285 device->IsHeadphones = AL_FALSE;
4286 device->mAmbiLayout = AmbiLayout_Default;
4287 device->mAmbiScale = AmbiNorm_Default;
4289 ConfigValueUInt(nullptr, nullptr, "sources", &device->SourcesMax);
4290 if(device->SourcesMax == 0) device->SourcesMax = 256;
4292 ConfigValueUInt(nullptr, nullptr, "slots", &device->AuxiliaryEffectSlotMax);
4293 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4294 else device->AuxiliaryEffectSlotMax = minu(device->AuxiliaryEffectSlotMax, INT_MAX);
4296 if(ConfigValueInt(nullptr, nullptr, "sends", &device->NumAuxSends))
4297 device->NumAuxSends = clampi(
4298 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4301 device->NumStereoSources = 1;
4302 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4304 device->Backend = LoopbackBackendFactory::getFactory().createBackend(
4305 device, ALCbackend_Loopback);
4306 if(!device->Backend)
4308 al_free(device);
4309 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
4310 return nullptr;
4313 // Open the "backend"
4314 V(device->Backend,open)("Loopback");
4317 ALCdevice *head{DeviceList.load()};
4318 do {
4319 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4320 } while(!DeviceList.compare_exchange_weak(head, device));
4323 TRACE("Created device %p\n", device);
4324 return device;
4327 /* alcIsRenderFormatSupportedSOFT
4329 * Determines if the loopback device supports the given format for rendering.
4331 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4333 ALCboolean ret{ALC_FALSE};
4335 if(!VerifyDevice(&device) || device->Type != Loopback)
4336 alcSetError(device, ALC_INVALID_DEVICE);
4337 else if(freq <= 0)
4338 alcSetError(device, ALC_INVALID_VALUE);
4339 else
4341 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4342 ret = ALC_TRUE;
4344 if(device) ALCdevice_DecRef(device);
4346 return ret;
4349 /* alcRenderSamplesSOFT
4351 * Renders some samples into a buffer, using the format last set by the
4352 * attributes given to alcCreateContext.
4354 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4356 if(!VerifyDevice(&device) || device->Type != Loopback)
4357 alcSetError(device, ALC_INVALID_DEVICE);
4358 else if(samples < 0 || (samples > 0 && buffer == nullptr))
4359 alcSetError(device, ALC_INVALID_VALUE);
4360 else
4362 V0(device->Backend,lock)();
4363 aluMixData(device, buffer, samples);
4364 V0(device->Backend,unlock)();
4366 if(device) ALCdevice_DecRef(device);
4370 /************************************************
4371 * ALC DSP pause/resume functions
4372 ************************************************/
4374 /* alcDevicePauseSOFT
4376 * Pause the DSP to stop audio processing.
4378 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4380 if(!VerifyDevice(&device) || device->Type != Playback)
4381 alcSetError(device, ALC_INVALID_DEVICE);
4382 else
4384 almtx_lock(&device->BackendLock);
4385 if((device->Flags&DEVICE_RUNNING))
4386 V0(device->Backend,stop)();
4387 device->Flags &= ~DEVICE_RUNNING;
4388 device->Flags |= DEVICE_PAUSED;
4389 almtx_unlock(&device->BackendLock);
4391 if(device) ALCdevice_DecRef(device);
4394 /* alcDeviceResumeSOFT
4396 * Resume the DSP to restart audio processing.
4398 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4400 if(!VerifyDevice(&device) || device->Type != Playback)
4401 alcSetError(device, ALC_INVALID_DEVICE);
4402 else
4404 almtx_lock(&device->BackendLock);
4405 if((device->Flags&DEVICE_PAUSED))
4407 device->Flags &= ~DEVICE_PAUSED;
4408 if(ATOMIC_LOAD_SEQ(&device->ContextList) != nullptr)
4410 if(V0(device->Backend,start)() != ALC_FALSE)
4411 device->Flags |= DEVICE_RUNNING;
4412 else
4414 V0(device->Backend,lock)();
4415 aluHandleDisconnect(device, "Device start failure");
4416 V0(device->Backend,unlock)();
4417 alcSetError(device, ALC_INVALID_DEVICE);
4421 almtx_unlock(&device->BackendLock);
4423 if(device) ALCdevice_DecRef(device);
4427 /************************************************
4428 * ALC HRTF functions
4429 ************************************************/
4431 /* alcGetStringiSOFT
4433 * Gets a string parameter at the given index.
4435 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4437 const ALCchar *str{nullptr};
4439 if(!VerifyDevice(&device) || device->Type == Capture)
4440 alcSetError(device, ALC_INVALID_DEVICE);
4441 else switch(paramName)
4443 case ALC_HRTF_SPECIFIER_SOFT:
4444 if(index >= 0 && (size_t)index < device->HrtfList.size())
4445 str = device->HrtfList[index].name.c_str();
4446 else
4447 alcSetError(device, ALC_INVALID_VALUE);
4448 break;
4450 default:
4451 alcSetError(device, ALC_INVALID_ENUM);
4452 break;
4454 if(device) ALCdevice_DecRef(device);
4456 return str;
4459 /* alcResetDeviceSOFT
4461 * Resets the given device output, using the specified attribute list.
4463 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4465 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4466 if(!VerifyDevice(&device) || device->Type == Capture ||
4467 !ATOMIC_LOAD(&device->Connected, almemory_order_relaxed))
4469 listlock.unlock();
4470 alcSetError(device, ALC_INVALID_DEVICE);
4471 if(device) ALCdevice_DecRef(device);
4472 return ALC_FALSE;
4474 almtx_lock(&device->BackendLock);
4475 listlock.unlock();
4477 ALCenum err{UpdateDeviceParams(device, attribs)};
4478 almtx_unlock(&device->BackendLock);
4480 if(err != ALC_NO_ERROR)
4482 alcSetError(device, err);
4483 if(err == ALC_INVALID_DEVICE)
4485 V0(device->Backend,lock)();
4486 aluHandleDisconnect(device, "Device start failure");
4487 V0(device->Backend,unlock)();
4489 ALCdevice_DecRef(device);
4490 return ALC_FALSE;
4492 ALCdevice_DecRef(device);
4494 return ALC_TRUE;