Avoid a separate function to clean up effect slots
[openal-soft.git] / Alc / alc.cpp
blob5fae13b37780623365873f0b4a3c1d31f8e9439e
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"
56 #include "bs2b.h"
58 #include "fpu_modes.h"
59 #include "cpu_caps.h"
60 #include "compat.h"
61 #include "threads.h"
62 #include "almalloc.h"
64 #include "backends/base.h"
65 #include "backends/null.h"
66 #include "backends/loopback.h"
67 #ifdef HAVE_JACK
68 #include "backends/jack.h"
69 #endif
70 #ifdef HAVE_PULSEAUDIO
71 #include "backends/pulseaudio.h"
72 #endif
73 #ifdef HAVE_ALSA
74 #include "backends/alsa.h"
75 #endif
76 #ifdef HAVE_WASAPI
77 #include "backends/wasapi.h"
78 #endif
79 #ifdef HAVE_COREAUDIO
80 #include "backends/coreaudio.h"
81 #endif
82 #ifdef HAVE_OPENSL
83 #include "backends/opensl.h"
84 #endif
85 #ifdef HAVE_SOLARIS
86 #include "backends/solaris.h"
87 #endif
88 #ifdef HAVE_SNDIO
89 #include "backends/sndio.h"
90 #endif
91 #ifdef HAVE_OSS
92 #include "backends/oss.h"
93 #endif
94 #ifdef HAVE_QSA
95 #include "backends/qsa.h"
96 #endif
97 #ifdef HAVE_DSOUND
98 #include "backends/dsound.h"
99 #endif
100 #ifdef HAVE_WINMM
101 #include "backends/winmm.h"
102 #endif
103 #ifdef HAVE_PORTAUDIO
104 #include "backends/portaudio.h"
105 #endif
106 #ifdef HAVE_SDL2
107 #include "backends/sdl2.h"
108 #endif
109 #ifdef HAVE_WAVE
110 #include "backends/wave.h"
111 #endif
114 namespace {
116 /************************************************
117 * Backends
118 ************************************************/
119 struct BackendInfo {
120 const char *name;
121 BackendFactory& (*getFactory)(void);
124 struct BackendInfo BackendList[] = {
125 #ifdef HAVE_JACK
126 { "jack", JackBackendFactory::getFactory },
127 #endif
128 #ifdef HAVE_PULSEAUDIO
129 { "pulse", PulseBackendFactory::getFactory },
130 #endif
131 #ifdef HAVE_ALSA
132 { "alsa", AlsaBackendFactory::getFactory },
133 #endif
134 #ifdef HAVE_WASAPI
135 { "wasapi", WasapiBackendFactory::getFactory },
136 #endif
137 #ifdef HAVE_COREAUDIO
138 { "core", CoreAudioBackendFactory::getFactory },
139 #endif
140 #ifdef HAVE_OPENSL
141 { "opensl", OSLBackendFactory::getFactory },
142 #endif
143 #ifdef HAVE_SOLARIS
144 { "solaris", SolarisBackendFactory::getFactory },
145 #endif
146 #ifdef HAVE_SNDIO
147 { "sndio", SndIOBackendFactory::getFactory },
148 #endif
149 #ifdef HAVE_OSS
150 { "oss", OSSBackendFactory::getFactory },
151 #endif
152 #ifdef HAVE_QSA
153 { "qsa", QSABackendFactory::getFactory },
154 #endif
155 #ifdef HAVE_DSOUND
156 { "dsound", DSoundBackendFactory::getFactory },
157 #endif
158 #ifdef HAVE_WINMM
159 { "winmm", WinMMBackendFactory::getFactory },
160 #endif
161 #ifdef HAVE_PORTAUDIO
162 { "port", PortBackendFactory::getFactory },
163 #endif
164 #ifdef HAVE_SDL2
165 { "sdl2", SDL2BackendFactory::getFactory },
166 #endif
168 { "null", NullBackendFactory::getFactory },
169 #ifdef HAVE_WAVE
170 { "wave", WaveBackendFactory::getFactory },
171 #endif
173 ALsizei BackendListSize = COUNTOF(BackendList);
175 struct BackendInfo PlaybackBackend;
176 struct BackendInfo CaptureBackend;
179 /************************************************
180 * Functions, enums, and errors
181 ************************************************/
182 #define DECL(x) { #x, (ALCvoid*)(x) }
183 constexpr struct {
184 const ALCchar *funcName;
185 ALCvoid *address;
186 } alcFunctions[] = {
187 DECL(alcCreateContext),
188 DECL(alcMakeContextCurrent),
189 DECL(alcProcessContext),
190 DECL(alcSuspendContext),
191 DECL(alcDestroyContext),
192 DECL(alcGetCurrentContext),
193 DECL(alcGetContextsDevice),
194 DECL(alcOpenDevice),
195 DECL(alcCloseDevice),
196 DECL(alcGetError),
197 DECL(alcIsExtensionPresent),
198 DECL(alcGetProcAddress),
199 DECL(alcGetEnumValue),
200 DECL(alcGetString),
201 DECL(alcGetIntegerv),
202 DECL(alcCaptureOpenDevice),
203 DECL(alcCaptureCloseDevice),
204 DECL(alcCaptureStart),
205 DECL(alcCaptureStop),
206 DECL(alcCaptureSamples),
208 DECL(alcSetThreadContext),
209 DECL(alcGetThreadContext),
211 DECL(alcLoopbackOpenDeviceSOFT),
212 DECL(alcIsRenderFormatSupportedSOFT),
213 DECL(alcRenderSamplesSOFT),
215 DECL(alcDevicePauseSOFT),
216 DECL(alcDeviceResumeSOFT),
218 DECL(alcGetStringiSOFT),
219 DECL(alcResetDeviceSOFT),
221 DECL(alcGetInteger64vSOFT),
223 DECL(alEnable),
224 DECL(alDisable),
225 DECL(alIsEnabled),
226 DECL(alGetString),
227 DECL(alGetBooleanv),
228 DECL(alGetIntegerv),
229 DECL(alGetFloatv),
230 DECL(alGetDoublev),
231 DECL(alGetBoolean),
232 DECL(alGetInteger),
233 DECL(alGetFloat),
234 DECL(alGetDouble),
235 DECL(alGetError),
236 DECL(alIsExtensionPresent),
237 DECL(alGetProcAddress),
238 DECL(alGetEnumValue),
239 DECL(alListenerf),
240 DECL(alListener3f),
241 DECL(alListenerfv),
242 DECL(alListeneri),
243 DECL(alListener3i),
244 DECL(alListeneriv),
245 DECL(alGetListenerf),
246 DECL(alGetListener3f),
247 DECL(alGetListenerfv),
248 DECL(alGetListeneri),
249 DECL(alGetListener3i),
250 DECL(alGetListeneriv),
251 DECL(alGenSources),
252 DECL(alDeleteSources),
253 DECL(alIsSource),
254 DECL(alSourcef),
255 DECL(alSource3f),
256 DECL(alSourcefv),
257 DECL(alSourcei),
258 DECL(alSource3i),
259 DECL(alSourceiv),
260 DECL(alGetSourcef),
261 DECL(alGetSource3f),
262 DECL(alGetSourcefv),
263 DECL(alGetSourcei),
264 DECL(alGetSource3i),
265 DECL(alGetSourceiv),
266 DECL(alSourcePlayv),
267 DECL(alSourceStopv),
268 DECL(alSourceRewindv),
269 DECL(alSourcePausev),
270 DECL(alSourcePlay),
271 DECL(alSourceStop),
272 DECL(alSourceRewind),
273 DECL(alSourcePause),
274 DECL(alSourceQueueBuffers),
275 DECL(alSourceUnqueueBuffers),
276 DECL(alGenBuffers),
277 DECL(alDeleteBuffers),
278 DECL(alIsBuffer),
279 DECL(alBufferData),
280 DECL(alBufferf),
281 DECL(alBuffer3f),
282 DECL(alBufferfv),
283 DECL(alBufferi),
284 DECL(alBuffer3i),
285 DECL(alBufferiv),
286 DECL(alGetBufferf),
287 DECL(alGetBuffer3f),
288 DECL(alGetBufferfv),
289 DECL(alGetBufferi),
290 DECL(alGetBuffer3i),
291 DECL(alGetBufferiv),
292 DECL(alDopplerFactor),
293 DECL(alDopplerVelocity),
294 DECL(alSpeedOfSound),
295 DECL(alDistanceModel),
297 DECL(alGenFilters),
298 DECL(alDeleteFilters),
299 DECL(alIsFilter),
300 DECL(alFilteri),
301 DECL(alFilteriv),
302 DECL(alFilterf),
303 DECL(alFilterfv),
304 DECL(alGetFilteri),
305 DECL(alGetFilteriv),
306 DECL(alGetFilterf),
307 DECL(alGetFilterfv),
308 DECL(alGenEffects),
309 DECL(alDeleteEffects),
310 DECL(alIsEffect),
311 DECL(alEffecti),
312 DECL(alEffectiv),
313 DECL(alEffectf),
314 DECL(alEffectfv),
315 DECL(alGetEffecti),
316 DECL(alGetEffectiv),
317 DECL(alGetEffectf),
318 DECL(alGetEffectfv),
319 DECL(alGenAuxiliaryEffectSlots),
320 DECL(alDeleteAuxiliaryEffectSlots),
321 DECL(alIsAuxiliaryEffectSlot),
322 DECL(alAuxiliaryEffectSloti),
323 DECL(alAuxiliaryEffectSlotiv),
324 DECL(alAuxiliaryEffectSlotf),
325 DECL(alAuxiliaryEffectSlotfv),
326 DECL(alGetAuxiliaryEffectSloti),
327 DECL(alGetAuxiliaryEffectSlotiv),
328 DECL(alGetAuxiliaryEffectSlotf),
329 DECL(alGetAuxiliaryEffectSlotfv),
331 DECL(alDeferUpdatesSOFT),
332 DECL(alProcessUpdatesSOFT),
334 DECL(alSourcedSOFT),
335 DECL(alSource3dSOFT),
336 DECL(alSourcedvSOFT),
337 DECL(alGetSourcedSOFT),
338 DECL(alGetSource3dSOFT),
339 DECL(alGetSourcedvSOFT),
340 DECL(alSourcei64SOFT),
341 DECL(alSource3i64SOFT),
342 DECL(alSourcei64vSOFT),
343 DECL(alGetSourcei64SOFT),
344 DECL(alGetSource3i64SOFT),
345 DECL(alGetSourcei64vSOFT),
347 DECL(alGetStringiSOFT),
349 DECL(alBufferStorageSOFT),
350 DECL(alMapBufferSOFT),
351 DECL(alUnmapBufferSOFT),
352 DECL(alFlushMappedBufferSOFT),
354 DECL(alEventControlSOFT),
355 DECL(alEventCallbackSOFT),
356 DECL(alGetPointerSOFT),
357 DECL(alGetPointervSOFT),
359 #undef DECL
361 #define DECL(x) { #x, (x) }
362 constexpr struct {
363 const ALCchar *enumName;
364 ALCenum value;
365 } alcEnumerations[] = {
366 DECL(ALC_INVALID),
367 DECL(ALC_FALSE),
368 DECL(ALC_TRUE),
370 DECL(ALC_MAJOR_VERSION),
371 DECL(ALC_MINOR_VERSION),
372 DECL(ALC_ATTRIBUTES_SIZE),
373 DECL(ALC_ALL_ATTRIBUTES),
374 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
375 DECL(ALC_DEVICE_SPECIFIER),
376 DECL(ALC_ALL_DEVICES_SPECIFIER),
377 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
378 DECL(ALC_EXTENSIONS),
379 DECL(ALC_FREQUENCY),
380 DECL(ALC_REFRESH),
381 DECL(ALC_SYNC),
382 DECL(ALC_MONO_SOURCES),
383 DECL(ALC_STEREO_SOURCES),
384 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
385 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
386 DECL(ALC_CAPTURE_SAMPLES),
387 DECL(ALC_CONNECTED),
389 DECL(ALC_EFX_MAJOR_VERSION),
390 DECL(ALC_EFX_MINOR_VERSION),
391 DECL(ALC_MAX_AUXILIARY_SENDS),
393 DECL(ALC_FORMAT_CHANNELS_SOFT),
394 DECL(ALC_FORMAT_TYPE_SOFT),
396 DECL(ALC_MONO_SOFT),
397 DECL(ALC_STEREO_SOFT),
398 DECL(ALC_QUAD_SOFT),
399 DECL(ALC_5POINT1_SOFT),
400 DECL(ALC_6POINT1_SOFT),
401 DECL(ALC_7POINT1_SOFT),
402 DECL(ALC_BFORMAT3D_SOFT),
404 DECL(ALC_BYTE_SOFT),
405 DECL(ALC_UNSIGNED_BYTE_SOFT),
406 DECL(ALC_SHORT_SOFT),
407 DECL(ALC_UNSIGNED_SHORT_SOFT),
408 DECL(ALC_INT_SOFT),
409 DECL(ALC_UNSIGNED_INT_SOFT),
410 DECL(ALC_FLOAT_SOFT),
412 DECL(ALC_HRTF_SOFT),
413 DECL(ALC_DONT_CARE_SOFT),
414 DECL(ALC_HRTF_STATUS_SOFT),
415 DECL(ALC_HRTF_DISABLED_SOFT),
416 DECL(ALC_HRTF_ENABLED_SOFT),
417 DECL(ALC_HRTF_DENIED_SOFT),
418 DECL(ALC_HRTF_REQUIRED_SOFT),
419 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
420 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
421 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
422 DECL(ALC_HRTF_SPECIFIER_SOFT),
423 DECL(ALC_HRTF_ID_SOFT),
425 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
426 DECL(ALC_AMBISONIC_SCALING_SOFT),
427 DECL(ALC_AMBISONIC_ORDER_SOFT),
428 DECL(ALC_ACN_SOFT),
429 DECL(ALC_FUMA_SOFT),
430 DECL(ALC_N3D_SOFT),
431 DECL(ALC_SN3D_SOFT),
433 DECL(ALC_OUTPUT_LIMITER_SOFT),
435 DECL(ALC_NO_ERROR),
436 DECL(ALC_INVALID_DEVICE),
437 DECL(ALC_INVALID_CONTEXT),
438 DECL(ALC_INVALID_ENUM),
439 DECL(ALC_INVALID_VALUE),
440 DECL(ALC_OUT_OF_MEMORY),
443 DECL(AL_INVALID),
444 DECL(AL_NONE),
445 DECL(AL_FALSE),
446 DECL(AL_TRUE),
448 DECL(AL_SOURCE_RELATIVE),
449 DECL(AL_CONE_INNER_ANGLE),
450 DECL(AL_CONE_OUTER_ANGLE),
451 DECL(AL_PITCH),
452 DECL(AL_POSITION),
453 DECL(AL_DIRECTION),
454 DECL(AL_VELOCITY),
455 DECL(AL_LOOPING),
456 DECL(AL_BUFFER),
457 DECL(AL_GAIN),
458 DECL(AL_MIN_GAIN),
459 DECL(AL_MAX_GAIN),
460 DECL(AL_ORIENTATION),
461 DECL(AL_REFERENCE_DISTANCE),
462 DECL(AL_ROLLOFF_FACTOR),
463 DECL(AL_CONE_OUTER_GAIN),
464 DECL(AL_MAX_DISTANCE),
465 DECL(AL_SEC_OFFSET),
466 DECL(AL_SAMPLE_OFFSET),
467 DECL(AL_BYTE_OFFSET),
468 DECL(AL_SOURCE_TYPE),
469 DECL(AL_STATIC),
470 DECL(AL_STREAMING),
471 DECL(AL_UNDETERMINED),
472 DECL(AL_METERS_PER_UNIT),
473 DECL(AL_LOOP_POINTS_SOFT),
474 DECL(AL_DIRECT_CHANNELS_SOFT),
476 DECL(AL_DIRECT_FILTER),
477 DECL(AL_AUXILIARY_SEND_FILTER),
478 DECL(AL_AIR_ABSORPTION_FACTOR),
479 DECL(AL_ROOM_ROLLOFF_FACTOR),
480 DECL(AL_CONE_OUTER_GAINHF),
481 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
482 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
483 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
485 DECL(AL_SOURCE_STATE),
486 DECL(AL_INITIAL),
487 DECL(AL_PLAYING),
488 DECL(AL_PAUSED),
489 DECL(AL_STOPPED),
491 DECL(AL_BUFFERS_QUEUED),
492 DECL(AL_BUFFERS_PROCESSED),
494 DECL(AL_FORMAT_MONO8),
495 DECL(AL_FORMAT_MONO16),
496 DECL(AL_FORMAT_MONO_FLOAT32),
497 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
498 DECL(AL_FORMAT_STEREO8),
499 DECL(AL_FORMAT_STEREO16),
500 DECL(AL_FORMAT_STEREO_FLOAT32),
501 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
502 DECL(AL_FORMAT_MONO_IMA4),
503 DECL(AL_FORMAT_STEREO_IMA4),
504 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
505 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
506 DECL(AL_FORMAT_QUAD8_LOKI),
507 DECL(AL_FORMAT_QUAD16_LOKI),
508 DECL(AL_FORMAT_QUAD8),
509 DECL(AL_FORMAT_QUAD16),
510 DECL(AL_FORMAT_QUAD32),
511 DECL(AL_FORMAT_51CHN8),
512 DECL(AL_FORMAT_51CHN16),
513 DECL(AL_FORMAT_51CHN32),
514 DECL(AL_FORMAT_61CHN8),
515 DECL(AL_FORMAT_61CHN16),
516 DECL(AL_FORMAT_61CHN32),
517 DECL(AL_FORMAT_71CHN8),
518 DECL(AL_FORMAT_71CHN16),
519 DECL(AL_FORMAT_71CHN32),
520 DECL(AL_FORMAT_REAR8),
521 DECL(AL_FORMAT_REAR16),
522 DECL(AL_FORMAT_REAR32),
523 DECL(AL_FORMAT_MONO_MULAW),
524 DECL(AL_FORMAT_MONO_MULAW_EXT),
525 DECL(AL_FORMAT_STEREO_MULAW),
526 DECL(AL_FORMAT_STEREO_MULAW_EXT),
527 DECL(AL_FORMAT_QUAD_MULAW),
528 DECL(AL_FORMAT_51CHN_MULAW),
529 DECL(AL_FORMAT_61CHN_MULAW),
530 DECL(AL_FORMAT_71CHN_MULAW),
531 DECL(AL_FORMAT_REAR_MULAW),
532 DECL(AL_FORMAT_MONO_ALAW_EXT),
533 DECL(AL_FORMAT_STEREO_ALAW_EXT),
535 DECL(AL_FORMAT_BFORMAT2D_8),
536 DECL(AL_FORMAT_BFORMAT2D_16),
537 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
538 DECL(AL_FORMAT_BFORMAT2D_MULAW),
539 DECL(AL_FORMAT_BFORMAT3D_8),
540 DECL(AL_FORMAT_BFORMAT3D_16),
541 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
542 DECL(AL_FORMAT_BFORMAT3D_MULAW),
544 DECL(AL_FREQUENCY),
545 DECL(AL_BITS),
546 DECL(AL_CHANNELS),
547 DECL(AL_SIZE),
548 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
549 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
551 DECL(AL_SOURCE_RADIUS),
553 DECL(AL_STEREO_ANGLES),
555 DECL(AL_UNUSED),
556 DECL(AL_PENDING),
557 DECL(AL_PROCESSED),
559 DECL(AL_NO_ERROR),
560 DECL(AL_INVALID_NAME),
561 DECL(AL_INVALID_ENUM),
562 DECL(AL_INVALID_VALUE),
563 DECL(AL_INVALID_OPERATION),
564 DECL(AL_OUT_OF_MEMORY),
566 DECL(AL_VENDOR),
567 DECL(AL_VERSION),
568 DECL(AL_RENDERER),
569 DECL(AL_EXTENSIONS),
571 DECL(AL_DOPPLER_FACTOR),
572 DECL(AL_DOPPLER_VELOCITY),
573 DECL(AL_DISTANCE_MODEL),
574 DECL(AL_SPEED_OF_SOUND),
575 DECL(AL_SOURCE_DISTANCE_MODEL),
576 DECL(AL_DEFERRED_UPDATES_SOFT),
577 DECL(AL_GAIN_LIMIT_SOFT),
579 DECL(AL_INVERSE_DISTANCE),
580 DECL(AL_INVERSE_DISTANCE_CLAMPED),
581 DECL(AL_LINEAR_DISTANCE),
582 DECL(AL_LINEAR_DISTANCE_CLAMPED),
583 DECL(AL_EXPONENT_DISTANCE),
584 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
586 DECL(AL_FILTER_TYPE),
587 DECL(AL_FILTER_NULL),
588 DECL(AL_FILTER_LOWPASS),
589 DECL(AL_FILTER_HIGHPASS),
590 DECL(AL_FILTER_BANDPASS),
592 DECL(AL_LOWPASS_GAIN),
593 DECL(AL_LOWPASS_GAINHF),
595 DECL(AL_HIGHPASS_GAIN),
596 DECL(AL_HIGHPASS_GAINLF),
598 DECL(AL_BANDPASS_GAIN),
599 DECL(AL_BANDPASS_GAINHF),
600 DECL(AL_BANDPASS_GAINLF),
602 DECL(AL_EFFECT_TYPE),
603 DECL(AL_EFFECT_NULL),
604 DECL(AL_EFFECT_REVERB),
605 DECL(AL_EFFECT_EAXREVERB),
606 DECL(AL_EFFECT_CHORUS),
607 DECL(AL_EFFECT_DISTORTION),
608 DECL(AL_EFFECT_ECHO),
609 DECL(AL_EFFECT_FLANGER),
610 DECL(AL_EFFECT_PITCH_SHIFTER),
611 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
612 #if 0
613 DECL(AL_EFFECT_VOCAL_MORPHER),
614 #endif
615 DECL(AL_EFFECT_RING_MODULATOR),
616 DECL(AL_EFFECT_AUTOWAH),
617 DECL(AL_EFFECT_COMPRESSOR),
618 DECL(AL_EFFECT_EQUALIZER),
619 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
620 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
622 DECL(AL_EFFECTSLOT_EFFECT),
623 DECL(AL_EFFECTSLOT_GAIN),
624 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
625 DECL(AL_EFFECTSLOT_NULL),
627 DECL(AL_EAXREVERB_DENSITY),
628 DECL(AL_EAXREVERB_DIFFUSION),
629 DECL(AL_EAXREVERB_GAIN),
630 DECL(AL_EAXREVERB_GAINHF),
631 DECL(AL_EAXREVERB_GAINLF),
632 DECL(AL_EAXREVERB_DECAY_TIME),
633 DECL(AL_EAXREVERB_DECAY_HFRATIO),
634 DECL(AL_EAXREVERB_DECAY_LFRATIO),
635 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
636 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
637 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
638 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
639 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
640 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
641 DECL(AL_EAXREVERB_ECHO_TIME),
642 DECL(AL_EAXREVERB_ECHO_DEPTH),
643 DECL(AL_EAXREVERB_MODULATION_TIME),
644 DECL(AL_EAXREVERB_MODULATION_DEPTH),
645 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
646 DECL(AL_EAXREVERB_HFREFERENCE),
647 DECL(AL_EAXREVERB_LFREFERENCE),
648 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
649 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
651 DECL(AL_REVERB_DENSITY),
652 DECL(AL_REVERB_DIFFUSION),
653 DECL(AL_REVERB_GAIN),
654 DECL(AL_REVERB_GAINHF),
655 DECL(AL_REVERB_DECAY_TIME),
656 DECL(AL_REVERB_DECAY_HFRATIO),
657 DECL(AL_REVERB_REFLECTIONS_GAIN),
658 DECL(AL_REVERB_REFLECTIONS_DELAY),
659 DECL(AL_REVERB_LATE_REVERB_GAIN),
660 DECL(AL_REVERB_LATE_REVERB_DELAY),
661 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
662 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
663 DECL(AL_REVERB_DECAY_HFLIMIT),
665 DECL(AL_CHORUS_WAVEFORM),
666 DECL(AL_CHORUS_PHASE),
667 DECL(AL_CHORUS_RATE),
668 DECL(AL_CHORUS_DEPTH),
669 DECL(AL_CHORUS_FEEDBACK),
670 DECL(AL_CHORUS_DELAY),
672 DECL(AL_DISTORTION_EDGE),
673 DECL(AL_DISTORTION_GAIN),
674 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
675 DECL(AL_DISTORTION_EQCENTER),
676 DECL(AL_DISTORTION_EQBANDWIDTH),
678 DECL(AL_ECHO_DELAY),
679 DECL(AL_ECHO_LRDELAY),
680 DECL(AL_ECHO_DAMPING),
681 DECL(AL_ECHO_FEEDBACK),
682 DECL(AL_ECHO_SPREAD),
684 DECL(AL_FLANGER_WAVEFORM),
685 DECL(AL_FLANGER_PHASE),
686 DECL(AL_FLANGER_RATE),
687 DECL(AL_FLANGER_DEPTH),
688 DECL(AL_FLANGER_FEEDBACK),
689 DECL(AL_FLANGER_DELAY),
691 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY),
692 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION),
693 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION),
695 DECL(AL_RING_MODULATOR_FREQUENCY),
696 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
697 DECL(AL_RING_MODULATOR_WAVEFORM),
699 DECL(AL_PITCH_SHIFTER_COARSE_TUNE),
700 DECL(AL_PITCH_SHIFTER_FINE_TUNE),
702 DECL(AL_COMPRESSOR_ONOFF),
704 DECL(AL_EQUALIZER_LOW_GAIN),
705 DECL(AL_EQUALIZER_LOW_CUTOFF),
706 DECL(AL_EQUALIZER_MID1_GAIN),
707 DECL(AL_EQUALIZER_MID1_CENTER),
708 DECL(AL_EQUALIZER_MID1_WIDTH),
709 DECL(AL_EQUALIZER_MID2_GAIN),
710 DECL(AL_EQUALIZER_MID2_CENTER),
711 DECL(AL_EQUALIZER_MID2_WIDTH),
712 DECL(AL_EQUALIZER_HIGH_GAIN),
713 DECL(AL_EQUALIZER_HIGH_CUTOFF),
715 DECL(AL_DEDICATED_GAIN),
717 DECL(AL_AUTOWAH_ATTACK_TIME),
718 DECL(AL_AUTOWAH_RELEASE_TIME),
719 DECL(AL_AUTOWAH_RESONANCE),
720 DECL(AL_AUTOWAH_PEAK_GAIN),
722 DECL(AL_NUM_RESAMPLERS_SOFT),
723 DECL(AL_DEFAULT_RESAMPLER_SOFT),
724 DECL(AL_SOURCE_RESAMPLER_SOFT),
725 DECL(AL_RESAMPLER_NAME_SOFT),
727 DECL(AL_SOURCE_SPATIALIZE_SOFT),
728 DECL(AL_AUTO_SOFT),
730 DECL(AL_MAP_READ_BIT_SOFT),
731 DECL(AL_MAP_WRITE_BIT_SOFT),
732 DECL(AL_MAP_PERSISTENT_BIT_SOFT),
733 DECL(AL_PRESERVE_DATA_BIT_SOFT),
735 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT),
736 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT),
737 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT),
738 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT),
739 DECL(AL_EVENT_TYPE_ERROR_SOFT),
740 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT),
741 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT),
743 #undef DECL
745 constexpr ALCchar alcNoError[] = "No Error";
746 constexpr ALCchar alcErrInvalidDevice[] = "Invalid Device";
747 constexpr ALCchar alcErrInvalidContext[] = "Invalid Context";
748 constexpr ALCchar alcErrInvalidEnum[] = "Invalid Enum";
749 constexpr ALCchar alcErrInvalidValue[] = "Invalid Value";
750 constexpr ALCchar alcErrOutOfMemory[] = "Out of Memory";
753 /************************************************
754 * Global variables
755 ************************************************/
757 /* Enumerated device names */
758 constexpr ALCchar alcDefaultName[] = "OpenAL Soft\0";
760 std::string alcAllDevicesList;
761 std::string alcCaptureDeviceList;
763 /* Default is always the first in the list */
764 std::string alcDefaultAllDevicesSpecifier;
765 std::string alcCaptureDefaultDeviceSpecifier;
767 /* Default context extensions */
768 constexpr ALchar alExtList[] =
769 "AL_EXT_ALAW "
770 "AL_EXT_BFORMAT "
771 "AL_EXT_DOUBLE "
772 "AL_EXT_EXPONENT_DISTANCE "
773 "AL_EXT_FLOAT32 "
774 "AL_EXT_IMA4 "
775 "AL_EXT_LINEAR_DISTANCE "
776 "AL_EXT_MCFORMATS "
777 "AL_EXT_MULAW "
778 "AL_EXT_MULAW_BFORMAT "
779 "AL_EXT_MULAW_MCFORMATS "
780 "AL_EXT_OFFSET "
781 "AL_EXT_source_distance_model "
782 "AL_EXT_SOURCE_RADIUS "
783 "AL_EXT_STEREO_ANGLES "
784 "AL_LOKI_quadriphonic "
785 "AL_SOFT_block_alignment "
786 "AL_SOFT_deferred_updates "
787 "AL_SOFT_direct_channels "
788 "AL_SOFTX_events "
789 "AL_SOFTX_filter_gain_ex "
790 "AL_SOFT_gain_clamp_ex "
791 "AL_SOFT_loop_points "
792 "AL_SOFTX_map_buffer "
793 "AL_SOFT_MSADPCM "
794 "AL_SOFT_source_latency "
795 "AL_SOFT_source_length "
796 "AL_SOFT_source_resampler "
797 "AL_SOFT_source_spatialize";
799 std::atomic<ALCenum> LastNullDeviceError{ALC_NO_ERROR};
801 /* Thread-local current context */
802 std::atomic<void(*)(ALCcontext*)> ThreadCtxProc{nullptr};
803 class ThreadCtx {
804 ALCcontext *ctx{nullptr};
806 public:
807 ~ThreadCtx()
809 auto destruct = ThreadCtxProc.load();
810 if(destruct && ctx)
811 destruct(ctx);
812 ctx = nullptr;
815 ALCcontext *get() const noexcept { return ctx; }
816 void set(ALCcontext *ctx_) noexcept { ctx = ctx_; }
818 thread_local ThreadCtx LocalContext;
819 /* Process-wide current context */
820 std::atomic<ALCcontext*> GlobalContext{nullptr};
822 /* Flag to trap ALC device errors */
823 bool TrapALCError{false};
825 /* One-time configuration init control */
826 std::once_flag alc_config_once{};
828 /* Default effect that applies to sources that don't have an effect on send 0 */
829 ALeffect DefaultEffect;
831 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
832 * updates.
834 bool SuspendDefers{true};
837 /************************************************
838 * ALC information
839 ************************************************/
840 constexpr ALCchar alcNoDeviceExtList[] =
841 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
842 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
843 constexpr ALCchar alcExtensionList[] =
844 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
845 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
846 "ALC_EXT_thread_local_context ALC_SOFT_device_clock ALC_SOFT_HRTF "
847 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
848 constexpr ALCint alcMajorVersion = 1;
849 constexpr ALCint alcMinorVersion = 1;
851 constexpr ALCint alcEFXMajorVersion = 1;
852 constexpr ALCint alcEFXMinorVersion = 0;
855 /************************************************
856 * Device lists
857 ************************************************/
858 std::atomic<ALCdevice*> DeviceList{nullptr};
860 std::recursive_mutex ListLock;
862 } // namespace
864 /* Mixing thread piority level */
865 ALint RTPrioLevel;
867 FILE *LogFile;
868 #ifdef _DEBUG
869 enum LogLevel LogLevel = LogWarning;
870 #else
871 enum LogLevel LogLevel = LogError;
872 #endif
874 /************************************************
875 * Library initialization
876 ************************************************/
877 #if defined(_WIN32)
878 static void alc_init(void);
879 static void alc_deinit(void);
880 static void alc_deinit_safe(void);
882 #ifndef AL_LIBTYPE_STATIC
883 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
885 switch(reason)
887 case DLL_PROCESS_ATTACH:
888 /* Pin the DLL so we won't get unloaded until the process terminates */
889 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
890 (WCHAR*)hModule, &hModule);
891 alc_init();
892 break;
894 case DLL_PROCESS_DETACH:
895 if(!lpReserved)
896 alc_deinit();
897 else
898 alc_deinit_safe();
899 break;
901 return TRUE;
903 #elif defined(_MSC_VER)
904 #pragma section(".CRT$XCU",read)
905 static void alc_constructor(void);
906 static void alc_destructor(void);
907 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
909 static void alc_constructor(void)
911 atexit(alc_destructor);
912 alc_init();
915 static void alc_destructor(void)
917 alc_deinit();
919 #elif defined(HAVE_GCC_DESTRUCTOR)
920 static void alc_init(void) __attribute__((constructor));
921 static void alc_deinit(void) __attribute__((destructor));
922 #else
923 #error "No static initialization available on this platform!"
924 #endif
926 #elif defined(HAVE_GCC_DESTRUCTOR)
928 static void alc_init(void) __attribute__((constructor));
929 static void alc_deinit(void) __attribute__((destructor));
931 #else
932 #error "No global initialization available on this platform!"
933 #endif
935 static void ReleaseThreadCtx(ALCcontext *ctx);
936 static void alc_init(void)
938 LogFile = stderr;
940 const char *str{getenv("__ALSOFT_HALF_ANGLE_CONES")};
941 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
942 ConeScale *= 0.5f;
944 str = getenv("__ALSOFT_REVERSE_Z");
945 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
946 ZScale *= -1.0f;
948 str = getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
949 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
950 OverrideReverbSpeedOfSound = AL_TRUE;
952 ThreadCtxProc = ReleaseThreadCtx;
955 static void alc_initconfig(void)
957 const char *devs, *str;
958 int capfilter;
959 float valf;
960 int i, n;
962 str = getenv("ALSOFT_LOGLEVEL");
963 if(str)
965 long lvl = strtol(str, nullptr, 0);
966 if(lvl >= NoLog && lvl <= LogRef)
967 LogLevel = static_cast<enum LogLevel>(lvl);
970 str = getenv("ALSOFT_LOGFILE");
971 if(str && str[0])
973 #ifdef _WIN32
974 std::wstring wname{utf8_to_wstr(str)};
975 FILE *logfile = _wfopen(wname.c_str(), L"wt");
976 #else
977 FILE *logfile = fopen(str, "wt");
978 #endif
979 if(logfile) LogFile = logfile;
980 else ERR("Failed to open log file '%s'\n", str);
983 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION,
984 ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH);
986 std::string names;
987 if(BackendListSize > 0)
988 names += BackendList[0].name;
989 for(i = 1;i < BackendListSize;i++)
991 names += ", ";
992 names += BackendList[i].name;
994 TRACE("Supported backends: %s\n", names.c_str());
996 ReadALConfig();
998 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
999 if(str && *str)
1001 if(strcasecmp(str, "ignore") == 0)
1003 SuspendDefers = false;
1004 TRACE("Selected context suspend behavior, \"ignore\"\n");
1006 else
1007 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
1010 capfilter = 0;
1011 #if defined(HAVE_SSE4_1)
1012 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
1013 #elif defined(HAVE_SSE3)
1014 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
1015 #elif defined(HAVE_SSE2)
1016 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
1017 #elif defined(HAVE_SSE)
1018 capfilter |= CPU_CAP_SSE;
1019 #endif
1020 #ifdef HAVE_NEON
1021 capfilter |= CPU_CAP_NEON;
1022 #endif
1023 if(ConfigValueStr(nullptr, nullptr, "disable-cpu-exts", &str))
1025 if(strcasecmp(str, "all") == 0)
1026 capfilter = 0;
1027 else
1029 size_t len;
1030 const char *next = str;
1032 do {
1033 str = next;
1034 while(isspace(str[0]))
1035 str++;
1036 next = strchr(str, ',');
1038 if(!str[0] || str[0] == ',')
1039 continue;
1041 len = (next ? ((size_t)(next-str)) : strlen(str));
1042 while(len > 0 && isspace(str[len-1]))
1043 len--;
1044 if(len == 3 && strncasecmp(str, "sse", len) == 0)
1045 capfilter &= ~CPU_CAP_SSE;
1046 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
1047 capfilter &= ~CPU_CAP_SSE2;
1048 else if(len == 4 && strncasecmp(str, "sse3", len) == 0)
1049 capfilter &= ~CPU_CAP_SSE3;
1050 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
1051 capfilter &= ~CPU_CAP_SSE4_1;
1052 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
1053 capfilter &= ~CPU_CAP_NEON;
1054 else
1055 WARN("Invalid CPU extension \"%s\"\n", str);
1056 } while(next++);
1059 FillCPUCaps(capfilter);
1061 #ifdef _WIN32
1062 RTPrioLevel = 1;
1063 #else
1064 RTPrioLevel = 0;
1065 #endif
1066 ConfigValueInt(nullptr, nullptr, "rt-prio", &RTPrioLevel);
1068 aluInit();
1069 aluInitMixer();
1071 str = getenv("ALSOFT_TRAP_ERROR");
1072 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
1074 TrapALError = AL_TRUE;
1075 TrapALCError = true;
1077 else
1079 str = getenv("ALSOFT_TRAP_AL_ERROR");
1080 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
1081 TrapALError = AL_TRUE;
1082 TrapALError = GetConfigValueBool(nullptr, nullptr, "trap-al-error", TrapALError);
1084 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1085 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
1086 TrapALCError = true;
1087 TrapALCError = !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", TrapALCError);
1090 if(ConfigValueFloat(nullptr, "reverb", "boost", &valf))
1091 ReverbBoost *= std::pow(10.0f, valf / 20.0f);
1093 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1094 ConfigValueStr(nullptr, nullptr, "drivers", &devs))
1096 int n;
1097 size_t len;
1098 const char *next = devs;
1099 int endlist, delitem;
1101 i = 0;
1102 do {
1103 devs = next;
1104 while(isspace(devs[0]))
1105 devs++;
1106 next = strchr(devs, ',');
1108 delitem = (devs[0] == '-');
1109 if(devs[0] == '-') devs++;
1111 if(!devs[0] || devs[0] == ',')
1113 endlist = 0;
1114 continue;
1116 endlist = 1;
1118 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1119 while(len > 0 && isspace(devs[len-1]))
1120 len--;
1121 #ifdef HAVE_WASAPI
1122 /* HACK: For backwards compatibility, convert backend references of
1123 * mmdevapi to wasapi. This should eventually be removed.
1125 if(len == 8 && strncmp(devs, "mmdevapi", len) == 0)
1127 devs = "wasapi";
1128 len = 6;
1130 #endif
1131 for(n = i;n < BackendListSize;n++)
1133 if(len == strlen(BackendList[n].name) &&
1134 strncmp(BackendList[n].name, devs, len) == 0)
1136 if(delitem)
1138 for(;n+1 < BackendListSize;n++)
1139 BackendList[n] = BackendList[n+1];
1140 BackendListSize--;
1142 else
1144 struct BackendInfo Bkp = BackendList[n];
1145 for(;n > i;n--)
1146 BackendList[n] = BackendList[n-1];
1147 BackendList[n] = Bkp;
1149 i++;
1151 break;
1154 } while(next++);
1156 if(endlist)
1157 BackendListSize = i;
1160 for(n = i = 0;i < BackendListSize && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1162 BackendList[n] = BackendList[i];
1164 BackendFactory &factory = BackendList[n].getFactory();
1165 if(!factory.init())
1167 WARN("Failed to initialize backend \"%s\"\n", BackendList[n].name);
1168 continue;
1171 TRACE("Initialized backend \"%s\"\n", BackendList[n].name);
1172 if(!PlaybackBackend.name && factory.querySupport(ALCbackend_Playback))
1174 PlaybackBackend = BackendList[n];
1175 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1177 if(!CaptureBackend.name && factory.querySupport(ALCbackend_Capture))
1179 CaptureBackend = BackendList[n];
1180 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1182 n++;
1184 BackendListSize = n;
1186 LoopbackBackendFactory::getFactory().init();
1188 if(!PlaybackBackend.name)
1189 WARN("No playback backend available!\n");
1190 if(!CaptureBackend.name)
1191 WARN("No capture backend available!\n");
1193 if(ConfigValueStr(nullptr, nullptr, "excludefx", &str))
1195 size_t len;
1196 const char *next = str;
1198 do {
1199 str = next;
1200 next = strchr(str, ',');
1202 if(!str[0] || next == str)
1203 continue;
1205 len = (next ? ((size_t)(next-str)) : strlen(str));
1206 for(n = 0;n < EFFECTLIST_SIZE;n++)
1208 if(len == strlen(EffectList[n].name) &&
1209 strncmp(EffectList[n].name, str, len) == 0)
1210 DisabledEffects[EffectList[n].type] = AL_TRUE;
1212 } while(next++);
1215 InitEffect(&DefaultEffect);
1216 str = getenv("ALSOFT_DEFAULT_REVERB");
1217 if((str && str[0]) || ConfigValueStr(nullptr, nullptr, "default-reverb", &str))
1218 LoadReverbPreset(str, &DefaultEffect);
1220 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1223 /************************************************
1224 * Library deinitialization
1225 ************************************************/
1226 static void alc_cleanup(void)
1228 alcAllDevicesList.clear();
1229 alcCaptureDeviceList.clear();
1231 alcDefaultAllDevicesSpecifier.clear();
1232 alcCaptureDefaultDeviceSpecifier.clear();
1234 if(ALCdevice *dev{DeviceList.exchange(nullptr)})
1236 ALCuint num = 0;
1237 do {
1238 num++;
1239 dev = dev->next.load(std::memory_order_relaxed);
1240 } while(dev != nullptr);
1241 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1245 static void alc_deinit_safe(void)
1247 alc_cleanup();
1249 FreeHrtfs();
1250 FreeALConfig();
1252 ThreadCtxProc = nullptr;
1254 if(LogFile != stderr)
1255 fclose(LogFile);
1256 LogFile = nullptr;
1259 static void alc_deinit(void)
1261 int i;
1263 alc_cleanup();
1265 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1266 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1268 for(i = 0;i < BackendListSize;i++)
1269 BackendList[i].getFactory().deinit();
1271 LoopbackBackendFactory::getFactory().deinit();
1273 alc_deinit_safe();
1277 /************************************************
1278 * Device enumeration
1279 ************************************************/
1280 static void ProbeDevices(std::string *list, struct BackendInfo *backendinfo, enum DevProbe type)
1282 DO_INITCONFIG();
1284 std::lock_guard<std::recursive_mutex> _{ListLock};
1285 list->clear();
1286 if(backendinfo->getFactory)
1287 backendinfo->getFactory().probe(type, list);
1289 static void ProbeAllDevicesList(void)
1290 { ProbeDevices(&alcAllDevicesList, &PlaybackBackend, ALL_DEVICE_PROBE); }
1291 static void ProbeCaptureDeviceList(void)
1292 { ProbeDevices(&alcCaptureDeviceList, &CaptureBackend, CAPTURE_DEVICE_PROBE); }
1295 /************************************************
1296 * Device format information
1297 ************************************************/
1298 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1300 switch(type)
1302 case DevFmtByte: return "Signed Byte";
1303 case DevFmtUByte: return "Unsigned Byte";
1304 case DevFmtShort: return "Signed Short";
1305 case DevFmtUShort: return "Unsigned Short";
1306 case DevFmtInt: return "Signed Int";
1307 case DevFmtUInt: return "Unsigned Int";
1308 case DevFmtFloat: return "Float";
1310 return "(unknown type)";
1312 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1314 switch(chans)
1316 case DevFmtMono: return "Mono";
1317 case DevFmtStereo: return "Stereo";
1318 case DevFmtQuad: return "Quadraphonic";
1319 case DevFmtX51: return "5.1 Surround";
1320 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1321 case DevFmtX61: return "6.1 Surround";
1322 case DevFmtX71: return "7.1 Surround";
1323 case DevFmtAmbi3D: return "Ambisonic 3D";
1325 return "(unknown channels)";
1328 ALsizei BytesFromDevFmt(enum DevFmtType type)
1330 switch(type)
1332 case DevFmtByte: return sizeof(ALbyte);
1333 case DevFmtUByte: return sizeof(ALubyte);
1334 case DevFmtShort: return sizeof(ALshort);
1335 case DevFmtUShort: return sizeof(ALushort);
1336 case DevFmtInt: return sizeof(ALint);
1337 case DevFmtUInt: return sizeof(ALuint);
1338 case DevFmtFloat: return sizeof(ALfloat);
1340 return 0;
1342 ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans, ALsizei ambiorder)
1344 switch(chans)
1346 case DevFmtMono: return 1;
1347 case DevFmtStereo: return 2;
1348 case DevFmtQuad: return 4;
1349 case DevFmtX51: return 6;
1350 case DevFmtX51Rear: return 6;
1351 case DevFmtX61: return 7;
1352 case DevFmtX71: return 8;
1353 case DevFmtAmbi3D: return (ambiorder >= 3) ? 16 :
1354 (ambiorder == 2) ? 9 :
1355 (ambiorder == 1) ? 4 : 1;
1357 return 0;
1360 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1361 enum DevFmtType *type)
1363 static const struct {
1364 ALenum format;
1365 enum DevFmtChannels channels;
1366 enum DevFmtType type;
1367 } list[] = {
1368 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1369 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1370 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1372 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1373 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1374 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1376 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1377 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1378 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1380 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1381 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1382 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1384 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1385 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1386 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1388 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1389 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1390 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1392 ALuint i;
1394 for(i = 0;i < COUNTOF(list);i++)
1396 if(list[i].format == format)
1398 *chans = list[i].channels;
1399 *type = list[i].type;
1400 return AL_TRUE;
1404 return AL_FALSE;
1407 static ALCboolean IsValidALCType(ALCenum type)
1409 switch(type)
1411 case ALC_BYTE_SOFT:
1412 case ALC_UNSIGNED_BYTE_SOFT:
1413 case ALC_SHORT_SOFT:
1414 case ALC_UNSIGNED_SHORT_SOFT:
1415 case ALC_INT_SOFT:
1416 case ALC_UNSIGNED_INT_SOFT:
1417 case ALC_FLOAT_SOFT:
1418 return ALC_TRUE;
1420 return ALC_FALSE;
1423 static ALCboolean IsValidALCChannels(ALCenum channels)
1425 switch(channels)
1427 case ALC_MONO_SOFT:
1428 case ALC_STEREO_SOFT:
1429 case ALC_QUAD_SOFT:
1430 case ALC_5POINT1_SOFT:
1431 case ALC_6POINT1_SOFT:
1432 case ALC_7POINT1_SOFT:
1433 case ALC_BFORMAT3D_SOFT:
1434 return ALC_TRUE;
1436 return ALC_FALSE;
1439 static ALCboolean IsValidAmbiLayout(ALCenum layout)
1441 switch(layout)
1443 case ALC_ACN_SOFT:
1444 case ALC_FUMA_SOFT:
1445 return ALC_TRUE;
1447 return ALC_FALSE;
1450 static ALCboolean IsValidAmbiScaling(ALCenum scaling)
1452 switch(scaling)
1454 case ALC_N3D_SOFT:
1455 case ALC_SN3D_SOFT:
1456 case ALC_FUMA_SOFT:
1457 return ALC_TRUE;
1459 return ALC_FALSE;
1462 /************************************************
1463 * Miscellaneous ALC helpers
1464 ************************************************/
1466 /* SetDefaultWFXChannelOrder
1468 * Sets the default channel order used by WaveFormatEx.
1470 void SetDefaultWFXChannelOrder(ALCdevice *device)
1472 ALsizei i;
1474 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1475 device->RealOut.ChannelName[i] = InvalidChannel;
1477 switch(device->FmtChans)
1479 case DevFmtMono:
1480 device->RealOut.ChannelName[0] = FrontCenter;
1481 break;
1482 case DevFmtStereo:
1483 device->RealOut.ChannelName[0] = FrontLeft;
1484 device->RealOut.ChannelName[1] = FrontRight;
1485 break;
1486 case DevFmtQuad:
1487 device->RealOut.ChannelName[0] = FrontLeft;
1488 device->RealOut.ChannelName[1] = FrontRight;
1489 device->RealOut.ChannelName[2] = BackLeft;
1490 device->RealOut.ChannelName[3] = BackRight;
1491 break;
1492 case DevFmtX51:
1493 device->RealOut.ChannelName[0] = FrontLeft;
1494 device->RealOut.ChannelName[1] = FrontRight;
1495 device->RealOut.ChannelName[2] = FrontCenter;
1496 device->RealOut.ChannelName[3] = LFE;
1497 device->RealOut.ChannelName[4] = SideLeft;
1498 device->RealOut.ChannelName[5] = SideRight;
1499 break;
1500 case DevFmtX51Rear:
1501 device->RealOut.ChannelName[0] = FrontLeft;
1502 device->RealOut.ChannelName[1] = FrontRight;
1503 device->RealOut.ChannelName[2] = FrontCenter;
1504 device->RealOut.ChannelName[3] = LFE;
1505 device->RealOut.ChannelName[4] = BackLeft;
1506 device->RealOut.ChannelName[5] = BackRight;
1507 break;
1508 case DevFmtX61:
1509 device->RealOut.ChannelName[0] = FrontLeft;
1510 device->RealOut.ChannelName[1] = FrontRight;
1511 device->RealOut.ChannelName[2] = FrontCenter;
1512 device->RealOut.ChannelName[3] = LFE;
1513 device->RealOut.ChannelName[4] = BackCenter;
1514 device->RealOut.ChannelName[5] = SideLeft;
1515 device->RealOut.ChannelName[6] = SideRight;
1516 break;
1517 case DevFmtX71:
1518 device->RealOut.ChannelName[0] = FrontLeft;
1519 device->RealOut.ChannelName[1] = FrontRight;
1520 device->RealOut.ChannelName[2] = FrontCenter;
1521 device->RealOut.ChannelName[3] = LFE;
1522 device->RealOut.ChannelName[4] = BackLeft;
1523 device->RealOut.ChannelName[5] = BackRight;
1524 device->RealOut.ChannelName[6] = SideLeft;
1525 device->RealOut.ChannelName[7] = SideRight;
1526 break;
1527 case DevFmtAmbi3D:
1528 device->RealOut.ChannelName[0] = Aux0;
1529 if(device->mAmbiOrder > 0)
1531 device->RealOut.ChannelName[1] = Aux1;
1532 device->RealOut.ChannelName[2] = Aux2;
1533 device->RealOut.ChannelName[3] = Aux3;
1535 if(device->mAmbiOrder > 1)
1537 device->RealOut.ChannelName[4] = Aux4;
1538 device->RealOut.ChannelName[5] = Aux5;
1539 device->RealOut.ChannelName[6] = Aux6;
1540 device->RealOut.ChannelName[7] = Aux7;
1541 device->RealOut.ChannelName[8] = Aux8;
1543 if(device->mAmbiOrder > 2)
1545 device->RealOut.ChannelName[9] = Aux9;
1546 device->RealOut.ChannelName[10] = Aux10;
1547 device->RealOut.ChannelName[11] = Aux11;
1548 device->RealOut.ChannelName[12] = Aux12;
1549 device->RealOut.ChannelName[13] = Aux13;
1550 device->RealOut.ChannelName[14] = Aux14;
1551 device->RealOut.ChannelName[15] = Aux15;
1553 break;
1557 /* SetDefaultChannelOrder
1559 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1561 void SetDefaultChannelOrder(ALCdevice *device)
1563 ALsizei i;
1565 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1566 device->RealOut.ChannelName[i] = InvalidChannel;
1568 switch(device->FmtChans)
1570 case DevFmtX51Rear:
1571 device->RealOut.ChannelName[0] = FrontLeft;
1572 device->RealOut.ChannelName[1] = FrontRight;
1573 device->RealOut.ChannelName[2] = BackLeft;
1574 device->RealOut.ChannelName[3] = BackRight;
1575 device->RealOut.ChannelName[4] = FrontCenter;
1576 device->RealOut.ChannelName[5] = LFE;
1577 return;
1578 case DevFmtX71:
1579 device->RealOut.ChannelName[0] = FrontLeft;
1580 device->RealOut.ChannelName[1] = FrontRight;
1581 device->RealOut.ChannelName[2] = BackLeft;
1582 device->RealOut.ChannelName[3] = BackRight;
1583 device->RealOut.ChannelName[4] = FrontCenter;
1584 device->RealOut.ChannelName[5] = LFE;
1585 device->RealOut.ChannelName[6] = SideLeft;
1586 device->RealOut.ChannelName[7] = SideRight;
1587 return;
1589 /* Same as WFX order */
1590 case DevFmtMono:
1591 case DevFmtStereo:
1592 case DevFmtQuad:
1593 case DevFmtX51:
1594 case DevFmtX61:
1595 case DevFmtAmbi3D:
1596 SetDefaultWFXChannelOrder(device);
1597 break;
1602 /* ALCcontext_DeferUpdates
1604 * Defers/suspends updates for the given context's listener and sources. This
1605 * does *NOT* stop mixing, but rather prevents certain property changes from
1606 * taking effect.
1608 void ALCcontext_DeferUpdates(ALCcontext *context)
1610 context->DeferUpdates.store(true);
1613 /* ALCcontext_ProcessUpdates
1615 * Resumes update processing after being deferred.
1617 void ALCcontext_ProcessUpdates(ALCcontext *context)
1619 std::lock_guard<almtx_t> _{context->PropLock};
1620 if(context->DeferUpdates.exchange(false))
1622 /* Tell the mixer to stop applying updates, then wait for any active
1623 * updating to finish, before providing updates.
1625 context->HoldUpdates.store(AL_TRUE);
1626 while((context->UpdateCount.load(std::memory_order_acquire)&1) != 0)
1627 althrd_yield();
1629 if(!context->PropsClean.test_and_set(std::memory_order_acq_rel))
1630 UpdateContextProps(context);
1631 if(!context->Listener.PropsClean.test_and_set(std::memory_order_acq_rel))
1632 UpdateListenerProps(context);
1633 UpdateAllEffectSlotProps(context);
1634 UpdateAllSourceProps(context);
1636 /* Now with all updates declared, let the mixer continue applying them
1637 * so they all happen at once.
1639 context->HoldUpdates.store(AL_FALSE);
1644 /* alcSetError
1646 * Stores the latest ALC device error
1648 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1650 WARN("Error generated on device %p, code 0x%04x\n", device, errorCode);
1651 if(TrapALCError)
1653 #ifdef _WIN32
1654 /* DebugBreak() will cause an exception if there is no debugger */
1655 if(IsDebuggerPresent())
1656 DebugBreak();
1657 #elif defined(SIGTRAP)
1658 raise(SIGTRAP);
1659 #endif
1662 if(device)
1663 device->LastError.store(errorCode);
1664 else
1665 LastNullDeviceError.store(errorCode);
1669 static struct Compressor *CreateDeviceLimiter(const ALCdevice *device, const ALfloat threshold)
1671 return CompressorInit(device->RealOut.NumChannels, device->Frequency,
1672 AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, 0.001f, 0.002f,
1673 0.0f, 0.0f, threshold, INFINITY, 0.0f, 0.020f, 0.200f);
1676 /* UpdateClockBase
1678 * Updates the device's base clock time with however many samples have been
1679 * done. This is used so frequency changes on the device don't cause the time
1680 * to jump forward or back. Must not be called while the device is running/
1681 * mixing.
1683 static inline void UpdateClockBase(ALCdevice *device)
1685 using std::chrono::seconds;
1686 using std::chrono::nanoseconds;
1687 using std::chrono::duration_cast;
1689 IncrementRef(&device->MixCount);
1690 device->ClockBase += duration_cast<nanoseconds>(seconds{device->SamplesDone}) /
1691 device->Frequency;
1692 device->SamplesDone = 0;
1693 IncrementRef(&device->MixCount);
1696 /* UpdateDeviceParams
1698 * Updates device parameters according to the attribute list (caller is
1699 * responsible for holding the list lock).
1701 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1703 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1704 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1705 ALCenum gainLimiter = device->LimiterState;
1706 const ALsizei old_sends = device->NumAuxSends;
1707 ALsizei new_sends = device->NumAuxSends;
1708 enum DevFmtChannels oldChans;
1709 enum DevFmtType oldType;
1710 ALboolean update_failed;
1711 ALCsizei hrtf_id = -1;
1712 ALCcontext *context;
1713 ALCuint oldFreq;
1714 int val;
1716 // Check for attributes
1717 if(device->Type == Loopback)
1719 ALCsizei numMono, numStereo, numSends;
1720 ALCenum alayout = AL_NONE;
1721 ALCenum ascale = AL_NONE;
1722 ALCenum schans = AL_NONE;
1723 ALCenum stype = AL_NONE;
1724 ALCsizei attrIdx = 0;
1725 ALCsizei aorder = 0;
1726 ALCuint freq = 0;
1728 if(!attrList)
1730 WARN("Missing attributes for loopback device\n");
1731 return ALC_INVALID_VALUE;
1734 numMono = device->NumMonoSources;
1735 numStereo = device->NumStereoSources;
1736 numSends = old_sends;
1738 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1739 while(attrList[attrIdx])
1741 switch(attrList[attrIdx])
1743 case ALC_FORMAT_CHANNELS_SOFT:
1744 schans = attrList[attrIdx + 1];
1745 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1746 if(!IsValidALCChannels(schans))
1747 return ALC_INVALID_VALUE;
1748 break;
1750 case ALC_FORMAT_TYPE_SOFT:
1751 stype = attrList[attrIdx + 1];
1752 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1753 if(!IsValidALCType(stype))
1754 return ALC_INVALID_VALUE;
1755 break;
1757 case ALC_FREQUENCY:
1758 freq = attrList[attrIdx + 1];
1759 TRACE_ATTR(ALC_FREQUENCY, freq);
1760 if(freq < MIN_OUTPUT_RATE)
1761 return ALC_INVALID_VALUE;
1762 break;
1764 case ALC_AMBISONIC_LAYOUT_SOFT:
1765 alayout = attrList[attrIdx + 1];
1766 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1767 if(!IsValidAmbiLayout(alayout))
1768 return ALC_INVALID_VALUE;
1769 break;
1771 case ALC_AMBISONIC_SCALING_SOFT:
1772 ascale = attrList[attrIdx + 1];
1773 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1774 if(!IsValidAmbiScaling(ascale))
1775 return ALC_INVALID_VALUE;
1776 break;
1778 case ALC_AMBISONIC_ORDER_SOFT:
1779 aorder = attrList[attrIdx + 1];
1780 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1781 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1782 return ALC_INVALID_VALUE;
1783 break;
1785 case ALC_MONO_SOURCES:
1786 numMono = attrList[attrIdx + 1];
1787 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1788 numMono = maxi(numMono, 0);
1789 break;
1791 case ALC_STEREO_SOURCES:
1792 numStereo = attrList[attrIdx + 1];
1793 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1794 numStereo = maxi(numStereo, 0);
1795 break;
1797 case ALC_MAX_AUXILIARY_SENDS:
1798 numSends = attrList[attrIdx + 1];
1799 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1800 numSends = clampi(numSends, 0, MAX_SENDS);
1801 break;
1803 case ALC_HRTF_SOFT:
1804 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1805 if(attrList[attrIdx + 1] == ALC_FALSE)
1806 hrtf_appreq = Hrtf_Disable;
1807 else if(attrList[attrIdx + 1] == ALC_TRUE)
1808 hrtf_appreq = Hrtf_Enable;
1809 else
1810 hrtf_appreq = Hrtf_Default;
1811 break;
1813 case ALC_HRTF_ID_SOFT:
1814 hrtf_id = attrList[attrIdx + 1];
1815 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1816 break;
1818 case ALC_OUTPUT_LIMITER_SOFT:
1819 gainLimiter = attrList[attrIdx + 1];
1820 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1821 break;
1823 default:
1824 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList[attrIdx],
1825 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1826 break;
1829 attrIdx += 2;
1831 #undef TRACE_ATTR
1833 if(!schans || !stype || !freq)
1835 WARN("Missing format for loopback device\n");
1836 return ALC_INVALID_VALUE;
1838 if(schans == ALC_BFORMAT3D_SOFT && (!alayout || !ascale || !aorder))
1840 WARN("Missing ambisonic info for loopback device\n");
1841 return ALC_INVALID_VALUE;
1844 if((device->Flags&DEVICE_RUNNING))
1845 V0(device->Backend,stop)();
1846 device->Flags &= ~DEVICE_RUNNING;
1848 UpdateClockBase(device);
1850 device->Frequency = freq;
1851 device->FmtChans = static_cast<enum DevFmtChannels>(schans);
1852 device->FmtType = static_cast<enum DevFmtType>(stype);
1853 if(schans == ALC_BFORMAT3D_SOFT)
1855 device->mAmbiOrder = aorder;
1856 device->mAmbiLayout = static_cast<AmbiLayout>(alayout);
1857 device->mAmbiScale = static_cast<AmbiNorm>(ascale);
1860 if(numMono > INT_MAX-numStereo)
1861 numMono = INT_MAX-numStereo;
1862 numMono += numStereo;
1863 if(ConfigValueInt(nullptr, nullptr, "sources", &numMono))
1865 if(numMono <= 0)
1866 numMono = 256;
1868 else
1869 numMono = maxi(numMono, 256);
1870 numStereo = mini(numStereo, numMono);
1871 numMono -= numStereo;
1872 device->SourcesMax = numMono + numStereo;
1874 device->NumMonoSources = numMono;
1875 device->NumStereoSources = numStereo;
1877 if(ConfigValueInt(nullptr, nullptr, "sends", &new_sends))
1878 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1879 else
1880 new_sends = numSends;
1882 else if(attrList && attrList[0])
1884 ALCsizei numMono, numStereo, numSends;
1885 ALCsizei attrIdx = 0;
1886 ALCuint freq;
1888 /* If a context is already running on the device, stop playback so the
1889 * device attributes can be updated. */
1890 if((device->Flags&DEVICE_RUNNING))
1891 V0(device->Backend,stop)();
1892 device->Flags &= ~DEVICE_RUNNING;
1894 UpdateClockBase(device);
1896 freq = device->Frequency;
1897 numMono = device->NumMonoSources;
1898 numStereo = device->NumStereoSources;
1899 numSends = old_sends;
1901 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1902 while(attrList[attrIdx])
1904 switch(attrList[attrIdx])
1906 case ALC_FREQUENCY:
1907 freq = attrList[attrIdx + 1];
1908 TRACE_ATTR(ALC_FREQUENCY, freq);
1909 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1910 break;
1912 case ALC_MONO_SOURCES:
1913 numMono = attrList[attrIdx + 1];
1914 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1915 numMono = maxi(numMono, 0);
1916 break;
1918 case ALC_STEREO_SOURCES:
1919 numStereo = attrList[attrIdx + 1];
1920 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1921 numStereo = maxi(numStereo, 0);
1922 break;
1924 case ALC_MAX_AUXILIARY_SENDS:
1925 numSends = attrList[attrIdx + 1];
1926 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1927 numSends = clampi(numSends, 0, MAX_SENDS);
1928 break;
1930 case ALC_HRTF_SOFT:
1931 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1932 if(attrList[attrIdx + 1] == ALC_FALSE)
1933 hrtf_appreq = Hrtf_Disable;
1934 else if(attrList[attrIdx + 1] == ALC_TRUE)
1935 hrtf_appreq = Hrtf_Enable;
1936 else
1937 hrtf_appreq = Hrtf_Default;
1938 break;
1940 case ALC_HRTF_ID_SOFT:
1941 hrtf_id = attrList[attrIdx + 1];
1942 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1943 break;
1945 case ALC_OUTPUT_LIMITER_SOFT:
1946 gainLimiter = attrList[attrIdx + 1];
1947 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1948 break;
1950 default:
1951 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1952 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1953 break;
1956 attrIdx += 2;
1958 #undef TRACE_ATTR
1960 ConfigValueUInt(device->DeviceName.c_str(), nullptr, "frequency", &freq);
1961 freq = maxu(freq, MIN_OUTPUT_RATE);
1963 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1964 device->Frequency;
1965 /* SSE and Neon do best with the update size being a multiple of 4 */
1966 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1967 device->UpdateSize = (device->UpdateSize+3)&~3;
1969 device->Frequency = freq;
1971 if(numMono > INT_MAX-numStereo)
1972 numMono = INT_MAX-numStereo;
1973 numMono += numStereo;
1974 if(ConfigValueInt(device->DeviceName.c_str(), nullptr, "sources", &numMono))
1976 if(numMono <= 0)
1977 numMono = 256;
1979 else
1980 numMono = maxi(numMono, 256);
1981 numStereo = mini(numStereo, numMono);
1982 numMono -= numStereo;
1983 device->SourcesMax = numMono + numStereo;
1985 device->NumMonoSources = numMono;
1986 device->NumStereoSources = numStereo;
1988 if(ConfigValueInt(device->DeviceName.c_str(), nullptr, "sends", &new_sends))
1989 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1990 else
1991 new_sends = numSends;
1994 if((device->Flags&DEVICE_RUNNING))
1995 return ALC_NO_ERROR;
1997 device->Uhj_Encoder = nullptr;
1998 device->Bs2b = nullptr;
2000 device->ChannelDelay.clear();
2001 device->ChannelDelay.shrink_to_fit();
2003 device->Dry.Buffer = nullptr;
2004 device->Dry.NumChannels = 0;
2005 device->FOAOut.Buffer = nullptr;
2006 device->FOAOut.NumChannels = 0;
2007 device->RealOut.Buffer = nullptr;
2008 device->RealOut.NumChannels = 0;
2009 device->MixBuffer.clear();
2010 device->MixBuffer.shrink_to_fit();
2012 UpdateClockBase(device);
2013 device->FixedLatency = std::chrono::nanoseconds::zero();
2015 device->DitherSeed = DITHER_RNG_SEED;
2017 /*************************************************************************
2018 * Update device format request if HRTF is requested
2020 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
2021 if(device->Type != Loopback)
2023 const char *hrtf;
2024 if(ConfigValueStr(device->DeviceName.c_str(), nullptr, "hrtf", &hrtf))
2026 if(strcasecmp(hrtf, "true") == 0)
2027 hrtf_userreq = Hrtf_Enable;
2028 else if(strcasecmp(hrtf, "false") == 0)
2029 hrtf_userreq = Hrtf_Disable;
2030 else if(strcasecmp(hrtf, "auto") != 0)
2031 ERR("Unexpected hrtf value: %s\n", hrtf);
2034 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
2036 struct Hrtf *hrtf = nullptr;
2037 if(device->HrtfList.empty())
2038 device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
2039 if(!device->HrtfList.empty())
2041 if(hrtf_id >= 0 && (size_t)hrtf_id < device->HrtfList.size())
2042 hrtf = GetLoadedHrtf(device->HrtfList[hrtf_id].hrtf);
2043 else
2044 hrtf = GetLoadedHrtf(device->HrtfList.front().hrtf);
2047 if(hrtf)
2049 device->FmtChans = DevFmtStereo;
2050 device->Frequency = hrtf->sampleRate;
2051 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
2052 if(device->HrtfHandle)
2053 Hrtf_DecRef(device->HrtfHandle);
2054 device->HrtfHandle = hrtf;
2056 else
2058 hrtf_userreq = Hrtf_Default;
2059 hrtf_appreq = Hrtf_Disable;
2060 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2065 oldFreq = device->Frequency;
2066 oldChans = device->FmtChans;
2067 oldType = device->FmtType;
2069 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2070 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
2071 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
2072 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
2073 device->UpdateSize, device->NumUpdates
2076 if(V0(device->Backend,reset)() == ALC_FALSE)
2077 return ALC_INVALID_DEVICE;
2079 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
2081 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2082 DevFmtChannelsString(device->FmtChans));
2083 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2085 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2087 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2088 DevFmtTypeString(device->FmtType));
2089 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2091 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2093 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2094 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2097 if((device->UpdateSize&3) != 0)
2099 if((CPUCapFlags&CPU_CAP_SSE))
2100 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2101 if((CPUCapFlags&CPU_CAP_NEON))
2102 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2105 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2106 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2107 device->Frequency, device->UpdateSize, device->NumUpdates
2110 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2111 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device->Dry.NumChannels,
2112 device->FOAOut.NumChannels, device->RealOut.NumChannels);
2114 /* Allocate extra channels for any post-filter output. */
2115 ALsizei num_chans{device->Dry.NumChannels + device->FOAOut.NumChannels +
2116 device->RealOut.NumChannels};
2118 TRACE("Allocating %d channels, " SZFMT " bytes\n", num_chans,
2119 num_chans*sizeof(device->MixBuffer[0]));
2120 device->MixBuffer.resize(num_chans);
2122 device->Dry.Buffer = &reinterpret_cast<ALfloat(&)[BUFFERSIZE]>(device->MixBuffer[0]);
2123 if(device->RealOut.NumChannels != 0)
2124 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels +
2125 device->FOAOut.NumChannels;
2126 else
2128 device->RealOut.Buffer = device->Dry.Buffer;
2129 device->RealOut.NumChannels = device->Dry.NumChannels;
2132 if(device->FOAOut.NumChannels != 0)
2133 device->FOAOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2134 else
2136 device->FOAOut.Buffer = device->Dry.Buffer;
2137 device->FOAOut.NumChannels = device->Dry.NumChannels;
2140 device->NumAuxSends = new_sends;
2141 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2142 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
2143 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
2145 device->DitherDepth = 0.0f;
2146 if(GetConfigValueBool(device->DeviceName.c_str(), nullptr, "dither", 1))
2148 ALint depth = 0;
2149 ConfigValueInt(device->DeviceName.c_str(), nullptr, "dither-depth", &depth);
2150 if(depth <= 0)
2152 switch(device->FmtType)
2154 case DevFmtByte:
2155 case DevFmtUByte:
2156 depth = 8;
2157 break;
2158 case DevFmtShort:
2159 case DevFmtUShort:
2160 depth = 16;
2161 break;
2162 case DevFmtInt:
2163 case DevFmtUInt:
2164 case DevFmtFloat:
2165 break;
2169 if(depth > 0)
2171 depth = clampi(depth, 2, 24);
2172 device->DitherDepth = std::pow(2.0f, (ALfloat)(depth-1));
2175 if(!(device->DitherDepth > 0.0f))
2176 TRACE("Dithering disabled\n");
2177 else
2178 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device->DitherDepth)+0.5f)+1,
2179 device->DitherDepth);
2181 device->LimiterState = gainLimiter;
2182 if(ConfigValueBool(device->DeviceName.c_str(), nullptr, "output-limiter", &val))
2183 gainLimiter = val ? ALC_TRUE : ALC_FALSE;
2185 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2186 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2187 * output (where samples must be clamped), and don't for floating-point
2188 * (which can take unclamped samples).
2190 if(gainLimiter == ALC_DONT_CARE_SOFT)
2192 switch(device->FmtType)
2194 case DevFmtByte:
2195 case DevFmtUByte:
2196 case DevFmtShort:
2197 case DevFmtUShort:
2198 case DevFmtInt:
2199 case DevFmtUInt:
2200 gainLimiter = ALC_TRUE;
2201 break;
2202 case DevFmtFloat:
2203 gainLimiter = ALC_FALSE;
2204 break;
2207 if(gainLimiter != ALC_FALSE)
2209 ALfloat thrshld = 1.0f;
2210 switch(device->FmtType)
2212 case DevFmtByte:
2213 case DevFmtUByte:
2214 thrshld = 127.0f / 128.0f;
2215 break;
2216 case DevFmtShort:
2217 case DevFmtUShort:
2218 thrshld = 32767.0f / 32768.0f;
2219 break;
2220 case DevFmtInt:
2221 case DevFmtUInt:
2222 case DevFmtFloat:
2223 break;
2225 if(device->DitherDepth > 0.0f)
2226 thrshld -= 1.0f / device->DitherDepth;
2228 device->Limiter.reset(CreateDeviceLimiter(device, std::log10(thrshld) * 20.0f));
2229 /* Convert the lookahead from samples to nanosamples to nanoseconds. */
2230 device->FixedLatency += std::chrono::duration_cast<std::chrono::nanoseconds>(
2231 std::chrono::seconds(GetCompressorLookAhead(device->Limiter.get()))
2232 ) / device->Frequency;
2234 else
2235 device->Limiter = nullptr;
2236 TRACE("Output limiter %s\n", device->Limiter ? "enabled" : "disabled");
2238 aluSelectPostProcess(device);
2240 TRACE("Fixed device latency: %ldns\n", (long)device->FixedLatency.count());
2242 /* Need to delay returning failure until replacement Send arrays have been
2243 * allocated with the appropriate size.
2245 update_failed = AL_FALSE;
2246 FPUCtl mixer_mode{};
2247 context = device->ContextList.load();
2248 while(context)
2250 if(context->DefaultSlot)
2252 ALeffectslot *slot = context->DefaultSlot.get();
2253 EffectState *state = slot->Effect.State;
2255 state->mOutBuffer = device->Dry.Buffer;
2256 state->mOutChannels = device->Dry.NumChannels;
2257 if(state->deviceUpdate(device) == AL_FALSE)
2258 update_failed = AL_TRUE;
2259 else
2260 UpdateEffectSlotProps(slot, context);
2263 std::unique_lock<almtx_t> proplock{context->PropLock};
2264 std::unique_lock<almtx_t> slotlock{context->EffectSlotLock};
2265 for(auto &slot : context->EffectSlotList)
2267 EffectState *state = slot->Effect.State;
2269 state->mOutBuffer = device->Dry.Buffer;
2270 state->mOutChannels = device->Dry.NumChannels;
2271 if(state->deviceUpdate(device) == AL_FALSE)
2272 update_failed = AL_TRUE;
2273 else
2274 UpdateEffectSlotProps(slot.get(), context);
2276 slotlock.unlock();
2278 std::unique_lock<almtx_t> srclock{context->SourceLock};
2279 for(auto &sublist : context->SourceList)
2281 uint64_t usemask = ~sublist.FreeMask;
2282 while(usemask)
2284 ALsizei idx = CTZ64(usemask);
2285 ALsource *source = sublist.Sources + idx;
2287 usemask &= ~(U64(1) << idx);
2289 if(old_sends != device->NumAuxSends)
2291 ALsizei s;
2292 for(s = device->NumAuxSends;s < old_sends;s++)
2294 if(source->Send[s].Slot)
2295 DecrementRef(&source->Send[s].Slot->ref);
2296 source->Send[s].Slot = nullptr;
2298 source->Send.resize(device->NumAuxSends);
2299 source->Send.shrink_to_fit();
2300 for(s = old_sends;s < device->NumAuxSends;s++)
2302 source->Send[s].Slot = nullptr;
2303 source->Send[s].Gain = 1.0f;
2304 source->Send[s].GainHF = 1.0f;
2305 source->Send[s].HFReference = LOWPASSFREQREF;
2306 source->Send[s].GainLF = 1.0f;
2307 source->Send[s].LFReference = HIGHPASSFREQREF;
2311 source->PropsClean.clear(std::memory_order_release);
2315 /* Clear any pre-existing voice property structs, in case the number of
2316 * auxiliary sends is changing. Active sources will have updates
2317 * respecified in UpdateAllSourceProps.
2319 ALvoiceProps *vprops{context->FreeVoiceProps.exchange(nullptr, std::memory_order_acq_rel)};
2320 while(vprops)
2322 struct ALvoiceProps *next = vprops->next.load(std::memory_order_relaxed);
2323 al_free(vprops);
2324 vprops = next;
2327 AllocateVoices(context, context->MaxVoices, old_sends);
2328 auto voices_end = context->Voices + context->VoiceCount.load(std::memory_order_relaxed);
2329 std::for_each(context->Voices, voices_end,
2330 [device](ALvoice *voice) -> void
2332 al_free(voice->Update.exchange(nullptr, std::memory_order_acq_rel));
2334 if(voice->Source.load(std::memory_order_acquire) == nullptr)
2335 return;
2337 if(device->AvgSpeakerDist > 0.0f)
2339 /* Reinitialize the NFC filters for new parameters. */
2340 ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
2341 (device->AvgSpeakerDist * device->Frequency);
2342 std::for_each(voice->Direct.Params, voice->Direct.Params+voice->NumChannels,
2343 [w1](DirectParams &params) -> void
2344 { NfcFilterCreate(&params.NFCtrlFilter, 0.0f, w1); }
2349 srclock.unlock();
2351 context->PropsClean.test_and_set(std::memory_order_release);
2352 UpdateContextProps(context);
2353 context->Listener.PropsClean.test_and_set(std::memory_order_release);
2354 UpdateListenerProps(context);
2355 UpdateAllSourceProps(context);
2357 context = context->next.load(std::memory_order_relaxed);
2359 mixer_mode.leave();
2360 if(update_failed)
2361 return ALC_INVALID_DEVICE;
2363 if(!(device->Flags&DEVICE_PAUSED))
2365 if(V0(device->Backend,start)() == ALC_FALSE)
2366 return ALC_INVALID_DEVICE;
2367 device->Flags |= DEVICE_RUNNING;
2370 return ALC_NO_ERROR;
2374 ALCdevice_struct::ALCdevice_struct(DeviceType type)
2375 : Type{type}
2377 almtx_init(&BufferLock, almtx_plain);
2378 almtx_init(&EffectLock, almtx_plain);
2379 almtx_init(&FilterLock, almtx_plain);
2381 almtx_init(&BackendLock, almtx_plain);
2384 /* ALCdevice_struct::~ALCdevice_struct
2386 * Frees the device structure, and destroys any objects the app failed to
2387 * delete. Called once there's no more references on the device.
2389 ALCdevice_struct::~ALCdevice_struct()
2391 TRACE("%p\n", this);
2393 if(Backend)
2394 DELETE_OBJ(Backend);
2395 Backend = nullptr;
2397 almtx_destroy(&BackendLock);
2399 ReleaseALBuffers(this);
2400 std::for_each(BufferList.begin(), BufferList.end(),
2401 [](BufferSubList &entry) noexcept -> void
2402 { al_free(entry.Buffers); }
2404 BufferList.clear();
2405 almtx_destroy(&BufferLock);
2407 ReleaseALEffects(this);
2408 std::for_each(EffectList.begin(), EffectList.end(),
2409 [](EffectSubList &entry) noexcept -> void
2410 { al_free(entry.Effects); }
2412 EffectList.clear();
2413 almtx_destroy(&EffectLock);
2415 ReleaseALFilters(this);
2416 std::for_each(FilterList.begin(), FilterList.end(),
2417 [](FilterSubList &entry) noexcept -> void
2418 { al_free(entry.Filters); }
2420 FilterList.clear();
2421 almtx_destroy(&FilterLock);
2423 HrtfList.clear();
2424 if(HrtfHandle)
2425 Hrtf_DecRef(HrtfHandle);
2426 HrtfHandle = nullptr;
2430 static void ALCdevice_IncRef(ALCdevice *device)
2432 auto ref = IncrementRef(&device->ref);
2433 TRACEREF("%p increasing refcount to %u\n", device, ref);
2436 static 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 /* Simple RAII device reference. Takes the reference of the provided ALCdevice,
2444 * and decrements it when leaving scope. Movable (transfer reference) but not
2445 * copyable (no new references).
2447 class DeviceRef {
2448 ALCdevice *mDev{nullptr};
2450 void reset() noexcept
2452 if(mDev)
2453 ALCdevice_DecRef(mDev);
2454 mDev = nullptr;
2457 public:
2458 DeviceRef() noexcept = default;
2459 DeviceRef(DeviceRef&& rhs) noexcept : mDev{rhs.mDev}
2460 { rhs.mDev = nullptr; }
2461 explicit DeviceRef(ALCdevice *dev) noexcept : mDev(dev) { }
2462 ~DeviceRef() { reset(); }
2464 DeviceRef& operator=(const DeviceRef&) = delete;
2465 DeviceRef& operator=(DeviceRef&& rhs) noexcept
2467 reset();
2468 mDev = rhs.mDev;
2469 rhs.mDev = nullptr;
2470 return *this;
2473 operator bool() const noexcept { return mDev != nullptr; }
2475 ALCdevice* operator->() noexcept { return mDev; }
2476 ALCdevice* get() noexcept { return mDev; }
2478 ALCdevice* release() noexcept
2480 ALCdevice *ret{mDev};
2481 mDev = nullptr;
2482 return ret;
2487 /* VerifyDevice
2489 * Checks if the device handle is valid, and returns a new reference if so.
2491 static DeviceRef VerifyDevice(ALCdevice *device)
2493 std::lock_guard<std::recursive_mutex> _{ListLock};
2494 ALCdevice *tmpDevice{DeviceList.load()};
2495 while(tmpDevice)
2497 if(tmpDevice == device)
2499 ALCdevice_IncRef(tmpDevice);
2500 return DeviceRef{tmpDevice};
2502 tmpDevice = tmpDevice->next.load(std::memory_order_relaxed);
2505 return DeviceRef{};
2509 ALCcontext_struct::ALCcontext_struct(ALCdevice *device)
2510 : Device{device}
2514 /* InitContext
2516 * Initializes context fields
2518 static ALvoid InitContext(ALCcontext *Context)
2520 ALlistener &listener = Context->Listener;
2521 struct ALeffectslotArray *auxslots;
2523 //Validate Context
2524 almtx_init(&Context->PropLock, almtx_plain);
2525 almtx_init(&Context->SourceLock, almtx_plain);
2526 almtx_init(&Context->EffectSlotLock, almtx_plain);
2528 if(Context->DefaultSlot)
2530 auxslots = static_cast<ALeffectslotArray*>(al_calloc(DEF_ALIGN,
2531 FAM_SIZE(struct ALeffectslotArray, slot, 1)));
2532 auxslots->count = 1;
2533 auxslots->slot[0] = Context->DefaultSlot.get();
2535 else
2537 auxslots = static_cast<ALeffectslotArray*>(al_calloc(DEF_ALIGN,
2538 sizeof(struct ALeffectslotArray)));
2539 auxslots->count = 0;
2541 ATOMIC_INIT(&Context->ActiveAuxSlots, auxslots);
2543 //Set globals
2544 Context->mDistanceModel = DistanceModel::Default;
2545 Context->SourceDistanceModel = AL_FALSE;
2546 Context->DopplerFactor = 1.0f;
2547 Context->DopplerVelocity = 1.0f;
2548 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2549 Context->MetersPerUnit = AL_DEFAULT_METERS_PER_UNIT;
2550 alsem_init(&Context->EventSem, 0);
2552 Context->ExtensionList = alExtList;
2555 listener.Params.Matrix = aluMatrixf::Identity;
2556 aluVectorSet(&listener.Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2557 listener.Params.Gain = listener.Gain;
2558 listener.Params.MetersPerUnit = Context->MetersPerUnit;
2559 listener.Params.DopplerFactor = Context->DopplerFactor;
2560 listener.Params.SpeedOfSound = Context->SpeedOfSound * Context->DopplerVelocity;
2561 listener.Params.ReverbSpeedOfSound = listener.Params.SpeedOfSound *
2562 listener.Params.MetersPerUnit;
2563 listener.Params.SourceDistanceModel = Context->SourceDistanceModel;
2564 listener.Params.mDistanceModel = Context->mDistanceModel;
2567 Context->AsyncEvents = ll_ringbuffer_create(63, sizeof(AsyncEvent), false);
2568 StartEventThrd(Context);
2572 /* ALCcontext_struct::~ALCcontext_struct()
2574 * Cleans up the context, and destroys any remaining objects the app failed to
2575 * delete. Called once there's no more references on the context.
2577 ALCcontext_struct::~ALCcontext_struct()
2579 TRACE("%p\n", this);
2581 struct ALcontextProps *cprops{Update.load(std::memory_order_relaxed)};
2582 if(cprops)
2584 TRACE("Freed unapplied context update %p\n", cprops);
2585 al_free(cprops);
2587 size_t count{0};
2588 cprops = FreeContextProps.load(std::memory_order_acquire);
2589 while(cprops)
2591 struct ALcontextProps *next{cprops->next.load(std::memory_order_relaxed)};
2592 al_free(cprops);
2593 cprops = next;
2594 ++count;
2596 TRACE("Freed " SZFMT " context property object%s\n", count, (count==1)?"":"s");
2598 al_free(ActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed));
2599 DefaultSlot = nullptr;
2601 count = 0;
2602 for(auto &sublist : SourceList)
2603 count += POPCNT64(~sublist.FreeMask);
2604 if(count > 0)
2605 WARN(SZFMT " Source%s not deleted\n", count, (count==1)?"":"s");
2606 SourceList.clear();
2607 NumSources = 0;
2608 almtx_destroy(&SourceLock);
2610 count = 0;
2611 struct ALeffectslotProps *eprops{FreeEffectslotProps.load(std::memory_order_acquire)};
2612 while(eprops)
2614 struct ALeffectslotProps *next{eprops->next.load(std::memory_order_relaxed)};
2615 if(eprops->State) eprops->State->DecRef();
2616 al_free(eprops);
2617 eprops = next;
2618 ++count;
2620 TRACE("Freed " SZFMT " AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2622 count = 0;
2623 for(auto &slot : EffectSlotList)
2624 count += slot ? 1 : 0;
2625 if(count > 0)
2626 WARN(SZFMT " AuxiliaryEffectSlot%s not deleted\n", count, (count==1)?"":"s");
2627 EffectSlotList.clear();
2628 almtx_destroy(&EffectSlotLock);
2630 count = 0;
2631 struct ALvoiceProps *vprops{FreeVoiceProps.load(std::memory_order_acquire)};
2632 while(vprops)
2634 struct ALvoiceProps *next{vprops->next.load(std::memory_order_relaxed)};
2635 al_free(vprops);
2636 vprops = next;
2637 ++count;
2639 TRACE("Freed " SZFMT " voice property object%s\n", count, (count==1)?"":"s");
2641 std::for_each(Voices, Voices + VoiceCount.load(std::memory_order_relaxed),
2642 [](ALvoice *voice) -> void { DeinitVoice(voice); }
2644 al_free(Voices);
2645 Voices = nullptr;
2646 VoiceCount.store(0, std::memory_order_relaxed);
2647 MaxVoices = 0;
2649 struct ALlistenerProps *lprops{Listener.Update.load(std::memory_order_relaxed)};
2650 if(lprops)
2652 TRACE("Freed unapplied listener update %p\n", lprops);
2653 al_free(lprops);
2655 count = 0;
2656 lprops = FreeListenerProps.load(std::memory_order_acquire);
2657 while(lprops)
2659 struct ALlistenerProps *next{lprops->next.load(std::memory_order_relaxed)};
2660 al_free(lprops);
2661 lprops = next;
2662 ++count;
2664 TRACE("Freed " SZFMT " listener property object%s\n", count, (count==1)?"":"s");
2666 alsem_destroy(&EventSem);
2668 ll_ringbuffer_free(AsyncEvents);
2669 AsyncEvents = nullptr;
2671 almtx_destroy(&PropLock);
2673 ALCdevice_DecRef(Device);
2676 /* ReleaseContext
2678 * Removes the context reference from the given device and removes it from
2679 * being current on the running thread or globally. Returns true if other
2680 * contexts still exist on the device.
2682 static bool ReleaseContext(ALCcontext *context, ALCdevice *device)
2684 ALCcontext *origctx, *newhead;
2685 bool ret = true;
2687 if(LocalContext.get() == context)
2689 WARN("%p released while current on thread\n", context);
2690 LocalContext.set(nullptr);
2691 ALCcontext_DecRef(context);
2694 origctx = context;
2695 if(GlobalContext.compare_exchange_strong(origctx, nullptr))
2696 ALCcontext_DecRef(context);
2698 V0(device->Backend,lock)();
2699 origctx = context;
2700 newhead = context->next.load(std::memory_order_relaxed);
2701 if(!device->ContextList.compare_exchange_strong(origctx, newhead))
2703 ALCcontext *list;
2704 do {
2705 /* origctx is what the desired context failed to match. Try
2706 * swapping out the next one in the list.
2708 list = origctx;
2709 origctx = context;
2710 } while(!list->next.compare_exchange_strong(origctx, newhead));
2712 else
2713 ret = !!newhead;
2714 V0(device->Backend,unlock)();
2716 /* Make sure the context is finished and no longer processing in the mixer
2717 * before sending the message queue kill event. The backend's lock does
2718 * this, although waiting for a non-odd mix count would work too.
2721 StopEventThrd(context);
2723 ALCcontext_DecRef(context);
2724 return ret;
2727 static void ALCcontext_IncRef(ALCcontext *context)
2729 auto ref = IncrementRef(&context->ref);
2730 TRACEREF("%p increasing refcount to %u\n", context, ref);
2733 void ALCcontext_DecRef(ALCcontext *context)
2735 auto ref = DecrementRef(&context->ref);
2736 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2737 if(ref == 0) delete context;
2740 static void ReleaseThreadCtx(ALCcontext *context)
2742 auto ref = DecrementRef(&context->ref);
2743 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2744 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2747 /* VerifyContext
2749 * Checks if the given context is valid, returning a new reference to it if so.
2751 static ContextRef VerifyContext(ALCcontext *context)
2753 std::lock_guard<std::recursive_mutex> _{ListLock};
2754 ALCdevice *dev{DeviceList.load()};
2755 while(dev)
2757 ALCcontext *ctx = dev->ContextList.load(std::memory_order_acquire);
2758 while(ctx)
2760 if(ctx == context)
2762 ALCcontext_IncRef(ctx);
2763 return ContextRef{ctx};
2765 ctx = ctx->next.load(std::memory_order_relaxed);
2767 dev = dev->next.load(std::memory_order_relaxed);
2770 return ContextRef{};
2774 /* GetContextRef
2776 * Returns a new reference to the currently active context for this thread.
2778 ContextRef GetContextRef(void)
2780 ALCcontext *context{LocalContext.get()};
2781 if(context)
2782 ALCcontext_IncRef(context);
2783 else
2785 std::lock_guard<std::recursive_mutex> _{ListLock};
2786 context = GlobalContext.load(std::memory_order_acquire);
2787 if(context) ALCcontext_IncRef(context);
2789 return ContextRef{context};
2793 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
2795 ALCdevice *device{context->Device};
2796 ALsizei num_sends{device->NumAuxSends};
2798 if(num_voices == context->MaxVoices && num_sends == old_sends)
2799 return;
2801 /* Allocate the voice pointers, voices, and the voices' stored source
2802 * property set (including the dynamically-sized Send[] array) in one
2803 * chunk.
2805 size_t sizeof_voice{RoundUp(FAM_SIZE(ALvoice, Send, num_sends), 16)};
2806 size_t sizeof_props{RoundUp(FAM_SIZE(struct ALvoiceProps, Send, num_sends), 16)};
2807 size_t size{sizeof(ALvoice*) + sizeof_voice + sizeof_props};
2809 auto voices = static_cast<ALvoice**>(al_calloc(16, RoundUp(size*num_voices, 16)));
2810 /* The voice and property objects are stored interleaved since they're
2811 * paired together.
2813 auto voice = reinterpret_cast<ALvoice*>((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
2814 auto props = reinterpret_cast<ALvoiceProps*>((char*)voice + sizeof_voice);
2816 ALsizei v{0};
2817 if(context->Voices)
2819 const ALsizei v_count = mini(context->VoiceCount.load(std::memory_order_relaxed),
2820 num_voices);
2821 const ALsizei s_count = mini(old_sends, num_sends);
2823 for(;v < v_count;v++)
2825 ALvoice *old_voice{context->Voices[v]};
2827 /* Copy the old voice data and source property set to the new
2828 * storage.
2830 memcpy(voice, old_voice, sizeof(*voice));
2831 std::copy_n(old_voice->Send, s_count, voice->Send);
2833 memcpy(props, old_voice->Props, sizeof(*props));
2834 std::copy_n(old_voice->Props->Send, s_count, props->Send);
2836 /* Set this voice's property set pointer and voice reference. */
2837 voice->Props = props;
2838 voices[v] = voice;
2840 /* Increment pointers to the next storage space. */
2841 voice = reinterpret_cast<ALvoice*>((char*)props + sizeof_props);
2842 props = reinterpret_cast<ALvoiceProps*>((char*)voice + sizeof_voice);
2844 /* Deinit any left over voices that weren't copied over to the new
2845 * array. NOTE: If this does anything, v equals num_voices and
2846 * num_voices is less than VoiceCount, so the following loop won't do
2847 * anything.
2849 auto voices_end = context->Voices + context->VoiceCount.load(std::memory_order_relaxed);
2850 std::for_each(context->Voices + v, voices_end,
2851 [](ALvoice *voice) -> void { DeinitVoice(voice); }
2854 /* Finish setting the voices' property set pointers and references. */
2855 for(;v < num_voices;v++)
2857 ATOMIC_INIT(&voice->Update, static_cast<ALvoiceProps*>(nullptr));
2859 voice->Props = props;
2860 voices[v] = voice;
2862 voice = reinterpret_cast<ALvoice*>((char*)props + sizeof_props);
2863 props = reinterpret_cast<ALvoiceProps*>((char*)voice + sizeof_voice);
2866 al_free(context->Voices);
2867 context->Voices = voices;
2868 context->MaxVoices = num_voices;
2869 context->VoiceCount = mini(context->VoiceCount.load(std::memory_order_relaxed), num_voices);
2873 /************************************************
2874 * Standard ALC functions
2875 ************************************************/
2877 /* alcGetError
2879 * Return last ALC generated error code for the given device
2881 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2883 DeviceRef dev{VerifyDevice(device)};
2884 if(dev) return dev->LastError.exchange(ALC_NO_ERROR);
2885 return LastNullDeviceError.exchange(ALC_NO_ERROR);
2889 /* alcSuspendContext
2891 * Suspends updates for the given context
2893 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2895 if(!SuspendDefers)
2896 return;
2898 ContextRef ctx{VerifyContext(context)};
2899 if(!ctx)
2900 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2901 else
2902 ALCcontext_DeferUpdates(ctx.get());
2905 /* alcProcessContext
2907 * Resumes processing updates for the given context
2909 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2911 if(!SuspendDefers)
2912 return;
2914 ContextRef ctx{VerifyContext(context)};
2915 if(!ctx)
2916 alcSetError(nullptr, ALC_INVALID_CONTEXT);
2917 else
2918 ALCcontext_ProcessUpdates(ctx.get());
2922 /* alcGetString
2924 * Returns information about the device, and error strings
2926 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2928 const ALCchar *value = nullptr;
2929 DeviceRef dev;
2931 switch(param)
2933 case ALC_NO_ERROR:
2934 value = alcNoError;
2935 break;
2937 case ALC_INVALID_ENUM:
2938 value = alcErrInvalidEnum;
2939 break;
2941 case ALC_INVALID_VALUE:
2942 value = alcErrInvalidValue;
2943 break;
2945 case ALC_INVALID_DEVICE:
2946 value = alcErrInvalidDevice;
2947 break;
2949 case ALC_INVALID_CONTEXT:
2950 value = alcErrInvalidContext;
2951 break;
2953 case ALC_OUT_OF_MEMORY:
2954 value = alcErrOutOfMemory;
2955 break;
2957 case ALC_DEVICE_SPECIFIER:
2958 value = alcDefaultName;
2959 break;
2961 case ALC_ALL_DEVICES_SPECIFIER:
2962 dev = VerifyDevice(Device);
2963 if(dev)
2964 value = dev->DeviceName.c_str();
2965 else
2967 ProbeAllDevicesList();
2968 value = alcAllDevicesList.c_str();
2970 break;
2972 case ALC_CAPTURE_DEVICE_SPECIFIER:
2973 dev = VerifyDevice(Device);
2974 if(dev)
2975 value = dev->DeviceName.c_str();
2976 else
2978 ProbeCaptureDeviceList();
2979 value = alcCaptureDeviceList.c_str();
2981 break;
2983 /* Default devices are always first in the list */
2984 case ALC_DEFAULT_DEVICE_SPECIFIER:
2985 value = alcDefaultName;
2986 break;
2988 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2989 if(alcAllDevicesList.empty())
2990 ProbeAllDevicesList();
2992 /* Copy first entry as default. */
2993 alcDefaultAllDevicesSpecifier = alcAllDevicesList.c_str();
2994 value = alcDefaultAllDevicesSpecifier.c_str();
2995 break;
2997 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2998 if(alcCaptureDeviceList.empty())
2999 ProbeCaptureDeviceList();
3001 /* Copy first entry as default. */
3002 alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList.c_str();
3003 value = alcCaptureDefaultDeviceSpecifier.c_str();
3004 break;
3006 case ALC_EXTENSIONS:
3007 dev = VerifyDevice(Device);
3008 if(dev) value = alcExtensionList;
3009 else value = alcNoDeviceExtList;
3010 break;
3012 case ALC_HRTF_SPECIFIER_SOFT:
3013 dev = VerifyDevice(Device);
3014 if(!dev)
3015 alcSetError(nullptr, ALC_INVALID_DEVICE);
3016 else
3018 std::lock_guard<almtx_t> _{dev->BackendLock};
3019 value = (dev->HrtfHandle ? dev->HrtfName.c_str() : "");
3021 break;
3023 default:
3024 dev = VerifyDevice(Device);
3025 alcSetError(dev.get(), ALC_INVALID_ENUM);
3026 break;
3029 return value;
3033 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
3035 if(device->Type == Capture) return 9;
3036 if(device->Type != Loopback) return 29;
3037 if(device->FmtChans == DevFmtAmbi3D)
3038 return 35;
3039 return 29;
3042 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3044 ALCsizei i;
3046 if(size <= 0 || values == nullptr)
3048 alcSetError(device, ALC_INVALID_VALUE);
3049 return 0;
3052 if(!device)
3054 switch(param)
3056 case ALC_MAJOR_VERSION:
3057 values[0] = alcMajorVersion;
3058 return 1;
3059 case ALC_MINOR_VERSION:
3060 values[0] = alcMinorVersion;
3061 return 1;
3063 case ALC_ATTRIBUTES_SIZE:
3064 case ALC_ALL_ATTRIBUTES:
3065 case ALC_FREQUENCY:
3066 case ALC_REFRESH:
3067 case ALC_SYNC:
3068 case ALC_MONO_SOURCES:
3069 case ALC_STEREO_SOURCES:
3070 case ALC_CAPTURE_SAMPLES:
3071 case ALC_FORMAT_CHANNELS_SOFT:
3072 case ALC_FORMAT_TYPE_SOFT:
3073 case ALC_AMBISONIC_LAYOUT_SOFT:
3074 case ALC_AMBISONIC_SCALING_SOFT:
3075 case ALC_AMBISONIC_ORDER_SOFT:
3076 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3077 alcSetError(nullptr, ALC_INVALID_DEVICE);
3078 return 0;
3080 default:
3081 alcSetError(nullptr, ALC_INVALID_ENUM);
3082 return 0;
3084 return 0;
3087 if(device->Type == Capture)
3089 switch(param)
3091 case ALC_ATTRIBUTES_SIZE:
3092 values[0] = NumAttrsForDevice(device);
3093 return 1;
3095 case ALC_ALL_ATTRIBUTES:
3096 i = 0;
3097 if(size < NumAttrsForDevice(device))
3098 alcSetError(device, ALC_INVALID_VALUE);
3099 else
3101 std::lock_guard<almtx_t> _{device->BackendLock};
3102 values[i++] = ALC_MAJOR_VERSION;
3103 values[i++] = alcMajorVersion;
3104 values[i++] = ALC_MINOR_VERSION;
3105 values[i++] = alcMinorVersion;
3106 values[i++] = ALC_CAPTURE_SAMPLES;
3107 values[i++] = V0(device->Backend,availableSamples)();
3108 values[i++] = ALC_CONNECTED;
3109 values[i++] = device->Connected.load(std::memory_order_relaxed);
3110 values[i++] = 0;
3112 return i;
3114 case ALC_MAJOR_VERSION:
3115 values[0] = alcMajorVersion;
3116 return 1;
3117 case ALC_MINOR_VERSION:
3118 values[0] = alcMinorVersion;
3119 return 1;
3121 case ALC_CAPTURE_SAMPLES:
3122 { std::lock_guard<almtx_t> _{device->BackendLock};
3123 values[0] = V0(device->Backend,availableSamples)();
3125 return 1;
3127 case ALC_CONNECTED:
3128 values[0] = device->Connected.load(std::memory_order_acquire);
3129 return 1;
3131 default:
3132 alcSetError(device, ALC_INVALID_ENUM);
3133 return 0;
3135 return 0;
3138 /* render device */
3139 switch(param)
3141 case ALC_ATTRIBUTES_SIZE:
3142 values[0] = NumAttrsForDevice(device);
3143 return 1;
3145 case ALC_ALL_ATTRIBUTES:
3146 i = 0;
3147 if(size < NumAttrsForDevice(device))
3148 alcSetError(device, ALC_INVALID_VALUE);
3149 else
3151 std::lock_guard<almtx_t> _{device->BackendLock};
3152 values[i++] = ALC_MAJOR_VERSION;
3153 values[i++] = alcMajorVersion;
3154 values[i++] = ALC_MINOR_VERSION;
3155 values[i++] = alcMinorVersion;
3156 values[i++] = ALC_EFX_MAJOR_VERSION;
3157 values[i++] = alcEFXMajorVersion;
3158 values[i++] = ALC_EFX_MINOR_VERSION;
3159 values[i++] = alcEFXMinorVersion;
3161 values[i++] = ALC_FREQUENCY;
3162 values[i++] = device->Frequency;
3163 if(device->Type != Loopback)
3165 values[i++] = ALC_REFRESH;
3166 values[i++] = device->Frequency / device->UpdateSize;
3168 values[i++] = ALC_SYNC;
3169 values[i++] = ALC_FALSE;
3171 else
3173 if(device->FmtChans == DevFmtAmbi3D)
3175 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3176 values[i++] = static_cast<ALCint>(device->mAmbiLayout);
3178 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3179 values[i++] = static_cast<ALCint>(device->mAmbiScale);
3181 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3182 values[i++] = device->mAmbiOrder;
3185 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3186 values[i++] = device->FmtChans;
3188 values[i++] = ALC_FORMAT_TYPE_SOFT;
3189 values[i++] = device->FmtType;
3192 values[i++] = ALC_MONO_SOURCES;
3193 values[i++] = device->NumMonoSources;
3195 values[i++] = ALC_STEREO_SOURCES;
3196 values[i++] = device->NumStereoSources;
3198 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3199 values[i++] = device->NumAuxSends;
3201 values[i++] = ALC_HRTF_SOFT;
3202 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3204 values[i++] = ALC_HRTF_STATUS_SOFT;
3205 values[i++] = device->HrtfStatus;
3207 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3208 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3210 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
3211 values[i++] = MAX_AMBI_ORDER;
3213 values[i++] = 0;
3215 return i;
3217 case ALC_MAJOR_VERSION:
3218 values[0] = alcMajorVersion;
3219 return 1;
3221 case ALC_MINOR_VERSION:
3222 values[0] = alcMinorVersion;
3223 return 1;
3225 case ALC_EFX_MAJOR_VERSION:
3226 values[0] = alcEFXMajorVersion;
3227 return 1;
3229 case ALC_EFX_MINOR_VERSION:
3230 values[0] = alcEFXMinorVersion;
3231 return 1;
3233 case ALC_FREQUENCY:
3234 values[0] = device->Frequency;
3235 return 1;
3237 case ALC_REFRESH:
3238 if(device->Type == Loopback)
3240 alcSetError(device, ALC_INVALID_DEVICE);
3241 return 0;
3243 { std::lock_guard<almtx_t> _{device->BackendLock};
3244 values[0] = device->Frequency / device->UpdateSize;
3246 return 1;
3248 case ALC_SYNC:
3249 if(device->Type == Loopback)
3251 alcSetError(device, ALC_INVALID_DEVICE);
3252 return 0;
3254 values[0] = ALC_FALSE;
3255 return 1;
3257 case ALC_FORMAT_CHANNELS_SOFT:
3258 if(device->Type != Loopback)
3260 alcSetError(device, ALC_INVALID_DEVICE);
3261 return 0;
3263 values[0] = device->FmtChans;
3264 return 1;
3266 case ALC_FORMAT_TYPE_SOFT:
3267 if(device->Type != Loopback)
3269 alcSetError(device, ALC_INVALID_DEVICE);
3270 return 0;
3272 values[0] = device->FmtType;
3273 return 1;
3275 case ALC_AMBISONIC_LAYOUT_SOFT:
3276 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3278 alcSetError(device, ALC_INVALID_DEVICE);
3279 return 0;
3281 values[0] = static_cast<ALCint>(device->mAmbiLayout);
3282 return 1;
3284 case ALC_AMBISONIC_SCALING_SOFT:
3285 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3287 alcSetError(device, ALC_INVALID_DEVICE);
3288 return 0;
3290 values[0] = static_cast<ALCint>(device->mAmbiScale);
3291 return 1;
3293 case ALC_AMBISONIC_ORDER_SOFT:
3294 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3296 alcSetError(device, ALC_INVALID_DEVICE);
3297 return 0;
3299 values[0] = device->mAmbiOrder;
3300 return 1;
3302 case ALC_MONO_SOURCES:
3303 values[0] = device->NumMonoSources;
3304 return 1;
3306 case ALC_STEREO_SOURCES:
3307 values[0] = device->NumStereoSources;
3308 return 1;
3310 case ALC_MAX_AUXILIARY_SENDS:
3311 values[0] = device->NumAuxSends;
3312 return 1;
3314 case ALC_CONNECTED:
3315 values[0] = device->Connected.load(std::memory_order_acquire);
3316 return 1;
3318 case ALC_HRTF_SOFT:
3319 values[0] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3320 return 1;
3322 case ALC_HRTF_STATUS_SOFT:
3323 values[0] = device->HrtfStatus;
3324 return 1;
3326 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3327 { std::lock_guard<almtx_t> _{device->BackendLock};
3328 device->HrtfList.clear();
3329 device->HrtfList = EnumerateHrtf(device->DeviceName.c_str());
3330 values[0] = (ALCint)device->HrtfList.size();
3332 return 1;
3334 case ALC_OUTPUT_LIMITER_SOFT:
3335 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3336 return 1;
3338 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3339 values[0] = MAX_AMBI_ORDER;
3340 return 1;
3342 default:
3343 alcSetError(device, ALC_INVALID_ENUM);
3344 return 0;
3346 return 0;
3349 /* alcGetIntegerv
3351 * Returns information about the device and the version of OpenAL
3353 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3355 DeviceRef dev{VerifyDevice(device)};
3356 if(size <= 0 || values == nullptr)
3357 alcSetError(dev.get(), ALC_INVALID_VALUE);
3358 else
3359 GetIntegerv(dev.get(), param, size, values);
3362 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3364 DeviceRef dev{VerifyDevice(device)};
3365 if(size <= 0 || values == nullptr)
3366 alcSetError(dev.get(), ALC_INVALID_VALUE);
3367 else if(!dev || dev->Type == Capture)
3369 al::vector<ALCint> ivals(size);
3370 size = GetIntegerv(dev.get(), pname, size, ivals.data());
3371 std::copy(ivals.begin(), ivals.begin()+size, values);
3373 else /* render device */
3375 switch(pname)
3377 case ALC_ATTRIBUTES_SIZE:
3378 *values = NumAttrsForDevice(dev.get())+4;
3379 break;
3381 case ALC_ALL_ATTRIBUTES:
3382 if(size < NumAttrsForDevice(dev.get())+4)
3383 alcSetError(dev.get(), ALC_INVALID_VALUE);
3384 else
3386 ALsizei i{0};
3387 std::lock_guard<almtx_t> _{dev->BackendLock};
3388 values[i++] = ALC_FREQUENCY;
3389 values[i++] = dev->Frequency;
3391 if(dev->Type != Loopback)
3393 values[i++] = ALC_REFRESH;
3394 values[i++] = dev->Frequency / dev->UpdateSize;
3396 values[i++] = ALC_SYNC;
3397 values[i++] = ALC_FALSE;
3399 else
3401 if(dev->FmtChans == DevFmtAmbi3D)
3403 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3404 values[i++] = static_cast<ALCint64SOFT>(dev->mAmbiLayout);
3406 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3407 values[i++] = static_cast<ALCint64SOFT>(dev->mAmbiScale);
3409 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3410 values[i++] = dev->mAmbiOrder;
3413 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3414 values[i++] = dev->FmtChans;
3416 values[i++] = ALC_FORMAT_TYPE_SOFT;
3417 values[i++] = dev->FmtType;
3420 values[i++] = ALC_MONO_SOURCES;
3421 values[i++] = dev->NumMonoSources;
3423 values[i++] = ALC_STEREO_SOURCES;
3424 values[i++] = dev->NumStereoSources;
3426 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3427 values[i++] = dev->NumAuxSends;
3429 values[i++] = ALC_HRTF_SOFT;
3430 values[i++] = (dev->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3432 values[i++] = ALC_HRTF_STATUS_SOFT;
3433 values[i++] = dev->HrtfStatus;
3435 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3436 values[i++] = dev->Limiter ? ALC_TRUE : ALC_FALSE;
3438 ClockLatency clock{GetClockLatency(dev.get())};
3439 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3440 values[i++] = clock.ClockTime.count();
3442 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3443 values[i++] = clock.Latency.count();
3445 values[i++] = 0;
3447 break;
3449 case ALC_DEVICE_CLOCK_SOFT:
3450 { std::lock_guard<almtx_t> _{dev->BackendLock};
3451 using std::chrono::seconds;
3452 using std::chrono::nanoseconds;
3453 using std::chrono::duration_cast;
3455 nanoseconds basecount;
3456 ALuint samplecount;
3457 ALuint refcount;
3458 do {
3459 while(((refcount=ReadRef(&dev->MixCount))&1) != 0)
3460 althrd_yield();
3461 basecount = dev->ClockBase;
3462 samplecount = dev->SamplesDone;
3463 } while(refcount != ReadRef(&dev->MixCount));
3464 *values = (duration_cast<nanoseconds>(seconds{samplecount})/dev->Frequency +
3465 basecount).count();
3467 break;
3469 case ALC_DEVICE_LATENCY_SOFT:
3470 { std::lock_guard<almtx_t> _{dev->BackendLock};
3471 ClockLatency clock{GetClockLatency(dev.get())};
3472 *values = clock.Latency.count();
3474 break;
3476 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3477 if(size < 2)
3478 alcSetError(dev.get(), ALC_INVALID_VALUE);
3479 else
3481 std::lock_guard<almtx_t> _{dev->BackendLock};
3482 ClockLatency clock{GetClockLatency(dev.get())};
3483 values[0] = clock.ClockTime.count();
3484 values[1] = clock.Latency.count();
3486 break;
3488 default:
3489 al::vector<ALCint> ivals(size);
3490 size = GetIntegerv(dev.get(), pname, size, ivals.data());
3491 std::copy(ivals.begin(), ivals.begin()+size, values);
3492 break;
3498 /* alcIsExtensionPresent
3500 * Determines if there is support for a particular extension
3502 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3504 DeviceRef dev{VerifyDevice(device)};
3505 if(!extName)
3506 alcSetError(dev.get(), ALC_INVALID_VALUE);
3507 else
3509 size_t len = strlen(extName);
3510 const char *ptr = (dev ? alcExtensionList : alcNoDeviceExtList);
3511 while(ptr && *ptr)
3513 if(strncasecmp(ptr, extName, len) == 0 &&
3514 (ptr[len] == '\0' || isspace(ptr[len])))
3515 return ALC_TRUE;
3517 if((ptr=strchr(ptr, ' ')) != nullptr)
3519 do {
3520 ++ptr;
3521 } while(isspace(*ptr));
3525 return ALC_FALSE;
3529 /* alcGetProcAddress
3531 * Retrieves the function address for a particular extension function
3533 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3535 if(!funcName)
3537 DeviceRef dev{VerifyDevice(device)};
3538 alcSetError(dev.get(), ALC_INVALID_VALUE);
3540 else
3542 for(const auto &func : alcFunctions)
3544 if(strcmp(func.funcName, funcName) == 0)
3545 return func.address;
3549 return nullptr;
3553 /* alcGetEnumValue
3555 * Get the value for a particular ALC enumeration name
3557 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3559 if(!enumName)
3561 DeviceRef dev{VerifyDevice(device)};
3562 alcSetError(dev.get(), ALC_INVALID_VALUE);
3564 else
3566 for(const auto &enm : alcEnumerations)
3568 if(strcmp(enm.enumName, enumName) == 0)
3569 return enm.value;
3573 return 0;
3577 /* alcCreateContext
3579 * Create and attach a context to the given device.
3581 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3583 ALCcontext *ALContext;
3584 ALfloat valf;
3585 ALCenum err;
3587 /* Explicitly hold the list lock while taking the BackendLock in case the
3588 * device is asynchronously destropyed, to ensure this new context is
3589 * properly cleaned up after being made.
3591 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3592 DeviceRef dev{VerifyDevice(device)};
3593 if(!dev || dev->Type == Capture || !dev->Connected.load(std::memory_order_relaxed))
3595 listlock.unlock();
3596 alcSetError(dev.get(), ALC_INVALID_DEVICE);
3597 return nullptr;
3599 std::unique_lock<almtx_t> backlock{dev->BackendLock};
3600 listlock.unlock();
3602 dev->LastError.store(ALC_NO_ERROR);
3604 ALContext = new ALCcontext{dev.get()};
3605 ALCdevice_IncRef(ALContext->Device);
3607 if((err=UpdateDeviceParams(dev.get(), attrList)) != ALC_NO_ERROR)
3609 backlock.unlock();
3611 delete ALContext;
3612 ALContext = nullptr;
3614 alcSetError(dev.get(), err);
3615 if(err == ALC_INVALID_DEVICE)
3617 V0(dev->Backend,lock)();
3618 aluHandleDisconnect(dev.get(), "Device update failure");
3619 V0(dev->Backend,unlock)();
3621 return nullptr;
3623 AllocateVoices(ALContext, 256, dev->NumAuxSends);
3625 if(DefaultEffect.type != AL_EFFECT_NULL && dev->Type == Playback)
3627 ALContext->DefaultSlot.reset(new ALeffectslot{});
3628 if(InitEffectSlot(ALContext->DefaultSlot.get()) == AL_NO_ERROR)
3629 aluInitEffectPanning(ALContext->DefaultSlot.get());
3630 else
3632 ALContext->DefaultSlot = nullptr;
3633 ERR("Failed to initialize the default effect slot\n");
3637 InitContext(ALContext);
3639 if(ConfigValueFloat(dev->DeviceName.c_str(), nullptr, "volume-adjust", &valf))
3641 if(!std::isfinite(valf))
3642 ERR("volume-adjust must be finite: %f\n", valf);
3643 else
3645 ALfloat db = clampf(valf, -24.0f, 24.0f);
3646 if(db != valf)
3647 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3648 ALContext->GainBoost = std::pow(10.0f, db/20.0f);
3649 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3652 UpdateListenerProps(ALContext);
3655 ALCcontext *head = dev->ContextList.load();
3656 do {
3657 ALContext->next.store(head, std::memory_order_relaxed);
3658 } while(!dev->ContextList.compare_exchange_weak(head, ALContext));
3660 backlock.unlock();
3662 if(ALContext->DefaultSlot)
3664 if(InitializeEffect(ALContext, ALContext->DefaultSlot.get(), &DefaultEffect) == AL_NO_ERROR)
3665 UpdateEffectSlotProps(ALContext->DefaultSlot.get(), ALContext);
3666 else
3667 ERR("Failed to initialize the default effect\n");
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 std::unique_ptr<ALCdevice> 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(
3933 device.get(), ALCbackend_Playback);
3934 if(!device->Backend)
3936 device = nullptr;
3937 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
3938 return nullptr;
3941 // Find a playback device to open
3942 ALCenum err{V(device->Backend,open)(deviceName)};
3943 if(err != ALC_NO_ERROR)
3945 device = nullptr;
3946 alcSetError(nullptr, err);
3947 return nullptr;
3950 if(ConfigValueStr(device->DeviceName.c_str(), nullptr, "ambi-format", &fmt))
3952 if(strcasecmp(fmt, "fuma") == 0)
3954 device->mAmbiLayout = AmbiLayout::FuMa;
3955 device->mAmbiScale = AmbiNorm::FuMa;
3957 else if(strcasecmp(fmt, "acn+sn3d") == 0)
3959 device->mAmbiLayout = AmbiLayout::ACN;
3960 device->mAmbiScale = AmbiNorm::SN3D;
3962 else if(strcasecmp(fmt, "acn+n3d") == 0)
3964 device->mAmbiLayout = AmbiLayout::ACN;
3965 device->mAmbiScale = AmbiNorm::N3D;
3967 else
3968 ERR("Unsupported ambi-format: %s\n", fmt);
3972 ALCdevice *head{DeviceList.load()};
3973 do {
3974 device->next.store(head, std::memory_order_relaxed);
3975 } while(!DeviceList.compare_exchange_weak(head, device.get()));
3978 TRACE("Created device %p, \"%s\"\n", device.get(), device->DeviceName.c_str());
3979 return device.release();
3982 /* alcCloseDevice
3984 * Closes the given device.
3986 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3988 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3989 ALCdevice *iter{DeviceList.load()};
3990 do {
3991 if(iter == device)
3992 break;
3993 iter = iter->next.load(std::memory_order_relaxed);
3994 } while(iter != nullptr);
3995 if(!iter || iter->Type == Capture)
3997 alcSetError(iter, ALC_INVALID_DEVICE);
3998 return ALC_FALSE;
4000 std::unique_lock<almtx_t> backlock{device->BackendLock};
4002 ALCdevice *origdev{device};
4003 ALCdevice *nextdev{device->next.load(std::memory_order_relaxed)};
4004 if(!DeviceList.compare_exchange_strong(origdev, nextdev))
4006 ALCdevice *list;
4007 do {
4008 list = origdev;
4009 origdev = device;
4010 } while(!list->next.compare_exchange_strong(origdev, nextdev));
4012 listlock.unlock();
4014 ALCcontext *ctx{device->ContextList.load()};
4015 while(ctx != nullptr)
4017 ALCcontext *next = ctx->next.load(std::memory_order_relaxed);
4018 WARN("Releasing context %p\n", ctx);
4019 ReleaseContext(ctx, device);
4020 ctx = next;
4022 if((device->Flags&DEVICE_RUNNING))
4023 V0(device->Backend,stop)();
4024 device->Flags &= ~DEVICE_RUNNING;
4025 backlock.unlock();
4027 ALCdevice_DecRef(device);
4029 return ALC_TRUE;
4033 /************************************************
4034 * ALC capture functions
4035 ************************************************/
4036 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
4038 DO_INITCONFIG();
4040 if(!CaptureBackend.name)
4042 alcSetError(nullptr, ALC_INVALID_VALUE);
4043 return nullptr;
4046 if(samples <= 0)
4048 alcSetError(nullptr, ALC_INVALID_VALUE);
4049 return nullptr;
4052 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
4053 deviceName = nullptr;
4055 std::unique_ptr<ALCdevice> device{new ALCdevice{Capture}};
4057 device->Frequency = frequency;
4058 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4060 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
4062 device = nullptr;
4063 alcSetError(nullptr, ALC_INVALID_ENUM);
4064 return nullptr;
4066 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
4068 device->UpdateSize = samples;
4069 device->NumUpdates = 1;
4071 device->Backend = CaptureBackend.getFactory().createBackend(device.get(), ALCbackend_Capture);
4072 if(!device->Backend)
4074 device = nullptr;
4075 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
4076 return nullptr;
4079 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4080 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
4081 device->Frequency, device->UpdateSize, device->NumUpdates
4083 ALCenum err{V(device->Backend,open)(deviceName)};
4084 if(err != ALC_NO_ERROR)
4086 device = nullptr;
4087 alcSetError(nullptr, err);
4088 return nullptr;
4092 ALCdevice *head{DeviceList.load()};
4093 do {
4094 device->next.store(head, std::memory_order_relaxed);
4095 } while(!DeviceList.compare_exchange_weak(head, device.get()));
4098 TRACE("Created device %p, \"%s\"\n", device.get(), device->DeviceName.c_str());
4099 return device.release();
4102 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
4104 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4106 ALCdevice *iter{DeviceList.load()};
4107 do {
4108 if(iter == device)
4109 break;
4110 iter = iter->next.load(std::memory_order_relaxed);
4111 } while(iter != nullptr);
4112 if(!iter || iter->Type != Capture)
4114 alcSetError(iter, ALC_INVALID_DEVICE);
4115 return ALC_FALSE;
4118 ALCdevice *origdev{device};
4119 ALCdevice *nextdev{device->next.load(std::memory_order_relaxed)};
4120 if(!DeviceList.compare_exchange_strong(origdev, nextdev))
4122 ALCdevice *list;
4123 do {
4124 list = origdev;
4125 origdev = device;
4126 } while(!list->next.compare_exchange_strong(origdev, nextdev));
4128 listlock.unlock();
4130 { std::lock_guard<almtx_t> _{device->BackendLock};
4131 if((device->Flags&DEVICE_RUNNING))
4132 V0(device->Backend,stop)();
4133 device->Flags &= ~DEVICE_RUNNING;
4136 ALCdevice_DecRef(device);
4138 return ALC_TRUE;
4141 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
4143 DeviceRef dev{VerifyDevice(device)};
4144 if(!dev || dev->Type != Capture)
4146 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4147 return;
4150 std::lock_guard<almtx_t> _{dev->BackendLock};
4151 if(!dev->Connected.load(std::memory_order_acquire))
4152 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4153 else if(!(dev->Flags&DEVICE_RUNNING))
4155 if(V0(dev->Backend,start)())
4156 dev->Flags |= DEVICE_RUNNING;
4157 else
4159 aluHandleDisconnect(dev.get(), "Device start failure");
4160 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4165 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
4167 DeviceRef dev{VerifyDevice(device)};
4168 if(!dev || dev->Type != Capture)
4169 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4170 else
4172 std::lock_guard<almtx_t> _{dev->BackendLock};
4173 if((dev->Flags&DEVICE_RUNNING))
4174 V0(dev->Backend,stop)();
4175 dev->Flags &= ~DEVICE_RUNNING;
4179 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4181 DeviceRef dev{VerifyDevice(device)};
4182 if(!dev || dev->Type != Capture)
4184 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4185 return;
4188 ALCenum err{ALC_INVALID_VALUE};
4189 { std::lock_guard<almtx_t> _{dev->BackendLock};
4190 if(samples >= 0 && V0(dev->Backend,availableSamples)() >= (ALCuint)samples)
4191 err = V(dev->Backend,captureSamples)(buffer, samples);
4193 if(err != ALC_NO_ERROR)
4194 alcSetError(dev.get(), err);
4198 /************************************************
4199 * ALC loopback functions
4200 ************************************************/
4202 /* alcLoopbackOpenDeviceSOFT
4204 * Open a loopback device, for manual rendering.
4206 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
4208 DO_INITCONFIG();
4210 /* Make sure the device name, if specified, is us. */
4211 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
4213 alcSetError(nullptr, ALC_INVALID_VALUE);
4214 return nullptr;
4217 std::unique_ptr<ALCdevice> device{new ALCdevice{Loopback}};
4219 device->SourcesMax = 256;
4220 device->AuxiliaryEffectSlotMax = 64;
4221 device->NumAuxSends = DEFAULT_SENDS;
4223 //Set output format
4224 device->NumUpdates = 0;
4225 device->UpdateSize = 0;
4227 device->Frequency = DEFAULT_OUTPUT_RATE;
4228 device->FmtChans = DevFmtChannelsDefault;
4229 device->FmtType = DevFmtTypeDefault;
4231 ConfigValueUInt(nullptr, nullptr, "sources", &device->SourcesMax);
4232 if(device->SourcesMax == 0) device->SourcesMax = 256;
4234 ConfigValueUInt(nullptr, nullptr, "slots", &device->AuxiliaryEffectSlotMax);
4235 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4236 else device->AuxiliaryEffectSlotMax = minu(device->AuxiliaryEffectSlotMax, INT_MAX);
4238 if(ConfigValueInt(nullptr, nullptr, "sends", &device->NumAuxSends))
4239 device->NumAuxSends = clampi(
4240 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4243 device->NumStereoSources = 1;
4244 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4246 device->Backend = LoopbackBackendFactory::getFactory().createBackend(
4247 device.get(), ALCbackend_Loopback);
4248 if(!device->Backend)
4250 device = nullptr;
4251 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
4252 return nullptr;
4255 // Open the "backend"
4256 V(device->Backend,open)("Loopback");
4259 ALCdevice *head{DeviceList.load()};
4260 do {
4261 device->next.store(head, std::memory_order_relaxed);
4262 } while(!DeviceList.compare_exchange_weak(head, device.get()));
4265 TRACE("Created device %p\n", device.get());
4266 return device.release();
4269 /* alcIsRenderFormatSupportedSOFT
4271 * Determines if the loopback device supports the given format for rendering.
4273 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4275 DeviceRef dev{VerifyDevice(device)};
4276 if(!dev || dev->Type != Loopback)
4277 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4278 else if(freq <= 0)
4279 alcSetError(dev.get(), ALC_INVALID_VALUE);
4280 else
4282 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4283 return ALC_TRUE;
4286 return ALC_FALSE;
4289 /* alcRenderSamplesSOFT
4291 * Renders some samples into a buffer, using the format last set by the
4292 * attributes given to alcCreateContext.
4294 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4296 DeviceRef dev{VerifyDevice(device)};
4297 if(!dev || dev->Type != Loopback)
4298 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4299 else if(samples < 0 || (samples > 0 && buffer == nullptr))
4300 alcSetError(dev.get(), ALC_INVALID_VALUE);
4301 else
4303 V0(dev->Backend,lock)();
4304 aluMixData(dev.get(), buffer, samples);
4305 V0(dev->Backend,unlock)();
4310 /************************************************
4311 * ALC DSP pause/resume functions
4312 ************************************************/
4314 /* alcDevicePauseSOFT
4316 * Pause the DSP to stop audio processing.
4318 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4320 DeviceRef dev{VerifyDevice(device)};
4321 if(!dev || dev->Type != Playback)
4322 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4323 else
4325 std::lock_guard<almtx_t> _{dev->BackendLock};
4326 if((dev->Flags&DEVICE_RUNNING))
4327 V0(dev->Backend,stop)();
4328 dev->Flags &= ~DEVICE_RUNNING;
4329 dev->Flags |= DEVICE_PAUSED;
4333 /* alcDeviceResumeSOFT
4335 * Resume the DSP to restart audio processing.
4337 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4339 DeviceRef dev{VerifyDevice(device)};
4340 if(!dev || dev->Type != Playback)
4341 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4342 else
4344 std::lock_guard<almtx_t> _{dev->BackendLock};
4345 if((dev->Flags&DEVICE_PAUSED))
4347 dev->Flags &= ~DEVICE_PAUSED;
4348 if(dev->ContextList.load() != nullptr)
4350 if(V0(dev->Backend,start)() != ALC_FALSE)
4351 dev->Flags |= DEVICE_RUNNING;
4352 else
4354 V0(dev->Backend,lock)();
4355 aluHandleDisconnect(dev.get(), "Device start failure");
4356 V0(dev->Backend,unlock)();
4357 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4365 /************************************************
4366 * ALC HRTF functions
4367 ************************************************/
4369 /* alcGetStringiSOFT
4371 * Gets a string parameter at the given index.
4373 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4375 DeviceRef dev{VerifyDevice(device)};
4376 if(!dev || dev->Type == Capture)
4377 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4378 else switch(paramName)
4380 case ALC_HRTF_SPECIFIER_SOFT:
4381 if(index >= 0 && (size_t)index < dev->HrtfList.size())
4382 return dev->HrtfList[index].name.c_str();
4383 alcSetError(dev.get(), ALC_INVALID_VALUE);
4384 break;
4386 default:
4387 alcSetError(dev.get(), ALC_INVALID_ENUM);
4388 break;
4391 return nullptr;
4394 /* alcResetDeviceSOFT
4396 * Resets the given device output, using the specified attribute list.
4398 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4400 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4401 DeviceRef dev{VerifyDevice(device)};
4402 if(!dev || dev->Type == Capture || !dev->Connected.load(std::memory_order_relaxed))
4404 listlock.unlock();
4405 alcSetError(dev.get(), ALC_INVALID_DEVICE);
4406 return ALC_FALSE;
4408 std::unique_lock<almtx_t> backlock{dev->BackendLock};
4409 listlock.unlock();
4411 ALCenum err{UpdateDeviceParams(dev.get(), attribs)};
4412 backlock.unlock();
4414 if(err != ALC_NO_ERROR)
4416 alcSetError(dev.get(), err);
4417 if(err == ALC_INVALID_DEVICE)
4419 V0(dev->Backend,lock)();
4420 aluHandleDisconnect(dev.get(), "Device start failure");
4421 V0(dev->Backend,unlock)();
4423 return ALC_FALSE;
4426 return ALC_TRUE;