Start a new backend factory API
[openal-soft.git] / Alc / alc.cpp
blob04300d8ae488544ff4316c73851b72d65a5c3261
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>
38 #include "alMain.h"
39 #include "alSource.h"
40 #include "alListener.h"
41 #include "alSource.h"
42 #include "alBuffer.h"
43 #include "alFilter.h"
44 #include "alEffect.h"
45 #include "alAuxEffectSlot.h"
46 #include "alError.h"
47 #include "mastering.h"
48 #include "bformatdec.h"
49 #include "alu.h"
50 #include "alconfig.h"
51 #include "ringbuffer.h"
53 #include "fpu_modes.h"
54 #include "cpu_caps.h"
55 #include "compat.h"
56 #include "threads.h"
57 #include "almalloc.h"
59 #include "backends/base.h"
60 #include "backends/null.h"
63 namespace {
65 /************************************************
66 * Backends
67 ************************************************/
68 struct BackendInfo {
69 const char *name;
70 BackendFactory& (*getFactory)(void);
73 struct BackendInfo BackendList[] = {
74 #if 0
75 #ifdef HAVE_JACK
76 { "jack", ALCjackBackendFactory_getFactory },
77 #endif
78 #ifdef HAVE_PULSEAUDIO
79 { "pulse", ALCpulseBackendFactory_getFactory },
80 #endif
81 #ifdef HAVE_ALSA
82 { "alsa", ALCalsaBackendFactory_getFactory },
83 #endif
84 #ifdef HAVE_COREAUDIO
85 { "core", ALCcoreAudioBackendFactory_getFactory },
86 #endif
87 #ifdef HAVE_SOLARIS
88 { "solaris", ALCsolarisBackendFactory_getFactory },
89 #endif
90 #ifdef HAVE_SNDIO
91 { "sndio", SndioBackendFactory_getFactory },
92 #endif
93 #ifdef HAVE_OSS
94 { "oss", ALCossBackendFactory_getFactory },
95 #endif
96 #ifdef HAVE_QSA
97 { "qsa", ALCqsaBackendFactory_getFactory },
98 #endif
99 #ifdef HAVE_WASAPI
100 { "wasapi", ALCwasapiBackendFactory_getFactory },
101 #endif
102 #ifdef HAVE_DSOUND
103 { "dsound", ALCdsoundBackendFactory_getFactory },
104 #endif
105 #ifdef HAVE_WINMM
106 { "winmm", ALCwinmmBackendFactory_getFactory },
107 #endif
108 #ifdef HAVE_PORTAUDIO
109 { "port", ALCportBackendFactory_getFactory },
110 #endif
111 #ifdef HAVE_OPENSL
112 { "opensl", ALCopenslBackendFactory_getFactory },
113 #endif
114 #ifdef HAVE_SDL2
115 { "sdl2", ALCsdl2BackendFactory_getFactory },
116 #endif
118 { "null", ALCnullBackendFactory_getFactory },
119 #ifdef HAVE_WAVE
120 { "wave", ALCwaveBackendFactory_getFactory },
121 #endif
122 #endif /* 0 */
123 { "null", NullBackendFactory::getFactory },
125 ALsizei BackendListSize = COUNTOF(BackendList);
126 #undef EmptyFuncs
128 struct BackendInfo PlaybackBackend;
129 struct BackendInfo CaptureBackend;
132 /************************************************
133 * Functions, enums, and errors
134 ************************************************/
135 #define DECL(x) { #x, (ALCvoid*)(x) }
136 constexpr struct {
137 const ALCchar *funcName;
138 ALCvoid *address;
139 } alcFunctions[] = {
140 DECL(alcCreateContext),
141 DECL(alcMakeContextCurrent),
142 DECL(alcProcessContext),
143 DECL(alcSuspendContext),
144 DECL(alcDestroyContext),
145 DECL(alcGetCurrentContext),
146 DECL(alcGetContextsDevice),
147 DECL(alcOpenDevice),
148 DECL(alcCloseDevice),
149 DECL(alcGetError),
150 DECL(alcIsExtensionPresent),
151 DECL(alcGetProcAddress),
152 DECL(alcGetEnumValue),
153 DECL(alcGetString),
154 DECL(alcGetIntegerv),
155 DECL(alcCaptureOpenDevice),
156 DECL(alcCaptureCloseDevice),
157 DECL(alcCaptureStart),
158 DECL(alcCaptureStop),
159 DECL(alcCaptureSamples),
161 DECL(alcSetThreadContext),
162 DECL(alcGetThreadContext),
164 DECL(alcLoopbackOpenDeviceSOFT),
165 DECL(alcIsRenderFormatSupportedSOFT),
166 DECL(alcRenderSamplesSOFT),
168 DECL(alcDevicePauseSOFT),
169 DECL(alcDeviceResumeSOFT),
171 DECL(alcGetStringiSOFT),
172 DECL(alcResetDeviceSOFT),
174 DECL(alcGetInteger64vSOFT),
176 DECL(alEnable),
177 DECL(alDisable),
178 DECL(alIsEnabled),
179 DECL(alGetString),
180 DECL(alGetBooleanv),
181 DECL(alGetIntegerv),
182 DECL(alGetFloatv),
183 DECL(alGetDoublev),
184 DECL(alGetBoolean),
185 DECL(alGetInteger),
186 DECL(alGetFloat),
187 DECL(alGetDouble),
188 DECL(alGetError),
189 DECL(alIsExtensionPresent),
190 DECL(alGetProcAddress),
191 DECL(alGetEnumValue),
192 DECL(alListenerf),
193 DECL(alListener3f),
194 DECL(alListenerfv),
195 DECL(alListeneri),
196 DECL(alListener3i),
197 DECL(alListeneriv),
198 DECL(alGetListenerf),
199 DECL(alGetListener3f),
200 DECL(alGetListenerfv),
201 DECL(alGetListeneri),
202 DECL(alGetListener3i),
203 DECL(alGetListeneriv),
204 DECL(alGenSources),
205 DECL(alDeleteSources),
206 DECL(alIsSource),
207 DECL(alSourcef),
208 DECL(alSource3f),
209 DECL(alSourcefv),
210 DECL(alSourcei),
211 DECL(alSource3i),
212 DECL(alSourceiv),
213 DECL(alGetSourcef),
214 DECL(alGetSource3f),
215 DECL(alGetSourcefv),
216 DECL(alGetSourcei),
217 DECL(alGetSource3i),
218 DECL(alGetSourceiv),
219 DECL(alSourcePlayv),
220 DECL(alSourceStopv),
221 DECL(alSourceRewindv),
222 DECL(alSourcePausev),
223 DECL(alSourcePlay),
224 DECL(alSourceStop),
225 DECL(alSourceRewind),
226 DECL(alSourcePause),
227 DECL(alSourceQueueBuffers),
228 DECL(alSourceUnqueueBuffers),
229 DECL(alGenBuffers),
230 DECL(alDeleteBuffers),
231 DECL(alIsBuffer),
232 DECL(alBufferData),
233 DECL(alBufferf),
234 DECL(alBuffer3f),
235 DECL(alBufferfv),
236 DECL(alBufferi),
237 DECL(alBuffer3i),
238 DECL(alBufferiv),
239 DECL(alGetBufferf),
240 DECL(alGetBuffer3f),
241 DECL(alGetBufferfv),
242 DECL(alGetBufferi),
243 DECL(alGetBuffer3i),
244 DECL(alGetBufferiv),
245 DECL(alDopplerFactor),
246 DECL(alDopplerVelocity),
247 DECL(alSpeedOfSound),
248 DECL(alDistanceModel),
250 DECL(alGenFilters),
251 DECL(alDeleteFilters),
252 DECL(alIsFilter),
253 DECL(alFilteri),
254 DECL(alFilteriv),
255 DECL(alFilterf),
256 DECL(alFilterfv),
257 DECL(alGetFilteri),
258 DECL(alGetFilteriv),
259 DECL(alGetFilterf),
260 DECL(alGetFilterfv),
261 DECL(alGenEffects),
262 DECL(alDeleteEffects),
263 DECL(alIsEffect),
264 DECL(alEffecti),
265 DECL(alEffectiv),
266 DECL(alEffectf),
267 DECL(alEffectfv),
268 DECL(alGetEffecti),
269 DECL(alGetEffectiv),
270 DECL(alGetEffectf),
271 DECL(alGetEffectfv),
272 DECL(alGenAuxiliaryEffectSlots),
273 DECL(alDeleteAuxiliaryEffectSlots),
274 DECL(alIsAuxiliaryEffectSlot),
275 DECL(alAuxiliaryEffectSloti),
276 DECL(alAuxiliaryEffectSlotiv),
277 DECL(alAuxiliaryEffectSlotf),
278 DECL(alAuxiliaryEffectSlotfv),
279 DECL(alGetAuxiliaryEffectSloti),
280 DECL(alGetAuxiliaryEffectSlotiv),
281 DECL(alGetAuxiliaryEffectSlotf),
282 DECL(alGetAuxiliaryEffectSlotfv),
284 DECL(alDeferUpdatesSOFT),
285 DECL(alProcessUpdatesSOFT),
287 DECL(alSourcedSOFT),
288 DECL(alSource3dSOFT),
289 DECL(alSourcedvSOFT),
290 DECL(alGetSourcedSOFT),
291 DECL(alGetSource3dSOFT),
292 DECL(alGetSourcedvSOFT),
293 DECL(alSourcei64SOFT),
294 DECL(alSource3i64SOFT),
295 DECL(alSourcei64vSOFT),
296 DECL(alGetSourcei64SOFT),
297 DECL(alGetSource3i64SOFT),
298 DECL(alGetSourcei64vSOFT),
300 DECL(alGetStringiSOFT),
302 DECL(alBufferStorageSOFT),
303 DECL(alMapBufferSOFT),
304 DECL(alUnmapBufferSOFT),
305 DECL(alFlushMappedBufferSOFT),
307 DECL(alEventControlSOFT),
308 DECL(alEventCallbackSOFT),
309 DECL(alGetPointerSOFT),
310 DECL(alGetPointervSOFT),
312 #undef DECL
314 #define DECL(x) { #x, (x) }
315 constexpr struct {
316 const ALCchar *enumName;
317 ALCenum value;
318 } alcEnumerations[] = {
319 DECL(ALC_INVALID),
320 DECL(ALC_FALSE),
321 DECL(ALC_TRUE),
323 DECL(ALC_MAJOR_VERSION),
324 DECL(ALC_MINOR_VERSION),
325 DECL(ALC_ATTRIBUTES_SIZE),
326 DECL(ALC_ALL_ATTRIBUTES),
327 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
328 DECL(ALC_DEVICE_SPECIFIER),
329 DECL(ALC_ALL_DEVICES_SPECIFIER),
330 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
331 DECL(ALC_EXTENSIONS),
332 DECL(ALC_FREQUENCY),
333 DECL(ALC_REFRESH),
334 DECL(ALC_SYNC),
335 DECL(ALC_MONO_SOURCES),
336 DECL(ALC_STEREO_SOURCES),
337 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
338 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
339 DECL(ALC_CAPTURE_SAMPLES),
340 DECL(ALC_CONNECTED),
342 DECL(ALC_EFX_MAJOR_VERSION),
343 DECL(ALC_EFX_MINOR_VERSION),
344 DECL(ALC_MAX_AUXILIARY_SENDS),
346 DECL(ALC_FORMAT_CHANNELS_SOFT),
347 DECL(ALC_FORMAT_TYPE_SOFT),
349 DECL(ALC_MONO_SOFT),
350 DECL(ALC_STEREO_SOFT),
351 DECL(ALC_QUAD_SOFT),
352 DECL(ALC_5POINT1_SOFT),
353 DECL(ALC_6POINT1_SOFT),
354 DECL(ALC_7POINT1_SOFT),
355 DECL(ALC_BFORMAT3D_SOFT),
357 DECL(ALC_BYTE_SOFT),
358 DECL(ALC_UNSIGNED_BYTE_SOFT),
359 DECL(ALC_SHORT_SOFT),
360 DECL(ALC_UNSIGNED_SHORT_SOFT),
361 DECL(ALC_INT_SOFT),
362 DECL(ALC_UNSIGNED_INT_SOFT),
363 DECL(ALC_FLOAT_SOFT),
365 DECL(ALC_HRTF_SOFT),
366 DECL(ALC_DONT_CARE_SOFT),
367 DECL(ALC_HRTF_STATUS_SOFT),
368 DECL(ALC_HRTF_DISABLED_SOFT),
369 DECL(ALC_HRTF_ENABLED_SOFT),
370 DECL(ALC_HRTF_DENIED_SOFT),
371 DECL(ALC_HRTF_REQUIRED_SOFT),
372 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
373 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
374 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
375 DECL(ALC_HRTF_SPECIFIER_SOFT),
376 DECL(ALC_HRTF_ID_SOFT),
378 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
379 DECL(ALC_AMBISONIC_SCALING_SOFT),
380 DECL(ALC_AMBISONIC_ORDER_SOFT),
381 DECL(ALC_ACN_SOFT),
382 DECL(ALC_FUMA_SOFT),
383 DECL(ALC_N3D_SOFT),
384 DECL(ALC_SN3D_SOFT),
386 DECL(ALC_OUTPUT_LIMITER_SOFT),
388 DECL(ALC_NO_ERROR),
389 DECL(ALC_INVALID_DEVICE),
390 DECL(ALC_INVALID_CONTEXT),
391 DECL(ALC_INVALID_ENUM),
392 DECL(ALC_INVALID_VALUE),
393 DECL(ALC_OUT_OF_MEMORY),
396 DECL(AL_INVALID),
397 DECL(AL_NONE),
398 DECL(AL_FALSE),
399 DECL(AL_TRUE),
401 DECL(AL_SOURCE_RELATIVE),
402 DECL(AL_CONE_INNER_ANGLE),
403 DECL(AL_CONE_OUTER_ANGLE),
404 DECL(AL_PITCH),
405 DECL(AL_POSITION),
406 DECL(AL_DIRECTION),
407 DECL(AL_VELOCITY),
408 DECL(AL_LOOPING),
409 DECL(AL_BUFFER),
410 DECL(AL_GAIN),
411 DECL(AL_MIN_GAIN),
412 DECL(AL_MAX_GAIN),
413 DECL(AL_ORIENTATION),
414 DECL(AL_REFERENCE_DISTANCE),
415 DECL(AL_ROLLOFF_FACTOR),
416 DECL(AL_CONE_OUTER_GAIN),
417 DECL(AL_MAX_DISTANCE),
418 DECL(AL_SEC_OFFSET),
419 DECL(AL_SAMPLE_OFFSET),
420 DECL(AL_BYTE_OFFSET),
421 DECL(AL_SOURCE_TYPE),
422 DECL(AL_STATIC),
423 DECL(AL_STREAMING),
424 DECL(AL_UNDETERMINED),
425 DECL(AL_METERS_PER_UNIT),
426 DECL(AL_LOOP_POINTS_SOFT),
427 DECL(AL_DIRECT_CHANNELS_SOFT),
429 DECL(AL_DIRECT_FILTER),
430 DECL(AL_AUXILIARY_SEND_FILTER),
431 DECL(AL_AIR_ABSORPTION_FACTOR),
432 DECL(AL_ROOM_ROLLOFF_FACTOR),
433 DECL(AL_CONE_OUTER_GAINHF),
434 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
435 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
436 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
438 DECL(AL_SOURCE_STATE),
439 DECL(AL_INITIAL),
440 DECL(AL_PLAYING),
441 DECL(AL_PAUSED),
442 DECL(AL_STOPPED),
444 DECL(AL_BUFFERS_QUEUED),
445 DECL(AL_BUFFERS_PROCESSED),
447 DECL(AL_FORMAT_MONO8),
448 DECL(AL_FORMAT_MONO16),
449 DECL(AL_FORMAT_MONO_FLOAT32),
450 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
451 DECL(AL_FORMAT_STEREO8),
452 DECL(AL_FORMAT_STEREO16),
453 DECL(AL_FORMAT_STEREO_FLOAT32),
454 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
455 DECL(AL_FORMAT_MONO_IMA4),
456 DECL(AL_FORMAT_STEREO_IMA4),
457 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
458 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
459 DECL(AL_FORMAT_QUAD8_LOKI),
460 DECL(AL_FORMAT_QUAD16_LOKI),
461 DECL(AL_FORMAT_QUAD8),
462 DECL(AL_FORMAT_QUAD16),
463 DECL(AL_FORMAT_QUAD32),
464 DECL(AL_FORMAT_51CHN8),
465 DECL(AL_FORMAT_51CHN16),
466 DECL(AL_FORMAT_51CHN32),
467 DECL(AL_FORMAT_61CHN8),
468 DECL(AL_FORMAT_61CHN16),
469 DECL(AL_FORMAT_61CHN32),
470 DECL(AL_FORMAT_71CHN8),
471 DECL(AL_FORMAT_71CHN16),
472 DECL(AL_FORMAT_71CHN32),
473 DECL(AL_FORMAT_REAR8),
474 DECL(AL_FORMAT_REAR16),
475 DECL(AL_FORMAT_REAR32),
476 DECL(AL_FORMAT_MONO_MULAW),
477 DECL(AL_FORMAT_MONO_MULAW_EXT),
478 DECL(AL_FORMAT_STEREO_MULAW),
479 DECL(AL_FORMAT_STEREO_MULAW_EXT),
480 DECL(AL_FORMAT_QUAD_MULAW),
481 DECL(AL_FORMAT_51CHN_MULAW),
482 DECL(AL_FORMAT_61CHN_MULAW),
483 DECL(AL_FORMAT_71CHN_MULAW),
484 DECL(AL_FORMAT_REAR_MULAW),
485 DECL(AL_FORMAT_MONO_ALAW_EXT),
486 DECL(AL_FORMAT_STEREO_ALAW_EXT),
488 DECL(AL_FORMAT_BFORMAT2D_8),
489 DECL(AL_FORMAT_BFORMAT2D_16),
490 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
491 DECL(AL_FORMAT_BFORMAT2D_MULAW),
492 DECL(AL_FORMAT_BFORMAT3D_8),
493 DECL(AL_FORMAT_BFORMAT3D_16),
494 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
495 DECL(AL_FORMAT_BFORMAT3D_MULAW),
497 DECL(AL_FREQUENCY),
498 DECL(AL_BITS),
499 DECL(AL_CHANNELS),
500 DECL(AL_SIZE),
501 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
502 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
504 DECL(AL_SOURCE_RADIUS),
506 DECL(AL_STEREO_ANGLES),
508 DECL(AL_UNUSED),
509 DECL(AL_PENDING),
510 DECL(AL_PROCESSED),
512 DECL(AL_NO_ERROR),
513 DECL(AL_INVALID_NAME),
514 DECL(AL_INVALID_ENUM),
515 DECL(AL_INVALID_VALUE),
516 DECL(AL_INVALID_OPERATION),
517 DECL(AL_OUT_OF_MEMORY),
519 DECL(AL_VENDOR),
520 DECL(AL_VERSION),
521 DECL(AL_RENDERER),
522 DECL(AL_EXTENSIONS),
524 DECL(AL_DOPPLER_FACTOR),
525 DECL(AL_DOPPLER_VELOCITY),
526 DECL(AL_DISTANCE_MODEL),
527 DECL(AL_SPEED_OF_SOUND),
528 DECL(AL_SOURCE_DISTANCE_MODEL),
529 DECL(AL_DEFERRED_UPDATES_SOFT),
530 DECL(AL_GAIN_LIMIT_SOFT),
532 DECL(AL_INVERSE_DISTANCE),
533 DECL(AL_INVERSE_DISTANCE_CLAMPED),
534 DECL(AL_LINEAR_DISTANCE),
535 DECL(AL_LINEAR_DISTANCE_CLAMPED),
536 DECL(AL_EXPONENT_DISTANCE),
537 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
539 DECL(AL_FILTER_TYPE),
540 DECL(AL_FILTER_NULL),
541 DECL(AL_FILTER_LOWPASS),
542 DECL(AL_FILTER_HIGHPASS),
543 DECL(AL_FILTER_BANDPASS),
545 DECL(AL_LOWPASS_GAIN),
546 DECL(AL_LOWPASS_GAINHF),
548 DECL(AL_HIGHPASS_GAIN),
549 DECL(AL_HIGHPASS_GAINLF),
551 DECL(AL_BANDPASS_GAIN),
552 DECL(AL_BANDPASS_GAINHF),
553 DECL(AL_BANDPASS_GAINLF),
555 DECL(AL_EFFECT_TYPE),
556 DECL(AL_EFFECT_NULL),
557 DECL(AL_EFFECT_REVERB),
558 DECL(AL_EFFECT_EAXREVERB),
559 DECL(AL_EFFECT_CHORUS),
560 DECL(AL_EFFECT_DISTORTION),
561 DECL(AL_EFFECT_ECHO),
562 DECL(AL_EFFECT_FLANGER),
563 DECL(AL_EFFECT_PITCH_SHIFTER),
564 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
565 #if 0
566 DECL(AL_EFFECT_VOCAL_MORPHER),
567 #endif
568 DECL(AL_EFFECT_RING_MODULATOR),
569 DECL(AL_EFFECT_AUTOWAH),
570 DECL(AL_EFFECT_COMPRESSOR),
571 DECL(AL_EFFECT_EQUALIZER),
572 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
573 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
575 DECL(AL_EFFECTSLOT_EFFECT),
576 DECL(AL_EFFECTSLOT_GAIN),
577 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
578 DECL(AL_EFFECTSLOT_NULL),
580 DECL(AL_EAXREVERB_DENSITY),
581 DECL(AL_EAXREVERB_DIFFUSION),
582 DECL(AL_EAXREVERB_GAIN),
583 DECL(AL_EAXREVERB_GAINHF),
584 DECL(AL_EAXREVERB_GAINLF),
585 DECL(AL_EAXREVERB_DECAY_TIME),
586 DECL(AL_EAXREVERB_DECAY_HFRATIO),
587 DECL(AL_EAXREVERB_DECAY_LFRATIO),
588 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
589 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
590 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
591 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
592 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
593 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
594 DECL(AL_EAXREVERB_ECHO_TIME),
595 DECL(AL_EAXREVERB_ECHO_DEPTH),
596 DECL(AL_EAXREVERB_MODULATION_TIME),
597 DECL(AL_EAXREVERB_MODULATION_DEPTH),
598 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
599 DECL(AL_EAXREVERB_HFREFERENCE),
600 DECL(AL_EAXREVERB_LFREFERENCE),
601 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
602 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
604 DECL(AL_REVERB_DENSITY),
605 DECL(AL_REVERB_DIFFUSION),
606 DECL(AL_REVERB_GAIN),
607 DECL(AL_REVERB_GAINHF),
608 DECL(AL_REVERB_DECAY_TIME),
609 DECL(AL_REVERB_DECAY_HFRATIO),
610 DECL(AL_REVERB_REFLECTIONS_GAIN),
611 DECL(AL_REVERB_REFLECTIONS_DELAY),
612 DECL(AL_REVERB_LATE_REVERB_GAIN),
613 DECL(AL_REVERB_LATE_REVERB_DELAY),
614 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
615 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
616 DECL(AL_REVERB_DECAY_HFLIMIT),
618 DECL(AL_CHORUS_WAVEFORM),
619 DECL(AL_CHORUS_PHASE),
620 DECL(AL_CHORUS_RATE),
621 DECL(AL_CHORUS_DEPTH),
622 DECL(AL_CHORUS_FEEDBACK),
623 DECL(AL_CHORUS_DELAY),
625 DECL(AL_DISTORTION_EDGE),
626 DECL(AL_DISTORTION_GAIN),
627 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
628 DECL(AL_DISTORTION_EQCENTER),
629 DECL(AL_DISTORTION_EQBANDWIDTH),
631 DECL(AL_ECHO_DELAY),
632 DECL(AL_ECHO_LRDELAY),
633 DECL(AL_ECHO_DAMPING),
634 DECL(AL_ECHO_FEEDBACK),
635 DECL(AL_ECHO_SPREAD),
637 DECL(AL_FLANGER_WAVEFORM),
638 DECL(AL_FLANGER_PHASE),
639 DECL(AL_FLANGER_RATE),
640 DECL(AL_FLANGER_DEPTH),
641 DECL(AL_FLANGER_FEEDBACK),
642 DECL(AL_FLANGER_DELAY),
644 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY),
645 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION),
646 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION),
648 DECL(AL_RING_MODULATOR_FREQUENCY),
649 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
650 DECL(AL_RING_MODULATOR_WAVEFORM),
652 DECL(AL_PITCH_SHIFTER_COARSE_TUNE),
653 DECL(AL_PITCH_SHIFTER_FINE_TUNE),
655 DECL(AL_COMPRESSOR_ONOFF),
657 DECL(AL_EQUALIZER_LOW_GAIN),
658 DECL(AL_EQUALIZER_LOW_CUTOFF),
659 DECL(AL_EQUALIZER_MID1_GAIN),
660 DECL(AL_EQUALIZER_MID1_CENTER),
661 DECL(AL_EQUALIZER_MID1_WIDTH),
662 DECL(AL_EQUALIZER_MID2_GAIN),
663 DECL(AL_EQUALIZER_MID2_CENTER),
664 DECL(AL_EQUALIZER_MID2_WIDTH),
665 DECL(AL_EQUALIZER_HIGH_GAIN),
666 DECL(AL_EQUALIZER_HIGH_CUTOFF),
668 DECL(AL_DEDICATED_GAIN),
670 DECL(AL_AUTOWAH_ATTACK_TIME),
671 DECL(AL_AUTOWAH_RELEASE_TIME),
672 DECL(AL_AUTOWAH_RESONANCE),
673 DECL(AL_AUTOWAH_PEAK_GAIN),
675 DECL(AL_NUM_RESAMPLERS_SOFT),
676 DECL(AL_DEFAULT_RESAMPLER_SOFT),
677 DECL(AL_SOURCE_RESAMPLER_SOFT),
678 DECL(AL_RESAMPLER_NAME_SOFT),
680 DECL(AL_SOURCE_SPATIALIZE_SOFT),
681 DECL(AL_AUTO_SOFT),
683 DECL(AL_MAP_READ_BIT_SOFT),
684 DECL(AL_MAP_WRITE_BIT_SOFT),
685 DECL(AL_MAP_PERSISTENT_BIT_SOFT),
686 DECL(AL_PRESERVE_DATA_BIT_SOFT),
688 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT),
689 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT),
690 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT),
691 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT),
692 DECL(AL_EVENT_TYPE_ERROR_SOFT),
693 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT),
694 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT),
696 #undef DECL
698 constexpr ALCchar alcNoError[] = "No Error";
699 constexpr ALCchar alcErrInvalidDevice[] = "Invalid Device";
700 constexpr ALCchar alcErrInvalidContext[] = "Invalid Context";
701 constexpr ALCchar alcErrInvalidEnum[] = "Invalid Enum";
702 constexpr ALCchar alcErrInvalidValue[] = "Invalid Value";
703 constexpr ALCchar alcErrOutOfMemory[] = "Out of Memory";
706 /************************************************
707 * Global variables
708 ************************************************/
710 /* Enumerated device names */
711 constexpr ALCchar alcDefaultName[] = "OpenAL Soft\0";
713 std::string alcAllDevicesList;
714 std::string alcCaptureDeviceList;
716 /* Default is always the first in the list */
717 std::string alcDefaultAllDevicesSpecifier;
718 std::string alcCaptureDefaultDeviceSpecifier;
720 /* Default context extensions */
721 constexpr ALchar alExtList[] =
722 "AL_EXT_ALAW "
723 "AL_EXT_BFORMAT "
724 "AL_EXT_DOUBLE "
725 "AL_EXT_EXPONENT_DISTANCE "
726 "AL_EXT_FLOAT32 "
727 "AL_EXT_IMA4 "
728 "AL_EXT_LINEAR_DISTANCE "
729 "AL_EXT_MCFORMATS "
730 "AL_EXT_MULAW "
731 "AL_EXT_MULAW_BFORMAT "
732 "AL_EXT_MULAW_MCFORMATS "
733 "AL_EXT_OFFSET "
734 "AL_EXT_source_distance_model "
735 "AL_EXT_SOURCE_RADIUS "
736 "AL_EXT_STEREO_ANGLES "
737 "AL_LOKI_quadriphonic "
738 "AL_SOFT_block_alignment "
739 "AL_SOFT_deferred_updates "
740 "AL_SOFT_direct_channels "
741 "AL_SOFTX_events "
742 "AL_SOFTX_filter_gain_ex "
743 "AL_SOFT_gain_clamp_ex "
744 "AL_SOFT_loop_points "
745 "AL_SOFTX_map_buffer "
746 "AL_SOFT_MSADPCM "
747 "AL_SOFT_source_latency "
748 "AL_SOFT_source_length "
749 "AL_SOFT_source_resampler "
750 "AL_SOFT_source_spatialize";
752 std::atomic<ALCenum> LastNullDeviceError{ALC_NO_ERROR};
754 /* Thread-local current context */
755 altss_t LocalContext;
756 /* Process-wide current context */
757 std::atomic<ALCcontext*> GlobalContext{nullptr};
759 /* Flag to trap ALC device errors */
760 bool TrapALCError{false};
762 /* One-time configuration init control */
763 std::once_flag alc_config_once{};
765 /* Default effect that applies to sources that don't have an effect on send 0 */
766 ALeffect DefaultEffect;
768 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
769 * updates.
771 bool SuspendDefers{true};
774 /************************************************
775 * ALC information
776 ************************************************/
777 constexpr ALCchar alcNoDeviceExtList[] =
778 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
779 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
780 constexpr ALCchar alcExtensionList[] =
781 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
782 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
783 "ALC_EXT_thread_local_context ALC_SOFT_device_clock ALC_SOFT_HRTF "
784 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
785 constexpr ALCint alcMajorVersion = 1;
786 constexpr ALCint alcMinorVersion = 1;
788 constexpr ALCint alcEFXMajorVersion = 1;
789 constexpr ALCint alcEFXMinorVersion = 0;
792 /************************************************
793 * Device lists
794 ************************************************/
795 std::atomic<ALCdevice*> DeviceList{nullptr};
797 std::recursive_mutex ListLock;
799 } // namespace
801 /* Mixing thread piority level */
802 ALint RTPrioLevel;
804 FILE *LogFile;
805 #ifdef _DEBUG
806 enum LogLevel LogLevel = LogWarning;
807 #else
808 enum LogLevel LogLevel = LogError;
809 #endif
811 /************************************************
812 * Library initialization
813 ************************************************/
814 #if defined(_WIN32)
815 static void alc_init(void);
816 static void alc_deinit(void);
817 static void alc_deinit_safe(void);
819 #ifndef AL_LIBTYPE_STATIC
820 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
822 switch(reason)
824 case DLL_PROCESS_ATTACH:
825 /* Pin the DLL so we won't get unloaded until the process terminates */
826 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
827 (WCHAR*)hModule, &hModule);
828 alc_init();
829 break;
831 case DLL_THREAD_DETACH:
832 althrd_thread_detach();
833 break;
835 case DLL_PROCESS_DETACH:
836 if(!lpReserved)
837 alc_deinit();
838 else
839 alc_deinit_safe();
840 break;
842 return TRUE;
844 #elif defined(_MSC_VER)
845 #pragma section(".CRT$XCU",read)
846 static void alc_constructor(void);
847 static void alc_destructor(void);
848 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
850 static void alc_constructor(void)
852 atexit(alc_destructor);
853 alc_init();
856 static void alc_destructor(void)
858 alc_deinit();
860 #elif defined(HAVE_GCC_DESTRUCTOR)
861 static void alc_init(void) __attribute__((constructor));
862 static void alc_deinit(void) __attribute__((destructor));
863 #else
864 #error "No static initialization available on this platform!"
865 #endif
867 #elif defined(HAVE_GCC_DESTRUCTOR)
869 static void alc_init(void) __attribute__((constructor));
870 static void alc_deinit(void) __attribute__((destructor));
872 #else
873 #error "No global initialization available on this platform!"
874 #endif
876 static void ReleaseThreadCtx(void *ptr);
877 static void alc_init(void)
879 const char *str;
880 int ret;
882 LogFile = stderr;
884 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
885 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
886 ConeScale *= 0.5f;
888 str = getenv("__ALSOFT_REVERSE_Z");
889 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
890 ZScale *= -1.0f;
892 str = getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
893 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
894 OverrideReverbSpeedOfSound = AL_TRUE;
896 ret = altss_create(&LocalContext, ReleaseThreadCtx);
897 assert(ret == althrd_success);
900 static void alc_initconfig(void)
902 const char *devs, *str;
903 int capfilter;
904 float valf;
905 int i, n;
907 str = getenv("ALSOFT_LOGLEVEL");
908 if(str)
910 long lvl = strtol(str, nullptr, 0);
911 if(lvl >= NoLog && lvl <= LogRef)
912 LogLevel = static_cast<enum LogLevel>(lvl);
915 str = getenv("ALSOFT_LOGFILE");
916 if(str && str[0])
918 #ifdef _WIN32
919 std::wstring wname{utf8_to_wstr(str)};
920 FILE *logfile = _wfopen(wname.c_str(), L"wt");
921 #else
922 FILE *logfile = fopen(str, "wt");
923 #endif
924 if(logfile) LogFile = logfile;
925 else ERR("Failed to open log file '%s'\n", str);
928 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION,
929 ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH);
931 char buf[1024] = "";
932 int len = 0;
934 if(BackendListSize > 0)
935 len += snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
936 for(i = 1;i < BackendListSize;i++)
937 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
938 TRACE("Supported backends: %s\n", buf);
940 ReadALConfig();
942 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
943 if(str && *str)
945 if(strcasecmp(str, "ignore") == 0)
947 SuspendDefers = false;
948 TRACE("Selected context suspend behavior, \"ignore\"\n");
950 else
951 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
954 capfilter = 0;
955 #if defined(HAVE_SSE4_1)
956 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
957 #elif defined(HAVE_SSE3)
958 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
959 #elif defined(HAVE_SSE2)
960 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
961 #elif defined(HAVE_SSE)
962 capfilter |= CPU_CAP_SSE;
963 #endif
964 #ifdef HAVE_NEON
965 capfilter |= CPU_CAP_NEON;
966 #endif
967 if(ConfigValueStr(nullptr, nullptr, "disable-cpu-exts", &str))
969 if(strcasecmp(str, "all") == 0)
970 capfilter = 0;
971 else
973 size_t len;
974 const char *next = str;
976 do {
977 str = next;
978 while(isspace(str[0]))
979 str++;
980 next = strchr(str, ',');
982 if(!str[0] || str[0] == ',')
983 continue;
985 len = (next ? ((size_t)(next-str)) : strlen(str));
986 while(len > 0 && isspace(str[len-1]))
987 len--;
988 if(len == 3 && strncasecmp(str, "sse", len) == 0)
989 capfilter &= ~CPU_CAP_SSE;
990 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
991 capfilter &= ~CPU_CAP_SSE2;
992 else if(len == 4 && strncasecmp(str, "sse3", len) == 0)
993 capfilter &= ~CPU_CAP_SSE3;
994 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
995 capfilter &= ~CPU_CAP_SSE4_1;
996 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
997 capfilter &= ~CPU_CAP_NEON;
998 else
999 WARN("Invalid CPU extension \"%s\"\n", str);
1000 } while(next++);
1003 FillCPUCaps(capfilter);
1005 #ifdef _WIN32
1006 RTPrioLevel = 1;
1007 #else
1008 RTPrioLevel = 0;
1009 #endif
1010 ConfigValueInt(nullptr, nullptr, "rt-prio", &RTPrioLevel);
1012 aluInit();
1013 aluInitMixer();
1015 str = getenv("ALSOFT_TRAP_ERROR");
1016 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
1018 TrapALError = AL_TRUE;
1019 TrapALCError = true;
1021 else
1023 str = getenv("ALSOFT_TRAP_AL_ERROR");
1024 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
1025 TrapALError = AL_TRUE;
1026 TrapALError = GetConfigValueBool(nullptr, nullptr, "trap-al-error", TrapALError);
1028 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1029 if(str && (strcasecmp(str, "true") == 0 || strtol(str, nullptr, 0) == 1))
1030 TrapALCError = true;
1031 TrapALCError = !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", TrapALCError);
1034 if(ConfigValueFloat(nullptr, "reverb", "boost", &valf))
1035 ReverbBoost *= std::pow(10.0f, valf / 20.0f);
1037 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1038 ConfigValueStr(nullptr, nullptr, "drivers", &devs))
1040 int n;
1041 size_t len;
1042 const char *next = devs;
1043 int endlist, delitem;
1045 i = 0;
1046 do {
1047 devs = next;
1048 while(isspace(devs[0]))
1049 devs++;
1050 next = strchr(devs, ',');
1052 delitem = (devs[0] == '-');
1053 if(devs[0] == '-') devs++;
1055 if(!devs[0] || devs[0] == ',')
1057 endlist = 0;
1058 continue;
1060 endlist = 1;
1062 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1063 while(len > 0 && isspace(devs[len-1]))
1064 len--;
1065 #ifdef HAVE_WASAPI
1066 /* HACK: For backwards compatibility, convert backend references of
1067 * mmdevapi to wasapi. This should eventually be removed.
1069 if(len == 8 && strncmp(devs, "mmdevapi", len) == 0)
1071 devs = "wasapi";
1072 len = 6;
1074 #endif
1075 for(n = i;n < BackendListSize;n++)
1077 if(len == strlen(BackendList[n].name) &&
1078 strncmp(BackendList[n].name, devs, len) == 0)
1080 if(delitem)
1082 for(;n+1 < BackendListSize;n++)
1083 BackendList[n] = BackendList[n+1];
1084 BackendListSize--;
1086 else
1088 struct BackendInfo Bkp = BackendList[n];
1089 for(;n > i;n--)
1090 BackendList[n] = BackendList[n-1];
1091 BackendList[n] = Bkp;
1093 i++;
1095 break;
1098 } while(next++);
1100 if(endlist)
1101 BackendListSize = i;
1104 for(n = i = 0;i < BackendListSize && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1106 BackendList[n] = BackendList[i];
1108 BackendFactory &factory = BackendList[n].getFactory();
1109 if(!factory.init())
1111 WARN("Failed to initialize backend \"%s\"\n", BackendList[n].name);
1112 continue;
1115 TRACE("Initialized backend \"%s\"\n", BackendList[n].name);
1116 if(!PlaybackBackend.name && factory.querySupport(ALCbackend_Playback))
1118 PlaybackBackend = BackendList[n];
1119 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1121 if(!CaptureBackend.name && factory.querySupport(ALCbackend_Capture))
1123 CaptureBackend = BackendList[n];
1124 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1126 n++;
1128 BackendListSize = n;
1131 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1132 V0(factory,init)();
1135 if(!PlaybackBackend.name)
1136 WARN("No playback backend available!\n");
1137 if(!CaptureBackend.name)
1138 WARN("No capture backend available!\n");
1140 if(ConfigValueStr(nullptr, nullptr, "excludefx", &str))
1142 size_t len;
1143 const char *next = str;
1145 do {
1146 str = next;
1147 next = strchr(str, ',');
1149 if(!str[0] || next == str)
1150 continue;
1152 len = (next ? ((size_t)(next-str)) : strlen(str));
1153 for(n = 0;n < EFFECTLIST_SIZE;n++)
1155 if(len == strlen(EffectList[n].name) &&
1156 strncmp(EffectList[n].name, str, len) == 0)
1157 DisabledEffects[EffectList[n].type] = AL_TRUE;
1159 } while(next++);
1162 InitEffect(&DefaultEffect);
1163 str = getenv("ALSOFT_DEFAULT_REVERB");
1164 if((str && str[0]) || ConfigValueStr(nullptr, nullptr, "default-reverb", &str))
1165 LoadReverbPreset(str, &DefaultEffect);
1167 #define DO_INITCONFIG() std::call_once(alc_config_once, alc_initconfig)
1170 /************************************************
1171 * Library deinitialization
1172 ************************************************/
1173 static void alc_cleanup(void)
1175 alcAllDevicesList.clear();
1176 alcCaptureDeviceList.clear();
1178 alcDefaultAllDevicesSpecifier.clear();
1179 alcCaptureDefaultDeviceSpecifier.clear();
1181 if(ALCdevice *dev{DeviceList.exchange(nullptr)})
1183 ALCuint num = 0;
1184 do {
1185 num++;
1186 dev = ATOMIC_LOAD(&dev->next, almemory_order_relaxed);
1187 } while(dev != nullptr);
1188 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1192 static void alc_deinit_safe(void)
1194 alc_cleanup();
1196 FreeHrtfs();
1197 FreeALConfig();
1199 altss_delete(LocalContext);
1201 if(LogFile != stderr)
1202 fclose(LogFile);
1203 LogFile = nullptr;
1205 althrd_deinit();
1208 static void alc_deinit(void)
1210 int i;
1212 alc_cleanup();
1214 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1215 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1217 for(i = 0;i < BackendListSize;i++)
1218 BackendList[i].getFactory().deinit();
1221 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1222 V0(factory,deinit)();
1225 alc_deinit_safe();
1229 /************************************************
1230 * Device enumeration
1231 ************************************************/
1232 static void ProbeDevices(std::string *list, struct BackendInfo *backendinfo, enum DevProbe type)
1234 DO_INITCONFIG();
1236 std::lock_guard<std::recursive_mutex> _{ListLock};
1237 list->clear();
1238 if(backendinfo->getFactory)
1239 backendinfo->getFactory().probe(type, list);
1241 static void ProbeAllDevicesList(void)
1242 { ProbeDevices(&alcAllDevicesList, &PlaybackBackend, ALL_DEVICE_PROBE); }
1243 static void ProbeCaptureDeviceList(void)
1244 { ProbeDevices(&alcCaptureDeviceList, &CaptureBackend, CAPTURE_DEVICE_PROBE); }
1247 /************************************************
1248 * Device format information
1249 ************************************************/
1250 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1252 switch(type)
1254 case DevFmtByte: return "Signed Byte";
1255 case DevFmtUByte: return "Unsigned Byte";
1256 case DevFmtShort: return "Signed Short";
1257 case DevFmtUShort: return "Unsigned Short";
1258 case DevFmtInt: return "Signed Int";
1259 case DevFmtUInt: return "Unsigned Int";
1260 case DevFmtFloat: return "Float";
1262 return "(unknown type)";
1264 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1266 switch(chans)
1268 case DevFmtMono: return "Mono";
1269 case DevFmtStereo: return "Stereo";
1270 case DevFmtQuad: return "Quadraphonic";
1271 case DevFmtX51: return "5.1 Surround";
1272 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1273 case DevFmtX61: return "6.1 Surround";
1274 case DevFmtX71: return "7.1 Surround";
1275 case DevFmtAmbi3D: return "Ambisonic 3D";
1277 return "(unknown channels)";
1280 ALsizei BytesFromDevFmt(enum DevFmtType type)
1282 switch(type)
1284 case DevFmtByte: return sizeof(ALbyte);
1285 case DevFmtUByte: return sizeof(ALubyte);
1286 case DevFmtShort: return sizeof(ALshort);
1287 case DevFmtUShort: return sizeof(ALushort);
1288 case DevFmtInt: return sizeof(ALint);
1289 case DevFmtUInt: return sizeof(ALuint);
1290 case DevFmtFloat: return sizeof(ALfloat);
1292 return 0;
1294 ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans, ALsizei ambiorder)
1296 switch(chans)
1298 case DevFmtMono: return 1;
1299 case DevFmtStereo: return 2;
1300 case DevFmtQuad: return 4;
1301 case DevFmtX51: return 6;
1302 case DevFmtX51Rear: return 6;
1303 case DevFmtX61: return 7;
1304 case DevFmtX71: return 8;
1305 case DevFmtAmbi3D: return (ambiorder >= 3) ? 16 :
1306 (ambiorder == 2) ? 9 :
1307 (ambiorder == 1) ? 4 : 1;
1309 return 0;
1312 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1313 enum DevFmtType *type)
1315 static const struct {
1316 ALenum format;
1317 enum DevFmtChannels channels;
1318 enum DevFmtType type;
1319 } list[] = {
1320 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1321 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1322 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1324 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1325 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1326 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1328 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1329 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1330 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1332 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1333 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1334 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1336 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1337 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1338 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1340 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1341 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1342 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1344 ALuint i;
1346 for(i = 0;i < COUNTOF(list);i++)
1348 if(list[i].format == format)
1350 *chans = list[i].channels;
1351 *type = list[i].type;
1352 return AL_TRUE;
1356 return AL_FALSE;
1359 static ALCboolean IsValidALCType(ALCenum type)
1361 switch(type)
1363 case ALC_BYTE_SOFT:
1364 case ALC_UNSIGNED_BYTE_SOFT:
1365 case ALC_SHORT_SOFT:
1366 case ALC_UNSIGNED_SHORT_SOFT:
1367 case ALC_INT_SOFT:
1368 case ALC_UNSIGNED_INT_SOFT:
1369 case ALC_FLOAT_SOFT:
1370 return ALC_TRUE;
1372 return ALC_FALSE;
1375 static ALCboolean IsValidALCChannels(ALCenum channels)
1377 switch(channels)
1379 case ALC_MONO_SOFT:
1380 case ALC_STEREO_SOFT:
1381 case ALC_QUAD_SOFT:
1382 case ALC_5POINT1_SOFT:
1383 case ALC_6POINT1_SOFT:
1384 case ALC_7POINT1_SOFT:
1385 case ALC_BFORMAT3D_SOFT:
1386 return ALC_TRUE;
1388 return ALC_FALSE;
1391 static ALCboolean IsValidAmbiLayout(ALCenum layout)
1393 switch(layout)
1395 case ALC_ACN_SOFT:
1396 case ALC_FUMA_SOFT:
1397 return ALC_TRUE;
1399 return ALC_FALSE;
1402 static ALCboolean IsValidAmbiScaling(ALCenum scaling)
1404 switch(scaling)
1406 case ALC_N3D_SOFT:
1407 case ALC_SN3D_SOFT:
1408 case ALC_FUMA_SOFT:
1409 return ALC_TRUE;
1411 return ALC_FALSE;
1414 /************************************************
1415 * Miscellaneous ALC helpers
1416 ************************************************/
1418 /* SetDefaultWFXChannelOrder
1420 * Sets the default channel order used by WaveFormatEx.
1422 void SetDefaultWFXChannelOrder(ALCdevice *device)
1424 ALsizei i;
1426 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1427 device->RealOut.ChannelName[i] = InvalidChannel;
1429 switch(device->FmtChans)
1431 case DevFmtMono:
1432 device->RealOut.ChannelName[0] = FrontCenter;
1433 break;
1434 case DevFmtStereo:
1435 device->RealOut.ChannelName[0] = FrontLeft;
1436 device->RealOut.ChannelName[1] = FrontRight;
1437 break;
1438 case DevFmtQuad:
1439 device->RealOut.ChannelName[0] = FrontLeft;
1440 device->RealOut.ChannelName[1] = FrontRight;
1441 device->RealOut.ChannelName[2] = BackLeft;
1442 device->RealOut.ChannelName[3] = BackRight;
1443 break;
1444 case DevFmtX51:
1445 device->RealOut.ChannelName[0] = FrontLeft;
1446 device->RealOut.ChannelName[1] = FrontRight;
1447 device->RealOut.ChannelName[2] = FrontCenter;
1448 device->RealOut.ChannelName[3] = LFE;
1449 device->RealOut.ChannelName[4] = SideLeft;
1450 device->RealOut.ChannelName[5] = SideRight;
1451 break;
1452 case DevFmtX51Rear:
1453 device->RealOut.ChannelName[0] = FrontLeft;
1454 device->RealOut.ChannelName[1] = FrontRight;
1455 device->RealOut.ChannelName[2] = FrontCenter;
1456 device->RealOut.ChannelName[3] = LFE;
1457 device->RealOut.ChannelName[4] = BackLeft;
1458 device->RealOut.ChannelName[5] = BackRight;
1459 break;
1460 case DevFmtX61:
1461 device->RealOut.ChannelName[0] = FrontLeft;
1462 device->RealOut.ChannelName[1] = FrontRight;
1463 device->RealOut.ChannelName[2] = FrontCenter;
1464 device->RealOut.ChannelName[3] = LFE;
1465 device->RealOut.ChannelName[4] = BackCenter;
1466 device->RealOut.ChannelName[5] = SideLeft;
1467 device->RealOut.ChannelName[6] = SideRight;
1468 break;
1469 case DevFmtX71:
1470 device->RealOut.ChannelName[0] = FrontLeft;
1471 device->RealOut.ChannelName[1] = FrontRight;
1472 device->RealOut.ChannelName[2] = FrontCenter;
1473 device->RealOut.ChannelName[3] = LFE;
1474 device->RealOut.ChannelName[4] = BackLeft;
1475 device->RealOut.ChannelName[5] = BackRight;
1476 device->RealOut.ChannelName[6] = SideLeft;
1477 device->RealOut.ChannelName[7] = SideRight;
1478 break;
1479 case DevFmtAmbi3D:
1480 device->RealOut.ChannelName[0] = Aux0;
1481 if(device->AmbiOrder > 0)
1483 device->RealOut.ChannelName[1] = Aux1;
1484 device->RealOut.ChannelName[2] = Aux2;
1485 device->RealOut.ChannelName[3] = Aux3;
1487 if(device->AmbiOrder > 1)
1489 device->RealOut.ChannelName[4] = Aux4;
1490 device->RealOut.ChannelName[5] = Aux5;
1491 device->RealOut.ChannelName[6] = Aux6;
1492 device->RealOut.ChannelName[7] = Aux7;
1493 device->RealOut.ChannelName[8] = Aux8;
1495 if(device->AmbiOrder > 2)
1497 device->RealOut.ChannelName[9] = Aux9;
1498 device->RealOut.ChannelName[10] = Aux10;
1499 device->RealOut.ChannelName[11] = Aux11;
1500 device->RealOut.ChannelName[12] = Aux12;
1501 device->RealOut.ChannelName[13] = Aux13;
1502 device->RealOut.ChannelName[14] = Aux14;
1503 device->RealOut.ChannelName[15] = Aux15;
1505 break;
1509 /* SetDefaultChannelOrder
1511 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1513 void SetDefaultChannelOrder(ALCdevice *device)
1515 ALsizei i;
1517 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1518 device->RealOut.ChannelName[i] = InvalidChannel;
1520 switch(device->FmtChans)
1522 case DevFmtX51Rear:
1523 device->RealOut.ChannelName[0] = FrontLeft;
1524 device->RealOut.ChannelName[1] = FrontRight;
1525 device->RealOut.ChannelName[2] = BackLeft;
1526 device->RealOut.ChannelName[3] = BackRight;
1527 device->RealOut.ChannelName[4] = FrontCenter;
1528 device->RealOut.ChannelName[5] = LFE;
1529 return;
1530 case DevFmtX71:
1531 device->RealOut.ChannelName[0] = FrontLeft;
1532 device->RealOut.ChannelName[1] = FrontRight;
1533 device->RealOut.ChannelName[2] = BackLeft;
1534 device->RealOut.ChannelName[3] = BackRight;
1535 device->RealOut.ChannelName[4] = FrontCenter;
1536 device->RealOut.ChannelName[5] = LFE;
1537 device->RealOut.ChannelName[6] = SideLeft;
1538 device->RealOut.ChannelName[7] = SideRight;
1539 return;
1541 /* Same as WFX order */
1542 case DevFmtMono:
1543 case DevFmtStereo:
1544 case DevFmtQuad:
1545 case DevFmtX51:
1546 case DevFmtX61:
1547 case DevFmtAmbi3D:
1548 SetDefaultWFXChannelOrder(device);
1549 break;
1554 /* ALCcontext_DeferUpdates
1556 * Defers/suspends updates for the given context's listener and sources. This
1557 * does *NOT* stop mixing, but rather prevents certain property changes from
1558 * taking effect.
1560 void ALCcontext_DeferUpdates(ALCcontext *context)
1562 ATOMIC_STORE_SEQ(&context->DeferUpdates, AL_TRUE);
1565 /* ALCcontext_ProcessUpdates
1567 * Resumes update processing after being deferred.
1569 void ALCcontext_ProcessUpdates(ALCcontext *context)
1571 almtx_lock(&context->PropLock);
1572 if(ATOMIC_EXCHANGE_SEQ(&context->DeferUpdates, AL_FALSE))
1574 /* Tell the mixer to stop applying updates, then wait for any active
1575 * updating to finish, before providing updates.
1577 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_TRUE);
1578 while((ATOMIC_LOAD(&context->UpdateCount, almemory_order_acquire)&1) != 0)
1579 althrd_yield();
1581 if(!ATOMIC_EXCHANGE(&context->PropsClean, AL_TRUE, almemory_order_acq_rel))
1582 UpdateContextProps(context);
1583 if(!ATOMIC_EXCHANGE(&context->Listener->PropsClean, AL_TRUE, almemory_order_acq_rel))
1584 UpdateListenerProps(context);
1585 UpdateAllEffectSlotProps(context);
1586 UpdateAllSourceProps(context);
1588 /* Now with all updates declared, let the mixer continue applying them
1589 * so they all happen at once.
1591 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_FALSE);
1593 almtx_unlock(&context->PropLock);
1597 /* alcSetError
1599 * Stores the latest ALC device error
1601 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1603 WARN("Error generated on device %p, code 0x%04x\n", device, errorCode);
1604 if(TrapALCError)
1606 #ifdef _WIN32
1607 /* DebugBreak() will cause an exception if there is no debugger */
1608 if(IsDebuggerPresent())
1609 DebugBreak();
1610 #elif defined(SIGTRAP)
1611 raise(SIGTRAP);
1612 #endif
1615 if(device)
1616 ATOMIC_STORE_SEQ(&device->LastError, errorCode);
1617 else
1618 LastNullDeviceError.store(errorCode);
1622 static struct Compressor *CreateDeviceLimiter(const ALCdevice *device, const ALfloat threshold)
1624 return CompressorInit(device->RealOut.NumChannels, device->Frequency,
1625 AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, 0.001f, 0.002f,
1626 0.0f, 0.0f, threshold, INFINITY, 0.0f, 0.020f, 0.200f);
1629 /* UpdateClockBase
1631 * Updates the device's base clock time with however many samples have been
1632 * done. This is used so frequency changes on the device don't cause the time
1633 * to jump forward or back. Must not be called while the device is running/
1634 * mixing.
1636 static inline void UpdateClockBase(ALCdevice *device)
1638 IncrementRef(&device->MixCount);
1639 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1640 device->SamplesDone = 0;
1641 IncrementRef(&device->MixCount);
1644 /* UpdateDeviceParams
1646 * Updates device parameters according to the attribute list (caller is
1647 * responsible for holding the list lock).
1649 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1651 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1652 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1653 ALCenum gainLimiter = device->LimiterState;
1654 const ALsizei old_sends = device->NumAuxSends;
1655 ALsizei new_sends = device->NumAuxSends;
1656 enum DevFmtChannels oldChans;
1657 enum DevFmtType oldType;
1658 ALboolean update_failed;
1659 ALCsizei hrtf_id = -1;
1660 ALCcontext *context;
1661 ALCuint oldFreq;
1662 size_t size;
1663 ALCsizei i;
1664 int val;
1666 // Check for attributes
1667 if(device->Type == Loopback)
1669 ALCsizei numMono, numStereo, numSends;
1670 ALCenum alayout = AL_NONE;
1671 ALCenum ascale = AL_NONE;
1672 ALCenum schans = AL_NONE;
1673 ALCenum stype = AL_NONE;
1674 ALCsizei attrIdx = 0;
1675 ALCsizei aorder = 0;
1676 ALCuint freq = 0;
1678 if(!attrList)
1680 WARN("Missing attributes for loopback device\n");
1681 return ALC_INVALID_VALUE;
1684 numMono = device->NumMonoSources;
1685 numStereo = device->NumStereoSources;
1686 numSends = old_sends;
1688 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1689 while(attrList[attrIdx])
1691 switch(attrList[attrIdx])
1693 case ALC_FORMAT_CHANNELS_SOFT:
1694 schans = attrList[attrIdx + 1];
1695 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1696 if(!IsValidALCChannels(schans))
1697 return ALC_INVALID_VALUE;
1698 break;
1700 case ALC_FORMAT_TYPE_SOFT:
1701 stype = attrList[attrIdx + 1];
1702 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1703 if(!IsValidALCType(stype))
1704 return ALC_INVALID_VALUE;
1705 break;
1707 case ALC_FREQUENCY:
1708 freq = attrList[attrIdx + 1];
1709 TRACE_ATTR(ALC_FREQUENCY, freq);
1710 if(freq < MIN_OUTPUT_RATE)
1711 return ALC_INVALID_VALUE;
1712 break;
1714 case ALC_AMBISONIC_LAYOUT_SOFT:
1715 alayout = attrList[attrIdx + 1];
1716 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1717 if(!IsValidAmbiLayout(alayout))
1718 return ALC_INVALID_VALUE;
1719 break;
1721 case ALC_AMBISONIC_SCALING_SOFT:
1722 ascale = attrList[attrIdx + 1];
1723 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1724 if(!IsValidAmbiScaling(ascale))
1725 return ALC_INVALID_VALUE;
1726 break;
1728 case ALC_AMBISONIC_ORDER_SOFT:
1729 aorder = attrList[attrIdx + 1];
1730 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1731 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1732 return ALC_INVALID_VALUE;
1733 break;
1735 case ALC_MONO_SOURCES:
1736 numMono = attrList[attrIdx + 1];
1737 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1738 numMono = maxi(numMono, 0);
1739 break;
1741 case ALC_STEREO_SOURCES:
1742 numStereo = attrList[attrIdx + 1];
1743 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1744 numStereo = maxi(numStereo, 0);
1745 break;
1747 case ALC_MAX_AUXILIARY_SENDS:
1748 numSends = attrList[attrIdx + 1];
1749 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1750 numSends = clampi(numSends, 0, MAX_SENDS);
1751 break;
1753 case ALC_HRTF_SOFT:
1754 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1755 if(attrList[attrIdx + 1] == ALC_FALSE)
1756 hrtf_appreq = Hrtf_Disable;
1757 else if(attrList[attrIdx + 1] == ALC_TRUE)
1758 hrtf_appreq = Hrtf_Enable;
1759 else
1760 hrtf_appreq = Hrtf_Default;
1761 break;
1763 case ALC_HRTF_ID_SOFT:
1764 hrtf_id = attrList[attrIdx + 1];
1765 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1766 break;
1768 case ALC_OUTPUT_LIMITER_SOFT:
1769 gainLimiter = attrList[attrIdx + 1];
1770 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1771 break;
1773 default:
1774 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList[attrIdx],
1775 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1776 break;
1779 attrIdx += 2;
1781 #undef TRACE_ATTR
1783 if(!schans || !stype || !freq)
1785 WARN("Missing format for loopback device\n");
1786 return ALC_INVALID_VALUE;
1788 if(schans == ALC_BFORMAT3D_SOFT && (!alayout || !ascale || !aorder))
1790 WARN("Missing ambisonic info for loopback device\n");
1791 return ALC_INVALID_VALUE;
1794 if((device->Flags&DEVICE_RUNNING))
1795 V0(device->Backend,stop)();
1796 device->Flags &= ~DEVICE_RUNNING;
1798 UpdateClockBase(device);
1800 device->Frequency = freq;
1801 device->FmtChans = static_cast<enum DevFmtChannels>(schans);
1802 device->FmtType = static_cast<enum DevFmtType>(stype);
1803 if(schans == ALC_BFORMAT3D_SOFT)
1805 device->AmbiOrder = aorder;
1806 device->AmbiLayout = static_cast<enum AmbiLayout>(alayout);
1807 device->AmbiScale = static_cast<enum AmbiNorm>(ascale);
1810 if(numMono > INT_MAX-numStereo)
1811 numMono = INT_MAX-numStereo;
1812 numMono += numStereo;
1813 if(ConfigValueInt(nullptr, nullptr, "sources", &numMono))
1815 if(numMono <= 0)
1816 numMono = 256;
1818 else
1819 numMono = maxi(numMono, 256);
1820 numStereo = mini(numStereo, numMono);
1821 numMono -= numStereo;
1822 device->SourcesMax = numMono + numStereo;
1824 device->NumMonoSources = numMono;
1825 device->NumStereoSources = numStereo;
1827 if(ConfigValueInt(nullptr, nullptr, "sends", &new_sends))
1828 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1829 else
1830 new_sends = numSends;
1832 else if(attrList && attrList[0])
1834 ALCsizei numMono, numStereo, numSends;
1835 ALCsizei attrIdx = 0;
1836 ALCuint freq;
1838 /* If a context is already running on the device, stop playback so the
1839 * device attributes can be updated. */
1840 if((device->Flags&DEVICE_RUNNING))
1841 V0(device->Backend,stop)();
1842 device->Flags &= ~DEVICE_RUNNING;
1844 UpdateClockBase(device);
1846 freq = device->Frequency;
1847 numMono = device->NumMonoSources;
1848 numStereo = device->NumStereoSources;
1849 numSends = old_sends;
1851 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1852 while(attrList[attrIdx])
1854 switch(attrList[attrIdx])
1856 case ALC_FREQUENCY:
1857 freq = attrList[attrIdx + 1];
1858 TRACE_ATTR(ALC_FREQUENCY, freq);
1859 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1860 break;
1862 case ALC_MONO_SOURCES:
1863 numMono = attrList[attrIdx + 1];
1864 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1865 numMono = maxi(numMono, 0);
1866 break;
1868 case ALC_STEREO_SOURCES:
1869 numStereo = attrList[attrIdx + 1];
1870 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1871 numStereo = maxi(numStereo, 0);
1872 break;
1874 case ALC_MAX_AUXILIARY_SENDS:
1875 numSends = attrList[attrIdx + 1];
1876 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1877 numSends = clampi(numSends, 0, MAX_SENDS);
1878 break;
1880 case ALC_HRTF_SOFT:
1881 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1882 if(attrList[attrIdx + 1] == ALC_FALSE)
1883 hrtf_appreq = Hrtf_Disable;
1884 else if(attrList[attrIdx + 1] == ALC_TRUE)
1885 hrtf_appreq = Hrtf_Enable;
1886 else
1887 hrtf_appreq = Hrtf_Default;
1888 break;
1890 case ALC_HRTF_ID_SOFT:
1891 hrtf_id = attrList[attrIdx + 1];
1892 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1893 break;
1895 case ALC_OUTPUT_LIMITER_SOFT:
1896 gainLimiter = attrList[attrIdx + 1];
1897 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1898 break;
1900 default:
1901 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1902 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1903 break;
1906 attrIdx += 2;
1908 #undef TRACE_ATTR
1910 ConfigValueUInt(device->DeviceName, nullptr, "frequency", &freq);
1911 freq = maxu(freq, MIN_OUTPUT_RATE);
1913 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1914 device->Frequency;
1915 /* SSE and Neon do best with the update size being a multiple of 4 */
1916 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1917 device->UpdateSize = (device->UpdateSize+3)&~3;
1919 device->Frequency = freq;
1921 if(numMono > INT_MAX-numStereo)
1922 numMono = INT_MAX-numStereo;
1923 numMono += numStereo;
1924 if(ConfigValueInt(device->DeviceName, nullptr, "sources", &numMono))
1926 if(numMono <= 0)
1927 numMono = 256;
1929 else
1930 numMono = maxi(numMono, 256);
1931 numStereo = mini(numStereo, numMono);
1932 numMono -= numStereo;
1933 device->SourcesMax = numMono + numStereo;
1935 device->NumMonoSources = numMono;
1936 device->NumStereoSources = numStereo;
1938 if(ConfigValueInt(device->DeviceName, nullptr, "sends", &new_sends))
1939 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1940 else
1941 new_sends = numSends;
1944 if((device->Flags&DEVICE_RUNNING))
1945 return ALC_NO_ERROR;
1947 al_free(device->Uhj_Encoder);
1948 device->Uhj_Encoder = nullptr;
1950 al_free(device->Bs2b);
1951 device->Bs2b = nullptr;
1953 al_free(device->ChannelDelay[0].Buffer);
1954 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1956 device->ChannelDelay[i].Length = 0;
1957 device->ChannelDelay[i].Buffer = nullptr;
1960 al_free(device->Dry.Buffer);
1961 device->Dry.Buffer = nullptr;
1962 device->Dry.NumChannels = 0;
1963 device->FOAOut.Buffer = nullptr;
1964 device->FOAOut.NumChannels = 0;
1965 device->RealOut.Buffer = nullptr;
1966 device->RealOut.NumChannels = 0;
1968 UpdateClockBase(device);
1969 device->FixedLatency = 0;
1971 device->DitherSeed = DITHER_RNG_SEED;
1973 /*************************************************************************
1974 * Update device format request if HRTF is requested
1976 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
1977 if(device->Type != Loopback)
1979 const char *hrtf;
1980 if(ConfigValueStr(device->DeviceName, nullptr, "hrtf", &hrtf))
1982 if(strcasecmp(hrtf, "true") == 0)
1983 hrtf_userreq = Hrtf_Enable;
1984 else if(strcasecmp(hrtf, "false") == 0)
1985 hrtf_userreq = Hrtf_Disable;
1986 else if(strcasecmp(hrtf, "auto") != 0)
1987 ERR("Unexpected hrtf value: %s\n", hrtf);
1990 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
1992 struct Hrtf *hrtf = nullptr;
1993 if(VECTOR_SIZE(device->HrtfList) == 0)
1995 VECTOR_DEINIT(device->HrtfList);
1996 device->HrtfList = EnumerateHrtf(device->DeviceName);
1998 if(VECTOR_SIZE(device->HrtfList) > 0)
2000 if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->HrtfList))
2001 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, hrtf_id).hrtf);
2002 else
2003 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, 0).hrtf);
2006 if(hrtf)
2008 device->FmtChans = DevFmtStereo;
2009 device->Frequency = hrtf->sampleRate;
2010 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
2011 if(device->HrtfHandle)
2012 Hrtf_DecRef(device->HrtfHandle);
2013 device->HrtfHandle = hrtf;
2015 else
2017 hrtf_userreq = Hrtf_Default;
2018 hrtf_appreq = Hrtf_Disable;
2019 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2024 oldFreq = device->Frequency;
2025 oldChans = device->FmtChans;
2026 oldType = device->FmtType;
2028 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2029 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
2030 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
2031 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
2032 device->UpdateSize, device->NumUpdates
2035 if(V0(device->Backend,reset)() == ALC_FALSE)
2036 return ALC_INVALID_DEVICE;
2038 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
2040 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2041 DevFmtChannelsString(device->FmtChans));
2042 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2044 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2046 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2047 DevFmtTypeString(device->FmtType));
2048 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2050 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2052 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2053 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2056 if((device->UpdateSize&3) != 0)
2058 if((CPUCapFlags&CPU_CAP_SSE))
2059 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2060 if((CPUCapFlags&CPU_CAP_NEON))
2061 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2064 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2065 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2066 device->Frequency, device->UpdateSize, device->NumUpdates
2069 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2070 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device->Dry.NumChannels,
2071 device->FOAOut.NumChannels, device->RealOut.NumChannels);
2073 /* Allocate extra channels for any post-filter output. */
2074 size = (device->Dry.NumChannels + device->FOAOut.NumChannels +
2075 device->RealOut.NumChannels)*sizeof(device->Dry.Buffer[0]);
2077 TRACE("Allocating " SZFMT " channels, " SZFMT " bytes\n", size/sizeof(device->Dry.Buffer[0]), size);
2078 device->Dry.Buffer = static_cast<float(*)[BUFFERSIZE]>(al_calloc(16, size));
2079 if(!device->Dry.Buffer)
2081 ERR("Failed to allocate " SZFMT " bytes for mix buffer\n", size);
2082 return ALC_INVALID_DEVICE;
2085 if(device->RealOut.NumChannels != 0)
2086 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels +
2087 device->FOAOut.NumChannels;
2088 else
2090 device->RealOut.Buffer = device->Dry.Buffer;
2091 device->RealOut.NumChannels = device->Dry.NumChannels;
2094 if(device->FOAOut.NumChannels != 0)
2095 device->FOAOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2096 else
2098 device->FOAOut.Buffer = device->Dry.Buffer;
2099 device->FOAOut.NumChannels = device->Dry.NumChannels;
2102 device->NumAuxSends = new_sends;
2103 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2104 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
2105 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
2107 device->DitherDepth = 0.0f;
2108 if(GetConfigValueBool(device->DeviceName, nullptr, "dither", 1))
2110 ALint depth = 0;
2111 ConfigValueInt(device->DeviceName, nullptr, "dither-depth", &depth);
2112 if(depth <= 0)
2114 switch(device->FmtType)
2116 case DevFmtByte:
2117 case DevFmtUByte:
2118 depth = 8;
2119 break;
2120 case DevFmtShort:
2121 case DevFmtUShort:
2122 depth = 16;
2123 break;
2124 case DevFmtInt:
2125 case DevFmtUInt:
2126 case DevFmtFloat:
2127 break;
2131 if(depth > 0)
2133 depth = clampi(depth, 2, 24);
2134 device->DitherDepth = std::pow(2.0f, (ALfloat)(depth-1));
2137 if(!(device->DitherDepth > 0.0f))
2138 TRACE("Dithering disabled\n");
2139 else
2140 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device->DitherDepth)+0.5)+1,
2141 device->DitherDepth);
2143 device->LimiterState = gainLimiter;
2144 if(ConfigValueBool(device->DeviceName, nullptr, "output-limiter", &val))
2145 gainLimiter = val ? ALC_TRUE : ALC_FALSE;
2147 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2148 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2149 * output (where samples must be clamped), and don't for floating-point
2150 * (which can take unclamped samples).
2152 if(gainLimiter == ALC_DONT_CARE_SOFT)
2154 switch(device->FmtType)
2156 case DevFmtByte:
2157 case DevFmtUByte:
2158 case DevFmtShort:
2159 case DevFmtUShort:
2160 case DevFmtInt:
2161 case DevFmtUInt:
2162 gainLimiter = ALC_TRUE;
2163 break;
2164 case DevFmtFloat:
2165 gainLimiter = ALC_FALSE;
2166 break;
2169 if(gainLimiter != ALC_FALSE)
2171 ALfloat thrshld = 1.0f;
2172 switch(device->FmtType)
2174 case DevFmtByte:
2175 case DevFmtUByte:
2176 thrshld = 127.0f / 128.0f;
2177 break;
2178 case DevFmtShort:
2179 case DevFmtUShort:
2180 thrshld = 32767.0f / 32768.0f;
2181 break;
2182 case DevFmtInt:
2183 case DevFmtUInt:
2184 case DevFmtFloat:
2185 break;
2187 if(device->DitherDepth > 0.0f)
2188 thrshld -= 1.0f / device->DitherDepth;
2190 al_free(device->Limiter);
2191 device->Limiter = CreateDeviceLimiter(device, std::log10(thrshld) * 20.0f);
2192 device->FixedLatency += (ALuint)(GetCompressorLookAhead(device->Limiter) *
2193 DEVICE_CLOCK_RES / device->Frequency);
2195 else
2197 al_free(device->Limiter);
2198 device->Limiter = nullptr;
2200 TRACE("Output limiter %s\n", device->Limiter ? "enabled" : "disabled");
2202 aluSelectPostProcess(device);
2204 TRACE("Fixed device latency: %uns\n", device->FixedLatency);
2206 /* Need to delay returning failure until replacement Send arrays have been
2207 * allocated with the appropriate size.
2209 update_failed = AL_FALSE;
2210 START_MIXER_MODE();
2211 context = ATOMIC_LOAD_SEQ(&device->ContextList);
2212 while(context)
2214 SourceSubList *sublist, *subend;
2215 struct ALvoiceProps *vprops;
2216 ALsizei pos;
2218 if(context->DefaultSlot)
2220 ALeffectslot *slot = context->DefaultSlot;
2221 ALeffectState *state = slot->Effect.State;
2223 state->OutBuffer = device->Dry.Buffer;
2224 state->OutChannels = device->Dry.NumChannels;
2225 if(V(state,deviceUpdate)(device) == AL_FALSE)
2226 update_failed = AL_TRUE;
2227 else
2228 UpdateEffectSlotProps(slot, context);
2231 almtx_lock(&context->PropLock);
2232 almtx_lock(&context->EffectSlotLock);
2233 for(pos = 0;pos < (ALsizei)VECTOR_SIZE(context->EffectSlotList);pos++)
2235 ALeffectslot *slot = VECTOR_ELEM(context->EffectSlotList, pos);
2236 ALeffectState *state = slot->Effect.State;
2238 state->OutBuffer = device->Dry.Buffer;
2239 state->OutChannels = device->Dry.NumChannels;
2240 if(V(state,deviceUpdate)(device) == AL_FALSE)
2241 update_failed = AL_TRUE;
2242 else
2243 UpdateEffectSlotProps(slot, context);
2245 almtx_unlock(&context->EffectSlotLock);
2247 almtx_lock(&context->SourceLock);
2248 sublist = VECTOR_BEGIN(context->SourceList);
2249 subend = VECTOR_END(context->SourceList);
2250 for(;sublist != subend;++sublist)
2252 ALuint64 usemask = ~sublist->FreeMask;
2253 while(usemask)
2255 ALsizei idx = CTZ64(usemask);
2256 ALsource *source = sublist->Sources + idx;
2258 usemask &= ~(U64(1) << idx);
2260 if(old_sends != device->NumAuxSends)
2262 ALvoid *sends = al_calloc(16, device->NumAuxSends*sizeof(source->Send[0]));
2263 ALsizei s;
2265 memcpy(sends, source->Send,
2266 mini(device->NumAuxSends, old_sends)*sizeof(source->Send[0])
2268 for(s = device->NumAuxSends;s < old_sends;s++)
2270 if(source->Send[s].Slot)
2271 DecrementRef(&source->Send[s].Slot->ref);
2272 source->Send[s].Slot = nullptr;
2274 al_free(source->Send);
2275 source->Send = static_cast<decltype(source->Send)>(sends);
2276 for(s = old_sends;s < device->NumAuxSends;s++)
2278 source->Send[s].Slot = nullptr;
2279 source->Send[s].Gain = 1.0f;
2280 source->Send[s].GainHF = 1.0f;
2281 source->Send[s].HFReference = LOWPASSFREQREF;
2282 source->Send[s].GainLF = 1.0f;
2283 source->Send[s].LFReference = HIGHPASSFREQREF;
2287 ATOMIC_STORE(&source->PropsClean, AL_FALSE, almemory_order_release);
2291 /* Clear any pre-existing voice property structs, in case the number of
2292 * auxiliary sends is changing. Active sources will have updates
2293 * respecified in UpdateAllSourceProps.
2295 vprops = static_cast<ALvoiceProps*>(ATOMIC_EXCHANGE_PTR(&context->FreeVoiceProps,
2296 static_cast<ALvoiceProps*>(nullptr), almemory_order_acq_rel));
2297 while(vprops)
2299 struct ALvoiceProps *next = ATOMIC_LOAD(&vprops->next, almemory_order_relaxed);
2300 al_free(vprops);
2301 vprops = next;
2304 AllocateVoices(context, context->MaxVoices, old_sends);
2305 for(pos = 0;pos < context->VoiceCount;pos++)
2307 ALvoice *voice = context->Voices[pos];
2309 al_free(ATOMIC_EXCHANGE_PTR(&voice->Update, static_cast<ALvoiceProps*>(nullptr),
2310 almemory_order_acq_rel));
2312 if(ATOMIC_LOAD(&voice->Source, almemory_order_acquire) == nullptr)
2313 continue;
2315 if(device->AvgSpeakerDist > 0.0f)
2317 /* Reinitialize the NFC filters for new parameters. */
2318 ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
2319 (device->AvgSpeakerDist * device->Frequency);
2320 for(i = 0;i < voice->NumChannels;i++)
2321 NfcFilterCreate(&voice->Direct.Params[i].NFCtrlFilter, 0.0f, w1);
2324 almtx_unlock(&context->SourceLock);
2326 ATOMIC_STORE(&context->PropsClean, AL_TRUE, almemory_order_release);
2327 UpdateContextProps(context);
2328 ATOMIC_STORE(&context->Listener->PropsClean, AL_TRUE, almemory_order_release);
2329 UpdateListenerProps(context);
2330 UpdateAllSourceProps(context);
2331 almtx_unlock(&context->PropLock);
2333 context = ATOMIC_LOAD(&context->next, almemory_order_relaxed);
2335 END_MIXER_MODE();
2336 if(update_failed)
2337 return ALC_INVALID_DEVICE;
2339 if(!(device->Flags&DEVICE_PAUSED))
2341 if(V0(device->Backend,start)() == ALC_FALSE)
2342 return ALC_INVALID_DEVICE;
2343 device->Flags |= DEVICE_RUNNING;
2346 return ALC_NO_ERROR;
2350 static void InitDevice(ALCdevice *device, enum DeviceType type)
2352 ALsizei i;
2354 InitRef(&device->ref, 1);
2355 ATOMIC_INIT(&device->Connected, ALC_TRUE);
2356 device->Type = type;
2357 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
2359 device->Flags = 0;
2360 device->Render_Mode = NormalRender;
2361 device->AvgSpeakerDist = 0.0f;
2362 device->LimiterState = ALC_DONT_CARE_SOFT;
2364 ATOMIC_INIT(&device->ContextList, static_cast<ALCcontext*>(nullptr));
2366 device->ClockBase = 0;
2367 device->SamplesDone = 0;
2368 device->FixedLatency = 0;
2370 device->SourcesMax = 0;
2371 device->AuxiliaryEffectSlotMax = 0;
2372 device->NumAuxSends = 0;
2374 device->Dry.Buffer = nullptr;
2375 device->Dry.NumChannels = 0;
2376 device->FOAOut.Buffer = nullptr;
2377 device->FOAOut.NumChannels = 0;
2378 device->RealOut.Buffer = nullptr;
2379 device->RealOut.NumChannels = 0;
2381 device->DeviceName = nullptr;
2383 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2385 device->ChannelDelay[i].Gain = 1.0f;
2386 device->ChannelDelay[i].Length = 0;
2387 device->ChannelDelay[i].Buffer = nullptr;
2390 device->HrtfName = nullptr;
2391 VECTOR_INIT(device->HrtfList);
2392 device->HrtfHandle = nullptr;
2393 device->Hrtf = nullptr;
2394 device->Bs2b = nullptr;
2395 device->Uhj_Encoder = nullptr;
2396 device->AmbiDecoder = nullptr;
2397 device->AmbiUp = nullptr;
2398 device->Stablizer = nullptr;
2399 device->Limiter = nullptr;
2401 VECTOR_INIT(device->BufferList);
2402 almtx_init(&device->BufferLock, almtx_plain);
2404 VECTOR_INIT(device->EffectList);
2405 almtx_init(&device->EffectLock, almtx_plain);
2407 VECTOR_INIT(device->FilterList);
2408 almtx_init(&device->FilterLock, almtx_plain);
2410 almtx_init(&device->BackendLock, almtx_plain);
2411 device->Backend = nullptr;
2413 ATOMIC_INIT(&device->next, static_cast<ALCdevice*>(nullptr));
2416 /* FreeDevice
2418 * Frees the device structure, and destroys any objects the app failed to
2419 * delete. Called once there's no more references on the device.
2421 static ALCvoid FreeDevice(ALCdevice *device)
2423 ALsizei i;
2425 TRACE("%p\n", device);
2427 if(device->Backend)
2428 DELETE_OBJ(device->Backend);
2429 device->Backend = nullptr;
2431 almtx_destroy(&device->BackendLock);
2433 ReleaseALBuffers(device);
2434 #define FREE_BUFFERSUBLIST(x) al_free((x)->Buffers)
2435 VECTOR_FOR_EACH(BufferSubList, device->BufferList, FREE_BUFFERSUBLIST);
2436 #undef FREE_BUFFERSUBLIST
2437 VECTOR_DEINIT(device->BufferList);
2438 almtx_destroy(&device->BufferLock);
2440 ReleaseALEffects(device);
2441 #define FREE_EFFECTSUBLIST(x) al_free((x)->Effects)
2442 VECTOR_FOR_EACH(EffectSubList, device->EffectList, FREE_EFFECTSUBLIST);
2443 #undef FREE_EFFECTSUBLIST
2444 VECTOR_DEINIT(device->EffectList);
2445 almtx_destroy(&device->EffectLock);
2447 ReleaseALFilters(device);
2448 #define FREE_FILTERSUBLIST(x) al_free((x)->Filters)
2449 VECTOR_FOR_EACH(FilterSubList, device->FilterList, FREE_FILTERSUBLIST);
2450 #undef FREE_FILTERSUBLIST
2451 VECTOR_DEINIT(device->FilterList);
2452 almtx_destroy(&device->FilterLock);
2454 al_free(device->HrtfName);
2455 device->HrtfName = nullptr;
2456 FreeHrtfList(&device->HrtfList);
2457 if(device->HrtfHandle)
2458 Hrtf_DecRef(device->HrtfHandle);
2459 device->HrtfHandle = nullptr;
2460 al_free(device->Hrtf);
2461 device->Hrtf = nullptr;
2463 al_free(device->Bs2b);
2464 device->Bs2b = nullptr;
2466 al_free(device->Uhj_Encoder);
2467 device->Uhj_Encoder = nullptr;
2469 bformatdec_free(&device->AmbiDecoder);
2470 ambiup_free(&device->AmbiUp);
2472 al_free(device->Stablizer);
2473 device->Stablizer = nullptr;
2475 al_free(device->Limiter);
2476 device->Limiter = nullptr;
2478 al_free(device->ChannelDelay[0].Buffer);
2479 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2481 device->ChannelDelay[i].Gain = 1.0f;
2482 device->ChannelDelay[i].Length = 0;
2483 device->ChannelDelay[i].Buffer = nullptr;
2486 al_free(device->DeviceName);
2487 device->DeviceName = nullptr;
2489 al_free(device->Dry.Buffer);
2490 device->Dry.Buffer = nullptr;
2491 device->Dry.NumChannels = 0;
2492 device->FOAOut.Buffer = nullptr;
2493 device->FOAOut.NumChannels = 0;
2494 device->RealOut.Buffer = nullptr;
2495 device->RealOut.NumChannels = 0;
2497 al_free(device);
2501 void ALCdevice_IncRef(ALCdevice *device)
2503 uint ref;
2504 ref = IncrementRef(&device->ref);
2505 TRACEREF("%p increasing refcount to %u\n", device, ref);
2508 void ALCdevice_DecRef(ALCdevice *device)
2510 uint ref;
2511 ref = DecrementRef(&device->ref);
2512 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2513 if(ref == 0) FreeDevice(device);
2516 /* VerifyDevice
2518 * Checks if the device handle is valid, and increments its ref count if so.
2520 static ALCboolean VerifyDevice(ALCdevice **device)
2522 std::lock_guard<std::recursive_mutex> _{ListLock};
2523 ALCdevice *tmpDevice{DeviceList.load()};
2524 while(tmpDevice)
2526 if(tmpDevice == *device)
2528 ALCdevice_IncRef(tmpDevice);
2529 return ALC_TRUE;
2531 tmpDevice = ATOMIC_LOAD(&tmpDevice->next, almemory_order_relaxed);
2534 *device = nullptr;
2535 return ALC_FALSE;
2539 /* InitContext
2541 * Initializes context fields
2543 static ALvoid InitContext(ALCcontext *Context)
2545 ALlistener *listener = Context->Listener;
2546 struct ALeffectslotArray *auxslots;
2548 //Initialise listener
2549 listener->Gain = 1.0f;
2550 listener->Position[0] = 0.0f;
2551 listener->Position[1] = 0.0f;
2552 listener->Position[2] = 0.0f;
2553 listener->Velocity[0] = 0.0f;
2554 listener->Velocity[1] = 0.0f;
2555 listener->Velocity[2] = 0.0f;
2556 listener->Forward[0] = 0.0f;
2557 listener->Forward[1] = 0.0f;
2558 listener->Forward[2] = -1.0f;
2559 listener->Up[0] = 0.0f;
2560 listener->Up[1] = 1.0f;
2561 listener->Up[2] = 0.0f;
2562 ATOMIC_INIT(&listener->PropsClean, AL_TRUE);
2564 ATOMIC_INIT(&listener->Update, static_cast<ALlistenerProps*>(nullptr));
2566 //Validate Context
2567 InitRef(&Context->UpdateCount, 0);
2568 ATOMIC_INIT(&Context->HoldUpdates, AL_FALSE);
2569 Context->GainBoost = 1.0f;
2570 almtx_init(&Context->PropLock, almtx_plain);
2571 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2572 VECTOR_INIT(Context->SourceList);
2573 Context->NumSources = 0;
2574 almtx_init(&Context->SourceLock, almtx_plain);
2575 VECTOR_INIT(Context->EffectSlotList);
2576 almtx_init(&Context->EffectSlotLock, almtx_plain);
2578 if(Context->DefaultSlot)
2580 auxslots = static_cast<ALeffectslotArray*>(al_calloc(DEF_ALIGN,
2581 FAM_SIZE(struct ALeffectslotArray, slot, 1)));
2582 auxslots->count = 1;
2583 auxslots->slot[0] = Context->DefaultSlot;
2585 else
2587 auxslots = static_cast<ALeffectslotArray*>(al_calloc(DEF_ALIGN,
2588 sizeof(struct ALeffectslotArray)));
2589 auxslots->count = 0;
2591 ATOMIC_INIT(&Context->ActiveAuxSlots, auxslots);
2593 //Set globals
2594 Context->DistanceModel = DefaultDistanceModel;
2595 Context->SourceDistanceModel = AL_FALSE;
2596 Context->DopplerFactor = 1.0f;
2597 Context->DopplerVelocity = 1.0f;
2598 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2599 Context->MetersPerUnit = AL_DEFAULT_METERS_PER_UNIT;
2600 ATOMIC_INIT(&Context->PropsClean, AL_TRUE);
2601 ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
2602 alsem_init(&Context->EventSem, 0);
2603 Context->AsyncEvents = nullptr;
2604 ATOMIC_INIT(&Context->EnabledEvts, 0u);
2605 almtx_init(&Context->EventCbLock, almtx_plain);
2606 Context->EventCb = nullptr;
2607 Context->EventParam = nullptr;
2609 ATOMIC_INIT(&Context->Update, static_cast<ALcontextProps*>(nullptr));
2610 ATOMIC_INIT(&Context->FreeContextProps, static_cast<ALcontextProps*>(nullptr));
2611 ATOMIC_INIT(&Context->FreeListenerProps, static_cast<ALlistenerProps*>(nullptr));
2612 ATOMIC_INIT(&Context->FreeVoiceProps, static_cast<ALvoiceProps*>(nullptr));
2613 ATOMIC_INIT(&Context->FreeEffectslotProps, static_cast<ALeffectslotProps*>(nullptr));
2615 Context->ExtensionList = alExtList;
2618 listener->Params.Matrix = IdentityMatrixf;
2619 aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2620 listener->Params.Gain = listener->Gain;
2621 listener->Params.MetersPerUnit = Context->MetersPerUnit;
2622 listener->Params.DopplerFactor = Context->DopplerFactor;
2623 listener->Params.SpeedOfSound = Context->SpeedOfSound * Context->DopplerVelocity;
2624 listener->Params.ReverbSpeedOfSound = listener->Params.SpeedOfSound *
2625 listener->Params.MetersPerUnit;
2626 listener->Params.SourceDistanceModel = Context->SourceDistanceModel;
2627 listener->Params.DistanceModel = Context->DistanceModel;
2630 Context->AsyncEvents = ll_ringbuffer_create(63, sizeof(AsyncEvent), false);
2631 if(althrd_create(&Context->EventThread, EventThread, Context) != althrd_success)
2632 ERR("Failed to start event thread! Expect problems.\n");
2636 /* FreeContext
2638 * Cleans up the context, and destroys any remaining objects the app failed to
2639 * delete. Called once there's no more references on the context.
2641 static void FreeContext(ALCcontext *context)
2643 ALlistener *listener = context->Listener;
2644 struct ALeffectslotProps *eprops;
2645 struct ALlistenerProps *lprops;
2646 struct ALcontextProps *cprops;
2647 struct ALvoiceProps *vprops;
2648 size_t count;
2649 ALsizei i;
2651 TRACE("%p\n", context);
2653 if((cprops=ATOMIC_LOAD(&context->Update, almemory_order_acquire)) != nullptr)
2655 TRACE("Freed unapplied context update %p\n", cprops);
2656 al_free(cprops);
2659 count = 0;
2660 cprops = ATOMIC_LOAD(&context->FreeContextProps, almemory_order_acquire);
2661 while(cprops)
2663 struct ALcontextProps *next = ATOMIC_LOAD(&cprops->next, almemory_order_acquire);
2664 al_free(cprops);
2665 cprops = next;
2666 ++count;
2668 TRACE("Freed " SZFMT " context property object%s\n", count, (count==1)?"":"s");
2670 if(context->DefaultSlot)
2672 DeinitEffectSlot(context->DefaultSlot);
2673 context->DefaultSlot = nullptr;
2676 al_free(ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots,
2677 static_cast<ALeffectslotArray*>(nullptr), almemory_order_relaxed));
2679 ReleaseALSources(context);
2680 #define FREE_SOURCESUBLIST(x) al_free((x)->Sources)
2681 VECTOR_FOR_EACH(SourceSubList, context->SourceList, FREE_SOURCESUBLIST);
2682 #undef FREE_SOURCESUBLIST
2683 VECTOR_DEINIT(context->SourceList);
2684 context->NumSources = 0;
2685 almtx_destroy(&context->SourceLock);
2687 count = 0;
2688 eprops = ATOMIC_LOAD(&context->FreeEffectslotProps, almemory_order_relaxed);
2689 while(eprops)
2691 struct ALeffectslotProps *next = ATOMIC_LOAD(&eprops->next, almemory_order_relaxed);
2692 if(eprops->State) ALeffectState_DecRef(eprops->State);
2693 al_free(eprops);
2694 eprops = next;
2695 ++count;
2697 TRACE("Freed " SZFMT " AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2699 ReleaseALAuxiliaryEffectSlots(context);
2700 #define FREE_EFFECTSLOTPTR(x) al_free(*(x))
2701 VECTOR_FOR_EACH(ALeffectslotPtr, context->EffectSlotList, FREE_EFFECTSLOTPTR);
2702 #undef FREE_EFFECTSLOTPTR
2703 VECTOR_DEINIT(context->EffectSlotList);
2704 almtx_destroy(&context->EffectSlotLock);
2706 count = 0;
2707 vprops = ATOMIC_LOAD(&context->FreeVoiceProps, almemory_order_relaxed);
2708 while(vprops)
2710 struct ALvoiceProps *next = ATOMIC_LOAD(&vprops->next, almemory_order_relaxed);
2711 al_free(vprops);
2712 vprops = next;
2713 ++count;
2715 TRACE("Freed " SZFMT " voice property object%s\n", count, (count==1)?"":"s");
2717 for(i = 0;i < context->VoiceCount;i++)
2718 DeinitVoice(context->Voices[i]);
2719 al_free(context->Voices);
2720 context->Voices = nullptr;
2721 context->VoiceCount = 0;
2722 context->MaxVoices = 0;
2724 if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != nullptr)
2726 TRACE("Freed unapplied listener update %p\n", lprops);
2727 al_free(lprops);
2729 count = 0;
2730 lprops = ATOMIC_LOAD(&context->FreeListenerProps, almemory_order_acquire);
2731 while(lprops)
2733 struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_acquire);
2734 al_free(lprops);
2735 lprops = next;
2736 ++count;
2738 TRACE("Freed " SZFMT " listener property object%s\n", count, (count==1)?"":"s");
2740 almtx_destroy(&context->EventCbLock);
2741 alsem_destroy(&context->EventSem);
2743 ll_ringbuffer_free(context->AsyncEvents);
2744 context->AsyncEvents = nullptr;
2746 almtx_destroy(&context->PropLock);
2748 ALCdevice_DecRef(context->Device);
2749 context->Device = nullptr;
2751 //Invalidate context
2752 memset(context, 0, sizeof(ALCcontext));
2753 al_free(context);
2756 /* ReleaseContext
2758 * Removes the context reference from the given device and removes it from
2759 * being current on the running thread or globally. Returns true if other
2760 * contexts still exist on the device.
2762 static bool ReleaseContext(ALCcontext *context, ALCdevice *device)
2764 static const AsyncEvent kill_evt = ASYNC_EVENT(EventType_KillThread);
2765 ALCcontext *origctx, *newhead;
2766 bool ret = true;
2768 if(altss_get(LocalContext) == context)
2770 WARN("%p released while current on thread\n", context);
2771 altss_set(LocalContext, nullptr);
2772 ALCcontext_DecRef(context);
2775 origctx = context;
2776 if(GlobalContext.compare_exchange_strong(origctx, nullptr))
2777 ALCcontext_DecRef(context);
2779 V0(device->Backend,lock)();
2780 origctx = context;
2781 newhead = ATOMIC_LOAD(&context->next, almemory_order_relaxed);
2782 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device->ContextList, &origctx, newhead))
2784 ALCcontext *list;
2785 do {
2786 /* origctx is what the desired context failed to match. Try
2787 * swapping out the next one in the list.
2789 list = origctx;
2790 origctx = context;
2791 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list->next, &origctx, newhead));
2793 else
2794 ret = !!newhead;
2795 V0(device->Backend,unlock)();
2797 /* Make sure the context is finished and no longer processing in the mixer
2798 * before sending the message queue kill event. The backend's lock does
2799 * this, although waiting for a non-odd mix count would work too.
2802 while(ll_ringbuffer_write(context->AsyncEvents, (const char*)&kill_evt, 1) == 0)
2803 althrd_yield();
2804 alsem_post(&context->EventSem);
2805 althrd_join(context->EventThread, nullptr);
2807 ALCcontext_DecRef(context);
2808 return ret;
2811 static void ALCcontext_IncRef(ALCcontext *context)
2813 uint ref = IncrementRef(&context->ref);
2814 TRACEREF("%p increasing refcount to %u\n", context, ref);
2817 void ALCcontext_DecRef(ALCcontext *context)
2819 uint ref = DecrementRef(&context->ref);
2820 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2821 if(ref == 0) FreeContext(context);
2824 static void ReleaseThreadCtx(void *ptr)
2826 ALCcontext *context = static_cast<ALCcontext*>(ptr);
2827 uint ref = DecrementRef(&context->ref);
2828 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2829 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2832 /* VerifyContext
2834 * Checks that the given context is valid, and increments its reference count.
2836 static ALCboolean VerifyContext(ALCcontext **context)
2838 std::lock_guard<std::recursive_mutex> _{ListLock};
2839 ALCdevice *dev{DeviceList.load()};
2840 while(dev)
2842 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList, almemory_order_acquire);
2843 while(ctx)
2845 if(ctx == *context)
2847 ALCcontext_IncRef(ctx);
2848 return ALC_TRUE;
2850 ctx = ATOMIC_LOAD(&ctx->next, almemory_order_relaxed);
2852 dev = ATOMIC_LOAD(&dev->next, almemory_order_relaxed);
2855 *context = nullptr;
2856 return ALC_FALSE;
2860 /* GetContextRef
2862 * Returns the currently active context for this thread, and adds a reference
2863 * without locking it.
2865 ALCcontext *GetContextRef(void)
2867 ALCcontext *context{static_cast<ALCcontext*>(altss_get(LocalContext))};
2868 if(context)
2869 ALCcontext_IncRef(context);
2870 else
2872 std::lock_guard<std::recursive_mutex> _{ListLock};
2873 context = GlobalContext.load(std::memory_order_acquire);
2874 if(context) ALCcontext_IncRef(context);
2877 return context;
2881 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
2883 ALCdevice *device = context->Device;
2884 ALsizei num_sends = device->NumAuxSends;
2885 struct ALvoiceProps *props;
2886 size_t sizeof_props;
2887 size_t sizeof_voice;
2888 ALvoice **voices;
2889 ALvoice *voice;
2890 ALsizei v = 0;
2891 size_t size;
2893 if(num_voices == context->MaxVoices && num_sends == old_sends)
2894 return;
2896 /* Allocate the voice pointers, voices, and the voices' stored source
2897 * property set (including the dynamically-sized Send[] array) in one
2898 * chunk.
2900 sizeof_voice = RoundUp(FAM_SIZE(ALvoice, Send, num_sends), 16);
2901 sizeof_props = RoundUp(FAM_SIZE(struct ALvoiceProps, Send, num_sends), 16);
2902 size = sizeof(ALvoice*) + sizeof_voice + sizeof_props;
2904 voices = static_cast<ALvoice**>(al_calloc(16, RoundUp(size*num_voices, 16)));
2905 /* The voice and property objects are stored interleaved since they're
2906 * paired together.
2908 voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
2909 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2911 if(context->Voices)
2913 const ALsizei v_count = mini(context->VoiceCount, num_voices);
2914 const ALsizei s_count = mini(old_sends, num_sends);
2916 for(;v < v_count;v++)
2918 ALvoice *old_voice = context->Voices[v];
2919 ALsizei i;
2921 /* Copy the old voice data and source property set to the new
2922 * storage.
2924 memcpy(voice, old_voice, sizeof(*voice));
2925 for(i = 0;i < s_count;i++)
2926 voice->Send[i] = old_voice->Send[i];
2928 memcpy(props, old_voice->Props, sizeof(*props));
2929 for(i = 0;i < s_count;i++)
2930 props->Send[i] = old_voice->Props->Send[i];
2932 /* Set this voice's property set pointer and voice reference. */
2933 voice->Props = props;
2934 voices[v] = voice;
2936 /* Increment pointers to the next storage space. */
2937 voice = (ALvoice*)((char*)props + sizeof_props);
2938 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2940 /* Deinit any left over voices that weren't copied over to the new
2941 * array. NOTE: If this does anything, v equals num_voices and
2942 * num_voices is less than VoiceCount, so the following loop won't do
2943 * anything.
2945 for(;v < context->VoiceCount;v++)
2946 DeinitVoice(context->Voices[v]);
2948 /* Finish setting the voices' property set pointers and references. */
2949 for(;v < num_voices;v++)
2951 ATOMIC_INIT(&voice->Update, static_cast<ALvoiceProps*>(nullptr));
2953 voice->Props = props;
2954 voices[v] = voice;
2956 voice = (ALvoice*)((char*)props + sizeof_props);
2957 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2960 al_free(context->Voices);
2961 context->Voices = voices;
2962 context->MaxVoices = num_voices;
2963 context->VoiceCount = mini(context->VoiceCount, num_voices);
2967 /************************************************
2968 * Standard ALC functions
2969 ************************************************/
2971 /* alcGetError
2973 * Return last ALC generated error code for the given device
2975 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2977 ALCenum errorCode;
2979 if(VerifyDevice(&device))
2981 errorCode = ATOMIC_EXCHANGE_SEQ(&device->LastError, ALC_NO_ERROR);
2982 ALCdevice_DecRef(device);
2984 else
2985 errorCode = LastNullDeviceError.exchange(ALC_NO_ERROR);
2987 return errorCode;
2991 /* alcSuspendContext
2993 * Suspends updates for the given context
2995 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2997 if(!SuspendDefers)
2998 return;
3000 if(!VerifyContext(&context))
3001 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3002 else
3004 ALCcontext_DeferUpdates(context);
3005 ALCcontext_DecRef(context);
3009 /* alcProcessContext
3011 * Resumes processing updates for the given context
3013 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
3015 if(!SuspendDefers)
3016 return;
3018 if(!VerifyContext(&context))
3019 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3020 else
3022 ALCcontext_ProcessUpdates(context);
3023 ALCcontext_DecRef(context);
3028 /* alcGetString
3030 * Returns information about the device, and error strings
3032 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
3034 const ALCchar *value = nullptr;
3036 switch(param)
3038 case ALC_NO_ERROR:
3039 value = alcNoError;
3040 break;
3042 case ALC_INVALID_ENUM:
3043 value = alcErrInvalidEnum;
3044 break;
3046 case ALC_INVALID_VALUE:
3047 value = alcErrInvalidValue;
3048 break;
3050 case ALC_INVALID_DEVICE:
3051 value = alcErrInvalidDevice;
3052 break;
3054 case ALC_INVALID_CONTEXT:
3055 value = alcErrInvalidContext;
3056 break;
3058 case ALC_OUT_OF_MEMORY:
3059 value = alcErrOutOfMemory;
3060 break;
3062 case ALC_DEVICE_SPECIFIER:
3063 value = alcDefaultName;
3064 break;
3066 case ALC_ALL_DEVICES_SPECIFIER:
3067 if(VerifyDevice(&Device))
3069 value = Device->DeviceName;
3070 ALCdevice_DecRef(Device);
3072 else
3074 ProbeAllDevicesList();
3075 value = alcAllDevicesList.c_str();
3077 break;
3079 case ALC_CAPTURE_DEVICE_SPECIFIER:
3080 if(VerifyDevice(&Device))
3082 value = Device->DeviceName;
3083 ALCdevice_DecRef(Device);
3085 else
3087 ProbeCaptureDeviceList();
3088 value = alcCaptureDeviceList.c_str();
3090 break;
3092 /* Default devices are always first in the list */
3093 case ALC_DEFAULT_DEVICE_SPECIFIER:
3094 value = alcDefaultName;
3095 break;
3097 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
3098 if(alcAllDevicesList.empty())
3099 ProbeAllDevicesList();
3101 /* Copy first entry as default. */
3102 alcDefaultAllDevicesSpecifier = alcAllDevicesList.c_str();
3103 value = alcDefaultAllDevicesSpecifier.c_str();
3104 break;
3106 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
3107 if(alcCaptureDeviceList.empty())
3108 ProbeCaptureDeviceList();
3110 /* Copy first entry as default. */
3111 alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList.c_str();
3112 value = alcCaptureDefaultDeviceSpecifier.c_str();
3113 break;
3115 case ALC_EXTENSIONS:
3116 if(!VerifyDevice(&Device))
3117 value = alcNoDeviceExtList;
3118 else
3120 value = alcExtensionList;
3121 ALCdevice_DecRef(Device);
3123 break;
3125 case ALC_HRTF_SPECIFIER_SOFT:
3126 if(!VerifyDevice(&Device))
3127 alcSetError(nullptr, ALC_INVALID_DEVICE);
3128 else
3130 almtx_lock(&Device->BackendLock);
3131 value = ((Device->HrtfHandle && Device->HrtfName) ? Device->HrtfName : "");
3132 almtx_unlock(&Device->BackendLock);
3133 ALCdevice_DecRef(Device);
3135 break;
3137 default:
3138 VerifyDevice(&Device);
3139 alcSetError(Device, ALC_INVALID_ENUM);
3140 if(Device) ALCdevice_DecRef(Device);
3141 break;
3144 return value;
3148 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
3150 if(device->Type == Capture) return 9;
3151 if(device->Type != Loopback) return 29;
3152 if(device->FmtChans == DevFmtAmbi3D)
3153 return 35;
3154 return 29;
3157 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3159 ALCsizei i;
3161 if(size <= 0 || values == nullptr)
3163 alcSetError(device, ALC_INVALID_VALUE);
3164 return 0;
3167 if(!device)
3169 switch(param)
3171 case ALC_MAJOR_VERSION:
3172 values[0] = alcMajorVersion;
3173 return 1;
3174 case ALC_MINOR_VERSION:
3175 values[0] = alcMinorVersion;
3176 return 1;
3178 case ALC_ATTRIBUTES_SIZE:
3179 case ALC_ALL_ATTRIBUTES:
3180 case ALC_FREQUENCY:
3181 case ALC_REFRESH:
3182 case ALC_SYNC:
3183 case ALC_MONO_SOURCES:
3184 case ALC_STEREO_SOURCES:
3185 case ALC_CAPTURE_SAMPLES:
3186 case ALC_FORMAT_CHANNELS_SOFT:
3187 case ALC_FORMAT_TYPE_SOFT:
3188 case ALC_AMBISONIC_LAYOUT_SOFT:
3189 case ALC_AMBISONIC_SCALING_SOFT:
3190 case ALC_AMBISONIC_ORDER_SOFT:
3191 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3192 alcSetError(nullptr, ALC_INVALID_DEVICE);
3193 return 0;
3195 default:
3196 alcSetError(nullptr, ALC_INVALID_ENUM);
3197 return 0;
3199 return 0;
3202 if(device->Type == Capture)
3204 switch(param)
3206 case ALC_ATTRIBUTES_SIZE:
3207 values[0] = NumAttrsForDevice(device);
3208 return 1;
3210 case ALC_ALL_ATTRIBUTES:
3211 if(size < NumAttrsForDevice(device))
3213 alcSetError(device, ALC_INVALID_VALUE);
3214 return 0;
3217 i = 0;
3218 almtx_lock(&device->BackendLock);
3219 values[i++] = ALC_MAJOR_VERSION;
3220 values[i++] = alcMajorVersion;
3221 values[i++] = ALC_MINOR_VERSION;
3222 values[i++] = alcMinorVersion;
3223 values[i++] = ALC_CAPTURE_SAMPLES;
3224 values[i++] = V0(device->Backend,availableSamples)();
3225 values[i++] = ALC_CONNECTED;
3226 values[i++] = ATOMIC_LOAD(&device->Connected, almemory_order_relaxed);
3227 almtx_unlock(&device->BackendLock);
3229 values[i++] = 0;
3230 return i;
3232 case ALC_MAJOR_VERSION:
3233 values[0] = alcMajorVersion;
3234 return 1;
3235 case ALC_MINOR_VERSION:
3236 values[0] = alcMinorVersion;
3237 return 1;
3239 case ALC_CAPTURE_SAMPLES:
3240 almtx_lock(&device->BackendLock);
3241 values[0] = V0(device->Backend,availableSamples)();
3242 almtx_unlock(&device->BackendLock);
3243 return 1;
3245 case ALC_CONNECTED:
3246 values[0] = ATOMIC_LOAD(&device->Connected, almemory_order_acquire);
3247 return 1;
3249 default:
3250 alcSetError(device, ALC_INVALID_ENUM);
3251 return 0;
3253 return 0;
3256 /* render device */
3257 switch(param)
3259 case ALC_ATTRIBUTES_SIZE:
3260 values[0] = NumAttrsForDevice(device);
3261 return 1;
3263 case ALC_ALL_ATTRIBUTES:
3264 if(size < NumAttrsForDevice(device))
3266 alcSetError(device, ALC_INVALID_VALUE);
3267 return 0;
3270 i = 0;
3271 almtx_lock(&device->BackendLock);
3272 values[i++] = ALC_MAJOR_VERSION;
3273 values[i++] = alcMajorVersion;
3274 values[i++] = ALC_MINOR_VERSION;
3275 values[i++] = alcMinorVersion;
3276 values[i++] = ALC_EFX_MAJOR_VERSION;
3277 values[i++] = alcEFXMajorVersion;
3278 values[i++] = ALC_EFX_MINOR_VERSION;
3279 values[i++] = alcEFXMinorVersion;
3281 values[i++] = ALC_FREQUENCY;
3282 values[i++] = device->Frequency;
3283 if(device->Type != Loopback)
3285 values[i++] = ALC_REFRESH;
3286 values[i++] = device->Frequency / device->UpdateSize;
3288 values[i++] = ALC_SYNC;
3289 values[i++] = ALC_FALSE;
3291 else
3293 if(device->FmtChans == DevFmtAmbi3D)
3295 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3296 values[i++] = device->AmbiLayout;
3298 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3299 values[i++] = device->AmbiScale;
3301 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3302 values[i++] = device->AmbiOrder;
3305 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3306 values[i++] = device->FmtChans;
3308 values[i++] = ALC_FORMAT_TYPE_SOFT;
3309 values[i++] = device->FmtType;
3312 values[i++] = ALC_MONO_SOURCES;
3313 values[i++] = device->NumMonoSources;
3315 values[i++] = ALC_STEREO_SOURCES;
3316 values[i++] = device->NumStereoSources;
3318 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3319 values[i++] = device->NumAuxSends;
3321 values[i++] = ALC_HRTF_SOFT;
3322 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3324 values[i++] = ALC_HRTF_STATUS_SOFT;
3325 values[i++] = device->HrtfStatus;
3327 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3328 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3330 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
3331 values[i++] = MAX_AMBI_ORDER;
3332 almtx_unlock(&device->BackendLock);
3334 values[i++] = 0;
3335 return i;
3337 case ALC_MAJOR_VERSION:
3338 values[0] = alcMajorVersion;
3339 return 1;
3341 case ALC_MINOR_VERSION:
3342 values[0] = alcMinorVersion;
3343 return 1;
3345 case ALC_EFX_MAJOR_VERSION:
3346 values[0] = alcEFXMajorVersion;
3347 return 1;
3349 case ALC_EFX_MINOR_VERSION:
3350 values[0] = alcEFXMinorVersion;
3351 return 1;
3353 case ALC_FREQUENCY:
3354 values[0] = device->Frequency;
3355 return 1;
3357 case ALC_REFRESH:
3358 if(device->Type == Loopback)
3360 alcSetError(device, ALC_INVALID_DEVICE);
3361 return 0;
3363 almtx_lock(&device->BackendLock);
3364 values[0] = device->Frequency / device->UpdateSize;
3365 almtx_unlock(&device->BackendLock);
3366 return 1;
3368 case ALC_SYNC:
3369 if(device->Type == Loopback)
3371 alcSetError(device, ALC_INVALID_DEVICE);
3372 return 0;
3374 values[0] = ALC_FALSE;
3375 return 1;
3377 case ALC_FORMAT_CHANNELS_SOFT:
3378 if(device->Type != Loopback)
3380 alcSetError(device, ALC_INVALID_DEVICE);
3381 return 0;
3383 values[0] = device->FmtChans;
3384 return 1;
3386 case ALC_FORMAT_TYPE_SOFT:
3387 if(device->Type != Loopback)
3389 alcSetError(device, ALC_INVALID_DEVICE);
3390 return 0;
3392 values[0] = device->FmtType;
3393 return 1;
3395 case ALC_AMBISONIC_LAYOUT_SOFT:
3396 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3398 alcSetError(device, ALC_INVALID_DEVICE);
3399 return 0;
3401 values[0] = device->AmbiLayout;
3402 return 1;
3404 case ALC_AMBISONIC_SCALING_SOFT:
3405 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3407 alcSetError(device, ALC_INVALID_DEVICE);
3408 return 0;
3410 values[0] = device->AmbiScale;
3411 return 1;
3413 case ALC_AMBISONIC_ORDER_SOFT:
3414 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3416 alcSetError(device, ALC_INVALID_DEVICE);
3417 return 0;
3419 values[0] = device->AmbiOrder;
3420 return 1;
3422 case ALC_MONO_SOURCES:
3423 values[0] = device->NumMonoSources;
3424 return 1;
3426 case ALC_STEREO_SOURCES:
3427 values[0] = device->NumStereoSources;
3428 return 1;
3430 case ALC_MAX_AUXILIARY_SENDS:
3431 values[0] = device->NumAuxSends;
3432 return 1;
3434 case ALC_CONNECTED:
3435 values[0] = ATOMIC_LOAD(&device->Connected, almemory_order_acquire);
3436 return 1;
3438 case ALC_HRTF_SOFT:
3439 values[0] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3440 return 1;
3442 case ALC_HRTF_STATUS_SOFT:
3443 values[0] = device->HrtfStatus;
3444 return 1;
3446 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3447 almtx_lock(&device->BackendLock);
3448 FreeHrtfList(&device->HrtfList);
3449 device->HrtfList = EnumerateHrtf(device->DeviceName);
3450 values[0] = (ALCint)VECTOR_SIZE(device->HrtfList);
3451 almtx_unlock(&device->BackendLock);
3452 return 1;
3454 case ALC_OUTPUT_LIMITER_SOFT:
3455 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3456 return 1;
3458 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3459 values[0] = MAX_AMBI_ORDER;
3460 return 1;
3462 default:
3463 alcSetError(device, ALC_INVALID_ENUM);
3464 return 0;
3466 return 0;
3469 /* alcGetIntegerv
3471 * Returns information about the device and the version of OpenAL
3473 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3475 VerifyDevice(&device);
3476 if(size <= 0 || values == nullptr)
3477 alcSetError(device, ALC_INVALID_VALUE);
3478 else
3479 GetIntegerv(device, param, size, values);
3480 if(device) ALCdevice_DecRef(device);
3483 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3485 ALsizei i;
3487 VerifyDevice(&device);
3488 if(size <= 0 || values == nullptr)
3489 alcSetError(device, ALC_INVALID_VALUE);
3490 else if(!device || device->Type == Capture)
3492 std::vector<ALCint> ivals(size);
3493 size = GetIntegerv(device, pname, size, ivals.data());
3494 for(i = 0;i < size;i++)
3495 values[i] = ivals[i];
3497 else /* render device */
3499 ClockLatency clock;
3500 ALuint64 basecount;
3501 ALuint samplecount;
3502 ALuint refcount;
3504 switch(pname)
3506 case ALC_ATTRIBUTES_SIZE:
3507 *values = NumAttrsForDevice(device)+4;
3508 break;
3510 case ALC_ALL_ATTRIBUTES:
3511 if(size < NumAttrsForDevice(device)+4)
3512 alcSetError(device, ALC_INVALID_VALUE);
3513 else
3515 i = 0;
3516 almtx_lock(&device->BackendLock);
3517 values[i++] = ALC_FREQUENCY;
3518 values[i++] = device->Frequency;
3520 if(device->Type != Loopback)
3522 values[i++] = ALC_REFRESH;
3523 values[i++] = device->Frequency / device->UpdateSize;
3525 values[i++] = ALC_SYNC;
3526 values[i++] = ALC_FALSE;
3528 else
3530 if(device->FmtChans == DevFmtAmbi3D)
3532 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3533 values[i++] = device->AmbiLayout;
3535 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3536 values[i++] = device->AmbiScale;
3538 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3539 values[i++] = device->AmbiOrder;
3542 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3543 values[i++] = device->FmtChans;
3545 values[i++] = ALC_FORMAT_TYPE_SOFT;
3546 values[i++] = device->FmtType;
3549 values[i++] = ALC_MONO_SOURCES;
3550 values[i++] = device->NumMonoSources;
3552 values[i++] = ALC_STEREO_SOURCES;
3553 values[i++] = device->NumStereoSources;
3555 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3556 values[i++] = device->NumAuxSends;
3558 values[i++] = ALC_HRTF_SOFT;
3559 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3561 values[i++] = ALC_HRTF_STATUS_SOFT;
3562 values[i++] = device->HrtfStatus;
3564 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3565 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3567 clock = GetClockLatency(device);
3568 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3569 values[i++] = clock.ClockTime;
3571 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3572 values[i++] = clock.Latency;
3573 almtx_unlock(&device->BackendLock);
3575 values[i++] = 0;
3577 break;
3579 case ALC_DEVICE_CLOCK_SOFT:
3580 almtx_lock(&device->BackendLock);
3581 do {
3582 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3583 althrd_yield();
3584 basecount = device->ClockBase;
3585 samplecount = device->SamplesDone;
3586 } while(refcount != ReadRef(&device->MixCount));
3587 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3588 almtx_unlock(&device->BackendLock);
3589 break;
3591 case ALC_DEVICE_LATENCY_SOFT:
3592 almtx_lock(&device->BackendLock);
3593 clock = GetClockLatency(device);
3594 almtx_unlock(&device->BackendLock);
3595 *values = clock.Latency;
3596 break;
3598 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3599 if(size < 2)
3600 alcSetError(device, ALC_INVALID_VALUE);
3601 else
3603 almtx_lock(&device->BackendLock);
3604 clock = GetClockLatency(device);
3605 almtx_unlock(&device->BackendLock);
3606 values[0] = clock.ClockTime;
3607 values[1] = clock.Latency;
3609 break;
3611 default:
3612 std::vector<ALCint> ivals(size);
3613 size = GetIntegerv(device, pname, size, ivals.data());
3614 for(i = 0;i < size;i++)
3615 values[i] = ivals[i];
3616 break;
3619 if(device)
3620 ALCdevice_DecRef(device);
3624 /* alcIsExtensionPresent
3626 * Determines if there is support for a particular extension
3628 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3630 ALCboolean bResult = ALC_FALSE;
3632 VerifyDevice(&device);
3634 if(!extName)
3635 alcSetError(device, ALC_INVALID_VALUE);
3636 else
3638 size_t len = strlen(extName);
3639 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3640 while(ptr && *ptr)
3642 if(strncasecmp(ptr, extName, len) == 0 &&
3643 (ptr[len] == '\0' || isspace(ptr[len])))
3645 bResult = ALC_TRUE;
3646 break;
3648 if((ptr=strchr(ptr, ' ')) != nullptr)
3650 do {
3651 ++ptr;
3652 } while(isspace(*ptr));
3656 if(device)
3657 ALCdevice_DecRef(device);
3658 return bResult;
3662 /* alcGetProcAddress
3664 * Retrieves the function address for a particular extension function
3666 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3668 ALCvoid *ptr = nullptr;
3670 if(!funcName)
3672 VerifyDevice(&device);
3673 alcSetError(device, ALC_INVALID_VALUE);
3674 if(device) ALCdevice_DecRef(device);
3676 else
3678 size_t i = 0;
3679 for(i = 0;i < COUNTOF(alcFunctions);i++)
3681 if(strcmp(alcFunctions[i].funcName, funcName) == 0)
3683 ptr = alcFunctions[i].address;
3684 break;
3689 return ptr;
3693 /* alcGetEnumValue
3695 * Get the value for a particular ALC enumeration name
3697 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3699 ALCenum val = 0;
3701 if(!enumName)
3703 VerifyDevice(&device);
3704 alcSetError(device, ALC_INVALID_VALUE);
3705 if(device) ALCdevice_DecRef(device);
3707 else
3709 size_t i = 0;
3710 for(i = 0;i < COUNTOF(alcEnumerations);i++)
3712 if(strcmp(alcEnumerations[i].enumName, enumName) == 0)
3714 val = alcEnumerations[i].value;
3715 break;
3720 return val;
3724 /* alcCreateContext
3726 * Create and attach a context to the given device.
3728 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3730 ALCcontext *ALContext;
3731 ALfloat valf;
3732 ALCenum err;
3734 /* Explicitly hold the list lock while taking the BackendLock in case the
3735 * device is asynchronously destropyed, to ensure this new context is
3736 * properly cleaned up after being made.
3738 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3739 if(!VerifyDevice(&device) || device->Type == Capture ||
3740 !ATOMIC_LOAD(&device->Connected, almemory_order_relaxed))
3742 listlock.unlock();
3743 alcSetError(device, ALC_INVALID_DEVICE);
3744 if(device) ALCdevice_DecRef(device);
3745 return nullptr;
3747 almtx_lock(&device->BackendLock);
3748 listlock.unlock();
3750 ATOMIC_STORE_SEQ(&device->LastError, ALC_NO_ERROR);
3752 if(device->Type == Playback && DefaultEffect.type != AL_EFFECT_NULL)
3753 ALContext = static_cast<ALCcontext*>(al_calloc(16,
3754 sizeof(ALCcontext)+sizeof(ALlistener)+sizeof(ALeffectslot)));
3755 else
3756 ALContext = static_cast<ALCcontext*>(al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener)));
3757 if(!ALContext)
3759 almtx_unlock(&device->BackendLock);
3761 alcSetError(device, ALC_OUT_OF_MEMORY);
3762 ALCdevice_DecRef(device);
3763 return nullptr;
3766 InitRef(&ALContext->ref, 1);
3767 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3768 ALContext->DefaultSlot = nullptr;
3770 ALContext->Voices = nullptr;
3771 ALContext->VoiceCount = 0;
3772 ALContext->MaxVoices = 0;
3773 ATOMIC_INIT(&ALContext->ActiveAuxSlots, static_cast<ALeffectslotArray*>(nullptr));
3774 ALContext->Device = device;
3775 ATOMIC_INIT(&ALContext->next, static_cast<ALCcontext*>(nullptr));
3777 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3779 almtx_unlock(&device->BackendLock);
3781 al_free(ALContext);
3782 ALContext = nullptr;
3784 alcSetError(device, err);
3785 if(err == ALC_INVALID_DEVICE)
3787 V0(device->Backend,lock)();
3788 aluHandleDisconnect(device, "Device update failure");
3789 V0(device->Backend,unlock)();
3791 ALCdevice_DecRef(device);
3792 return nullptr;
3794 AllocateVoices(ALContext, 256, device->NumAuxSends);
3796 if(DefaultEffect.type != AL_EFFECT_NULL && device->Type == Playback)
3798 ALContext->DefaultSlot = (ALeffectslot*)(ALContext->_listener_mem + sizeof(ALlistener));
3799 if(InitEffectSlot(ALContext->DefaultSlot) == AL_NO_ERROR)
3800 aluInitEffectPanning(ALContext->DefaultSlot);
3801 else
3803 ALContext->DefaultSlot = nullptr;
3804 ERR("Failed to initialize the default effect slot\n");
3808 ALCdevice_IncRef(ALContext->Device);
3809 InitContext(ALContext);
3811 if(ConfigValueFloat(device->DeviceName, nullptr, "volume-adjust", &valf))
3813 if(!std::isfinite(valf))
3814 ERR("volume-adjust must be finite: %f\n", valf);
3815 else
3817 ALfloat db = clampf(valf, -24.0f, 24.0f);
3818 if(db != valf)
3819 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3820 ALContext->GainBoost = std::pow(10.0f, db/20.0f);
3821 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3824 UpdateListenerProps(ALContext);
3827 ALCcontext *head = ATOMIC_LOAD_SEQ(&device->ContextList);
3828 do {
3829 ATOMIC_STORE(&ALContext->next, head, almemory_order_relaxed);
3830 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device->ContextList, &head,
3831 ALContext) == 0);
3833 almtx_unlock(&device->BackendLock);
3835 if(ALContext->DefaultSlot)
3837 if(InitializeEffect(ALContext, ALContext->DefaultSlot, &DefaultEffect) == AL_NO_ERROR)
3838 UpdateEffectSlotProps(ALContext->DefaultSlot, ALContext);
3839 else
3840 ERR("Failed to initialize the default effect\n");
3843 ALCdevice_DecRef(device);
3845 TRACE("Created context %p\n", ALContext);
3846 return ALContext;
3849 /* alcDestroyContext
3851 * Remove a context from its device
3853 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3855 std::unique_lock<std::recursive_mutex> listlock{ListLock};
3856 if(!VerifyContext(&context))
3858 listlock.unlock();
3859 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3860 return;
3863 ALCdevice* Device{context->Device};
3864 if(Device)
3866 almtx_lock(&Device->BackendLock);
3867 if(!ReleaseContext(context, Device))
3869 V0(Device->Backend,stop)();
3870 Device->Flags &= ~DEVICE_RUNNING;
3872 almtx_unlock(&Device->BackendLock);
3874 listlock.unlock();
3876 ALCcontext_DecRef(context);
3880 /* alcGetCurrentContext
3882 * Returns the currently active context on the calling thread
3884 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3886 ALCcontext *Context{static_cast<ALCcontext*>(altss_get(LocalContext))};
3887 if(!Context) Context = GlobalContext.load();
3888 return Context;
3891 /* alcGetThreadContext
3893 * Returns the currently active thread-local context
3895 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3897 return static_cast<ALCcontext*>(altss_get(LocalContext));
3901 /* alcMakeContextCurrent
3903 * Makes the given context the active process-wide context, and removes the
3904 * thread-local context for the calling thread.
3906 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3908 /* context must be valid or nullptr */
3909 if(context && !VerifyContext(&context))
3911 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3912 return ALC_FALSE;
3914 /* context's reference count is already incremented */
3915 context = GlobalContext.exchange(context);
3916 if(context) ALCcontext_DecRef(context);
3918 if((context=static_cast<ALCcontext*>(altss_get(LocalContext))) != nullptr)
3920 altss_set(LocalContext, nullptr);
3921 ALCcontext_DecRef(context);
3924 return ALC_TRUE;
3927 /* alcSetThreadContext
3929 * Makes the given context the active context for the current thread
3931 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3933 /* context must be valid or nullptr */
3934 if(context && !VerifyContext(&context))
3936 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3937 return ALC_FALSE;
3939 /* context's reference count is already incremented */
3940 ALCcontext *old{static_cast<ALCcontext*>(altss_get(LocalContext))};
3941 altss_set(LocalContext, context);
3942 if(old) ALCcontext_DecRef(old);
3944 return ALC_TRUE;
3948 /* alcGetContextsDevice
3950 * Returns the device that a particular context is attached to
3952 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3954 if(!VerifyContext(&Context))
3956 alcSetError(nullptr, ALC_INVALID_CONTEXT);
3957 return nullptr;
3959 ALCdevice *Device{Context->Device};
3960 ALCcontext_DecRef(Context);
3962 return Device;
3966 /* alcOpenDevice
3968 * Opens the named device.
3970 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3972 const ALCchar *fmt;
3973 ALCdevice *device;
3974 ALCenum err;
3976 DO_INITCONFIG();
3978 if(!PlaybackBackend.name)
3980 alcSetError(nullptr, ALC_INVALID_VALUE);
3981 return nullptr;
3984 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
3985 #ifdef _WIN32
3986 /* Some old Windows apps hardcode these expecting OpenAL to use a
3987 * specific audio API, even when they're not enumerated. Creative's
3988 * router effectively ignores them too.
3990 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
3991 || strcasecmp(deviceName, "MMSYSTEM") == 0
3992 #endif
3994 deviceName = nullptr;
3996 device = static_cast<ALCdevice*>(al_calloc(16, sizeof(ALCdevice)));
3997 if(!device)
3999 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
4000 return nullptr;
4003 //Validate device
4004 InitDevice(device, Playback);
4006 //Set output format
4007 device->FmtChans = DevFmtChannelsDefault;
4008 device->FmtType = DevFmtTypeDefault;
4009 device->Frequency = DEFAULT_OUTPUT_RATE;
4010 device->IsHeadphones = AL_FALSE;
4011 device->AmbiLayout = AmbiLayout_Default;
4012 device->AmbiScale = AmbiNorm_Default;
4013 device->LimiterState = ALC_TRUE;
4014 device->NumUpdates = 3;
4015 device->UpdateSize = 1024;
4017 device->SourcesMax = 256;
4018 device->AuxiliaryEffectSlotMax = 64;
4019 device->NumAuxSends = DEFAULT_SENDS;
4021 if(ConfigValueStr(deviceName, nullptr, "channels", &fmt))
4023 static const struct {
4024 const char name[16];
4025 enum DevFmtChannels chans;
4026 ALsizei order;
4027 } chanlist[] = {
4028 { "mono", DevFmtMono, 0 },
4029 { "stereo", DevFmtStereo, 0 },
4030 { "quad", DevFmtQuad, 0 },
4031 { "surround51", DevFmtX51, 0 },
4032 { "surround61", DevFmtX61, 0 },
4033 { "surround71", DevFmtX71, 0 },
4034 { "surround51rear", DevFmtX51Rear, 0 },
4035 { "ambi1", DevFmtAmbi3D, 1 },
4036 { "ambi2", DevFmtAmbi3D, 2 },
4037 { "ambi3", DevFmtAmbi3D, 3 },
4039 size_t i;
4041 for(i = 0;i < COUNTOF(chanlist);i++)
4043 if(strcasecmp(chanlist[i].name, fmt) == 0)
4045 device->FmtChans = chanlist[i].chans;
4046 device->AmbiOrder = chanlist[i].order;
4047 device->Flags |= DEVICE_CHANNELS_REQUEST;
4048 break;
4051 if(i == COUNTOF(chanlist))
4052 ERR("Unsupported channels: %s\n", fmt);
4054 if(ConfigValueStr(deviceName, nullptr, "sample-type", &fmt))
4056 static const struct {
4057 const char name[16];
4058 enum DevFmtType type;
4059 } typelist[] = {
4060 { "int8", DevFmtByte },
4061 { "uint8", DevFmtUByte },
4062 { "int16", DevFmtShort },
4063 { "uint16", DevFmtUShort },
4064 { "int32", DevFmtInt },
4065 { "uint32", DevFmtUInt },
4066 { "float32", DevFmtFloat },
4068 size_t i;
4070 for(i = 0;i < COUNTOF(typelist);i++)
4072 if(strcasecmp(typelist[i].name, fmt) == 0)
4074 device->FmtType = typelist[i].type;
4075 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
4076 break;
4079 if(i == COUNTOF(typelist))
4080 ERR("Unsupported sample-type: %s\n", fmt);
4083 if(ConfigValueUInt(deviceName, nullptr, "frequency", &device->Frequency))
4085 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4086 if(device->Frequency < MIN_OUTPUT_RATE)
4087 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
4088 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
4091 ConfigValueUInt(deviceName, nullptr, "periods", &device->NumUpdates);
4092 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
4094 ConfigValueUInt(deviceName, nullptr, "period_size", &device->UpdateSize);
4095 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
4096 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
4097 device->UpdateSize = (device->UpdateSize+3)&~3;
4099 ConfigValueUInt(deviceName, nullptr, "sources", &device->SourcesMax);
4100 if(device->SourcesMax == 0) device->SourcesMax = 256;
4102 ConfigValueUInt(deviceName, nullptr, "slots", &device->AuxiliaryEffectSlotMax);
4103 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4104 else device->AuxiliaryEffectSlotMax = minu(device->AuxiliaryEffectSlotMax, INT_MAX);
4106 if(ConfigValueInt(deviceName, nullptr, "sends", &device->NumAuxSends))
4107 device->NumAuxSends = clampi(
4108 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4111 device->NumStereoSources = 1;
4112 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4114 device->Backend = PlaybackBackend.getFactory().createBackend(device, ALCbackend_Playback);
4115 if(!device->Backend)
4117 FreeDevice(device);
4118 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
4119 return nullptr;
4122 // Find a playback device to open
4123 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4125 FreeDevice(device);
4126 alcSetError(nullptr, err);
4127 return nullptr;
4130 if(ConfigValueStr(device->DeviceName, nullptr, "ambi-format", &fmt))
4132 if(strcasecmp(fmt, "fuma") == 0)
4134 device->AmbiLayout = AmbiLayout_FuMa;
4135 device->AmbiScale = AmbiNorm_FuMa;
4137 else if(strcasecmp(fmt, "acn+sn3d") == 0)
4139 device->AmbiLayout = AmbiLayout_ACN;
4140 device->AmbiScale = AmbiNorm_SN3D;
4142 else if(strcasecmp(fmt, "acn+n3d") == 0)
4144 device->AmbiLayout = AmbiLayout_ACN;
4145 device->AmbiScale = AmbiNorm_N3D;
4147 else
4148 ERR("Unsupported ambi-format: %s\n", fmt);
4152 ALCdevice *head{DeviceList.load()};
4153 do {
4154 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4155 } while(!DeviceList.compare_exchange_weak(head, device));
4158 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName);
4159 return device;
4162 /* alcCloseDevice
4164 * Closes the given device.
4166 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
4168 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4169 ALCdevice *iter{DeviceList.load()};
4170 do {
4171 if(iter == device)
4172 break;
4173 iter = ATOMIC_LOAD(&iter->next, almemory_order_relaxed);
4174 } while(iter != nullptr);
4175 if(!iter || iter->Type == Capture)
4177 alcSetError(iter, ALC_INVALID_DEVICE);
4178 return ALC_FALSE;
4180 almtx_lock(&device->BackendLock);
4182 ALCdevice *origdev{device};
4183 ALCdevice *nextdev{ATOMIC_LOAD(&device->next, almemory_order_relaxed)};
4184 if(!DeviceList.compare_exchange_strong(origdev, nextdev))
4186 ALCdevice *list;
4187 do {
4188 list = origdev;
4189 origdev = device;
4190 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list->next, &origdev, nextdev));
4192 listlock.unlock();
4194 ALCcontext *ctx{ATOMIC_LOAD_SEQ(&device->ContextList)};
4195 while(ctx != nullptr)
4197 ALCcontext *next = ATOMIC_LOAD(&ctx->next, almemory_order_relaxed);
4198 WARN("Releasing context %p\n", ctx);
4199 ReleaseContext(ctx, device);
4200 ctx = next;
4202 if((device->Flags&DEVICE_RUNNING))
4203 V0(device->Backend,stop)();
4204 device->Flags &= ~DEVICE_RUNNING;
4205 almtx_unlock(&device->BackendLock);
4207 ALCdevice_DecRef(device);
4209 return ALC_TRUE;
4213 /************************************************
4214 * ALC capture functions
4215 ************************************************/
4216 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
4218 ALCdevice *device = nullptr;
4219 ALCenum err;
4221 DO_INITCONFIG();
4223 if(!CaptureBackend.name)
4225 alcSetError(nullptr, ALC_INVALID_VALUE);
4226 return nullptr;
4229 if(samples <= 0)
4231 alcSetError(nullptr, ALC_INVALID_VALUE);
4232 return nullptr;
4235 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
4236 deviceName = nullptr;
4238 device = static_cast<ALCdevice*>(al_calloc(16, sizeof(ALCdevice)));
4239 if(!device)
4241 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
4242 return nullptr;
4245 //Validate device
4246 InitDevice(device, Capture);
4248 device->Frequency = frequency;
4249 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4251 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
4253 FreeDevice(device);
4254 alcSetError(nullptr, ALC_INVALID_ENUM);
4255 return nullptr;
4257 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
4258 device->IsHeadphones = AL_FALSE;
4259 device->AmbiOrder = 0;
4260 device->AmbiLayout = AmbiLayout_Default;
4261 device->AmbiScale = AmbiNorm_Default;
4263 device->UpdateSize = samples;
4264 device->NumUpdates = 1;
4266 device->Backend = CaptureBackend.getFactory().createBackend(device, ALCbackend_Capture);
4267 if(!device->Backend)
4269 FreeDevice(device);
4270 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
4271 return nullptr;
4274 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4275 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
4276 device->Frequency, device->UpdateSize, device->NumUpdates
4278 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4280 FreeDevice(device);
4281 alcSetError(nullptr, err);
4282 return nullptr;
4286 ALCdevice *head{DeviceList.load()};
4287 do {
4288 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4289 } while(!DeviceList.compare_exchange_weak(head, device));
4292 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName);
4293 return device;
4296 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
4298 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4300 ALCdevice *iter{DeviceList.load()};
4301 do {
4302 if(iter == device)
4303 break;
4304 iter = ATOMIC_LOAD(&iter->next, almemory_order_relaxed);
4305 } while(iter != nullptr);
4306 if(!iter || iter->Type != Capture)
4308 alcSetError(iter, ALC_INVALID_DEVICE);
4309 return ALC_FALSE;
4312 ALCdevice *origdev{device};
4313 ALCdevice *nextdev{ATOMIC_LOAD(&device->next, almemory_order_relaxed)};
4314 if(!DeviceList.compare_exchange_strong(origdev, nextdev))
4316 ALCdevice *list;
4317 do {
4318 list = origdev;
4319 origdev = device;
4320 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list->next, &origdev, nextdev));
4322 listlock.unlock();
4324 almtx_lock(&device->BackendLock);
4325 if((device->Flags&DEVICE_RUNNING))
4326 V0(device->Backend,stop)();
4327 device->Flags &= ~DEVICE_RUNNING;
4328 almtx_unlock(&device->BackendLock);
4330 ALCdevice_DecRef(device);
4332 return ALC_TRUE;
4335 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
4337 if(!VerifyDevice(&device) || device->Type != Capture)
4338 alcSetError(device, ALC_INVALID_DEVICE);
4339 else
4341 almtx_lock(&device->BackendLock);
4342 if(!ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
4343 alcSetError(device, ALC_INVALID_DEVICE);
4344 else if(!(device->Flags&DEVICE_RUNNING))
4346 if(V0(device->Backend,start)())
4347 device->Flags |= DEVICE_RUNNING;
4348 else
4350 aluHandleDisconnect(device, "Device start failure");
4351 alcSetError(device, ALC_INVALID_DEVICE);
4354 almtx_unlock(&device->BackendLock);
4357 if(device) ALCdevice_DecRef(device);
4360 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
4362 if(!VerifyDevice(&device) || device->Type != Capture)
4363 alcSetError(device, ALC_INVALID_DEVICE);
4364 else
4366 almtx_lock(&device->BackendLock);
4367 if((device->Flags&DEVICE_RUNNING))
4368 V0(device->Backend,stop)();
4369 device->Flags &= ~DEVICE_RUNNING;
4370 almtx_unlock(&device->BackendLock);
4373 if(device) ALCdevice_DecRef(device);
4376 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4378 if(!VerifyDevice(&device) || device->Type != Capture)
4379 alcSetError(device, ALC_INVALID_DEVICE);
4380 else
4382 ALCenum err = ALC_INVALID_VALUE;
4384 almtx_lock(&device->BackendLock);
4385 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
4386 err = V(device->Backend,captureSamples)(buffer, samples);
4387 almtx_unlock(&device->BackendLock);
4389 if(err != ALC_NO_ERROR)
4390 alcSetError(device, err);
4392 if(device) ALCdevice_DecRef(device);
4396 /************************************************
4397 * ALC loopback functions
4398 ************************************************/
4400 /* alcLoopbackOpenDeviceSOFT
4402 * Open a loopback device, for manual rendering.
4404 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
4406 DO_INITCONFIG();
4408 /* Make sure the device name, if specified, is us. */
4409 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
4411 alcSetError(nullptr, ALC_INVALID_VALUE);
4412 return nullptr;
4415 ALCdevice *device{static_cast<ALCdevice*>(al_calloc(16, sizeof(ALCdevice)))};
4416 if(!device)
4418 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
4419 return nullptr;
4422 //Validate device
4423 InitDevice(device, Loopback);
4425 device->SourcesMax = 256;
4426 device->AuxiliaryEffectSlotMax = 64;
4427 device->NumAuxSends = DEFAULT_SENDS;
4429 //Set output format
4430 device->NumUpdates = 0;
4431 device->UpdateSize = 0;
4433 device->Frequency = DEFAULT_OUTPUT_RATE;
4434 device->FmtChans = DevFmtChannelsDefault;
4435 device->FmtType = DevFmtTypeDefault;
4436 device->IsHeadphones = AL_FALSE;
4437 device->AmbiLayout = AmbiLayout_Default;
4438 device->AmbiScale = AmbiNorm_Default;
4440 ConfigValueUInt(nullptr, nullptr, "sources", &device->SourcesMax);
4441 if(device->SourcesMax == 0) device->SourcesMax = 256;
4443 ConfigValueUInt(nullptr, nullptr, "slots", &device->AuxiliaryEffectSlotMax);
4444 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4445 else device->AuxiliaryEffectSlotMax = minu(device->AuxiliaryEffectSlotMax, INT_MAX);
4447 if(ConfigValueInt(nullptr, nullptr, "sends", &device->NumAuxSends))
4448 device->NumAuxSends = clampi(
4449 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4452 device->NumStereoSources = 1;
4453 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4455 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
4456 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
4457 if(!device->Backend)
4459 al_free(device);
4460 alcSetError(nullptr, ALC_OUT_OF_MEMORY);
4461 return nullptr;
4464 // Open the "backend"
4465 V(device->Backend,open)("Loopback");
4468 ALCdevice *head{DeviceList.load()};
4469 do {
4470 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4471 } while(!DeviceList.compare_exchange_weak(head, device));
4474 TRACE("Created device %p\n", device);
4475 return device;
4478 /* alcIsRenderFormatSupportedSOFT
4480 * Determines if the loopback device supports the given format for rendering.
4482 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4484 ALCboolean ret = ALC_FALSE;
4486 if(!VerifyDevice(&device) || device->Type != Loopback)
4487 alcSetError(device, ALC_INVALID_DEVICE);
4488 else if(freq <= 0)
4489 alcSetError(device, ALC_INVALID_VALUE);
4490 else
4492 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4493 ret = ALC_TRUE;
4495 if(device) ALCdevice_DecRef(device);
4497 return ret;
4500 /* alcRenderSamplesSOFT
4502 * Renders some samples into a buffer, using the format last set by the
4503 * attributes given to alcCreateContext.
4505 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4507 if(!VerifyDevice(&device) || device->Type != Loopback)
4508 alcSetError(device, ALC_INVALID_DEVICE);
4509 else if(samples < 0 || (samples > 0 && buffer == nullptr))
4510 alcSetError(device, ALC_INVALID_VALUE);
4511 else
4513 V0(device->Backend,lock)();
4514 aluMixData(device, buffer, samples);
4515 V0(device->Backend,unlock)();
4517 if(device) ALCdevice_DecRef(device);
4521 /************************************************
4522 * ALC DSP pause/resume functions
4523 ************************************************/
4525 /* alcDevicePauseSOFT
4527 * Pause the DSP to stop audio processing.
4529 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4531 if(!VerifyDevice(&device) || device->Type != Playback)
4532 alcSetError(device, ALC_INVALID_DEVICE);
4533 else
4535 almtx_lock(&device->BackendLock);
4536 if((device->Flags&DEVICE_RUNNING))
4537 V0(device->Backend,stop)();
4538 device->Flags &= ~DEVICE_RUNNING;
4539 device->Flags |= DEVICE_PAUSED;
4540 almtx_unlock(&device->BackendLock);
4542 if(device) ALCdevice_DecRef(device);
4545 /* alcDeviceResumeSOFT
4547 * Resume the DSP to restart audio processing.
4549 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4551 if(!VerifyDevice(&device) || device->Type != Playback)
4552 alcSetError(device, ALC_INVALID_DEVICE);
4553 else
4555 almtx_lock(&device->BackendLock);
4556 if((device->Flags&DEVICE_PAUSED))
4558 device->Flags &= ~DEVICE_PAUSED;
4559 if(ATOMIC_LOAD_SEQ(&device->ContextList) != nullptr)
4561 if(V0(device->Backend,start)() != ALC_FALSE)
4562 device->Flags |= DEVICE_RUNNING;
4563 else
4565 V0(device->Backend,lock)();
4566 aluHandleDisconnect(device, "Device start failure");
4567 V0(device->Backend,unlock)();
4568 alcSetError(device, ALC_INVALID_DEVICE);
4572 almtx_unlock(&device->BackendLock);
4574 if(device) ALCdevice_DecRef(device);
4578 /************************************************
4579 * ALC HRTF functions
4580 ************************************************/
4582 /* alcGetStringiSOFT
4584 * Gets a string parameter at the given index.
4586 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4588 const ALCchar *str = nullptr;
4590 if(!VerifyDevice(&device) || device->Type == Capture)
4591 alcSetError(device, ALC_INVALID_DEVICE);
4592 else switch(paramName)
4594 case ALC_HRTF_SPECIFIER_SOFT:
4595 if(index >= 0 && (size_t)index < VECTOR_SIZE(device->HrtfList))
4596 str = VECTOR_ELEM(device->HrtfList, index).name;
4597 else
4598 alcSetError(device, ALC_INVALID_VALUE);
4599 break;
4601 default:
4602 alcSetError(device, ALC_INVALID_ENUM);
4603 break;
4605 if(device) ALCdevice_DecRef(device);
4607 return str;
4610 /* alcResetDeviceSOFT
4612 * Resets the given device output, using the specified attribute list.
4614 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4616 ALCenum err;
4618 std::unique_lock<std::recursive_mutex> listlock{ListLock};
4619 if(!VerifyDevice(&device) || device->Type == Capture ||
4620 !ATOMIC_LOAD(&device->Connected, almemory_order_relaxed))
4622 listlock.unlock();
4623 alcSetError(device, ALC_INVALID_DEVICE);
4624 if(device) ALCdevice_DecRef(device);
4625 return ALC_FALSE;
4627 almtx_lock(&device->BackendLock);
4628 listlock.unlock();
4630 err = UpdateDeviceParams(device, attribs);
4631 almtx_unlock(&device->BackendLock);
4633 if(err != ALC_NO_ERROR)
4635 alcSetError(device, err);
4636 if(err == ALC_INVALID_DEVICE)
4638 V0(device->Backend,lock)();
4639 aluHandleDisconnect(device, "Device start failure");
4640 V0(device->Backend,unlock)();
4642 ALCdevice_DecRef(device);
4643 return ALC_FALSE;
4645 ALCdevice_DecRef(device);
4647 return ALC_TRUE;