Use unique_ptr for BFormatDec and AmbiUpsampler
[openal-soft.git] / Alc / alc.cpp
blobd96f6df079ccdfe4b65b491891ac3c64a863fbcc
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 "uhjfilter.h"
52 #include "alu.h"
53 #include "alconfig.h"
54 #include "ringbuffer.h"
55 #include "filters/splitter.h"
57 #include "fpu_modes.h"
58 #include "cpu_caps.h"
59 #include "compat.h"
60 #include "threads.h"
61 #include "almalloc.h"
63 #include "backends/base.h"
64 #include "backends/null.h"
65 #include "backends/loopback.h"
66 #ifdef HAVE_JACK
67 #include "backends/jack.h"
68 #endif
69 #ifdef HAVE_PULSEAUDIO
70 #include "backends/pulseaudio.h"
71 #endif
72 #ifdef HAVE_ALSA
73 #include "backends/alsa.h"
74 #endif
75 #ifdef HAVE_WASAPI
76 #include "backends/wasapi.h"
77 #endif
78 #ifdef HAVE_COREAUDIO
79 #include "backends/coreaudio.h"
80 #endif
81 #ifdef HAVE_OPENSL
82 #include "backends/opensl.h"
83 #endif
84 #ifdef HAVE_SOLARIS
85 #include "backends/solaris.h"
86 #endif
87 #ifdef HAVE_SNDIO
88 #include "backends/sndio.h"
89 #endif
90 #ifdef HAVE_OSS
91 #include "backends/oss.h"
92 #endif
93 #ifdef HAVE_QSA
94 #include "backends/qsa.h"
95 #endif
96 #ifdef HAVE_DSOUND
97 #include "backends/dsound.h"
98 #endif
99 #ifdef HAVE_WINMM
100 #include "backends/winmm.h"
101 #endif
102 #ifdef HAVE_PORTAUDIO
103 #include "backends/portaudio.h"
104 #endif
105 #ifdef HAVE_SDL2
106 #include "backends/sdl2.h"
107 #endif
108 #ifdef HAVE_WAVE
109 #include "backends/wave.h"
110 #endif
113 namespace {
115 /************************************************
116 * Backends
117 ************************************************/
118 struct BackendInfo {
119 const char *name;
120 BackendFactory& (*getFactory)(void);
123 struct BackendInfo BackendList[] = {
124 #ifdef HAVE_JACK
125 { "jack", JackBackendFactory::getFactory },
126 #endif
127 #ifdef HAVE_PULSEAUDIO
128 { "pulse", PulseBackendFactory::getFactory },
129 #endif
130 #ifdef HAVE_ALSA
131 { "alsa", AlsaBackendFactory::getFactory },
132 #endif
133 #ifdef HAVE_WASAPI
134 { "wasapi", WasapiBackendFactory::getFactory },
135 #endif
136 #ifdef HAVE_COREAUDIO
137 { "core", CoreAudioBackendFactory::getFactory },
138 #endif
139 #ifdef HAVE_OPENSL
140 { "opensl", OSLBackendFactory::getFactory },
141 #endif
142 #ifdef HAVE_SOLARIS
143 { "solaris", SolarisBackendFactory::getFactory },
144 #endif
145 #ifdef HAVE_SNDIO
146 { "sndio", SndIOBackendFactory::getFactory },
147 #endif
148 #ifdef HAVE_OSS
149 { "oss", OSSBackendFactory::getFactory },
150 #endif
151 #ifdef HAVE_QSA
152 { "qsa", QSABackendFactory::getFactory },
153 #endif
154 #ifdef HAVE_DSOUND
155 { "dsound", DSoundBackendFactory::getFactory },
156 #endif
157 #ifdef HAVE_WINMM
158 { "winmm", WinMMBackendFactory::getFactory },
159 #endif
160 #ifdef HAVE_PORTAUDIO
161 { "port", PortBackendFactory::getFactory },
162 #endif
163 #ifdef HAVE_SDL2
164 { "sdl2", SDL2BackendFactory::getFactory },
165 #endif
167 { "null", NullBackendFactory::getFactory },
168 #ifdef HAVE_WAVE
169 { "wave", WaveBackendFactory::getFactory },
170 #endif
172 ALsizei BackendListSize = COUNTOF(BackendList);
174 struct BackendInfo PlaybackBackend;
175 struct BackendInfo CaptureBackend;
178 /************************************************
179 * Functions, enums, and errors
180 ************************************************/
181 #define DECL(x) { #x, (ALCvoid*)(x) }
182 constexpr struct {
183 const ALCchar *funcName;
184 ALCvoid *address;
185 } alcFunctions[] = {
186 DECL(alcCreateContext),
187 DECL(alcMakeContextCurrent),
188 DECL(alcProcessContext),
189 DECL(alcSuspendContext),
190 DECL(alcDestroyContext),
191 DECL(alcGetCurrentContext),
192 DECL(alcGetContextsDevice),
193 DECL(alcOpenDevice),
194 DECL(alcCloseDevice),
195 DECL(alcGetError),
196 DECL(alcIsExtensionPresent),
197 DECL(alcGetProcAddress),
198 DECL(alcGetEnumValue),
199 DECL(alcGetString),
200 DECL(alcGetIntegerv),
201 DECL(alcCaptureOpenDevice),
202 DECL(alcCaptureCloseDevice),
203 DECL(alcCaptureStart),
204 DECL(alcCaptureStop),
205 DECL(alcCaptureSamples),
207 DECL(alcSetThreadContext),
208 DECL(alcGetThreadContext),
210 DECL(alcLoopbackOpenDeviceSOFT),
211 DECL(alcIsRenderFormatSupportedSOFT),
212 DECL(alcRenderSamplesSOFT),
214 DECL(alcDevicePauseSOFT),
215 DECL(alcDeviceResumeSOFT),
217 DECL(alcGetStringiSOFT),
218 DECL(alcResetDeviceSOFT),
220 DECL(alcGetInteger64vSOFT),
222 DECL(alEnable),
223 DECL(alDisable),
224 DECL(alIsEnabled),
225 DECL(alGetString),
226 DECL(alGetBooleanv),
227 DECL(alGetIntegerv),
228 DECL(alGetFloatv),
229 DECL(alGetDoublev),
230 DECL(alGetBoolean),
231 DECL(alGetInteger),
232 DECL(alGetFloat),
233 DECL(alGetDouble),
234 DECL(alGetError),
235 DECL(alIsExtensionPresent),
236 DECL(alGetProcAddress),
237 DECL(alGetEnumValue),
238 DECL(alListenerf),
239 DECL(alListener3f),
240 DECL(alListenerfv),
241 DECL(alListeneri),
242 DECL(alListener3i),
243 DECL(alListeneriv),
244 DECL(alGetListenerf),
245 DECL(alGetListener3f),
246 DECL(alGetListenerfv),
247 DECL(alGetListeneri),
248 DECL(alGetListener3i),
249 DECL(alGetListeneriv),
250 DECL(alGenSources),
251 DECL(alDeleteSources),
252 DECL(alIsSource),
253 DECL(alSourcef),
254 DECL(alSource3f),
255 DECL(alSourcefv),
256 DECL(alSourcei),
257 DECL(alSource3i),
258 DECL(alSourceiv),
259 DECL(alGetSourcef),
260 DECL(alGetSource3f),
261 DECL(alGetSourcefv),
262 DECL(alGetSourcei),
263 DECL(alGetSource3i),
264 DECL(alGetSourceiv),
265 DECL(alSourcePlayv),
266 DECL(alSourceStopv),
267 DECL(alSourceRewindv),
268 DECL(alSourcePausev),
269 DECL(alSourcePlay),
270 DECL(alSourceStop),
271 DECL(alSourceRewind),
272 DECL(alSourcePause),
273 DECL(alSourceQueueBuffers),
274 DECL(alSourceUnqueueBuffers),
275 DECL(alGenBuffers),
276 DECL(alDeleteBuffers),
277 DECL(alIsBuffer),
278 DECL(alBufferData),
279 DECL(alBufferf),
280 DECL(alBuffer3f),
281 DECL(alBufferfv),
282 DECL(alBufferi),
283 DECL(alBuffer3i),
284 DECL(alBufferiv),
285 DECL(alGetBufferf),
286 DECL(alGetBuffer3f),
287 DECL(alGetBufferfv),
288 DECL(alGetBufferi),
289 DECL(alGetBuffer3i),
290 DECL(alGetBufferiv),
291 DECL(alDopplerFactor),
292 DECL(alDopplerVelocity),
293 DECL(alSpeedOfSound),
294 DECL(alDistanceModel),
296 DECL(alGenFilters),
297 DECL(alDeleteFilters),
298 DECL(alIsFilter),
299 DECL(alFilteri),
300 DECL(alFilteriv),
301 DECL(alFilterf),
302 DECL(alFilterfv),
303 DECL(alGetFilteri),
304 DECL(alGetFilteriv),
305 DECL(alGetFilterf),
306 DECL(alGetFilterfv),
307 DECL(alGenEffects),
308 DECL(alDeleteEffects),
309 DECL(alIsEffect),
310 DECL(alEffecti),
311 DECL(alEffectiv),
312 DECL(alEffectf),
313 DECL(alEffectfv),
314 DECL(alGetEffecti),
315 DECL(alGetEffectiv),
316 DECL(alGetEffectf),
317 DECL(alGetEffectfv),
318 DECL(alGenAuxiliaryEffectSlots),
319 DECL(alDeleteAuxiliaryEffectSlots),
320 DECL(alIsAuxiliaryEffectSlot),
321 DECL(alAuxiliaryEffectSloti),
322 DECL(alAuxiliaryEffectSlotiv),
323 DECL(alAuxiliaryEffectSlotf),
324 DECL(alAuxiliaryEffectSlotfv),
325 DECL(alGetAuxiliaryEffectSloti),
326 DECL(alGetAuxiliaryEffectSlotiv),
327 DECL(alGetAuxiliaryEffectSlotf),
328 DECL(alGetAuxiliaryEffectSlotfv),
330 DECL(alDeferUpdatesSOFT),
331 DECL(alProcessUpdatesSOFT),
333 DECL(alSourcedSOFT),
334 DECL(alSource3dSOFT),
335 DECL(alSourcedvSOFT),
336 DECL(alGetSourcedSOFT),
337 DECL(alGetSource3dSOFT),
338 DECL(alGetSourcedvSOFT),
339 DECL(alSourcei64SOFT),
340 DECL(alSource3i64SOFT),
341 DECL(alSourcei64vSOFT),
342 DECL(alGetSourcei64SOFT),
343 DECL(alGetSource3i64SOFT),
344 DECL(alGetSourcei64vSOFT),
346 DECL(alGetStringiSOFT),
348 DECL(alBufferStorageSOFT),
349 DECL(alMapBufferSOFT),
350 DECL(alUnmapBufferSOFT),
351 DECL(alFlushMappedBufferSOFT),
353 DECL(alEventControlSOFT),
354 DECL(alEventCallbackSOFT),
355 DECL(alGetPointerSOFT),
356 DECL(alGetPointervSOFT),
358 #undef DECL
360 #define DECL(x) { #x, (x) }
361 constexpr struct {
362 const ALCchar *enumName;
363 ALCenum value;
364 } alcEnumerations[] = {
365 DECL(ALC_INVALID),
366 DECL(ALC_FALSE),
367 DECL(ALC_TRUE),
369 DECL(ALC_MAJOR_VERSION),
370 DECL(ALC_MINOR_VERSION),
371 DECL(ALC_ATTRIBUTES_SIZE),
372 DECL(ALC_ALL_ATTRIBUTES),
373 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
374 DECL(ALC_DEVICE_SPECIFIER),
375 DECL(ALC_ALL_DEVICES_SPECIFIER),
376 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
377 DECL(ALC_EXTENSIONS),
378 DECL(ALC_FREQUENCY),
379 DECL(ALC_REFRESH),
380 DECL(ALC_SYNC),
381 DECL(ALC_MONO_SOURCES),
382 DECL(ALC_STEREO_SOURCES),
383 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
384 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
385 DECL(ALC_CAPTURE_SAMPLES),
386 DECL(ALC_CONNECTED),
388 DECL(ALC_EFX_MAJOR_VERSION),
389 DECL(ALC_EFX_MINOR_VERSION),
390 DECL(ALC_MAX_AUXILIARY_SENDS),
392 DECL(ALC_FORMAT_CHANNELS_SOFT),
393 DECL(ALC_FORMAT_TYPE_SOFT),
395 DECL(ALC_MONO_SOFT),
396 DECL(ALC_STEREO_SOFT),
397 DECL(ALC_QUAD_SOFT),
398 DECL(ALC_5POINT1_SOFT),
399 DECL(ALC_6POINT1_SOFT),
400 DECL(ALC_7POINT1_SOFT),
401 DECL(ALC_BFORMAT3D_SOFT),
403 DECL(ALC_BYTE_SOFT),
404 DECL(ALC_UNSIGNED_BYTE_SOFT),
405 DECL(ALC_SHORT_SOFT),
406 DECL(ALC_UNSIGNED_SHORT_SOFT),
407 DECL(ALC_INT_SOFT),
408 DECL(ALC_UNSIGNED_INT_SOFT),
409 DECL(ALC_FLOAT_SOFT),
411 DECL(ALC_HRTF_SOFT),
412 DECL(ALC_DONT_CARE_SOFT),
413 DECL(ALC_HRTF_STATUS_SOFT),
414 DECL(ALC_HRTF_DISABLED_SOFT),
415 DECL(ALC_HRTF_ENABLED_SOFT),
416 DECL(ALC_HRTF_DENIED_SOFT),
417 DECL(ALC_HRTF_REQUIRED_SOFT),
418 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
419 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
420 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
421 DECL(ALC_HRTF_SPECIFIER_SOFT),
422 DECL(ALC_HRTF_ID_SOFT),
424 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
425 DECL(ALC_AMBISONIC_SCALING_SOFT),
426 DECL(ALC_AMBISONIC_ORDER_SOFT),
427 DECL(ALC_ACN_SOFT),
428 DECL(ALC_FUMA_SOFT),
429 DECL(ALC_N3D_SOFT),
430 DECL(ALC_SN3D_SOFT),
432 DECL(ALC_OUTPUT_LIMITER_SOFT),
434 DECL(ALC_NO_ERROR),
435 DECL(ALC_INVALID_DEVICE),
436 DECL(ALC_INVALID_CONTEXT),
437 DECL(ALC_INVALID_ENUM),
438 DECL(ALC_INVALID_VALUE),
439 DECL(ALC_OUT_OF_MEMORY),
442 DECL(AL_INVALID),
443 DECL(AL_NONE),
444 DECL(AL_FALSE),
445 DECL(AL_TRUE),
447 DECL(AL_SOURCE_RELATIVE),
448 DECL(AL_CONE_INNER_ANGLE),
449 DECL(AL_CONE_OUTER_ANGLE),
450 DECL(AL_PITCH),
451 DECL(AL_POSITION),
452 DECL(AL_DIRECTION),
453 DECL(AL_VELOCITY),
454 DECL(AL_LOOPING),
455 DECL(AL_BUFFER),
456 DECL(AL_GAIN),
457 DECL(AL_MIN_GAIN),
458 DECL(AL_MAX_GAIN),
459 DECL(AL_ORIENTATION),
460 DECL(AL_REFERENCE_DISTANCE),
461 DECL(AL_ROLLOFF_FACTOR),
462 DECL(AL_CONE_OUTER_GAIN),
463 DECL(AL_MAX_DISTANCE),
464 DECL(AL_SEC_OFFSET),
465 DECL(AL_SAMPLE_OFFSET),
466 DECL(AL_BYTE_OFFSET),
467 DECL(AL_SOURCE_TYPE),
468 DECL(AL_STATIC),
469 DECL(AL_STREAMING),
470 DECL(AL_UNDETERMINED),
471 DECL(AL_METERS_PER_UNIT),
472 DECL(AL_LOOP_POINTS_SOFT),
473 DECL(AL_DIRECT_CHANNELS_SOFT),
475 DECL(AL_DIRECT_FILTER),
476 DECL(AL_AUXILIARY_SEND_FILTER),
477 DECL(AL_AIR_ABSORPTION_FACTOR),
478 DECL(AL_ROOM_ROLLOFF_FACTOR),
479 DECL(AL_CONE_OUTER_GAINHF),
480 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
481 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
482 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
484 DECL(AL_SOURCE_STATE),
485 DECL(AL_INITIAL),
486 DECL(AL_PLAYING),
487 DECL(AL_PAUSED),
488 DECL(AL_STOPPED),
490 DECL(AL_BUFFERS_QUEUED),
491 DECL(AL_BUFFERS_PROCESSED),
493 DECL(AL_FORMAT_MONO8),
494 DECL(AL_FORMAT_MONO16),
495 DECL(AL_FORMAT_MONO_FLOAT32),
496 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
497 DECL(AL_FORMAT_STEREO8),
498 DECL(AL_FORMAT_STEREO16),
499 DECL(AL_FORMAT_STEREO_FLOAT32),
500 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
501 DECL(AL_FORMAT_MONO_IMA4),
502 DECL(AL_FORMAT_STEREO_IMA4),
503 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
504 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
505 DECL(AL_FORMAT_QUAD8_LOKI),
506 DECL(AL_FORMAT_QUAD16_LOKI),
507 DECL(AL_FORMAT_QUAD8),
508 DECL(AL_FORMAT_QUAD16),
509 DECL(AL_FORMAT_QUAD32),
510 DECL(AL_FORMAT_51CHN8),
511 DECL(AL_FORMAT_51CHN16),
512 DECL(AL_FORMAT_51CHN32),
513 DECL(AL_FORMAT_61CHN8),
514 DECL(AL_FORMAT_61CHN16),
515 DECL(AL_FORMAT_61CHN32),
516 DECL(AL_FORMAT_71CHN8),
517 DECL(AL_FORMAT_71CHN16),
518 DECL(AL_FORMAT_71CHN32),
519 DECL(AL_FORMAT_REAR8),
520 DECL(AL_FORMAT_REAR16),
521 DECL(AL_FORMAT_REAR32),
522 DECL(AL_FORMAT_MONO_MULAW),
523 DECL(AL_FORMAT_MONO_MULAW_EXT),
524 DECL(AL_FORMAT_STEREO_MULAW),
525 DECL(AL_FORMAT_STEREO_MULAW_EXT),
526 DECL(AL_FORMAT_QUAD_MULAW),
527 DECL(AL_FORMAT_51CHN_MULAW),
528 DECL(AL_FORMAT_61CHN_MULAW),
529 DECL(AL_FORMAT_71CHN_MULAW),
530 DECL(AL_FORMAT_REAR_MULAW),
531 DECL(AL_FORMAT_MONO_ALAW_EXT),
532 DECL(AL_FORMAT_STEREO_ALAW_EXT),
534 DECL(AL_FORMAT_BFORMAT2D_8),
535 DECL(AL_FORMAT_BFORMAT2D_16),
536 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
537 DECL(AL_FORMAT_BFORMAT2D_MULAW),
538 DECL(AL_FORMAT_BFORMAT3D_8),
539 DECL(AL_FORMAT_BFORMAT3D_16),
540 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
541 DECL(AL_FORMAT_BFORMAT3D_MULAW),
543 DECL(AL_FREQUENCY),
544 DECL(AL_BITS),
545 DECL(AL_CHANNELS),
546 DECL(AL_SIZE),
547 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
548 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
550 DECL(AL_SOURCE_RADIUS),
552 DECL(AL_STEREO_ANGLES),
554 DECL(AL_UNUSED),
555 DECL(AL_PENDING),
556 DECL(AL_PROCESSED),
558 DECL(AL_NO_ERROR),
559 DECL(AL_INVALID_NAME),
560 DECL(AL_INVALID_ENUM),
561 DECL(AL_INVALID_VALUE),
562 DECL(AL_INVALID_OPERATION),
563 DECL(AL_OUT_OF_MEMORY),
565 DECL(AL_VENDOR),
566 DECL(AL_VERSION),
567 DECL(AL_RENDERER),
568 DECL(AL_EXTENSIONS),
570 DECL(AL_DOPPLER_FACTOR),
571 DECL(AL_DOPPLER_VELOCITY),
572 DECL(AL_DISTANCE_MODEL),
573 DECL(AL_SPEED_OF_SOUND),
574 DECL(AL_SOURCE_DISTANCE_MODEL),
575 DECL(AL_DEFERRED_UPDATES_SOFT),
576 DECL(AL_GAIN_LIMIT_SOFT),
578 DECL(AL_INVERSE_DISTANCE),
579 DECL(AL_INVERSE_DISTANCE_CLAMPED),
580 DECL(AL_LINEAR_DISTANCE),
581 DECL(AL_LINEAR_DISTANCE_CLAMPED),
582 DECL(AL_EXPONENT_DISTANCE),
583 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
585 DECL(AL_FILTER_TYPE),
586 DECL(AL_FILTER_NULL),
587 DECL(AL_FILTER_LOWPASS),
588 DECL(AL_FILTER_HIGHPASS),
589 DECL(AL_FILTER_BANDPASS),
591 DECL(AL_LOWPASS_GAIN),
592 DECL(AL_LOWPASS_GAINHF),
594 DECL(AL_HIGHPASS_GAIN),
595 DECL(AL_HIGHPASS_GAINLF),
597 DECL(AL_BANDPASS_GAIN),
598 DECL(AL_BANDPASS_GAINHF),
599 DECL(AL_BANDPASS_GAINLF),
601 DECL(AL_EFFECT_TYPE),
602 DECL(AL_EFFECT_NULL),
603 DECL(AL_EFFECT_REVERB),
604 DECL(AL_EFFECT_EAXREVERB),
605 DECL(AL_EFFECT_CHORUS),
606 DECL(AL_EFFECT_DISTORTION),
607 DECL(AL_EFFECT_ECHO),
608 DECL(AL_EFFECT_FLANGER),
609 DECL(AL_EFFECT_PITCH_SHIFTER),
610 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
611 #if 0
612 DECL(AL_EFFECT_VOCAL_MORPHER),
613 #endif
614 DECL(AL_EFFECT_RING_MODULATOR),
615 DECL(AL_EFFECT_AUTOWAH),
616 DECL(AL_EFFECT_COMPRESSOR),
617 DECL(AL_EFFECT_EQUALIZER),
618 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
619 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
621 DECL(AL_EFFECTSLOT_EFFECT),
622 DECL(AL_EFFECTSLOT_GAIN),
623 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
624 DECL(AL_EFFECTSLOT_NULL),
626 DECL(AL_EAXREVERB_DENSITY),
627 DECL(AL_EAXREVERB_DIFFUSION),
628 DECL(AL_EAXREVERB_GAIN),
629 DECL(AL_EAXREVERB_GAINHF),
630 DECL(AL_EAXREVERB_GAINLF),
631 DECL(AL_EAXREVERB_DECAY_TIME),
632 DECL(AL_EAXREVERB_DECAY_HFRATIO),
633 DECL(AL_EAXREVERB_DECAY_LFRATIO),
634 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
635 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
636 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
637 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
638 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
639 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
640 DECL(AL_EAXREVERB_ECHO_TIME),
641 DECL(AL_EAXREVERB_ECHO_DEPTH),
642 DECL(AL_EAXREVERB_MODULATION_TIME),
643 DECL(AL_EAXREVERB_MODULATION_DEPTH),
644 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
645 DECL(AL_EAXREVERB_HFREFERENCE),
646 DECL(AL_EAXREVERB_LFREFERENCE),
647 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
648 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
650 DECL(AL_REVERB_DENSITY),
651 DECL(AL_REVERB_DIFFUSION),
652 DECL(AL_REVERB_GAIN),
653 DECL(AL_REVERB_GAINHF),
654 DECL(AL_REVERB_DECAY_TIME),
655 DECL(AL_REVERB_DECAY_HFRATIO),
656 DECL(AL_REVERB_REFLECTIONS_GAIN),
657 DECL(AL_REVERB_REFLECTIONS_DELAY),
658 DECL(AL_REVERB_LATE_REVERB_GAIN),
659 DECL(AL_REVERB_LATE_REVERB_DELAY),
660 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
661 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
662 DECL(AL_REVERB_DECAY_HFLIMIT),
664 DECL(AL_CHORUS_WAVEFORM),
665 DECL(AL_CHORUS_PHASE),
666 DECL(AL_CHORUS_RATE),
667 DECL(AL_CHORUS_DEPTH),
668 DECL(AL_CHORUS_FEEDBACK),
669 DECL(AL_CHORUS_DELAY),
671 DECL(AL_DISTORTION_EDGE),
672 DECL(AL_DISTORTION_GAIN),
673 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
674 DECL(AL_DISTORTION_EQCENTER),
675 DECL(AL_DISTORTION_EQBANDWIDTH),
677 DECL(AL_ECHO_DELAY),
678 DECL(AL_ECHO_LRDELAY),
679 DECL(AL_ECHO_DAMPING),
680 DECL(AL_ECHO_FEEDBACK),
681 DECL(AL_ECHO_SPREAD),
683 DECL(AL_FLANGER_WAVEFORM),
684 DECL(AL_FLANGER_PHASE),
685 DECL(AL_FLANGER_RATE),
686 DECL(AL_FLANGER_DEPTH),
687 DECL(AL_FLANGER_FEEDBACK),
688 DECL(AL_FLANGER_DELAY),
690 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY),
691 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION),
692 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION),
694 DECL(AL_RING_MODULATOR_FREQUENCY),
695 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
696 DECL(AL_RING_MODULATOR_WAVEFORM),
698 DECL(AL_PITCH_SHIFTER_COARSE_TUNE),
699 DECL(AL_PITCH_SHIFTER_FINE_TUNE),
701 DECL(AL_COMPRESSOR_ONOFF),
703 DECL(AL_EQUALIZER_LOW_GAIN),
704 DECL(AL_EQUALIZER_LOW_CUTOFF),
705 DECL(AL_EQUALIZER_MID1_GAIN),
706 DECL(AL_EQUALIZER_MID1_CENTER),
707 DECL(AL_EQUALIZER_MID1_WIDTH),
708 DECL(AL_EQUALIZER_MID2_GAIN),
709 DECL(AL_EQUALIZER_MID2_CENTER),
710 DECL(AL_EQUALIZER_MID2_WIDTH),
711 DECL(AL_EQUALIZER_HIGH_GAIN),
712 DECL(AL_EQUALIZER_HIGH_CUTOFF),
714 DECL(AL_DEDICATED_GAIN),
716 DECL(AL_AUTOWAH_ATTACK_TIME),
717 DECL(AL_AUTOWAH_RELEASE_TIME),
718 DECL(AL_AUTOWAH_RESONANCE),
719 DECL(AL_AUTOWAH_PEAK_GAIN),
721 DECL(AL_NUM_RESAMPLERS_SOFT),
722 DECL(AL_DEFAULT_RESAMPLER_SOFT),
723 DECL(AL_SOURCE_RESAMPLER_SOFT),
724 DECL(AL_RESAMPLER_NAME_SOFT),
726 DECL(AL_SOURCE_SPATIALIZE_SOFT),
727 DECL(AL_AUTO_SOFT),
729 DECL(AL_MAP_READ_BIT_SOFT),
730 DECL(AL_MAP_WRITE_BIT_SOFT),
731 DECL(AL_MAP_PERSISTENT_BIT_SOFT),
732 DECL(AL_PRESERVE_DATA_BIT_SOFT),
734 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT),
735 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT),
736 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT),
737 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT),
738 DECL(AL_EVENT_TYPE_ERROR_SOFT),
739 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT),
740 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT),
742 #undef DECL
744 constexpr ALCchar alcNoError[] = "No Error";
745 constexpr ALCchar alcErrInvalidDevice[] = "Invalid Device";
746 constexpr ALCchar alcErrInvalidContext[] = "Invalid Context";
747 constexpr ALCchar alcErrInvalidEnum[] = "Invalid Enum";
748 constexpr ALCchar alcErrInvalidValue[] = "Invalid Value";
749 constexpr ALCchar alcErrOutOfMemory[] = "Out of Memory";
752 /************************************************
753 * Global variables
754 ************************************************/
756 /* Enumerated device names */
757 constexpr ALCchar alcDefaultName[] = "OpenAL Soft\0";
759 std::string alcAllDevicesList;
760 std::string alcCaptureDeviceList;
762 /* Default is always the first in the list */
763 std::string alcDefaultAllDevicesSpecifier;
764 std::string alcCaptureDefaultDeviceSpecifier;
766 /* Default context extensions */
767 constexpr ALchar alExtList[] =
768 "AL_EXT_ALAW "
769 "AL_EXT_BFORMAT "
770 "AL_EXT_DOUBLE "
771 "AL_EXT_EXPONENT_DISTANCE "
772 "AL_EXT_FLOAT32 "
773 "AL_EXT_IMA4 "
774 "AL_EXT_LINEAR_DISTANCE "
775 "AL_EXT_MCFORMATS "
776 "AL_EXT_MULAW "
777 "AL_EXT_MULAW_BFORMAT "
778 "AL_EXT_MULAW_MCFORMATS "
779 "AL_EXT_OFFSET "
780 "AL_EXT_source_distance_model "
781 "AL_EXT_SOURCE_RADIUS "
782 "AL_EXT_STEREO_ANGLES "
783 "AL_LOKI_quadriphonic "
784 "AL_SOFT_block_alignment "
785 "AL_SOFT_deferred_updates "
786 "AL_SOFT_direct_channels "
787 "AL_SOFTX_events "
788 "AL_SOFTX_filter_gain_ex "
789 "AL_SOFT_gain_clamp_ex "
790 "AL_SOFT_loop_points "
791 "AL_SOFTX_map_buffer "
792 "AL_SOFT_MSADPCM "
793 "AL_SOFT_source_latency "
794 "AL_SOFT_source_length "
795 "AL_SOFT_source_resampler "
796 "AL_SOFT_source_spatialize";
798 std::atomic<ALCenum> LastNullDeviceError{ALC_NO_ERROR};
800 /* Thread-local current context */
801 std::atomic<void(*)(ALCcontext*)> ThreadCtxProc{nullptr};
802 class ThreadCtx {
803 ALCcontext *ctx{nullptr};
805 public:
806 ~ThreadCtx()
808 auto destruct = ThreadCtxProc.load();
809 if(destruct && ctx)
810 destruct(ctx);
811 ctx = nullptr;
814 ALCcontext *get() const noexcept { return ctx; }
815 void set(ALCcontext *ctx_) noexcept { ctx = ctx_; }
817 thread_local ThreadCtx LocalContext;
818 /* Process-wide current context */
819 std::atomic<ALCcontext*> GlobalContext{nullptr};
821 /* Flag to trap ALC device errors */
822 bool TrapALCError{false};
824 /* One-time configuration init control */
825 std::once_flag alc_config_once{};
827 /* Default effect that applies to sources that don't have an effect on send 0 */
828 ALeffect DefaultEffect;
830 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
831 * updates.
833 bool SuspendDefers{true};
836 /************************************************
837 * ALC information
838 ************************************************/
839 constexpr ALCchar alcNoDeviceExtList[] =
840 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
841 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
842 constexpr ALCchar alcExtensionList[] =
843 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
844 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
845 "ALC_EXT_thread_local_context ALC_SOFT_device_clock ALC_SOFT_HRTF "
846 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
847 constexpr ALCint alcMajorVersion = 1;
848 constexpr ALCint alcMinorVersion = 1;
850 constexpr ALCint alcEFXMajorVersion = 1;
851 constexpr ALCint alcEFXMinorVersion = 0;
854 /************************************************
855 * Device lists
856 ************************************************/
857 std::atomic<ALCdevice*> DeviceList{nullptr};
859 std::recursive_mutex ListLock;
861 } // namespace
863 /* Mixing thread piority level */
864 ALint RTPrioLevel;
866 FILE *LogFile;
867 #ifdef _DEBUG
868 enum LogLevel LogLevel = LogWarning;
869 #else
870 enum LogLevel LogLevel = LogError;
871 #endif
873 /************************************************
874 * Library initialization
875 ************************************************/
876 #if defined(_WIN32)
877 static void alc_init(void);
878 static void alc_deinit(void);
879 static void alc_deinit_safe(void);
881 #ifndef AL_LIBTYPE_STATIC
882 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
884 switch(reason)
886 case DLL_PROCESS_ATTACH:
887 /* Pin the DLL so we won't get unloaded until the process terminates */
888 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
889 (WCHAR*)hModule, &hModule);
890 alc_init();
891 break;
893 case DLL_PROCESS_DETACH:
894 if(!lpReserved)
895 alc_deinit();
896 else
897 alc_deinit_safe();
898 break;
900 return TRUE;
902 #elif defined(_MSC_VER)
903 #pragma section(".CRT$XCU",read)
904 static void alc_constructor(void);
905 static void alc_destructor(void);
906 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
908 static void alc_constructor(void)
910 atexit(alc_destructor);
911 alc_init();
914 static void alc_destructor(void)
916 alc_deinit();
918 #elif defined(HAVE_GCC_DESTRUCTOR)
919 static void alc_init(void) __attribute__((constructor));
920 static void alc_deinit(void) __attribute__((destructor));
921 #else
922 #error "No static initialization available on this platform!"
923 #endif
925 #elif defined(HAVE_GCC_DESTRUCTOR)
927 static void alc_init(void) __attribute__((constructor));
928 static void alc_deinit(void) __attribute__((destructor));
930 #else
931 #error "No global initialization available on this platform!"
932 #endif
934 static void ReleaseThreadCtx(ALCcontext *ctx);
935 static void alc_init(void)
937 LogFile = stderr;
939 const char *str{getenv("__ALSOFT_HALF_ANGLE_CONES")};
940 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
941 ConeScale *= 0.5f;
943 str = getenv("__ALSOFT_REVERSE_Z");
944 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
945 ZScale *= -1.0f;
947 str = getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
948 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
949 OverrideReverbSpeedOfSound = AL_TRUE;
951 ThreadCtxProc = ReleaseThreadCtx;
954 static void alc_initconfig(void)
956 const char *devs, *str;
957 int capfilter;
958 float valf;
959 int i, n;
961 str = getenv("ALSOFT_LOGLEVEL");
962 if(str)
964 long lvl = strtol(str, nullptr, 0);
965 if(lvl >= NoLog && lvl <= LogRef)
966 LogLevel = static_cast<enum LogLevel>(lvl);
969 str = getenv("ALSOFT_LOGFILE");
970 if(str && str[0])
972 #ifdef _WIN32
973 std::wstring wname{utf8_to_wstr(str)};
974 FILE *logfile = _wfopen(wname.c_str(), L"wt");
975 #else
976 FILE *logfile = fopen(str, "wt");
977 #endif
978 if(logfile) LogFile = logfile;
979 else ERR("Failed to open log file '%s'\n", str);
982 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION,
983 ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH);
985 std::string names;
986 if(BackendListSize > 0)
987 names += BackendList[0].name;
988 for(i = 1;i < BackendListSize;i++)
990 names += ", ";
991 names += BackendList[i].name;
993 TRACE("Supported backends: %s\n", names.c_str());
995 ReadALConfig();
997 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
998 if(str && *str)
1000 if(strcasecmp(str, "ignore") == 0)
1002 SuspendDefers = false;
1003 TRACE("Selected context suspend behavior, \"ignore\"\n");
1005 else
1006 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
1009 capfilter = 0;
1010 #if defined(HAVE_SSE4_1)
1011 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
1012 #elif defined(HAVE_SSE3)
1013 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
1014 #elif defined(HAVE_SSE2)
1015 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
1016 #elif defined(HAVE_SSE)
1017 capfilter |= CPU_CAP_SSE;
1018 #endif
1019 #ifdef HAVE_NEON
1020 capfilter |= CPU_CAP_NEON;
1021 #endif
1022 if(ConfigValueStr(nullptr, nullptr, "disable-cpu-exts", &str))
1024 if(strcasecmp(str, "all") == 0)
1025 capfilter = 0;
1026 else
1028 size_t len;
1029 const char *next = str;
1031 do {
1032 str = next;
1033 while(isspace(str[0]))
1034 str++;
1035 next = strchr(str, ',');
1037 if(!str[0] || str[0] == ',')
1038 continue;
1040 len = (next ? ((size_t)(next-str)) : strlen(str));
1041 while(len > 0 && isspace(str[len-1]))
1042 len--;
1043 if(len == 3 && strncasecmp(str, "sse", len) == 0)
1044 capfilter &= ~CPU_CAP_SSE;
1045 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
1046 capfilter &= ~CPU_CAP_SSE2;
1047 else if(len == 4 && strncasecmp(str, "sse3", len) == 0)
1048 capfilter &= ~CPU_CAP_SSE3;
1049 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
1050 capfilter &= ~CPU_CAP_SSE4_1;
1051 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
1052 capfilter &= ~CPU_CAP_NEON;
1053 else
1054 WARN("Invalid CPU extension \"%s\"\n", str);
1055 } while(next++);
1058 FillCPUCaps(capfilter);
1060 #ifdef _WIN32
1061 RTPrioLevel = 1;
1062 #else
1063 RTPrioLevel = 0;
1064 #endif
1065 ConfigValueInt(nullptr, nullptr, "rt-prio", &RTPrioLevel);
1067 aluInit();
1068 aluInitMixer();
1070 str = getenv("ALSOFT_TRAP_ERROR");
1071 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
1073 TrapALError = AL_TRUE;
1074 TrapALCError = true;
1076 else
1078 str = getenv("ALSOFT_TRAP_AL_ERROR");
1079 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
1080 TrapALError = AL_TRUE;
1081 TrapALError = GetConfigValueBool(nullptr, nullptr, "trap-al-error", TrapALError);
1083 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1084 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
1085 TrapALCError = true;
1086 TrapALCError = !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", TrapALCError);
1089 if(ConfigValueFloat(nullptr, "reverb", "boost", &valf))
1090 ReverbBoost *= std::pow(10.0f, valf / 20.0f);
1092 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1093 ConfigValueStr(nullptr, nullptr, "drivers", &devs))
1095 int n;
1096 size_t len;
1097 const char *next = devs;
1098 int endlist, delitem;
1100 i = 0;
1101 do {
1102 devs = next;
1103 while(isspace(devs[0]))
1104 devs++;
1105 next = strchr(devs, ',');
1107 delitem = (devs[0] == '-');
1108 if(devs[0] == '-') devs++;
1110 if(!devs[0] || devs[0] == ',')
1112 endlist = 0;
1113 continue;
1115 endlist = 1;
1117 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1118 while(len > 0 && isspace(devs[len-1]))
1119 len--;
1120 #ifdef HAVE_WASAPI
1121 /* HACK: For backwards compatibility, convert backend references of
1122 * mmdevapi to wasapi. This should eventually be removed.
1124 if(len == 8 && strncmp(devs, "mmdevapi", len) == 0)
1126 devs = "wasapi";
1127 len = 6;
1129 #endif
1130 for(n = i;n < BackendListSize;n++)
1132 if(len == strlen(BackendList[n].name) &&
1133 strncmp(BackendList[n].name, devs, len) == 0)
1135 if(delitem)
1137 for(;n+1 < BackendListSize;n++)
1138 BackendList[n] = BackendList[n+1];
1139 BackendListSize--;
1141 else
1143 struct BackendInfo Bkp = BackendList[n];
1144 for(;n > i;n--)
1145 BackendList[n] = BackendList[n-1];
1146 BackendList[n] = Bkp;
1148 i++;
1150 break;
1153 } while(next++);
1155 if(endlist)
1156 BackendListSize = i;
1159 for(n = i = 0;i < BackendListSize && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1161 BackendList[n] = BackendList[i];
1163 BackendFactory &factory = BackendList[n].getFactory();
1164 if(!factory.init())
1166 WARN("Failed to initialize backend \"%s\"\n", BackendList[n].name);
1167 continue;
1170 TRACE("Initialized backend \"%s\"\n", BackendList[n].name);
1171 if(!PlaybackBackend.name && factory.querySupport(ALCbackend_Playback))
1173 PlaybackBackend = BackendList[n];
1174 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1176 if(!CaptureBackend.name && factory.querySupport(ALCbackend_Capture))
1178 CaptureBackend = BackendList[n];
1179 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1181 n++;
1183 BackendListSize = n;
1185 LoopbackBackendFactory::getFactory().init();
1187 if(!PlaybackBackend.name)
1188 WARN("No playback backend available!\n");
1189 if(!CaptureBackend.name)
1190 WARN("No capture backend available!\n");
1192 if(ConfigValueStr(nullptr, nullptr, "excludefx", &str))
1194 size_t len;
1195 const char *next = str;
1197 do {
1198 str = next;
1199 next = strchr(str, ',');
1201 if(!str[0] || next == str)
1202 continue;
1204 len = (next ? ((size_t)(next-str)) : strlen(str));
1205 for(n = 0;n < EFFECTLIST_SIZE;n++)
1207 if(len == strlen(EffectList[n].name) &&
1208 strncmp(EffectList[n].name, str, len) == 0)
1209 DisabledEffects[EffectList[n].type] = AL_TRUE;
1211 } while(next++);
1214 InitEffect(&DefaultEffect);
1215 str = getenv("ALSOFT_DEFAULT_REVERB");
1216 if((str && str[0]) || ConfigValueStr(nullptr, nullptr, "default-reverb", &str))
1217 LoadReverbPreset(str, &DefaultEffect);
1219 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1222 /************************************************
1223 * Library deinitialization
1224 ************************************************/
1225 static void alc_cleanup(void)
1227 alcAllDevicesList.clear();
1228 alcCaptureDeviceList.clear();
1230 alcDefaultAllDevicesSpecifier.clear();
1231 alcCaptureDefaultDeviceSpecifier.clear();
1233 if(ALCdevice *dev{DeviceList.exchange(nullptr)})
1235 ALCuint num = 0;
1236 do {
1237 num++;
1238 dev = dev->next.load(std::memory_order_relaxed);
1239 } while(dev != nullptr);
1240 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1244 static void alc_deinit_safe(void)
1246 alc_cleanup();
1248 FreeHrtfs();
1249 FreeALConfig();
1251 ThreadCtxProc = nullptr;
1253 if(LogFile != stderr)
1254 fclose(LogFile);
1255 LogFile = nullptr;
1258 static void alc_deinit(void)
1260 int i;
1262 alc_cleanup();
1264 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1265 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1267 for(i = 0;i < BackendListSize;i++)
1268 BackendList[i].getFactory().deinit();
1270 LoopbackBackendFactory::getFactory().deinit();
1272 alc_deinit_safe();
1276 /************************************************
1277 * Device enumeration
1278 ************************************************/
1279 static void ProbeDevices(std::string *list, struct BackendInfo *backendinfo, enum DevProbe type)
1281 DO_INITCONFIG();
1283 std::lock_guard<std::recursive_mutex> _{ListLock};
1284 list->clear();
1285 if(backendinfo->getFactory)
1286 backendinfo->getFactory().probe(type, list);
1288 static void ProbeAllDevicesList(void)
1289 { ProbeDevices(&alcAllDevicesList, &PlaybackBackend, ALL_DEVICE_PROBE); }
1290 static void ProbeCaptureDeviceList(void)
1291 { ProbeDevices(&alcCaptureDeviceList, &CaptureBackend, CAPTURE_DEVICE_PROBE); }
1294 /************************************************
1295 * Device format information
1296 ************************************************/
1297 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1299 switch(type)
1301 case DevFmtByte: return "Signed Byte";
1302 case DevFmtUByte: return "Unsigned Byte";
1303 case DevFmtShort: return "Signed Short";
1304 case DevFmtUShort: return "Unsigned Short";
1305 case DevFmtInt: return "Signed Int";
1306 case DevFmtUInt: return "Unsigned Int";
1307 case DevFmtFloat: return "Float";
1309 return "(unknown type)";
1311 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1313 switch(chans)
1315 case DevFmtMono: return "Mono";
1316 case DevFmtStereo: return "Stereo";
1317 case DevFmtQuad: return "Quadraphonic";
1318 case DevFmtX51: return "5.1 Surround";
1319 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1320 case DevFmtX61: return "6.1 Surround";
1321 case DevFmtX71: return "7.1 Surround";
1322 case DevFmtAmbi3D: return "Ambisonic 3D";
1324 return "(unknown channels)";
1327 ALsizei BytesFromDevFmt(enum DevFmtType type)
1329 switch(type)
1331 case DevFmtByte: return sizeof(ALbyte);
1332 case DevFmtUByte: return sizeof(ALubyte);
1333 case DevFmtShort: return sizeof(ALshort);
1334 case DevFmtUShort: return sizeof(ALushort);
1335 case DevFmtInt: return sizeof(ALint);
1336 case DevFmtUInt: return sizeof(ALuint);
1337 case DevFmtFloat: return sizeof(ALfloat);
1339 return 0;
1341 ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans, ALsizei ambiorder)
1343 switch(chans)
1345 case DevFmtMono: return 1;
1346 case DevFmtStereo: return 2;
1347 case DevFmtQuad: return 4;
1348 case DevFmtX51: return 6;
1349 case DevFmtX51Rear: return 6;
1350 case DevFmtX61: return 7;
1351 case DevFmtX71: return 8;
1352 case DevFmtAmbi3D: return (ambiorder >= 3) ? 16 :
1353 (ambiorder == 2) ? 9 :
1354 (ambiorder == 1) ? 4 : 1;
1356 return 0;
1359 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1360 enum DevFmtType *type)
1362 static const struct {
1363 ALenum format;
1364 enum DevFmtChannels channels;
1365 enum DevFmtType type;
1366 } list[] = {
1367 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1368 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1369 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1371 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1372 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1373 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1375 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1376 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1377 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1379 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1380 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1381 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1383 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1384 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1385 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1387 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1388 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1389 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1391 ALuint i;
1393 for(i = 0;i < COUNTOF(list);i++)
1395 if(list[i].format == format)
1397 *chans = list[i].channels;
1398 *type = list[i].type;
1399 return AL_TRUE;
1403 return AL_FALSE;
1406 static ALCboolean IsValidALCType(ALCenum type)
1408 switch(type)
1410 case ALC_BYTE_SOFT:
1411 case ALC_UNSIGNED_BYTE_SOFT:
1412 case ALC_SHORT_SOFT:
1413 case ALC_UNSIGNED_SHORT_SOFT:
1414 case ALC_INT_SOFT:
1415 case ALC_UNSIGNED_INT_SOFT:
1416 case ALC_FLOAT_SOFT:
1417 return ALC_TRUE;
1419 return ALC_FALSE;
1422 static ALCboolean IsValidALCChannels(ALCenum channels)
1424 switch(channels)
1426 case ALC_MONO_SOFT:
1427 case ALC_STEREO_SOFT:
1428 case ALC_QUAD_SOFT:
1429 case ALC_5POINT1_SOFT:
1430 case ALC_6POINT1_SOFT:
1431 case ALC_7POINT1_SOFT:
1432 case ALC_BFORMAT3D_SOFT:
1433 return ALC_TRUE;
1435 return ALC_FALSE;
1438 static ALCboolean IsValidAmbiLayout(ALCenum layout)
1440 switch(layout)
1442 case ALC_ACN_SOFT:
1443 case ALC_FUMA_SOFT:
1444 return ALC_TRUE;
1446 return ALC_FALSE;
1449 static ALCboolean IsValidAmbiScaling(ALCenum scaling)
1451 switch(scaling)
1453 case ALC_N3D_SOFT:
1454 case ALC_SN3D_SOFT:
1455 case ALC_FUMA_SOFT:
1456 return ALC_TRUE;
1458 return ALC_FALSE;
1461 /************************************************
1462 * Miscellaneous ALC helpers
1463 ************************************************/
1465 /* SetDefaultWFXChannelOrder
1467 * Sets the default channel order used by WaveFormatEx.
1469 void SetDefaultWFXChannelOrder(ALCdevice *device)
1471 ALsizei i;
1473 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1474 device->RealOut.ChannelName[i] = InvalidChannel;
1476 switch(device->FmtChans)
1478 case DevFmtMono:
1479 device->RealOut.ChannelName[0] = FrontCenter;
1480 break;
1481 case DevFmtStereo:
1482 device->RealOut.ChannelName[0] = FrontLeft;
1483 device->RealOut.ChannelName[1] = FrontRight;
1484 break;
1485 case DevFmtQuad:
1486 device->RealOut.ChannelName[0] = FrontLeft;
1487 device->RealOut.ChannelName[1] = FrontRight;
1488 device->RealOut.ChannelName[2] = BackLeft;
1489 device->RealOut.ChannelName[3] = BackRight;
1490 break;
1491 case DevFmtX51:
1492 device->RealOut.ChannelName[0] = FrontLeft;
1493 device->RealOut.ChannelName[1] = FrontRight;
1494 device->RealOut.ChannelName[2] = FrontCenter;
1495 device->RealOut.ChannelName[3] = LFE;
1496 device->RealOut.ChannelName[4] = SideLeft;
1497 device->RealOut.ChannelName[5] = SideRight;
1498 break;
1499 case DevFmtX51Rear:
1500 device->RealOut.ChannelName[0] = FrontLeft;
1501 device->RealOut.ChannelName[1] = FrontRight;
1502 device->RealOut.ChannelName[2] = FrontCenter;
1503 device->RealOut.ChannelName[3] = LFE;
1504 device->RealOut.ChannelName[4] = BackLeft;
1505 device->RealOut.ChannelName[5] = BackRight;
1506 break;
1507 case DevFmtX61:
1508 device->RealOut.ChannelName[0] = FrontLeft;
1509 device->RealOut.ChannelName[1] = FrontRight;
1510 device->RealOut.ChannelName[2] = FrontCenter;
1511 device->RealOut.ChannelName[3] = LFE;
1512 device->RealOut.ChannelName[4] = BackCenter;
1513 device->RealOut.ChannelName[5] = SideLeft;
1514 device->RealOut.ChannelName[6] = SideRight;
1515 break;
1516 case DevFmtX71:
1517 device->RealOut.ChannelName[0] = FrontLeft;
1518 device->RealOut.ChannelName[1] = FrontRight;
1519 device->RealOut.ChannelName[2] = FrontCenter;
1520 device->RealOut.ChannelName[3] = LFE;
1521 device->RealOut.ChannelName[4] = BackLeft;
1522 device->RealOut.ChannelName[5] = BackRight;
1523 device->RealOut.ChannelName[6] = SideLeft;
1524 device->RealOut.ChannelName[7] = SideRight;
1525 break;
1526 case DevFmtAmbi3D:
1527 device->RealOut.ChannelName[0] = Aux0;
1528 if(device->mAmbiOrder > 0)
1530 device->RealOut.ChannelName[1] = Aux1;
1531 device->RealOut.ChannelName[2] = Aux2;
1532 device->RealOut.ChannelName[3] = Aux3;
1534 if(device->mAmbiOrder > 1)
1536 device->RealOut.ChannelName[4] = Aux4;
1537 device->RealOut.ChannelName[5] = Aux5;
1538 device->RealOut.ChannelName[6] = Aux6;
1539 device->RealOut.ChannelName[7] = Aux7;
1540 device->RealOut.ChannelName[8] = Aux8;
1542 if(device->mAmbiOrder > 2)
1544 device->RealOut.ChannelName[9] = Aux9;
1545 device->RealOut.ChannelName[10] = Aux10;
1546 device->RealOut.ChannelName[11] = Aux11;
1547 device->RealOut.ChannelName[12] = Aux12;
1548 device->RealOut.ChannelName[13] = Aux13;
1549 device->RealOut.ChannelName[14] = Aux14;
1550 device->RealOut.ChannelName[15] = Aux15;
1552 break;
1556 /* SetDefaultChannelOrder
1558 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1560 void SetDefaultChannelOrder(ALCdevice *device)
1562 ALsizei i;
1564 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1565 device->RealOut.ChannelName[i] = InvalidChannel;
1567 switch(device->FmtChans)
1569 case DevFmtX51Rear:
1570 device->RealOut.ChannelName[0] = FrontLeft;
1571 device->RealOut.ChannelName[1] = FrontRight;
1572 device->RealOut.ChannelName[2] = BackLeft;
1573 device->RealOut.ChannelName[3] = BackRight;
1574 device->RealOut.ChannelName[4] = FrontCenter;
1575 device->RealOut.ChannelName[5] = LFE;
1576 return;
1577 case DevFmtX71:
1578 device->RealOut.ChannelName[0] = FrontLeft;
1579 device->RealOut.ChannelName[1] = FrontRight;
1580 device->RealOut.ChannelName[2] = BackLeft;
1581 device->RealOut.ChannelName[3] = BackRight;
1582 device->RealOut.ChannelName[4] = FrontCenter;
1583 device->RealOut.ChannelName[5] = LFE;
1584 device->RealOut.ChannelName[6] = SideLeft;
1585 device->RealOut.ChannelName[7] = SideRight;
1586 return;
1588 /* Same as WFX order */
1589 case DevFmtMono:
1590 case DevFmtStereo:
1591 case DevFmtQuad:
1592 case DevFmtX51:
1593 case DevFmtX61:
1594 case DevFmtAmbi3D:
1595 SetDefaultWFXChannelOrder(device);
1596 break;
1601 /* ALCcontext_DeferUpdates
1603 * Defers/suspends updates for the given context's listener and sources. This
1604 * does *NOT* stop mixing, but rather prevents certain property changes from
1605 * taking effect.
1607 void ALCcontext_DeferUpdates(ALCcontext *context)
1609 context->DeferUpdates.store(true);
1612 /* ALCcontext_ProcessUpdates
1614 * Resumes update processing after being deferred.
1616 void ALCcontext_ProcessUpdates(ALCcontext *context)
1618 std::lock_guard<almtx_t> _{context->PropLock};
1619 if(context->DeferUpdates.exchange(false))
1621 /* Tell the mixer to stop applying updates, then wait for any active
1622 * updating to finish, before providing updates.
1624 context->HoldUpdates.store(AL_TRUE);
1625 while((context->UpdateCount.load(std::memory_order_acquire)&1) != 0)
1626 althrd_yield();
1628 if(!context->PropsClean.test_and_set(std::memory_order_acq_rel))
1629 UpdateContextProps(context);
1630 if(!context->Listener.PropsClean.test_and_set(std::memory_order_acq_rel))
1631 UpdateListenerProps(context);
1632 UpdateAllEffectSlotProps(context);
1633 UpdateAllSourceProps(context);
1635 /* Now with all updates declared, let the mixer continue applying them
1636 * so they all happen at once.
1638 context->HoldUpdates.store(AL_FALSE);
1643 /* alcSetError
1645 * Stores the latest ALC device error
1647 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1649 WARN("Error generated on device %p, code 0x%04x\n", device, errorCode);
1650 if(TrapALCError)
1652 #ifdef _WIN32
1653 /* DebugBreak() will cause an exception if there is no debugger */
1654 if(IsDebuggerPresent())
1655 DebugBreak();
1656 #elif defined(SIGTRAP)
1657 raise(SIGTRAP);
1658 #endif
1661 if(device)
1662 device->LastError.store(errorCode);
1663 else
1664 LastNullDeviceError.store(errorCode);
1668 static struct Compressor *CreateDeviceLimiter(const ALCdevice *device, const ALfloat threshold)
1670 return CompressorInit(device->RealOut.NumChannels, device->Frequency,
1671 AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, 0.001f, 0.002f,
1672 0.0f, 0.0f, threshold, INFINITY, 0.0f, 0.020f, 0.200f);
1675 /* UpdateClockBase
1677 * Updates the device's base clock time with however many samples have been
1678 * done. This is used so frequency changes on the device don't cause the time
1679 * to jump forward or back. Must not be called while the device is running/
1680 * mixing.
1682 static inline void UpdateClockBase(ALCdevice *device)
1684 IncrementRef(&device->MixCount);
1685 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1686 device->SamplesDone = 0;
1687 IncrementRef(&device->MixCount);
1690 /* UpdateDeviceParams
1692 * Updates device parameters according to the attribute list (caller is
1693 * responsible for holding the list lock).
1695 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1697 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1698 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1699 ALCenum gainLimiter = device->LimiterState;
1700 const ALsizei old_sends = device->NumAuxSends;
1701 ALsizei new_sends = device->NumAuxSends;
1702 enum DevFmtChannels oldChans;
1703 enum DevFmtType oldType;
1704 ALboolean update_failed;
1705 ALCsizei hrtf_id = -1;
1706 ALCcontext *context;
1707 ALCuint oldFreq;
1708 ALCsizei i;
1709 int val;
1711 // Check for attributes
1712 if(device->Type == Loopback)
1714 ALCsizei numMono, numStereo, numSends;
1715 ALCenum alayout = AL_NONE;
1716 ALCenum ascale = AL_NONE;
1717 ALCenum schans = AL_NONE;
1718 ALCenum stype = AL_NONE;
1719 ALCsizei attrIdx = 0;
1720 ALCsizei aorder = 0;
1721 ALCuint freq = 0;
1723 if(!attrList)
1725 WARN("Missing attributes for loopback device\n");
1726 return ALC_INVALID_VALUE;
1729 numMono = device->NumMonoSources;
1730 numStereo = device->NumStereoSources;
1731 numSends = old_sends;
1733 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1734 while(attrList[attrIdx])
1736 switch(attrList[attrIdx])
1738 case ALC_FORMAT_CHANNELS_SOFT:
1739 schans = attrList[attrIdx + 1];
1740 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1741 if(!IsValidALCChannels(schans))
1742 return ALC_INVALID_VALUE;
1743 break;
1745 case ALC_FORMAT_TYPE_SOFT:
1746 stype = attrList[attrIdx + 1];
1747 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1748 if(!IsValidALCType(stype))
1749 return ALC_INVALID_VALUE;
1750 break;
1752 case ALC_FREQUENCY:
1753 freq = attrList[attrIdx + 1];
1754 TRACE_ATTR(ALC_FREQUENCY, freq);
1755 if(freq < MIN_OUTPUT_RATE)
1756 return ALC_INVALID_VALUE;
1757 break;
1759 case ALC_AMBISONIC_LAYOUT_SOFT:
1760 alayout = attrList[attrIdx + 1];
1761 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1762 if(!IsValidAmbiLayout(alayout))
1763 return ALC_INVALID_VALUE;
1764 break;
1766 case ALC_AMBISONIC_SCALING_SOFT:
1767 ascale = attrList[attrIdx + 1];
1768 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1769 if(!IsValidAmbiScaling(ascale))
1770 return ALC_INVALID_VALUE;
1771 break;
1773 case ALC_AMBISONIC_ORDER_SOFT:
1774 aorder = attrList[attrIdx + 1];
1775 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1776 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1777 return ALC_INVALID_VALUE;
1778 break;
1780 case ALC_MONO_SOURCES:
1781 numMono = attrList[attrIdx + 1];
1782 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1783 numMono = maxi(numMono, 0);
1784 break;
1786 case ALC_STEREO_SOURCES:
1787 numStereo = attrList[attrIdx + 1];
1788 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1789 numStereo = maxi(numStereo, 0);
1790 break;
1792 case ALC_MAX_AUXILIARY_SENDS:
1793 numSends = attrList[attrIdx + 1];
1794 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1795 numSends = clampi(numSends, 0, MAX_SENDS);
1796 break;
1798 case ALC_HRTF_SOFT:
1799 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1800 if(attrList[attrIdx + 1] == ALC_FALSE)
1801 hrtf_appreq = Hrtf_Disable;
1802 else if(attrList[attrIdx + 1] == ALC_TRUE)
1803 hrtf_appreq = Hrtf_Enable;
1804 else
1805 hrtf_appreq = Hrtf_Default;
1806 break;
1808 case ALC_HRTF_ID_SOFT:
1809 hrtf_id = attrList[attrIdx + 1];
1810 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1811 break;
1813 case ALC_OUTPUT_LIMITER_SOFT:
1814 gainLimiter = attrList[attrIdx + 1];
1815 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1816 break;
1818 default:
1819 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList[attrIdx],
1820 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1821 break;
1824 attrIdx += 2;
1826 #undef TRACE_ATTR
1828 if(!schans || !stype || !freq)
1830 WARN("Missing format for loopback device\n");
1831 return ALC_INVALID_VALUE;
1833 if(schans == ALC_BFORMAT3D_SOFT && (!alayout || !ascale || !aorder))
1835 WARN("Missing ambisonic info for loopback device\n");
1836 return ALC_INVALID_VALUE;
1839 if((device->Flags&DEVICE_RUNNING))
1840 V0(device->Backend,stop)();
1841 device->Flags &= ~DEVICE_RUNNING;
1843 UpdateClockBase(device);
1845 device->Frequency = freq;
1846 device->FmtChans = static_cast<enum DevFmtChannels>(schans);
1847 device->FmtType = static_cast<enum DevFmtType>(stype);
1848 if(schans == ALC_BFORMAT3D_SOFT)
1850 device->mAmbiOrder = aorder;
1851 device->mAmbiLayout = static_cast<AmbiLayout>(alayout);
1852 device->mAmbiScale = static_cast<AmbiNorm>(ascale);
1855 if(numMono > INT_MAX-numStereo)
1856 numMono = INT_MAX-numStereo;
1857 numMono += numStereo;
1858 if(ConfigValueInt(nullptr, nullptr, "sources", &numMono))
1860 if(numMono <= 0)
1861 numMono = 256;
1863 else
1864 numMono = maxi(numMono, 256);
1865 numStereo = mini(numStereo, numMono);
1866 numMono -= numStereo;
1867 device->SourcesMax = numMono + numStereo;
1869 device->NumMonoSources = numMono;
1870 device->NumStereoSources = numStereo;
1872 if(ConfigValueInt(nullptr, nullptr, "sends", &new_sends))
1873 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1874 else
1875 new_sends = numSends;
1877 else if(attrList && attrList[0])
1879 ALCsizei numMono, numStereo, numSends;
1880 ALCsizei attrIdx = 0;
1881 ALCuint freq;
1883 /* If a context is already running on the device, stop playback so the
1884 * device attributes can be updated. */
1885 if((device->Flags&DEVICE_RUNNING))
1886 V0(device->Backend,stop)();
1887 device->Flags &= ~DEVICE_RUNNING;
1889 UpdateClockBase(device);
1891 freq = device->Frequency;
1892 numMono = device->NumMonoSources;
1893 numStereo = device->NumStereoSources;
1894 numSends = old_sends;
1896 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1897 while(attrList[attrIdx])
1899 switch(attrList[attrIdx])
1901 case ALC_FREQUENCY:
1902 freq = attrList[attrIdx + 1];
1903 TRACE_ATTR(ALC_FREQUENCY, freq);
1904 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1905 break;
1907 case ALC_MONO_SOURCES:
1908 numMono = attrList[attrIdx + 1];
1909 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1910 numMono = maxi(numMono, 0);
1911 break;
1913 case ALC_STEREO_SOURCES:
1914 numStereo = attrList[attrIdx + 1];
1915 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1916 numStereo = maxi(numStereo, 0);
1917 break;
1919 case ALC_MAX_AUXILIARY_SENDS:
1920 numSends = attrList[attrIdx + 1];
1921 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1922 numSends = clampi(numSends, 0, MAX_SENDS);
1923 break;
1925 case ALC_HRTF_SOFT:
1926 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1927 if(attrList[attrIdx + 1] == ALC_FALSE)
1928 hrtf_appreq = Hrtf_Disable;
1929 else if(attrList[attrIdx + 1] == ALC_TRUE)
1930 hrtf_appreq = Hrtf_Enable;
1931 else
1932 hrtf_appreq = Hrtf_Default;
1933 break;
1935 case ALC_HRTF_ID_SOFT:
1936 hrtf_id = attrList[attrIdx + 1];
1937 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1938 break;
1940 case ALC_OUTPUT_LIMITER_SOFT:
1941 gainLimiter = attrList[attrIdx + 1];
1942 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1943 break;
1945 default:
1946 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1947 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1948 break;
1951 attrIdx += 2;
1953 #undef TRACE_ATTR
1955 ConfigValueUInt(device->DeviceName.c_str(), nullptr, "frequency", &freq);
1956 freq = maxu(freq, MIN_OUTPUT_RATE);
1958 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1959 device->Frequency;
1960 /* SSE and Neon do best with the update size being a multiple of 4 */
1961 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1962 device->UpdateSize = (device->UpdateSize+3)&~3;
1964 device->Frequency = freq;
1966 if(numMono > INT_MAX-numStereo)
1967 numMono = INT_MAX-numStereo;
1968 numMono += numStereo;
1969 if(ConfigValueInt(device->DeviceName.c_str(), nullptr, "sources", &numMono))
1971 if(numMono <= 0)
1972 numMono = 256;
1974 else
1975 numMono = maxi(numMono, 256);
1976 numStereo = mini(numStereo, numMono);
1977 numMono -= numStereo;
1978 device->SourcesMax = numMono + numStereo;
1980 device->NumMonoSources = numMono;
1981 device->NumStereoSources = numStereo;
1983 if(ConfigValueInt(device->DeviceName.c_str(), nullptr, "sends", &new_sends))
1984 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1985 else
1986 new_sends = numSends;
1989 if((device->Flags&DEVICE_RUNNING))
1990 return ALC_NO_ERROR;
1992 device->Uhj_Encoder = nullptr;
1994 al_free(device->Bs2b);
1995 device->Bs2b = nullptr;
1997 device->ChannelDelay.clear();
1998 device->ChannelDelay.shrink_to_fit();
2000 device->Dry.Buffer = nullptr;
2001 device->Dry.NumChannels = 0;
2002 device->FOAOut.Buffer = nullptr;
2003 device->FOAOut.NumChannels = 0;
2004 device->RealOut.Buffer = nullptr;
2005 device->RealOut.NumChannels = 0;
2006 device->MixBuffer.clear();
2007 device->MixBuffer.shrink_to_fit();
2009 UpdateClockBase(device);
2010 device->FixedLatency = 0;
2012 device->DitherSeed = DITHER_RNG_SEED;
2014 /*************************************************************************
2015 * Update device format request if HRTF is requested
2017 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
2018 if(device->Type != Loopback)
2020 const char *hrtf;
2021 if(ConfigValueStr(device->DeviceName.c_str(), nullptr, "hrtf", &hrtf))
2023 if(strcasecmp(hrtf, "true") == 0)
2024 hrtf_userreq = Hrtf_Enable;
2025 else if(strcasecmp(hrtf, "false") == 0)
2026 hrtf_userreq = Hrtf_Disable;
2027 else if(strcasecmp(hrtf, "auto") != 0)
2028 ERR("Unexpected hrtf value: %s\n", hrtf);
2031 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
2033 struct Hrtf *hrtf = nullptr;
2034 if(device->HrtfList.empty())
2035 device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
2036 if(!device->HrtfList.empty())
2038 if(hrtf_id >= 0 && (size_t)hrtf_id < device->HrtfList.size())
2039 hrtf = GetLoadedHrtf(device->HrtfList[hrtf_id].hrtf);
2040 else
2041 hrtf = GetLoadedHrtf(device->HrtfList.front().hrtf);
2044 if(hrtf)
2046 device->FmtChans = DevFmtStereo;
2047 device->Frequency = hrtf->sampleRate;
2048 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
2049 if(device->HrtfHandle)
2050 Hrtf_DecRef(device->HrtfHandle);
2051 device->HrtfHandle = hrtf;
2053 else
2055 hrtf_userreq = Hrtf_Default;
2056 hrtf_appreq = Hrtf_Disable;
2057 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2062 oldFreq = device->Frequency;
2063 oldChans = device->FmtChans;
2064 oldType = device->FmtType;
2066 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2067 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
2068 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
2069 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
2070 device->UpdateSize, device->NumUpdates
2073 if(V0(device->Backend,reset)() == ALC_FALSE)
2074 return ALC_INVALID_DEVICE;
2076 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
2078 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2079 DevFmtChannelsString(device->FmtChans));
2080 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2082 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2084 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2085 DevFmtTypeString(device->FmtType));
2086 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2088 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2090 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2091 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2094 if((device->UpdateSize&3) != 0)
2096 if((CPUCapFlags&CPU_CAP_SSE))
2097 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2098 if((CPUCapFlags&CPU_CAP_NEON))
2099 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2102 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2103 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2104 device->Frequency, device->UpdateSize, device->NumUpdates
2107 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2108 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device->Dry.NumChannels,
2109 device->FOAOut.NumChannels, device->RealOut.NumChannels);
2111 /* Allocate extra channels for any post-filter output. */
2112 ALsizei num_chans{device->Dry.NumChannels + device->FOAOut.NumChannels +
2113 device->RealOut.NumChannels};
2115 TRACE("Allocating %d channels, " SZFMT " bytes\n", num_chans,
2116 num_chans*sizeof(device->MixBuffer[0]));
2117 device->MixBuffer.resize(num_chans);
2119 device->Dry.Buffer = &reinterpret_cast<ALfloat(&)[BUFFERSIZE]>(device->MixBuffer[0]);
2120 if(device->RealOut.NumChannels != 0)
2121 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels +
2122 device->FOAOut.NumChannels;
2123 else
2125 device->RealOut.Buffer = device->Dry.Buffer;
2126 device->RealOut.NumChannels = device->Dry.NumChannels;
2129 if(device->FOAOut.NumChannels != 0)
2130 device->FOAOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2131 else
2133 device->FOAOut.Buffer = device->Dry.Buffer;
2134 device->FOAOut.NumChannels = device->Dry.NumChannels;
2137 device->NumAuxSends = new_sends;
2138 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2139 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
2140 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
2142 device->DitherDepth = 0.0f;
2143 if(GetConfigValueBool(device->DeviceName.c_str(), nullptr, "dither", 1))
2145 ALint depth = 0;
2146 ConfigValueInt(device->DeviceName.c_str(), nullptr, "dither-depth", &depth);
2147 if(depth <= 0)
2149 switch(device->FmtType)
2151 case DevFmtByte:
2152 case DevFmtUByte:
2153 depth = 8;
2154 break;
2155 case DevFmtShort:
2156 case DevFmtUShort:
2157 depth = 16;
2158 break;
2159 case DevFmtInt:
2160 case DevFmtUInt:
2161 case DevFmtFloat:
2162 break;
2166 if(depth > 0)
2168 depth = clampi(depth, 2, 24);
2169 device->DitherDepth = std::pow(2.0f, (ALfloat)(depth-1));
2172 if(!(device->DitherDepth > 0.0f))
2173 TRACE("Dithering disabled\n");
2174 else
2175 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device->DitherDepth)+0.5f)+1,
2176 device->DitherDepth);
2178 device->LimiterState = gainLimiter;
2179 if(ConfigValueBool(device->DeviceName.c_str(), nullptr, "output-limiter", &val))
2180 gainLimiter = val ? ALC_TRUE : ALC_FALSE;
2182 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2183 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2184 * output (where samples must be clamped), and don't for floating-point
2185 * (which can take unclamped samples).
2187 if(gainLimiter == ALC_DONT_CARE_SOFT)
2189 switch(device->FmtType)
2191 case DevFmtByte:
2192 case DevFmtUByte:
2193 case DevFmtShort:
2194 case DevFmtUShort:
2195 case DevFmtInt:
2196 case DevFmtUInt:
2197 gainLimiter = ALC_TRUE;
2198 break;
2199 case DevFmtFloat:
2200 gainLimiter = ALC_FALSE;
2201 break;
2204 if(gainLimiter != ALC_FALSE)
2206 ALfloat thrshld = 1.0f;
2207 switch(device->FmtType)
2209 case DevFmtByte:
2210 case DevFmtUByte:
2211 thrshld = 127.0f / 128.0f;
2212 break;
2213 case DevFmtShort:
2214 case DevFmtUShort:
2215 thrshld = 32767.0f / 32768.0f;
2216 break;
2217 case DevFmtInt:
2218 case DevFmtUInt:
2219 case DevFmtFloat:
2220 break;
2222 if(device->DitherDepth > 0.0f)
2223 thrshld -= 1.0f / device->DitherDepth;
2225 device->Limiter.reset(CreateDeviceLimiter(device, std::log10(thrshld) * 20.0f));
2226 device->FixedLatency += (ALuint)(GetCompressorLookAhead(device->Limiter.get()) *
2227 DEVICE_CLOCK_RES / device->Frequency);
2229 else
2230 device->Limiter = nullptr;
2231 TRACE("Output limiter %s\n", device->Limiter ? "enabled" : "disabled");
2233 aluSelectPostProcess(device);
2235 TRACE("Fixed device latency: %uns\n", device->FixedLatency);
2237 /* Need to delay returning failure until replacement Send arrays have been
2238 * allocated with the appropriate size.
2240 update_failed = AL_FALSE;
2241 FPUCtl mixer_mode{};
2242 context = device->ContextList.load();
2243 while(context)
2245 struct ALvoiceProps *vprops;
2246 ALsizei pos;
2248 if(context->DefaultSlot)
2250 ALeffectslot *slot = context->DefaultSlot.get();
2251 EffectState *state = slot->Effect.State;
2253 state->mOutBuffer = device->Dry.Buffer;
2254 state->mOutChannels = device->Dry.NumChannels;
2255 if(state->deviceUpdate(device) == AL_FALSE)
2256 update_failed = AL_TRUE;
2257 else
2258 UpdateEffectSlotProps(slot, context);
2261 std::unique_lock<almtx_t> proplock{context->PropLock};
2262 std::unique_lock<almtx_t> slotlock{context->EffectSlotLock};
2263 for(auto &slot : context->EffectSlotList)
2265 EffectState *state = slot->Effect.State;
2267 state->mOutBuffer = device->Dry.Buffer;
2268 state->mOutChannels = device->Dry.NumChannels;
2269 if(state->deviceUpdate(device) == AL_FALSE)
2270 update_failed = AL_TRUE;
2271 else
2272 UpdateEffectSlotProps(slot.get(), context);
2274 slotlock.unlock();
2276 std::unique_lock<almtx_t> srclock{context->SourceLock};
2277 for(auto &sublist : context->SourceList)
2279 uint64_t usemask = ~sublist.FreeMask;
2280 while(usemask)
2282 ALsizei idx = CTZ64(usemask);
2283 ALsource *source = sublist.Sources + idx;
2285 usemask &= ~(U64(1) << idx);
2287 if(old_sends != device->NumAuxSends)
2289 ALsizei s;
2290 for(s = device->NumAuxSends;s < old_sends;s++)
2292 if(source->Send[s].Slot)
2293 DecrementRef(&source->Send[s].Slot->ref);
2294 source->Send[s].Slot = nullptr;
2296 source->Send.resize(device->NumAuxSends);
2297 source->Send.shrink_to_fit();
2298 for(s = old_sends;s < device->NumAuxSends;s++)
2300 source->Send[s].Slot = nullptr;
2301 source->Send[s].Gain = 1.0f;
2302 source->Send[s].GainHF = 1.0f;
2303 source->Send[s].HFReference = LOWPASSFREQREF;
2304 source->Send[s].GainLF = 1.0f;
2305 source->Send[s].LFReference = HIGHPASSFREQREF;
2309 source->PropsClean.clear(std::memory_order_release);
2313 /* Clear any pre-existing voice property structs, in case the number of
2314 * auxiliary sends is changing. Active sources will have updates
2315 * respecified in UpdateAllSourceProps.
2317 vprops = context->FreeVoiceProps.exchange(nullptr, std::memory_order_acq_rel);
2318 while(vprops)
2320 struct ALvoiceProps *next = vprops->next.load(std::memory_order_relaxed);
2321 al_free(vprops);
2322 vprops = next;
2325 AllocateVoices(context, context->MaxVoices, old_sends);
2326 for(pos = 0;pos < context->VoiceCount;pos++)
2328 ALvoice *voice = context->Voices[pos];
2330 al_free(voice->Update.exchange(nullptr, std::memory_order_acq_rel));
2332 if(voice->Source.load(std::memory_order_acquire) == nullptr)
2333 continue;
2335 if(device->AvgSpeakerDist > 0.0f)
2337 /* Reinitialize the NFC filters for new parameters. */
2338 ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
2339 (device->AvgSpeakerDist * device->Frequency);
2340 for(i = 0;i < voice->NumChannels;i++)
2341 NfcFilterCreate(&voice->Direct.Params[i].NFCtrlFilter, 0.0f, w1);
2344 srclock.unlock();
2346 context->PropsClean.test_and_set(std::memory_order_release);
2347 UpdateContextProps(context);
2348 context->Listener.PropsClean.test_and_set(std::memory_order_release);
2349 UpdateListenerProps(context);
2350 UpdateAllSourceProps(context);
2352 context = context->next.load(std::memory_order_relaxed);
2354 mixer_mode.leave();
2355 if(update_failed)
2356 return ALC_INVALID_DEVICE;
2358 if(!(device->Flags&DEVICE_PAUSED))
2360 if(V0(device->Backend,start)() == ALC_FALSE)
2361 return ALC_INVALID_DEVICE;
2362 device->Flags |= DEVICE_RUNNING;
2365 return ALC_NO_ERROR;
2369 ALCdevice_struct::ALCdevice_struct(DeviceType type)
2370 : Type{type}
2372 almtx_init(&BufferLock, almtx_plain);
2373 almtx_init(&EffectLock, almtx_plain);
2374 almtx_init(&FilterLock, almtx_plain);
2376 almtx_init(&BackendLock, almtx_plain);
2379 /* ALCdevice_struct::~ALCdevice_struct
2381 * Frees the device structure, and destroys any objects the app failed to
2382 * delete. Called once there's no more references on the device.
2384 ALCdevice_struct::~ALCdevice_struct()
2386 TRACE("%p\n", this);
2388 if(Backend)
2389 DELETE_OBJ(Backend);
2390 Backend = nullptr;
2392 almtx_destroy(&BackendLock);
2394 ReleaseALBuffers(this);
2395 std::for_each(BufferList.begin(), BufferList.end(),
2396 [](BufferSubList &entry) noexcept -> void
2397 { al_free(entry.Buffers); }
2399 BufferList.clear();
2400 almtx_destroy(&BufferLock);
2402 ReleaseALEffects(this);
2403 std::for_each(EffectList.begin(), EffectList.end(),
2404 [](EffectSubList &entry) noexcept -> void
2405 { al_free(entry.Effects); }
2407 EffectList.clear();
2408 almtx_destroy(&EffectLock);
2410 ReleaseALFilters(this);
2411 std::for_each(FilterList.begin(), FilterList.end(),
2412 [](FilterSubList &entry) noexcept -> void
2413 { al_free(entry.Filters); }
2415 FilterList.clear();
2416 almtx_destroy(&FilterLock);
2418 HrtfList.clear();
2419 if(HrtfHandle)
2420 Hrtf_DecRef(HrtfHandle);
2421 HrtfHandle = nullptr;
2422 al_free(Hrtf);
2423 Hrtf = nullptr;
2425 al_free(Bs2b);
2426 Bs2b = nullptr;
2430 void ALCdevice_IncRef(ALCdevice *device)
2432 auto ref = IncrementRef(&device->ref);
2433 TRACEREF("%p increasing refcount to %u\n", device, ref);
2436 void ALCdevice_DecRef(ALCdevice *device)
2438 auto ref = DecrementRef(&device->ref);
2439 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2440 if(ref == 0) delete device;
2443 /* VerifyDevice
2445 * Checks if the device handle is valid, and increments its ref count if so.
2447 static ALCboolean VerifyDevice(ALCdevice **device)
2449 std::lock_guard<std::recursive_mutex> _{ListLock};
2450 ALCdevice *tmpDevice{DeviceList.load()};
2451 while(tmpDevice)
2453 if(tmpDevice == *device)
2455 ALCdevice_IncRef(tmpDevice);
2456 return ALC_TRUE;
2458 tmpDevice = tmpDevice->next.load(std::memory_order_relaxed);
2461 *device = nullptr;
2462 return ALC_FALSE;
2466 ALCcontext_struct::ALCcontext_struct(ALCdevice *device)
2467 : Device{device}
2471 /* InitContext
2473 * Initializes context fields
2475 static ALvoid InitContext(ALCcontext *Context)
2477 ALlistener &listener = Context->Listener;
2478 struct ALeffectslotArray *auxslots;
2480 //Validate Context
2481 almtx_init(&Context->PropLock, almtx_plain);
2482 almtx_init(&Context->SourceLock, almtx_plain);
2483 almtx_init(&Context->EffectSlotLock, almtx_plain);
2485 if(Context->DefaultSlot)
2487 auxslots = static_cast<ALeffectslotArray*>(al_calloc(DEF_ALIGN,
2488 FAM_SIZE(struct ALeffectslotArray, slot, 1)));
2489 auxslots->count = 1;
2490 auxslots->slot[0] = Context->DefaultSlot.get();
2492 else
2494 auxslots = static_cast<ALeffectslotArray*>(al_calloc(DEF_ALIGN,
2495 sizeof(struct ALeffectslotArray)));
2496 auxslots->count = 0;
2498 ATOMIC_INIT(&Context->ActiveAuxSlots, auxslots);
2500 //Set globals
2501 Context->mDistanceModel = DistanceModel::Default;
2502 Context->SourceDistanceModel = AL_FALSE;
2503 Context->DopplerFactor = 1.0f;
2504 Context->DopplerVelocity = 1.0f;
2505 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2506 Context->MetersPerUnit = AL_DEFAULT_METERS_PER_UNIT;
2507 alsem_init(&Context->EventSem, 0);
2509 Context->ExtensionList = alExtList;
2512 listener.Params.Matrix = aluMatrixf::Identity;
2513 aluVectorSet(&listener.Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2514 listener.Params.Gain = listener.Gain;
2515 listener.Params.MetersPerUnit = Context->MetersPerUnit;
2516 listener.Params.DopplerFactor = Context->DopplerFactor;
2517 listener.Params.SpeedOfSound = Context->SpeedOfSound * Context->DopplerVelocity;
2518 listener.Params.ReverbSpeedOfSound = listener.Params.SpeedOfSound *
2519 listener.Params.MetersPerUnit;
2520 listener.Params.SourceDistanceModel = Context->SourceDistanceModel;
2521 listener.Params.mDistanceModel = Context->mDistanceModel;
2524 Context->AsyncEvents = ll_ringbuffer_create(63, sizeof(AsyncEvent), false);
2525 StartEventThrd(Context);
2529 /* ALCcontext_struct::~ALCcontext_struct()
2531 * Cleans up the context, and destroys any remaining objects the app failed to
2532 * delete. Called once there's no more references on the context.
2534 ALCcontext_struct::~ALCcontext_struct()
2536 TRACE("%p\n", this);
2538 struct ALcontextProps *cprops{Update.load(std::memory_order_relaxed)};
2539 if(cprops)
2541 TRACE("Freed unapplied context update %p\n", cprops);
2542 al_free(cprops);
2544 size_t count{0};
2545 cprops = FreeContextProps.load(std::memory_order_acquire);
2546 while(cprops)
2548 struct ALcontextProps *next{cprops->next.load(std::memory_order_relaxed)};
2549 al_free(cprops);
2550 cprops = next;
2551 ++count;
2553 TRACE("Freed " SZFMT " context property object%s\n", count, (count==1)?"":"s");
2555 al_free(ActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed));
2556 DefaultSlot = nullptr;
2558 ReleaseALSources(this);
2559 std::for_each(SourceList.begin(), SourceList.end(),
2560 [](const SourceSubList &entry) noexcept -> void
2561 { al_free(entry.Sources); }
2563 SourceList.clear();
2564 NumSources = 0;
2565 almtx_destroy(&SourceLock);
2567 count = 0;
2568 struct ALeffectslotProps *eprops{FreeEffectslotProps.load(std::memory_order_acquire)};
2569 while(eprops)
2571 struct ALeffectslotProps *next{eprops->next.load(std::memory_order_relaxed)};
2572 if(eprops->State) eprops->State->DecRef();
2573 al_free(eprops);
2574 eprops = next;
2575 ++count;
2577 TRACE("Freed " SZFMT " AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2579 ReleaseALAuxiliaryEffectSlots(this);
2580 EffectSlotList.clear();
2581 almtx_destroy(&EffectSlotLock);
2583 count = 0;
2584 struct ALvoiceProps *vprops{FreeVoiceProps.load(std::memory_order_acquire)};
2585 while(vprops)
2587 struct ALvoiceProps *next{vprops->next.load(std::memory_order_relaxed)};
2588 al_free(vprops);
2589 vprops = next;
2590 ++count;
2592 TRACE("Freed " SZFMT " voice property object%s\n", count, (count==1)?"":"s");
2594 for(ALsizei i{0};i < VoiceCount;i++)
2595 DeinitVoice(Voices[i]);
2596 al_free(Voices);
2597 Voices = nullptr;
2598 VoiceCount = 0;
2599 MaxVoices = 0;
2601 struct ALlistenerProps *lprops{Listener.Update.load(std::memory_order_relaxed)};
2602 if(lprops)
2604 TRACE("Freed unapplied listener update %p\n", lprops);
2605 al_free(lprops);
2607 count = 0;
2608 lprops = FreeListenerProps.load(std::memory_order_acquire);
2609 while(lprops)
2611 struct ALlistenerProps *next{lprops->next.load(std::memory_order_relaxed)};
2612 al_free(lprops);
2613 lprops = next;
2614 ++count;
2616 TRACE("Freed " SZFMT " listener property object%s\n", count, (count==1)?"":"s");
2618 alsem_destroy(&EventSem);
2620 ll_ringbuffer_free(AsyncEvents);
2621 AsyncEvents = nullptr;
2623 almtx_destroy(&PropLock);
2625 ALCdevice_DecRef(Device);
2628 /* ReleaseContext
2630 * Removes the context reference from the given device and removes it from
2631 * being current on the running thread or globally. Returns true if other
2632 * contexts still exist on the device.
2634 static bool ReleaseContext(ALCcontext *context, ALCdevice *device)
2636 ALCcontext *origctx, *newhead;
2637 bool ret = true;
2639 if(LocalContext.get() == context)
2641 WARN("%p released while current on thread\n", context);
2642 LocalContext.set(nullptr);
2643 ALCcontext_DecRef(context);
2646 origctx = context;
2647 if(GlobalContext.compare_exchange_strong(origctx, nullptr))
2648 ALCcontext_DecRef(context);
2650 V0(device->Backend,lock)();
2651 origctx = context;
2652 newhead = context->next.load(std::memory_order_relaxed);
2653 if(!device->ContextList.compare_exchange_strong(origctx, newhead))
2655 ALCcontext *list;
2656 do {
2657 /* origctx is what the desired context failed to match. Try
2658 * swapping out the next one in the list.
2660 list = origctx;
2661 origctx = context;
2662 } while(!list->next.compare_exchange_strong(origctx, newhead));
2664 else
2665 ret = !!newhead;
2666 V0(device->Backend,unlock)();
2668 /* Make sure the context is finished and no longer processing in the mixer
2669 * before sending the message queue kill event. The backend's lock does
2670 * this, although waiting for a non-odd mix count would work too.
2673 StopEventThrd(context);
2675 ALCcontext_DecRef(context);
2676 return ret;
2679 static void ALCcontext_IncRef(ALCcontext *context)
2681 auto ref = IncrementRef(&context->ref);
2682 TRACEREF("%p increasing refcount to %u\n", context, ref);
2685 void ALCcontext_DecRef(ALCcontext *context)
2687 auto ref = DecrementRef(&context->ref);
2688 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2689 if(ref == 0) delete context;
2692 static void ReleaseThreadCtx(ALCcontext *context)
2694 auto ref = DecrementRef(&context->ref);
2695 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2696 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2699 /* VerifyContext
2701 * Checks if the given context is valid, returning a new reference to it if so.
2703 static ContextRef VerifyContext(ALCcontext *context)
2705 std::lock_guard<std::recursive_mutex> _{ListLock};
2706 ALCdevice *dev{DeviceList.load()};
2707 while(dev)
2709 ALCcontext *ctx = dev->ContextList.load(std::memory_order_acquire);
2710 while(ctx)
2712 if(ctx == context)
2714 ALCcontext_IncRef(ctx);
2715 return ContextRef{ctx};
2717 ctx = ctx->next.load(std::memory_order_relaxed);
2719 dev = dev->next.load(std::memory_order_relaxed);
2722 return ContextRef{};
2726 /* GetContextRef
2728 * Returns the currently active context for this thread, and adds a reference
2729 * without locking it.
2731 ALCcontext *GetContextRef(void)
2733 ALCcontext *context{LocalContext.get()};
2734 if(context)
2735 ALCcontext_IncRef(context);
2736 else
2738 std::lock_guard<std::recursive_mutex> _{ListLock};
2739 context = GlobalContext.load(std::memory_order_acquire);
2740 if(context) ALCcontext_IncRef(context);
2743 return context;
2747 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
2749 ALCdevice *device = context->Device;
2750 ALsizei num_sends = device->NumAuxSends;
2751 struct ALvoiceProps *props;
2752 size_t sizeof_props;
2753 size_t sizeof_voice;
2754 ALvoice **voices;
2755 ALvoice *voice;
2756 ALsizei v = 0;
2757 size_t size;
2759 if(num_voices == context->MaxVoices && num_sends == old_sends)
2760 return;
2762 /* Allocate the voice pointers, voices, and the voices' stored source
2763 * property set (including the dynamically-sized Send[] array) in one
2764 * chunk.
2766 sizeof_voice = RoundUp(FAM_SIZE(ALvoice, Send, num_sends), 16);
2767 sizeof_props = RoundUp(FAM_SIZE(struct ALvoiceProps, Send, num_sends), 16);
2768 size = sizeof(ALvoice*) + sizeof_voice + sizeof_props;
2770 voices = static_cast<ALvoice**>(al_calloc(16, RoundUp(size*num_voices, 16)));
2771 /* The voice and property objects are stored interleaved since they're
2772 * paired together.
2774 voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
2775 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2777 if(context->Voices)
2779 const ALsizei v_count = mini(context->VoiceCount, num_voices);
2780 const ALsizei s_count = mini(old_sends, num_sends);
2782 for(;v < v_count;v++)
2784 ALvoice *old_voice = context->Voices[v];
2785 ALsizei i;
2787 /* Copy the old voice data and source property set to the new
2788 * storage.
2790 memcpy(voice, old_voice, sizeof(*voice));
2791 for(i = 0;i < s_count;i++)
2792 voice->Send[i] = old_voice->Send[i];
2794 memcpy(props, old_voice->Props, sizeof(*props));
2795 for(i = 0;i < s_count;i++)
2796 props->Send[i] = old_voice->Props->Send[i];
2798 /* Set this voice's property set pointer and voice reference. */
2799 voice->Props = props;
2800 voices[v] = voice;
2802 /* Increment pointers to the next storage space. */
2803 voice = (ALvoice*)((char*)props + sizeof_props);
2804 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2806 /* Deinit any left over voices that weren't copied over to the new
2807 * array. NOTE: If this does anything, v equals num_voices and
2808 * num_voices is less than VoiceCount, so the following loop won't do
2809 * anything.
2811 for(;v < context->VoiceCount;v++)
2812 DeinitVoice(context->Voices[v]);
2814 /* Finish setting the voices' property set pointers and references. */
2815 for(;v < num_voices;v++)
2817 ATOMIC_INIT(&voice->Update, static_cast<ALvoiceProps*>(nullptr));
2819 voice->Props = props;
2820 voices[v] = voice;
2822 voice = (ALvoice*)((char*)props + sizeof_props);
2823 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2826 al_free(context->Voices);
2827 context->Voices = voices;
2828 context->MaxVoices = num_voices;
2829 context->VoiceCount = mini(context->VoiceCount, num_voices);
2833 /************************************************
2834 * Standard ALC functions
2835 ************************************************/
2837 /* alcGetError
2839 * Return last ALC generated error code for the given device
2841 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2843 ALCenum errorCode;
2845 if(VerifyDevice(&device))
2847 errorCode = device->LastError.exchange(ALC_NO_ERROR);
2848 ALCdevice_DecRef(device);
2850 else
2851 errorCode = LastNullDeviceError.exchange(ALC_NO_ERROR);
2853 return errorCode;
2857 /* alcSuspendContext
2859 * Suspends updates for the given context
2861 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2863 if(!SuspendDefers)
2864 return;
2866 ContextRef ctx{VerifyContext(context)};
2867 if(!ctx)
2868 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2869 else
2870 ALCcontext_DeferUpdates(ctx.get());
2873 /* alcProcessContext
2875 * Resumes processing updates for the given context
2877 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2879 if(!SuspendDefers)
2880 return;
2882 ContextRef ctx{VerifyContext(context)};
2883 if(!ctx)
2884 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2885 else
2886 ALCcontext_ProcessUpdates(ctx.get());
2890 /* alcGetString
2892 * Returns information about the device, and error strings
2894 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2896 const ALCchar *value = nullptr;
2898 switch(param)
2900 case ALC_NO_ERROR:
2901 value = alcNoError;
2902 break;
2904 case ALC_INVALID_ENUM:
2905 value = alcErrInvalidEnum;
2906 break;
2908 case ALC_INVALID_VALUE:
2909 value = alcErrInvalidValue;
2910 break;
2912 case ALC_INVALID_DEVICE:
2913 value = alcErrInvalidDevice;
2914 break;
2916 case ALC_INVALID_CONTEXT:
2917 value = alcErrInvalidContext;
2918 break;
2920 case ALC_OUT_OF_MEMORY:
2921 value = alcErrOutOfMemory;
2922 break;
2924 case ALC_DEVICE_SPECIFIER:
2925 value = alcDefaultName;
2926 break;
2928 case ALC_ALL_DEVICES_SPECIFIER:
2929 if(VerifyDevice(&Device))
2931 value = Device->DeviceName.c_str();
2932 ALCdevice_DecRef(Device);
2934 else
2936 ProbeAllDevicesList();
2937 value = alcAllDevicesList.c_str();
2939 break;
2941 case ALC_CAPTURE_DEVICE_SPECIFIER:
2942 if(VerifyDevice(&Device))
2944 value = Device->DeviceName.c_str();
2945 ALCdevice_DecRef(Device);
2947 else
2949 ProbeCaptureDeviceList();
2950 value = alcCaptureDeviceList.c_str();
2952 break;
2954 /* Default devices are always first in the list */
2955 case ALC_DEFAULT_DEVICE_SPECIFIER:
2956 value = alcDefaultName;
2957 break;
2959 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2960 if(alcAllDevicesList.empty())
2961 ProbeAllDevicesList();
2963 /* Copy first entry as default. */
2964 alcDefaultAllDevicesSpecifier = alcAllDevicesList.c_str();
2965 value = alcDefaultAllDevicesSpecifier.c_str();
2966 break;
2968 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2969 if(alcCaptureDeviceList.empty())
2970 ProbeCaptureDeviceList();
2972 /* Copy first entry as default. */
2973 alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList.c_str();
2974 value = alcCaptureDefaultDeviceSpecifier.c_str();
2975 break;
2977 case ALC_EXTENSIONS:
2978 if(!VerifyDevice(&Device))
2979 value = alcNoDeviceExtList;
2980 else
2982 value = alcExtensionList;
2983 ALCdevice_DecRef(Device);
2985 break;
2987 case ALC_HRTF_SPECIFIER_SOFT:
2988 if(!VerifyDevice(&Device))
2989 alcSetError(nullptr, ALC_INVALID_DEVICE);
2990 else
2992 { std::lock_guard<almtx_t> _{Device->BackendLock};
2993 value = (Device->HrtfHandle ? Device->HrtfName.c_str() : "");
2995 ALCdevice_DecRef(Device);
2997 break;
2999 default:
3000 VerifyDevice(&Device);
3001 alcSetError(Device, ALC_INVALID_ENUM);
3002 if(Device) ALCdevice_DecRef(Device);
3003 break;
3006 return value;
3010 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
3012 if(device->Type == Capture) return 9;
3013 if(device->Type != Loopback) return 29;
3014 if(device->FmtChans == DevFmtAmbi3D)
3015 return 35;
3016 return 29;
3019 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3021 ALCsizei i;
3023 if(size <= 0 || values == nullptr)
3025 alcSetError(device, ALC_INVALID_VALUE);
3026 return 0;
3029 if(!device)
3031 switch(param)
3033 case ALC_MAJOR_VERSION:
3034 values[0] = alcMajorVersion;
3035 return 1;
3036 case ALC_MINOR_VERSION:
3037 values[0] = alcMinorVersion;
3038 return 1;
3040 case ALC_ATTRIBUTES_SIZE:
3041 case ALC_ALL_ATTRIBUTES:
3042 case ALC_FREQUENCY:
3043 case ALC_REFRESH:
3044 case ALC_SYNC:
3045 case ALC_MONO_SOURCES:
3046 case ALC_STEREO_SOURCES:
3047 case ALC_CAPTURE_SAMPLES:
3048 case ALC_FORMAT_CHANNELS_SOFT:
3049 case ALC_FORMAT_TYPE_SOFT:
3050 case ALC_AMBISONIC_LAYOUT_SOFT:
3051 case ALC_AMBISONIC_SCALING_SOFT:
3052 case ALC_AMBISONIC_ORDER_SOFT:
3053 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3054 alcSetError(nullptr, ALC_INVALID_DEVICE);
3055 return 0;
3057 default:
3058 alcSetError(nullptr, ALC_INVALID_ENUM);
3059 return 0;
3061 return 0;
3064 if(device->Type == Capture)
3066 switch(param)
3068 case ALC_ATTRIBUTES_SIZE:
3069 values[0] = NumAttrsForDevice(device);
3070 return 1;
3072 case ALC_ALL_ATTRIBUTES:
3073 i = 0;
3074 if(size < NumAttrsForDevice(device))
3075 alcSetError(device, ALC_INVALID_VALUE);
3076 else
3078 std::lock_guard<almtx_t> _{device->BackendLock};
3079 values[i++] = ALC_MAJOR_VERSION;
3080 values[i++] = alcMajorVersion;
3081 values[i++] = ALC_MINOR_VERSION;
3082 values[i++] = alcMinorVersion;
3083 values[i++] = ALC_CAPTURE_SAMPLES;
3084 values[i++] = V0(device->Backend,availableSamples)();
3085 values[i++] = ALC_CONNECTED;
3086 values[i++] = device->Connected.load(std::memory_order_relaxed);
3087 values[i++] = 0;
3089 return i;
3091 case ALC_MAJOR_VERSION:
3092 values[0] = alcMajorVersion;
3093 return 1;
3094 case ALC_MINOR_VERSION:
3095 values[0] = alcMinorVersion;
3096 return 1;
3098 case ALC_CAPTURE_SAMPLES:
3099 { std::lock_guard<almtx_t> _{device->BackendLock};
3100 values[0] = V0(device->Backend,availableSamples)();
3102 return 1;
3104 case ALC_CONNECTED:
3105 values[0] = device->Connected.load(std::memory_order_acquire);
3106 return 1;
3108 default:
3109 alcSetError(device, ALC_INVALID_ENUM);
3110 return 0;
3112 return 0;
3115 /* render device */
3116 switch(param)
3118 case ALC_ATTRIBUTES_SIZE:
3119 values[0] = NumAttrsForDevice(device);
3120 return 1;
3122 case ALC_ALL_ATTRIBUTES:
3123 i = 0;
3124 if(size < NumAttrsForDevice(device))
3125 alcSetError(device, ALC_INVALID_VALUE);
3126 else
3128 std::lock_guard<almtx_t> _{device->BackendLock};
3129 values[i++] = ALC_MAJOR_VERSION;
3130 values[i++] = alcMajorVersion;
3131 values[i++] = ALC_MINOR_VERSION;
3132 values[i++] = alcMinorVersion;
3133 values[i++] = ALC_EFX_MAJOR_VERSION;
3134 values[i++] = alcEFXMajorVersion;
3135 values[i++] = ALC_EFX_MINOR_VERSION;
3136 values[i++] = alcEFXMinorVersion;
3138 values[i++] = ALC_FREQUENCY;
3139 values[i++] = device->Frequency;
3140 if(device->Type != Loopback)
3142 values[i++] = ALC_REFRESH;
3143 values[i++] = device->Frequency / device->UpdateSize;
3145 values[i++] = ALC_SYNC;
3146 values[i++] = ALC_FALSE;
3148 else
3150 if(device->FmtChans == DevFmtAmbi3D)
3152 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3153 values[i++] = static_cast<ALCint>(device->mAmbiLayout);
3155 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3156 values[i++] = static_cast<ALCint>(device->mAmbiScale);
3158 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3159 values[i++] = device->mAmbiOrder;
3162 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3163 values[i++] = device->FmtChans;
3165 values[i++] = ALC_FORMAT_TYPE_SOFT;
3166 values[i++] = device->FmtType;
3169 values[i++] = ALC_MONO_SOURCES;
3170 values[i++] = device->NumMonoSources;
3172 values[i++] = ALC_STEREO_SOURCES;
3173 values[i++] = device->NumStereoSources;
3175 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3176 values[i++] = device->NumAuxSends;
3178 values[i++] = ALC_HRTF_SOFT;
3179 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3181 values[i++] = ALC_HRTF_STATUS_SOFT;
3182 values[i++] = device->HrtfStatus;
3184 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3185 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3187 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
3188 values[i++] = MAX_AMBI_ORDER;
3190 values[i++] = 0;
3192 return i;
3194 case ALC_MAJOR_VERSION:
3195 values[0] = alcMajorVersion;
3196 return 1;
3198 case ALC_MINOR_VERSION:
3199 values[0] = alcMinorVersion;
3200 return 1;
3202 case ALC_EFX_MAJOR_VERSION:
3203 values[0] = alcEFXMajorVersion;
3204 return 1;
3206 case ALC_EFX_MINOR_VERSION:
3207 values[0] = alcEFXMinorVersion;
3208 return 1;
3210 case ALC_FREQUENCY:
3211 values[0] = device->Frequency;
3212 return 1;
3214 case ALC_REFRESH:
3215 if(device->Type == Loopback)
3217 alcSetError(device, ALC_INVALID_DEVICE);
3218 return 0;
3220 { std::lock_guard<almtx_t> _{device->BackendLock};
3221 values[0] = device->Frequency / device->UpdateSize;
3223 return 1;
3225 case ALC_SYNC:
3226 if(device->Type == Loopback)
3228 alcSetError(device, ALC_INVALID_DEVICE);
3229 return 0;
3231 values[0] = ALC_FALSE;
3232 return 1;
3234 case ALC_FORMAT_CHANNELS_SOFT:
3235 if(device->Type != Loopback)
3237 alcSetError(device, ALC_INVALID_DEVICE);
3238 return 0;
3240 values[0] = device->FmtChans;
3241 return 1;
3243 case ALC_FORMAT_TYPE_SOFT:
3244 if(device->Type != Loopback)
3246 alcSetError(device, ALC_INVALID_DEVICE);
3247 return 0;
3249 values[0] = device->FmtType;
3250 return 1;
3252 case ALC_AMBISONIC_LAYOUT_SOFT:
3253 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3255 alcSetError(device, ALC_INVALID_DEVICE);
3256 return 0;
3258 values[0] = static_cast<ALCint>(device->mAmbiLayout);
3259 return 1;
3261 case ALC_AMBISONIC_SCALING_SOFT:
3262 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3264 alcSetError(device, ALC_INVALID_DEVICE);
3265 return 0;
3267 values[0] = static_cast<ALCint>(device->mAmbiScale);
3268 return 1;
3270 case ALC_AMBISONIC_ORDER_SOFT:
3271 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3273 alcSetError(device, ALC_INVALID_DEVICE);
3274 return 0;
3276 values[0] = device->mAmbiOrder;
3277 return 1;
3279 case ALC_MONO_SOURCES:
3280 values[0] = device->NumMonoSources;
3281 return 1;
3283 case ALC_STEREO_SOURCES:
3284 values[0] = device->NumStereoSources;
3285 return 1;
3287 case ALC_MAX_AUXILIARY_SENDS:
3288 values[0] = device->NumAuxSends;
3289 return 1;
3291 case ALC_CONNECTED:
3292 values[0] = device->Connected.load(std::memory_order_acquire);
3293 return 1;
3295 case ALC_HRTF_SOFT:
3296 values[0] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3297 return 1;
3299 case ALC_HRTF_STATUS_SOFT:
3300 values[0] = device->HrtfStatus;
3301 return 1;
3303 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3304 { std::lock_guard<almtx_t> _{device->BackendLock};
3305 device->HrtfList.clear();
3306 device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
3307 values[0] = (ALCint)device->HrtfList.size();
3309 return 1;
3311 case ALC_OUTPUT_LIMITER_SOFT:
3312 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3313 return 1;
3315 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3316 values[0] = MAX_AMBI_ORDER;
3317 return 1;
3319 default:
3320 alcSetError(device, ALC_INVALID_ENUM);
3321 return 0;
3323 return 0;
3326 /* alcGetIntegerv
3328 * Returns information about the device and the version of OpenAL
3330 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3332 VerifyDevice(&device);
3333 if(size <= 0 || values == nullptr)
3334 alcSetError(device, ALC_INVALID_VALUE);
3335 else
3336 GetIntegerv(device, param, size, values);
3337 if(device) ALCdevice_DecRef(device);
3340 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3342 VerifyDevice(&device);
3343 if(size <= 0 || values == nullptr)
3344 alcSetError(device, ALC_INVALID_VALUE);
3345 else if(!device || device->Type == Capture)
3347 std::vector<ALCint> ivals(size);
3348 size = GetIntegerv(device, pname, size, ivals.data());
3349 std::copy(ivals.begin(), ivals.begin()+size, values);
3351 else /* render device */
3353 switch(pname)
3355 case ALC_ATTRIBUTES_SIZE:
3356 *values = NumAttrsForDevice(device)+4;
3357 break;
3359 case ALC_ALL_ATTRIBUTES:
3360 if(size < NumAttrsForDevice(device)+4)
3361 alcSetError(device, ALC_INVALID_VALUE);
3362 else
3364 ALsizei i{0};
3365 std::lock_guard<almtx_t> _{device->BackendLock};
3366 values[i++] = ALC_FREQUENCY;
3367 values[i++] = device->Frequency;
3369 if(device->Type != Loopback)
3371 values[i++] = ALC_REFRESH;
3372 values[i++] = device->Frequency / device->UpdateSize;
3374 values[i++] = ALC_SYNC;
3375 values[i++] = ALC_FALSE;
3377 else
3379 if(device->FmtChans == DevFmtAmbi3D)
3381 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3382 values[i++] = static_cast<ALCint64SOFT>(device->mAmbiLayout);
3384 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3385 values[i++] = static_cast<ALCint64SOFT>(device->mAmbiScale);
3387 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3388 values[i++] = device->mAmbiOrder;
3391 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3392 values[i++] = device->FmtChans;
3394 values[i++] = ALC_FORMAT_TYPE_SOFT;
3395 values[i++] = device->FmtType;
3398 values[i++] = ALC_MONO_SOURCES;
3399 values[i++] = device->NumMonoSources;
3401 values[i++] = ALC_STEREO_SOURCES;
3402 values[i++] = device->NumStereoSources;
3404 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3405 values[i++] = device->NumAuxSends;
3407 values[i++] = ALC_HRTF_SOFT;
3408 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3410 values[i++] = ALC_HRTF_STATUS_SOFT;
3411 values[i++] = device->HrtfStatus;
3413 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3414 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3416 ClockLatency clock{GetClockLatency(device)};
3417 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3418 values[i++] = clock.ClockTime;
3420 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3421 values[i++] = clock.Latency;
3423 values[i++] = 0;
3425 break;
3427 case ALC_DEVICE_CLOCK_SOFT:
3428 { std::lock_guard<almtx_t> _{device->BackendLock};
3429 ALuint64 basecount;
3430 ALuint samplecount;
3431 ALuint refcount;
3432 do {
3433 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3434 althrd_yield();
3435 basecount = device->ClockBase;
3436 samplecount = device->SamplesDone;
3437 } while(refcount != ReadRef(&device->MixCount));
3438 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3440 break;
3442 case ALC_DEVICE_LATENCY_SOFT:
3443 { std::lock_guard<almtx_t> _{device->BackendLock};
3444 ClockLatency clock{GetClockLatency(device)};
3445 *values = clock.Latency;
3447 break;
3449 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3450 if(size < 2)
3451 alcSetError(device, ALC_INVALID_VALUE);
3452 else
3454 std::lock_guard<almtx_t> _{device->BackendLock};
3455 ClockLatency clock{GetClockLatency(device)};
3456 values[0] = clock.ClockTime;
3457 values[1] = clock.Latency;
3459 break;
3461 default:
3462 std::vector<ALCint> ivals(size);
3463 size = GetIntegerv(device, pname, size, ivals.data());
3464 std::copy(ivals.begin(), ivals.begin()+size, values);
3465 break;
3468 if(device)
3469 ALCdevice_DecRef(device);
3473 /* alcIsExtensionPresent
3475 * Determines if there is support for a particular extension
3477 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3479 ALCboolean bResult = ALC_FALSE;
3481 VerifyDevice(&device);
3483 if(!extName)
3484 alcSetError(device, ALC_INVALID_VALUE);
3485 else
3487 size_t len = strlen(extName);
3488 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3489 while(ptr && *ptr)
3491 if(strncasecmp(ptr, extName, len) == 0 &&
3492 (ptr[len] == '\0' || isspace(ptr[len])))
3494 bResult = ALC_TRUE;
3495 break;
3497 if((ptr=strchr(ptr, ' ')) != nullptr)
3499 do {
3500 ++ptr;
3501 } while(isspace(*ptr));
3505 if(device)
3506 ALCdevice_DecRef(device);
3507 return bResult;
3511 /* alcGetProcAddress
3513 * Retrieves the function address for a particular extension function
3515 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3517 ALCvoid *ptr = nullptr;
3519 if(!funcName)
3521 VerifyDevice(&device);
3522 alcSetError(device, ALC_INVALID_VALUE);
3523 if(device) ALCdevice_DecRef(device);
3525 else
3527 size_t i = 0;
3528 for(i = 0;i < COUNTOF(alcFunctions);i++)
3530 if(strcmp(alcFunctions[i].funcName, funcName) == 0)
3532 ptr = alcFunctions[i].address;
3533 break;
3538 return ptr;
3542 /* alcGetEnumValue
3544 * Get the value for a particular ALC enumeration name
3546 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3548 ALCenum val = 0;
3550 if(!enumName)
3552 VerifyDevice(&device);
3553 alcSetError(device, ALC_INVALID_VALUE);
3554 if(device) ALCdevice_DecRef(device);
3556 else
3558 size_t i = 0;
3559 for(i = 0;i < COUNTOF(alcEnumerations);i++)
3561 if(strcmp(alcEnumerations[i].enumName, enumName) == 0)
3563 val = alcEnumerations[i].value;
3564 break;
3569 return val;
3573 /* alcCreateContext
3575 * Create and attach a context to the given device.
3577 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3579 ALCcontext *ALContext;
3580 ALfloat valf;
3581 ALCenum err;
3583 /* Explicitly hold the list lock while taking the BackendLock in case the
3584 * device is asynchronously destropyed, to ensure this new context is
3585 * properly cleaned up after being made.
3587 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3588 if(!VerifyDevice(&device) || device->Type == Capture ||
3589 !device->Connected.load(std::memory_order_relaxed))
3591 listlock.unlock();
3592 alcSetError(device, ALC_INVALID_DEVICE);
3593 if(device) ALCdevice_DecRef(device);
3594 return nullptr;
3596 std::unique_lock<almtx_t> backlock{device->BackendLock};
3597 listlock.unlock();
3599 device->LastError.store(ALC_NO_ERROR);
3601 ALContext = new ALCcontext{device};
3602 ALCdevice_IncRef(ALContext->Device);
3604 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3606 backlock.unlock();
3608 delete ALContext;
3609 ALContext = nullptr;
3611 alcSetError(device, err);
3612 if(err == ALC_INVALID_DEVICE)
3614 V0(device->Backend,lock)();
3615 aluHandleDisconnect(device, "Device update failure");
3616 V0(device->Backend,unlock)();
3618 ALCdevice_DecRef(device);
3619 return nullptr;
3621 AllocateVoices(ALContext, 256, device->NumAuxSends);
3623 if(DefaultEffect.type != AL_EFFECT_NULL && device->Type == Playback)
3625 ALContext->DefaultSlot.reset(new ALeffectslot{});
3626 if(InitEffectSlot(ALContext->DefaultSlot.get()) == AL_NO_ERROR)
3627 aluInitEffectPanning(ALContext->DefaultSlot.get());
3628 else
3630 ALContext->DefaultSlot = nullptr;
3631 ERR("Failed to initialize the default effect slot\n");
3635 InitContext(ALContext);
3637 if(ConfigValueFloat(device->DeviceName.c_str(), nullptr, "volume-adjust", &valf))
3639 if(!std::isfinite(valf))
3640 ERR("volume-adjust must be finite: %f\n", valf);
3641 else
3643 ALfloat db = clampf(valf, -24.0f, 24.0f);
3644 if(db != valf)
3645 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3646 ALContext->GainBoost = std::pow(10.0f, db/20.0f);
3647 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3650 UpdateListenerProps(ALContext);
3653 ALCcontext *head = device->ContextList.load();
3654 do {
3655 ALContext->next.store(head, std::memory_order_relaxed);
3656 } while(!device->ContextList.compare_exchange_weak(head, ALContext));
3658 backlock.unlock();
3660 if(ALContext->DefaultSlot)
3662 if(InitializeEffect(ALContext, ALContext->DefaultSlot.get(), &DefaultEffect) == AL_NO_ERROR)
3663 UpdateEffectSlotProps(ALContext->DefaultSlot.get(), ALContext);
3664 else
3665 ERR("Failed to initialize the default effect\n");
3668 ALCdevice_DecRef(device);
3670 TRACE("Created context %p\n", ALContext);
3671 return ALContext;
3674 /* alcDestroyContext
3676 * Remove a context from its device
3678 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3680 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3681 ContextRef ctx{VerifyContext(context)};
3682 if(!ctx)
3684 listlock.unlock();
3685 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3686 return;
3689 ALCdevice* Device{ctx->Device};
3690 if(Device)
3692 std::lock_guard<almtx_t> _{Device->BackendLock};
3693 if(!ReleaseContext(ctx.get(), Device))
3695 V0(Device->Backend,stop)();
3696 Device->Flags &= ~DEVICE_RUNNING;
3699 listlock.unlock();
3703 /* alcGetCurrentContext
3705 * Returns the currently active context on the calling thread
3707 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3709 ALCcontext *Context{LocalContext.get()};
3710 if(!Context) Context = GlobalContext.load();
3711 return Context;
3714 /* alcGetThreadContext
3716 * Returns the currently active thread-local context
3718 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3720 return LocalContext.get();
3724 /* alcMakeContextCurrent
3726 * Makes the given context the active process-wide context, and removes the
3727 * thread-local context for the calling thread.
3729 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3731 /* context must be valid or nullptr */
3732 ContextRef ctx;
3733 if(context)
3735 ctx = VerifyContext(context);
3736 if(!ctx)
3738 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3739 return ALC_FALSE;
3742 /* Release this reference (if any) to store it in the GlobalContext
3743 * pointer. Take ownership of the reference (if any) that was previously
3744 * stored there.
3746 ctx = ContextRef{GlobalContext.exchange(ctx.release())};
3748 /* Reset (decrement) the previous global reference by replacing it with the
3749 * thread-local context. Take ownership of the thread-local context
3750 * reference (if any), clearing the storage to null.
3752 ctx = ContextRef{LocalContext.get()};
3753 if(ctx) LocalContext.set(nullptr);
3754 /* Reset (decrement) the previous thread-local reference. */
3756 return ALC_TRUE;
3759 /* alcSetThreadContext
3761 * Makes the given context the active context for the current thread
3763 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3765 /* context must be valid or nullptr */
3766 ContextRef ctx;
3767 if(context)
3769 ctx = VerifyContext(context);
3770 if(!ctx)
3772 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3773 return ALC_FALSE;
3776 /* context's reference count is already incremented */
3777 ContextRef old{LocalContext.get()};
3778 LocalContext.set(ctx.release());
3780 return ALC_TRUE;
3784 /* alcGetContextsDevice
3786 * Returns the device that a particular context is attached to
3788 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3790 ContextRef ctx{VerifyContext(Context)};
3791 if(!ctx)
3793 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3794 return nullptr;
3796 return ctx->Device;
3800 /* alcOpenDevice
3802 * Opens the named device.
3804 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3806 DO_INITCONFIG();
3808 if(!PlaybackBackend.name)
3810 alcSetError(nullptr, ALC_INVALID_VALUE);
3811 return nullptr;
3814 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
3815 #ifdef _WIN32
3816 /* Some old Windows apps hardcode these expecting OpenAL to use a
3817 * specific audio API, even when they're not enumerated. Creative's
3818 * router effectively ignores them too.
3820 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
3821 || strcasecmp(deviceName, "MMSYSTEM") == 0
3822 #endif
3824 deviceName = nullptr;
3826 auto device = new ALCdevice{Playback};
3828 //Set output format
3829 device->FmtChans = DevFmtChannelsDefault;
3830 device->FmtType = DevFmtTypeDefault;
3831 device->Frequency = DEFAULT_OUTPUT_RATE;
3832 device->LimiterState = ALC_TRUE;
3833 device->NumUpdates = 3;
3834 device->UpdateSize = 1024;
3836 device->SourcesMax = 256;
3837 device->AuxiliaryEffectSlotMax = 64;
3838 device->NumAuxSends = DEFAULT_SENDS;
3840 const ALCchar *fmt{};
3841 if(ConfigValueStr(deviceName, nullptr, "channels", &fmt))
3843 static constexpr struct ChannelMap {
3844 const char name[16];
3845 enum DevFmtChannels chans;
3846 ALsizei order;
3847 } chanlist[] = {
3848 { "mono", DevFmtMono, 0 },
3849 { "stereo", DevFmtStereo, 0 },
3850 { "quad", DevFmtQuad, 0 },
3851 { "surround51", DevFmtX51, 0 },
3852 { "surround61", DevFmtX61, 0 },
3853 { "surround71", DevFmtX71, 0 },
3854 { "surround51rear", DevFmtX51Rear, 0 },
3855 { "ambi1", DevFmtAmbi3D, 1 },
3856 { "ambi2", DevFmtAmbi3D, 2 },
3857 { "ambi3", DevFmtAmbi3D, 3 },
3860 auto iter = std::find_if(std::begin(chanlist), std::end(chanlist),
3861 [fmt](const ChannelMap &entry) -> bool
3862 { return strcasecmp(entry.name, fmt) == 0; }
3864 if(iter == std::end(chanlist))
3865 ERR("Unsupported channels: %s\n", fmt);
3866 else
3868 device->FmtChans = iter->chans;
3869 device->mAmbiOrder = iter->order;
3870 device->Flags |= DEVICE_CHANNELS_REQUEST;
3873 if(ConfigValueStr(deviceName, nullptr, "sample-type", &fmt))
3875 static constexpr struct TypeMap {
3876 const char name[16];
3877 enum DevFmtType type;
3878 } typelist[] = {
3879 { "int8", DevFmtByte },
3880 { "uint8", DevFmtUByte },
3881 { "int16", DevFmtShort },
3882 { "uint16", DevFmtUShort },
3883 { "int32", DevFmtInt },
3884 { "uint32", DevFmtUInt },
3885 { "float32", DevFmtFloat },
3888 auto iter = std::find_if(std::begin(typelist), std::end(typelist),
3889 [fmt](const TypeMap &entry) -> bool
3890 { return strcasecmp(entry.name, fmt) == 0; }
3892 if(iter == std::end(typelist))
3893 ERR("Unsupported sample-type: %s\n", fmt);
3894 else
3896 device->FmtType = iter->type;
3897 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3901 if(ConfigValueUInt(deviceName, nullptr, "frequency", &device->Frequency))
3903 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3904 if(device->Frequency < MIN_OUTPUT_RATE)
3905 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3906 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3909 ConfigValueUInt(deviceName, nullptr, "periods", &device->NumUpdates);
3910 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3912 ConfigValueUInt(deviceName, nullptr, "period_size", &device->UpdateSize);
3913 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3914 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
3915 device->UpdateSize = (device->UpdateSize+3)&~3;
3917 ConfigValueUInt(deviceName, nullptr, "sources", &device->SourcesMax);
3918 if(device->SourcesMax == 0) device->SourcesMax = 256;
3920 ConfigValueUInt(deviceName, nullptr, "slots", &device->AuxiliaryEffectSlotMax);
3921 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
3922 else device->AuxiliaryEffectSlotMax = minu(device->AuxiliaryEffectSlotMax, INT_MAX);
3924 if(ConfigValueInt(deviceName, nullptr, "sends", &device->NumAuxSends))
3925 device->NumAuxSends = clampi(
3926 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
3929 device->NumStereoSources = 1;
3930 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3932 device->Backend = PlaybackBackend.getFactory().createBackend(device, ALCbackend_Playback);
3933 if(!device->Backend)
3935 delete device;
3936 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
3937 return nullptr;
3940 // Find a playback device to open
3941 ALCenum err{V(device->Backend,open)(deviceName)};
3942 if(err != ALC_NO_ERROR)
3944 delete device;
3945 alcSetError(nullptr, err);
3946 return nullptr;
3949 if(ConfigValueStr(device->DeviceName.c_str(), nullptr, "ambi-format", &fmt))
3951 if(strcasecmp(fmt, "fuma") == 0)
3953 device->mAmbiLayout = AmbiLayout::FuMa;
3954 device->mAmbiScale = AmbiNorm::FuMa;
3956 else if(strcasecmp(fmt, "acn+sn3d") == 0)
3958 device->mAmbiLayout = AmbiLayout::ACN;
3959 device->mAmbiScale = AmbiNorm::SN3D;
3961 else if(strcasecmp(fmt, "acn+n3d") == 0)
3963 device->mAmbiLayout = AmbiLayout::ACN;
3964 device->mAmbiScale = AmbiNorm::N3D;
3966 else
3967 ERR("Unsupported ambi-format: %s\n", fmt);
3971 ALCdevice *head{DeviceList.load()};
3972 do {
3973 device->next.store(head, std::memory_order_relaxed);
3974 } while(!DeviceList.compare_exchange_weak(head, device));
3977 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName.c_str());
3978 return device;
3981 /* alcCloseDevice
3983 * Closes the given device.
3985 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3987 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3988 ALCdevice *iter{DeviceList.load()};
3989 do {
3990 if(iter == device)
3991 break;
3992 iter = iter->next.load(std::memory_order_relaxed);
3993 } while(iter != nullptr);
3994 if(!iter || iter->Type == Capture)
3996 alcSetError(iter, ALC_INVALID_DEVICE);
3997 return ALC_FALSE;
3999 std::unique_lock<almtx_t> backlock{device->BackendLock};
4001 ALCdevice *origdev{device};
4002 ALCdevice *nextdev{device->next.load(std::memory_order_relaxed)};
4003 if(!DeviceList.compare_exchange_strong(origdev, nextdev))
4005 ALCdevice *list;
4006 do {
4007 list = origdev;
4008 origdev = device;
4009 } while(!list->next.compare_exchange_strong(origdev, nextdev));
4011 listlock.unlock();
4013 ALCcontext *ctx{device->ContextList.load()};
4014 while(ctx != nullptr)
4016 ALCcontext *next = ctx->next.load(std::memory_order_relaxed);
4017 WARN("Releasing context %p\n", ctx);
4018 ReleaseContext(ctx, device);
4019 ctx = next;
4021 if((device->Flags&DEVICE_RUNNING))
4022 V0(device->Backend,stop)();
4023 device->Flags &= ~DEVICE_RUNNING;
4024 backlock.unlock();
4026 ALCdevice_DecRef(device);
4028 return ALC_TRUE;
4032 /************************************************
4033 * ALC capture functions
4034 ************************************************/
4035 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
4037 DO_INITCONFIG();
4039 if(!CaptureBackend.name)
4041 alcSetError(nullptr, ALC_INVALID_VALUE);
4042 return nullptr;
4045 if(samples <= 0)
4047 alcSetError(nullptr, ALC_INVALID_VALUE);
4048 return nullptr;
4051 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
4052 deviceName = nullptr;
4054 auto device = new ALCdevice{Capture};
4056 device->Frequency = frequency;
4057 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4059 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
4061 delete device;
4062 alcSetError(nullptr, ALC_INVALID_ENUM);
4063 return nullptr;
4065 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
4067 device->UpdateSize = samples;
4068 device->NumUpdates = 1;
4070 device->Backend = CaptureBackend.getFactory().createBackend(device, ALCbackend_Capture);
4071 if(!device->Backend)
4073 delete device;
4074 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
4075 return nullptr;
4078 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4079 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
4080 device->Frequency, device->UpdateSize, device->NumUpdates
4082 ALCenum err{V(device->Backend,open)(deviceName)};
4083 if(err != ALC_NO_ERROR)
4085 delete device;
4086 alcSetError(nullptr, err);
4087 return nullptr;
4091 ALCdevice *head{DeviceList.load()};
4092 do {
4093 device->next.store(head, std::memory_order_relaxed);
4094 } while(!DeviceList.compare_exchange_weak(head, device));
4097 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName.c_str());
4098 return device;
4101 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
4103 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4105 ALCdevice *iter{DeviceList.load()};
4106 do {
4107 if(iter == device)
4108 break;
4109 iter = iter->next.load(std::memory_order_relaxed);
4110 } while(iter != nullptr);
4111 if(!iter || iter->Type != Capture)
4113 alcSetError(iter, ALC_INVALID_DEVICE);
4114 return ALC_FALSE;
4117 ALCdevice *origdev{device};
4118 ALCdevice *nextdev{device->next.load(std::memory_order_relaxed)};
4119 if(!DeviceList.compare_exchange_strong(origdev, nextdev))
4121 ALCdevice *list;
4122 do {
4123 list = origdev;
4124 origdev = device;
4125 } while(!list->next.compare_exchange_strong(origdev, nextdev));
4127 listlock.unlock();
4129 { std::lock_guard<almtx_t> _{device->BackendLock};
4130 if((device->Flags&DEVICE_RUNNING))
4131 V0(device->Backend,stop)();
4132 device->Flags &= ~DEVICE_RUNNING;
4135 ALCdevice_DecRef(device);
4137 return ALC_TRUE;
4140 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
4142 if(!VerifyDevice(&device) || device->Type != Capture)
4143 alcSetError(device, ALC_INVALID_DEVICE);
4144 else
4146 std::lock_guard<almtx_t> _{device->BackendLock};
4147 if(!device->Connected.load(std::memory_order_acquire))
4148 alcSetError(device, ALC_INVALID_DEVICE);
4149 else if(!(device->Flags&DEVICE_RUNNING))
4151 if(V0(device->Backend,start)())
4152 device->Flags |= DEVICE_RUNNING;
4153 else
4155 aluHandleDisconnect(device, "Device start failure");
4156 alcSetError(device, ALC_INVALID_DEVICE);
4161 if(device) ALCdevice_DecRef(device);
4164 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
4166 if(!VerifyDevice(&device) || device->Type != Capture)
4167 alcSetError(device, ALC_INVALID_DEVICE);
4168 else
4170 std::lock_guard<almtx_t> _{device->BackendLock};
4171 if((device->Flags&DEVICE_RUNNING))
4172 V0(device->Backend,stop)();
4173 device->Flags &= ~DEVICE_RUNNING;
4176 if(device) ALCdevice_DecRef(device);
4179 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4181 if(!VerifyDevice(&device) || device->Type != Capture)
4182 alcSetError(device, ALC_INVALID_DEVICE);
4183 else
4185 ALCenum err = ALC_INVALID_VALUE;
4186 { std::lock_guard<almtx_t> _{device->BackendLock};
4187 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
4188 err = V(device->Backend,captureSamples)(buffer, samples);
4190 if(err != ALC_NO_ERROR)
4191 alcSetError(device, err);
4193 if(device) ALCdevice_DecRef(device);
4197 /************************************************
4198 * ALC loopback functions
4199 ************************************************/
4201 /* alcLoopbackOpenDeviceSOFT
4203 * Open a loopback device, for manual rendering.
4205 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
4207 DO_INITCONFIG();
4209 /* Make sure the device name, if specified, is us. */
4210 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
4212 alcSetError(nullptr, ALC_INVALID_VALUE);
4213 return nullptr;
4216 auto device = new ALCdevice{Loopback};
4218 device->SourcesMax = 256;
4219 device->AuxiliaryEffectSlotMax = 64;
4220 device->NumAuxSends = DEFAULT_SENDS;
4222 //Set output format
4223 device->NumUpdates = 0;
4224 device->UpdateSize = 0;
4226 device->Frequency = DEFAULT_OUTPUT_RATE;
4227 device->FmtChans = DevFmtChannelsDefault;
4228 device->FmtType = DevFmtTypeDefault;
4230 ConfigValueUInt(nullptr, nullptr, "sources", &device->SourcesMax);
4231 if(device->SourcesMax == 0) device->SourcesMax = 256;
4233 ConfigValueUInt(nullptr, nullptr, "slots", &device->AuxiliaryEffectSlotMax);
4234 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4235 else device->AuxiliaryEffectSlotMax = minu(device->AuxiliaryEffectSlotMax, INT_MAX);
4237 if(ConfigValueInt(nullptr, nullptr, "sends", &device->NumAuxSends))
4238 device->NumAuxSends = clampi(
4239 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4242 device->NumStereoSources = 1;
4243 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4245 device->Backend = LoopbackBackendFactory::getFactory().createBackend(
4246 device, ALCbackend_Loopback);
4247 if(!device->Backend)
4249 al_free(device);
4250 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
4251 return nullptr;
4254 // Open the "backend"
4255 V(device->Backend,open)("Loopback");
4258 ALCdevice *head{DeviceList.load()};
4259 do {
4260 device->next.store(head, std::memory_order_relaxed);
4261 } while(!DeviceList.compare_exchange_weak(head, device));
4264 TRACE("Created device %p\n", device);
4265 return device;
4268 /* alcIsRenderFormatSupportedSOFT
4270 * Determines if the loopback device supports the given format for rendering.
4272 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4274 ALCboolean ret{ALC_FALSE};
4276 if(!VerifyDevice(&device) || device->Type != Loopback)
4277 alcSetError(device, ALC_INVALID_DEVICE);
4278 else if(freq <= 0)
4279 alcSetError(device, ALC_INVALID_VALUE);
4280 else
4282 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4283 ret = ALC_TRUE;
4285 if(device) ALCdevice_DecRef(device);
4287 return ret;
4290 /* alcRenderSamplesSOFT
4292 * Renders some samples into a buffer, using the format last set by the
4293 * attributes given to alcCreateContext.
4295 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4297 if(!VerifyDevice(&device) || device->Type != Loopback)
4298 alcSetError(device, ALC_INVALID_DEVICE);
4299 else if(samples < 0 || (samples > 0 && buffer == nullptr))
4300 alcSetError(device, ALC_INVALID_VALUE);
4301 else
4303 V0(device->Backend,lock)();
4304 aluMixData(device, buffer, samples);
4305 V0(device->Backend,unlock)();
4307 if(device) ALCdevice_DecRef(device);
4311 /************************************************
4312 * ALC DSP pause/resume functions
4313 ************************************************/
4315 /* alcDevicePauseSOFT
4317 * Pause the DSP to stop audio processing.
4319 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4321 if(!VerifyDevice(&device) || device->Type != Playback)
4322 alcSetError(device, ALC_INVALID_DEVICE);
4323 else
4325 std::lock_guard<almtx_t> _{device->BackendLock};
4326 if((device->Flags&DEVICE_RUNNING))
4327 V0(device->Backend,stop)();
4328 device->Flags &= ~DEVICE_RUNNING;
4329 device->Flags |= DEVICE_PAUSED;
4331 if(device) ALCdevice_DecRef(device);
4334 /* alcDeviceResumeSOFT
4336 * Resume the DSP to restart audio processing.
4338 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4340 if(!VerifyDevice(&device) || device->Type != Playback)
4341 alcSetError(device, ALC_INVALID_DEVICE);
4342 else
4344 std::lock_guard<almtx_t> _{device->BackendLock};
4345 if((device->Flags&DEVICE_PAUSED))
4347 device->Flags &= ~DEVICE_PAUSED;
4348 if(device->ContextList.load() != nullptr)
4350 if(V0(device->Backend,start)() != ALC_FALSE)
4351 device->Flags |= DEVICE_RUNNING;
4352 else
4354 V0(device->Backend,lock)();
4355 aluHandleDisconnect(device, "Device start failure");
4356 V0(device->Backend,unlock)();
4357 alcSetError(device, ALC_INVALID_DEVICE);
4362 if(device) ALCdevice_DecRef(device);
4366 /************************************************
4367 * ALC HRTF functions
4368 ************************************************/
4370 /* alcGetStringiSOFT
4372 * Gets a string parameter at the given index.
4374 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4376 const ALCchar *str{nullptr};
4378 if(!VerifyDevice(&device) || device->Type == Capture)
4379 alcSetError(device, ALC_INVALID_DEVICE);
4380 else switch(paramName)
4382 case ALC_HRTF_SPECIFIER_SOFT:
4383 if(index >= 0 && (size_t)index < device->HrtfList.size())
4384 str = device->HrtfList[index].name.c_str();
4385 else
4386 alcSetError(device, ALC_INVALID_VALUE);
4387 break;
4389 default:
4390 alcSetError(device, ALC_INVALID_ENUM);
4391 break;
4393 if(device) ALCdevice_DecRef(device);
4395 return str;
4398 /* alcResetDeviceSOFT
4400 * Resets the given device output, using the specified attribute list.
4402 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4404 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4405 if(!VerifyDevice(&device) || device->Type == Capture ||
4406 !device->Connected.load(std::memory_order_relaxed))
4408 listlock.unlock();
4409 alcSetError(device, ALC_INVALID_DEVICE);
4410 if(device) ALCdevice_DecRef(device);
4411 return ALC_FALSE;
4413 std::unique_lock<almtx_t> backlock{device->BackendLock};
4414 listlock.unlock();
4416 ALCenum err{UpdateDeviceParams(device, attribs)};
4417 backlock.unlock();
4419 if(err != ALC_NO_ERROR)
4421 alcSetError(device, err);
4422 if(err == ALC_INVALID_DEVICE)
4424 V0(device->Backend,lock)();
4425 aluHandleDisconnect(device, "Device start failure");
4426 V0(device->Backend,unlock)();
4428 ALCdevice_DecRef(device);
4429 return ALC_FALSE;
4431 ALCdevice_DecRef(device);
4433 return ALC_TRUE;