Use a 24-bit dither depth limit
[openal-soft.git] / Alc / ALc.c
blob6e10897b81c35701ca8d0910fa98722046571033
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 <math.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <memory.h>
29 #include <ctype.h>
30 #include <signal.h>
32 #include "alMain.h"
33 #include "alSource.h"
34 #include "alListener.h"
35 #include "alSource.h"
36 #include "alBuffer.h"
37 #include "alFilter.h"
38 #include "alEffect.h"
39 #include "alAuxEffectSlot.h"
40 #include "alError.h"
41 #include "mastering.h"
42 #include "bformatdec.h"
43 #include "alu.h"
44 #include "alconfig.h"
45 #include "ringbuffer.h"
47 #include "fpu_modes.h"
48 #include "cpu_caps.h"
49 #include "compat.h"
50 #include "threads.h"
51 #include "alstring.h"
52 #include "almalloc.h"
54 #include "backends/base.h"
57 /************************************************
58 * Backends
59 ************************************************/
60 struct BackendInfo {
61 const char *name;
62 ALCbackendFactory* (*getFactory)(void);
65 static struct BackendInfo BackendList[] = {
66 #ifdef HAVE_JACK
67 { "jack", ALCjackBackendFactory_getFactory },
68 #endif
69 #ifdef HAVE_PULSEAUDIO
70 { "pulse", ALCpulseBackendFactory_getFactory },
71 #endif
72 #ifdef HAVE_ALSA
73 { "alsa", ALCalsaBackendFactory_getFactory },
74 #endif
75 #ifdef HAVE_COREAUDIO
76 { "core", ALCcoreAudioBackendFactory_getFactory },
77 #endif
78 #ifdef HAVE_SOLARIS
79 { "solaris", ALCsolarisBackendFactory_getFactory },
80 #endif
81 #ifdef HAVE_SNDIO
82 { "sndio", SndioBackendFactory_getFactory },
83 #endif
84 #ifdef HAVE_OSS
85 { "oss", ALCossBackendFactory_getFactory },
86 #endif
87 #ifdef HAVE_QSA
88 { "qsa", ALCqsaBackendFactory_getFactory },
89 #endif
90 #ifdef HAVE_WASAPI
91 { "wasapi", ALCwasapiBackendFactory_getFactory },
92 #endif
93 #ifdef HAVE_DSOUND
94 { "dsound", ALCdsoundBackendFactory_getFactory },
95 #endif
96 #ifdef HAVE_WINMM
97 { "winmm", ALCwinmmBackendFactory_getFactory },
98 #endif
99 #ifdef HAVE_PORTAUDIO
100 { "port", ALCportBackendFactory_getFactory },
101 #endif
102 #ifdef HAVE_OPENSL
103 { "opensl", ALCopenslBackendFactory_getFactory },
104 #endif
105 #ifdef HAVE_SDL2
106 { "sdl2", ALCsdl2BackendFactory_getFactory },
107 #endif
109 { "null", ALCnullBackendFactory_getFactory },
110 #ifdef HAVE_WAVE
111 { "wave", ALCwaveBackendFactory_getFactory },
112 #endif
114 static ALsizei BackendListSize = COUNTOF(BackendList);
115 #undef EmptyFuncs
117 static struct BackendInfo PlaybackBackend;
118 static struct BackendInfo CaptureBackend;
121 /************************************************
122 * Functions, enums, and errors
123 ************************************************/
124 #define DECL(x) { #x, (ALCvoid*)(x) }
125 static const struct {
126 const ALCchar *funcName;
127 ALCvoid *address;
128 } alcFunctions[] = {
129 DECL(alcCreateContext),
130 DECL(alcMakeContextCurrent),
131 DECL(alcProcessContext),
132 DECL(alcSuspendContext),
133 DECL(alcDestroyContext),
134 DECL(alcGetCurrentContext),
135 DECL(alcGetContextsDevice),
136 DECL(alcOpenDevice),
137 DECL(alcCloseDevice),
138 DECL(alcGetError),
139 DECL(alcIsExtensionPresent),
140 DECL(alcGetProcAddress),
141 DECL(alcGetEnumValue),
142 DECL(alcGetString),
143 DECL(alcGetIntegerv),
144 DECL(alcCaptureOpenDevice),
145 DECL(alcCaptureCloseDevice),
146 DECL(alcCaptureStart),
147 DECL(alcCaptureStop),
148 DECL(alcCaptureSamples),
150 DECL(alcSetThreadContext),
151 DECL(alcGetThreadContext),
153 DECL(alcLoopbackOpenDeviceSOFT),
154 DECL(alcIsRenderFormatSupportedSOFT),
155 DECL(alcRenderSamplesSOFT),
157 DECL(alcDevicePauseSOFT),
158 DECL(alcDeviceResumeSOFT),
160 DECL(alcGetStringiSOFT),
161 DECL(alcResetDeviceSOFT),
163 DECL(alcGetInteger64vSOFT),
165 DECL(alEnable),
166 DECL(alDisable),
167 DECL(alIsEnabled),
168 DECL(alGetString),
169 DECL(alGetBooleanv),
170 DECL(alGetIntegerv),
171 DECL(alGetFloatv),
172 DECL(alGetDoublev),
173 DECL(alGetBoolean),
174 DECL(alGetInteger),
175 DECL(alGetFloat),
176 DECL(alGetDouble),
177 DECL(alGetError),
178 DECL(alIsExtensionPresent),
179 DECL(alGetProcAddress),
180 DECL(alGetEnumValue),
181 DECL(alListenerf),
182 DECL(alListener3f),
183 DECL(alListenerfv),
184 DECL(alListeneri),
185 DECL(alListener3i),
186 DECL(alListeneriv),
187 DECL(alGetListenerf),
188 DECL(alGetListener3f),
189 DECL(alGetListenerfv),
190 DECL(alGetListeneri),
191 DECL(alGetListener3i),
192 DECL(alGetListeneriv),
193 DECL(alGenSources),
194 DECL(alDeleteSources),
195 DECL(alIsSource),
196 DECL(alSourcef),
197 DECL(alSource3f),
198 DECL(alSourcefv),
199 DECL(alSourcei),
200 DECL(alSource3i),
201 DECL(alSourceiv),
202 DECL(alGetSourcef),
203 DECL(alGetSource3f),
204 DECL(alGetSourcefv),
205 DECL(alGetSourcei),
206 DECL(alGetSource3i),
207 DECL(alGetSourceiv),
208 DECL(alSourcePlayv),
209 DECL(alSourceStopv),
210 DECL(alSourceRewindv),
211 DECL(alSourcePausev),
212 DECL(alSourcePlay),
213 DECL(alSourceStop),
214 DECL(alSourceRewind),
215 DECL(alSourcePause),
216 DECL(alSourceQueueBuffers),
217 DECL(alSourceUnqueueBuffers),
218 DECL(alGenBuffers),
219 DECL(alDeleteBuffers),
220 DECL(alIsBuffer),
221 DECL(alBufferData),
222 DECL(alBufferf),
223 DECL(alBuffer3f),
224 DECL(alBufferfv),
225 DECL(alBufferi),
226 DECL(alBuffer3i),
227 DECL(alBufferiv),
228 DECL(alGetBufferf),
229 DECL(alGetBuffer3f),
230 DECL(alGetBufferfv),
231 DECL(alGetBufferi),
232 DECL(alGetBuffer3i),
233 DECL(alGetBufferiv),
234 DECL(alDopplerFactor),
235 DECL(alDopplerVelocity),
236 DECL(alSpeedOfSound),
237 DECL(alDistanceModel),
239 DECL(alGenFilters),
240 DECL(alDeleteFilters),
241 DECL(alIsFilter),
242 DECL(alFilteri),
243 DECL(alFilteriv),
244 DECL(alFilterf),
245 DECL(alFilterfv),
246 DECL(alGetFilteri),
247 DECL(alGetFilteriv),
248 DECL(alGetFilterf),
249 DECL(alGetFilterfv),
250 DECL(alGenEffects),
251 DECL(alDeleteEffects),
252 DECL(alIsEffect),
253 DECL(alEffecti),
254 DECL(alEffectiv),
255 DECL(alEffectf),
256 DECL(alEffectfv),
257 DECL(alGetEffecti),
258 DECL(alGetEffectiv),
259 DECL(alGetEffectf),
260 DECL(alGetEffectfv),
261 DECL(alGenAuxiliaryEffectSlots),
262 DECL(alDeleteAuxiliaryEffectSlots),
263 DECL(alIsAuxiliaryEffectSlot),
264 DECL(alAuxiliaryEffectSloti),
265 DECL(alAuxiliaryEffectSlotiv),
266 DECL(alAuxiliaryEffectSlotf),
267 DECL(alAuxiliaryEffectSlotfv),
268 DECL(alGetAuxiliaryEffectSloti),
269 DECL(alGetAuxiliaryEffectSlotiv),
270 DECL(alGetAuxiliaryEffectSlotf),
271 DECL(alGetAuxiliaryEffectSlotfv),
273 DECL(alDeferUpdatesSOFT),
274 DECL(alProcessUpdatesSOFT),
276 DECL(alSourcedSOFT),
277 DECL(alSource3dSOFT),
278 DECL(alSourcedvSOFT),
279 DECL(alGetSourcedSOFT),
280 DECL(alGetSource3dSOFT),
281 DECL(alGetSourcedvSOFT),
282 DECL(alSourcei64SOFT),
283 DECL(alSource3i64SOFT),
284 DECL(alSourcei64vSOFT),
285 DECL(alGetSourcei64SOFT),
286 DECL(alGetSource3i64SOFT),
287 DECL(alGetSourcei64vSOFT),
289 DECL(alGetStringiSOFT),
291 DECL(alBufferStorageSOFT),
292 DECL(alMapBufferSOFT),
293 DECL(alUnmapBufferSOFT),
294 DECL(alFlushMappedBufferSOFT),
296 DECL(alEventControlSOFT),
297 DECL(alEventCallbackSOFT),
298 DECL(alGetPointerSOFT),
299 DECL(alGetPointervSOFT),
301 #undef DECL
303 #define DECL(x) { #x, (x) }
304 static const struct {
305 const ALCchar *enumName;
306 ALCenum value;
307 } alcEnumerations[] = {
308 DECL(ALC_INVALID),
309 DECL(ALC_FALSE),
310 DECL(ALC_TRUE),
312 DECL(ALC_MAJOR_VERSION),
313 DECL(ALC_MINOR_VERSION),
314 DECL(ALC_ATTRIBUTES_SIZE),
315 DECL(ALC_ALL_ATTRIBUTES),
316 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
317 DECL(ALC_DEVICE_SPECIFIER),
318 DECL(ALC_ALL_DEVICES_SPECIFIER),
319 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
320 DECL(ALC_EXTENSIONS),
321 DECL(ALC_FREQUENCY),
322 DECL(ALC_REFRESH),
323 DECL(ALC_SYNC),
324 DECL(ALC_MONO_SOURCES),
325 DECL(ALC_STEREO_SOURCES),
326 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
327 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
328 DECL(ALC_CAPTURE_SAMPLES),
329 DECL(ALC_CONNECTED),
331 DECL(ALC_EFX_MAJOR_VERSION),
332 DECL(ALC_EFX_MINOR_VERSION),
333 DECL(ALC_MAX_AUXILIARY_SENDS),
335 DECL(ALC_FORMAT_CHANNELS_SOFT),
336 DECL(ALC_FORMAT_TYPE_SOFT),
338 DECL(ALC_MONO_SOFT),
339 DECL(ALC_STEREO_SOFT),
340 DECL(ALC_QUAD_SOFT),
341 DECL(ALC_5POINT1_SOFT),
342 DECL(ALC_6POINT1_SOFT),
343 DECL(ALC_7POINT1_SOFT),
344 DECL(ALC_BFORMAT3D_SOFT),
346 DECL(ALC_BYTE_SOFT),
347 DECL(ALC_UNSIGNED_BYTE_SOFT),
348 DECL(ALC_SHORT_SOFT),
349 DECL(ALC_UNSIGNED_SHORT_SOFT),
350 DECL(ALC_INT_SOFT),
351 DECL(ALC_UNSIGNED_INT_SOFT),
352 DECL(ALC_FLOAT_SOFT),
354 DECL(ALC_HRTF_SOFT),
355 DECL(ALC_DONT_CARE_SOFT),
356 DECL(ALC_HRTF_STATUS_SOFT),
357 DECL(ALC_HRTF_DISABLED_SOFT),
358 DECL(ALC_HRTF_ENABLED_SOFT),
359 DECL(ALC_HRTF_DENIED_SOFT),
360 DECL(ALC_HRTF_REQUIRED_SOFT),
361 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
362 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
363 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
364 DECL(ALC_HRTF_SPECIFIER_SOFT),
365 DECL(ALC_HRTF_ID_SOFT),
367 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
368 DECL(ALC_AMBISONIC_SCALING_SOFT),
369 DECL(ALC_AMBISONIC_ORDER_SOFT),
370 DECL(ALC_ACN_SOFT),
371 DECL(ALC_FUMA_SOFT),
372 DECL(ALC_N3D_SOFT),
373 DECL(ALC_SN3D_SOFT),
375 DECL(ALC_OUTPUT_LIMITER_SOFT),
377 DECL(ALC_NO_ERROR),
378 DECL(ALC_INVALID_DEVICE),
379 DECL(ALC_INVALID_CONTEXT),
380 DECL(ALC_INVALID_ENUM),
381 DECL(ALC_INVALID_VALUE),
382 DECL(ALC_OUT_OF_MEMORY),
385 DECL(AL_INVALID),
386 DECL(AL_NONE),
387 DECL(AL_FALSE),
388 DECL(AL_TRUE),
390 DECL(AL_SOURCE_RELATIVE),
391 DECL(AL_CONE_INNER_ANGLE),
392 DECL(AL_CONE_OUTER_ANGLE),
393 DECL(AL_PITCH),
394 DECL(AL_POSITION),
395 DECL(AL_DIRECTION),
396 DECL(AL_VELOCITY),
397 DECL(AL_LOOPING),
398 DECL(AL_BUFFER),
399 DECL(AL_GAIN),
400 DECL(AL_MIN_GAIN),
401 DECL(AL_MAX_GAIN),
402 DECL(AL_ORIENTATION),
403 DECL(AL_REFERENCE_DISTANCE),
404 DECL(AL_ROLLOFF_FACTOR),
405 DECL(AL_CONE_OUTER_GAIN),
406 DECL(AL_MAX_DISTANCE),
407 DECL(AL_SEC_OFFSET),
408 DECL(AL_SAMPLE_OFFSET),
409 DECL(AL_BYTE_OFFSET),
410 DECL(AL_SOURCE_TYPE),
411 DECL(AL_STATIC),
412 DECL(AL_STREAMING),
413 DECL(AL_UNDETERMINED),
414 DECL(AL_METERS_PER_UNIT),
415 DECL(AL_LOOP_POINTS_SOFT),
416 DECL(AL_DIRECT_CHANNELS_SOFT),
418 DECL(AL_DIRECT_FILTER),
419 DECL(AL_AUXILIARY_SEND_FILTER),
420 DECL(AL_AIR_ABSORPTION_FACTOR),
421 DECL(AL_ROOM_ROLLOFF_FACTOR),
422 DECL(AL_CONE_OUTER_GAINHF),
423 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
424 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
425 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
427 DECL(AL_SOURCE_STATE),
428 DECL(AL_INITIAL),
429 DECL(AL_PLAYING),
430 DECL(AL_PAUSED),
431 DECL(AL_STOPPED),
433 DECL(AL_BUFFERS_QUEUED),
434 DECL(AL_BUFFERS_PROCESSED),
436 DECL(AL_FORMAT_MONO8),
437 DECL(AL_FORMAT_MONO16),
438 DECL(AL_FORMAT_MONO_FLOAT32),
439 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
440 DECL(AL_FORMAT_STEREO8),
441 DECL(AL_FORMAT_STEREO16),
442 DECL(AL_FORMAT_STEREO_FLOAT32),
443 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
444 DECL(AL_FORMAT_MONO_IMA4),
445 DECL(AL_FORMAT_STEREO_IMA4),
446 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
447 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
448 DECL(AL_FORMAT_QUAD8_LOKI),
449 DECL(AL_FORMAT_QUAD16_LOKI),
450 DECL(AL_FORMAT_QUAD8),
451 DECL(AL_FORMAT_QUAD16),
452 DECL(AL_FORMAT_QUAD32),
453 DECL(AL_FORMAT_51CHN8),
454 DECL(AL_FORMAT_51CHN16),
455 DECL(AL_FORMAT_51CHN32),
456 DECL(AL_FORMAT_61CHN8),
457 DECL(AL_FORMAT_61CHN16),
458 DECL(AL_FORMAT_61CHN32),
459 DECL(AL_FORMAT_71CHN8),
460 DECL(AL_FORMAT_71CHN16),
461 DECL(AL_FORMAT_71CHN32),
462 DECL(AL_FORMAT_REAR8),
463 DECL(AL_FORMAT_REAR16),
464 DECL(AL_FORMAT_REAR32),
465 DECL(AL_FORMAT_MONO_MULAW),
466 DECL(AL_FORMAT_MONO_MULAW_EXT),
467 DECL(AL_FORMAT_STEREO_MULAW),
468 DECL(AL_FORMAT_STEREO_MULAW_EXT),
469 DECL(AL_FORMAT_QUAD_MULAW),
470 DECL(AL_FORMAT_51CHN_MULAW),
471 DECL(AL_FORMAT_61CHN_MULAW),
472 DECL(AL_FORMAT_71CHN_MULAW),
473 DECL(AL_FORMAT_REAR_MULAW),
474 DECL(AL_FORMAT_MONO_ALAW_EXT),
475 DECL(AL_FORMAT_STEREO_ALAW_EXT),
477 DECL(AL_FORMAT_BFORMAT2D_8),
478 DECL(AL_FORMAT_BFORMAT2D_16),
479 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
480 DECL(AL_FORMAT_BFORMAT2D_MULAW),
481 DECL(AL_FORMAT_BFORMAT3D_8),
482 DECL(AL_FORMAT_BFORMAT3D_16),
483 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
484 DECL(AL_FORMAT_BFORMAT3D_MULAW),
486 DECL(AL_FREQUENCY),
487 DECL(AL_BITS),
488 DECL(AL_CHANNELS),
489 DECL(AL_SIZE),
490 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
491 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
493 DECL(AL_SOURCE_RADIUS),
495 DECL(AL_STEREO_ANGLES),
497 DECL(AL_UNUSED),
498 DECL(AL_PENDING),
499 DECL(AL_PROCESSED),
501 DECL(AL_NO_ERROR),
502 DECL(AL_INVALID_NAME),
503 DECL(AL_INVALID_ENUM),
504 DECL(AL_INVALID_VALUE),
505 DECL(AL_INVALID_OPERATION),
506 DECL(AL_OUT_OF_MEMORY),
508 DECL(AL_VENDOR),
509 DECL(AL_VERSION),
510 DECL(AL_RENDERER),
511 DECL(AL_EXTENSIONS),
513 DECL(AL_DOPPLER_FACTOR),
514 DECL(AL_DOPPLER_VELOCITY),
515 DECL(AL_DISTANCE_MODEL),
516 DECL(AL_SPEED_OF_SOUND),
517 DECL(AL_SOURCE_DISTANCE_MODEL),
518 DECL(AL_DEFERRED_UPDATES_SOFT),
519 DECL(AL_GAIN_LIMIT_SOFT),
521 DECL(AL_INVERSE_DISTANCE),
522 DECL(AL_INVERSE_DISTANCE_CLAMPED),
523 DECL(AL_LINEAR_DISTANCE),
524 DECL(AL_LINEAR_DISTANCE_CLAMPED),
525 DECL(AL_EXPONENT_DISTANCE),
526 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
528 DECL(AL_FILTER_TYPE),
529 DECL(AL_FILTER_NULL),
530 DECL(AL_FILTER_LOWPASS),
531 DECL(AL_FILTER_HIGHPASS),
532 DECL(AL_FILTER_BANDPASS),
534 DECL(AL_LOWPASS_GAIN),
535 DECL(AL_LOWPASS_GAINHF),
537 DECL(AL_HIGHPASS_GAIN),
538 DECL(AL_HIGHPASS_GAINLF),
540 DECL(AL_BANDPASS_GAIN),
541 DECL(AL_BANDPASS_GAINHF),
542 DECL(AL_BANDPASS_GAINLF),
544 DECL(AL_EFFECT_TYPE),
545 DECL(AL_EFFECT_NULL),
546 DECL(AL_EFFECT_REVERB),
547 DECL(AL_EFFECT_EAXREVERB),
548 DECL(AL_EFFECT_CHORUS),
549 DECL(AL_EFFECT_DISTORTION),
550 DECL(AL_EFFECT_ECHO),
551 DECL(AL_EFFECT_FLANGER),
552 DECL(AL_EFFECT_PITCH_SHIFTER),
553 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
554 #if 0
555 DECL(AL_EFFECT_VOCAL_MORPHER),
556 #endif
557 DECL(AL_EFFECT_RING_MODULATOR),
558 DECL(AL_EFFECT_AUTOWAH),
559 DECL(AL_EFFECT_COMPRESSOR),
560 DECL(AL_EFFECT_EQUALIZER),
561 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
562 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
564 DECL(AL_EFFECTSLOT_EFFECT),
565 DECL(AL_EFFECTSLOT_GAIN),
566 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
567 DECL(AL_EFFECTSLOT_NULL),
569 DECL(AL_EAXREVERB_DENSITY),
570 DECL(AL_EAXREVERB_DIFFUSION),
571 DECL(AL_EAXREVERB_GAIN),
572 DECL(AL_EAXREVERB_GAINHF),
573 DECL(AL_EAXREVERB_GAINLF),
574 DECL(AL_EAXREVERB_DECAY_TIME),
575 DECL(AL_EAXREVERB_DECAY_HFRATIO),
576 DECL(AL_EAXREVERB_DECAY_LFRATIO),
577 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
578 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
579 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
580 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
581 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
582 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
583 DECL(AL_EAXREVERB_ECHO_TIME),
584 DECL(AL_EAXREVERB_ECHO_DEPTH),
585 DECL(AL_EAXREVERB_MODULATION_TIME),
586 DECL(AL_EAXREVERB_MODULATION_DEPTH),
587 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
588 DECL(AL_EAXREVERB_HFREFERENCE),
589 DECL(AL_EAXREVERB_LFREFERENCE),
590 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
591 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
593 DECL(AL_REVERB_DENSITY),
594 DECL(AL_REVERB_DIFFUSION),
595 DECL(AL_REVERB_GAIN),
596 DECL(AL_REVERB_GAINHF),
597 DECL(AL_REVERB_DECAY_TIME),
598 DECL(AL_REVERB_DECAY_HFRATIO),
599 DECL(AL_REVERB_REFLECTIONS_GAIN),
600 DECL(AL_REVERB_REFLECTIONS_DELAY),
601 DECL(AL_REVERB_LATE_REVERB_GAIN),
602 DECL(AL_REVERB_LATE_REVERB_DELAY),
603 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
604 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
605 DECL(AL_REVERB_DECAY_HFLIMIT),
607 DECL(AL_CHORUS_WAVEFORM),
608 DECL(AL_CHORUS_PHASE),
609 DECL(AL_CHORUS_RATE),
610 DECL(AL_CHORUS_DEPTH),
611 DECL(AL_CHORUS_FEEDBACK),
612 DECL(AL_CHORUS_DELAY),
614 DECL(AL_DISTORTION_EDGE),
615 DECL(AL_DISTORTION_GAIN),
616 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
617 DECL(AL_DISTORTION_EQCENTER),
618 DECL(AL_DISTORTION_EQBANDWIDTH),
620 DECL(AL_ECHO_DELAY),
621 DECL(AL_ECHO_LRDELAY),
622 DECL(AL_ECHO_DAMPING),
623 DECL(AL_ECHO_FEEDBACK),
624 DECL(AL_ECHO_SPREAD),
626 DECL(AL_FLANGER_WAVEFORM),
627 DECL(AL_FLANGER_PHASE),
628 DECL(AL_FLANGER_RATE),
629 DECL(AL_FLANGER_DEPTH),
630 DECL(AL_FLANGER_FEEDBACK),
631 DECL(AL_FLANGER_DELAY),
633 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY),
634 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION),
635 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION),
637 DECL(AL_RING_MODULATOR_FREQUENCY),
638 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
639 DECL(AL_RING_MODULATOR_WAVEFORM),
641 DECL(AL_PITCH_SHIFTER_COARSE_TUNE),
642 DECL(AL_PITCH_SHIFTER_FINE_TUNE),
644 DECL(AL_COMPRESSOR_ONOFF),
646 DECL(AL_EQUALIZER_LOW_GAIN),
647 DECL(AL_EQUALIZER_LOW_CUTOFF),
648 DECL(AL_EQUALIZER_MID1_GAIN),
649 DECL(AL_EQUALIZER_MID1_CENTER),
650 DECL(AL_EQUALIZER_MID1_WIDTH),
651 DECL(AL_EQUALIZER_MID2_GAIN),
652 DECL(AL_EQUALIZER_MID2_CENTER),
653 DECL(AL_EQUALIZER_MID2_WIDTH),
654 DECL(AL_EQUALIZER_HIGH_GAIN),
655 DECL(AL_EQUALIZER_HIGH_CUTOFF),
657 DECL(AL_DEDICATED_GAIN),
659 DECL(AL_AUTOWAH_ATTACK_TIME),
660 DECL(AL_AUTOWAH_RELEASE_TIME),
661 DECL(AL_AUTOWAH_RESONANCE),
662 DECL(AL_AUTOWAH_PEAK_GAIN),
664 DECL(AL_NUM_RESAMPLERS_SOFT),
665 DECL(AL_DEFAULT_RESAMPLER_SOFT),
666 DECL(AL_SOURCE_RESAMPLER_SOFT),
667 DECL(AL_RESAMPLER_NAME_SOFT),
669 DECL(AL_SOURCE_SPATIALIZE_SOFT),
670 DECL(AL_AUTO_SOFT),
672 DECL(AL_MAP_READ_BIT_SOFT),
673 DECL(AL_MAP_WRITE_BIT_SOFT),
674 DECL(AL_MAP_PERSISTENT_BIT_SOFT),
675 DECL(AL_PRESERVE_DATA_BIT_SOFT),
677 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT),
678 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT),
679 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT),
680 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT),
681 DECL(AL_EVENT_TYPE_ERROR_SOFT),
682 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT),
683 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT),
685 #undef DECL
687 static const ALCchar alcNoError[] = "No Error";
688 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
689 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
690 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
691 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
692 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
695 /************************************************
696 * Global variables
697 ************************************************/
699 /* Enumerated device names */
700 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
702 static al_string alcAllDevicesList;
703 static al_string alcCaptureDeviceList;
705 /* Default is always the first in the list */
706 static ALCchar *alcDefaultAllDevicesSpecifier;
707 static ALCchar *alcCaptureDefaultDeviceSpecifier;
709 /* Default context extensions */
710 static const ALchar alExtList[] =
711 "AL_EXT_ALAW "
712 "AL_EXT_BFORMAT "
713 "AL_EXT_DOUBLE "
714 "AL_EXT_EXPONENT_DISTANCE "
715 "AL_EXT_FLOAT32 "
716 "AL_EXT_IMA4 "
717 "AL_EXT_LINEAR_DISTANCE "
718 "AL_EXT_MCFORMATS "
719 "AL_EXT_MULAW "
720 "AL_EXT_MULAW_BFORMAT "
721 "AL_EXT_MULAW_MCFORMATS "
722 "AL_EXT_OFFSET "
723 "AL_EXT_source_distance_model "
724 "AL_EXT_SOURCE_RADIUS "
725 "AL_EXT_STEREO_ANGLES "
726 "AL_LOKI_quadriphonic "
727 "AL_SOFT_block_alignment "
728 "AL_SOFT_deferred_updates "
729 "AL_SOFT_direct_channels "
730 "AL_SOFTX_events "
731 "AL_SOFTX_filter_gain_ex "
732 "AL_SOFT_gain_clamp_ex "
733 "AL_SOFT_loop_points "
734 "AL_SOFTX_map_buffer "
735 "AL_SOFT_MSADPCM "
736 "AL_SOFT_source_latency "
737 "AL_SOFT_source_length "
738 "AL_SOFT_source_resampler "
739 "AL_SOFT_source_spatialize";
741 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
743 /* Thread-local current context */
744 static altss_t LocalContext;
745 /* Process-wide current context */
746 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
748 /* Mixing thread piority level */
749 ALint RTPrioLevel;
751 FILE *LogFile;
752 #ifdef _DEBUG
753 enum LogLevel LogLevel = LogWarning;
754 #else
755 enum LogLevel LogLevel = LogError;
756 #endif
758 /* Flag to trap ALC device errors */
759 static ALCboolean TrapALCError = ALC_FALSE;
761 /* One-time configuration init control */
762 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
764 /* Default effect that applies to sources that don't have an effect on send 0 */
765 static ALeffect DefaultEffect;
767 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
768 * updates.
770 static ALCboolean SuspendDefers = ALC_TRUE;
773 /************************************************
774 * ALC information
775 ************************************************/
776 static const ALCchar alcNoDeviceExtList[] =
777 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
778 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
779 static const ALCchar alcExtensionList[] =
780 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
781 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
782 "ALC_EXT_thread_local_context ALC_SOFT_device_clock ALC_SOFT_HRTF "
783 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
784 static const ALCint alcMajorVersion = 1;
785 static const ALCint alcMinorVersion = 1;
787 static const ALCint alcEFXMajorVersion = 1;
788 static const ALCint alcEFXMinorVersion = 0;
791 /************************************************
792 * Device lists
793 ************************************************/
794 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
796 static almtx_t ListLock;
797 static inline void LockLists(void)
799 int ret = almtx_lock(&ListLock);
800 assert(ret == althrd_success);
802 static inline void UnlockLists(void)
804 int ret = almtx_unlock(&ListLock);
805 assert(ret == althrd_success);
808 /************************************************
809 * Library initialization
810 ************************************************/
811 #if defined(_WIN32)
812 static void alc_init(void);
813 static void alc_deinit(void);
814 static void alc_deinit_safe(void);
816 #ifndef AL_LIBTYPE_STATIC
817 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
819 switch(reason)
821 case DLL_PROCESS_ATTACH:
822 /* Pin the DLL so we won't get unloaded until the process terminates */
823 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
824 (WCHAR*)hModule, &hModule);
825 alc_init();
826 break;
828 case DLL_THREAD_DETACH:
829 althrd_thread_detach();
830 break;
832 case DLL_PROCESS_DETACH:
833 if(!lpReserved)
834 alc_deinit();
835 else
836 alc_deinit_safe();
837 break;
839 return TRUE;
841 #elif defined(_MSC_VER)
842 #pragma section(".CRT$XCU",read)
843 static void alc_constructor(void);
844 static void alc_destructor(void);
845 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
847 static void alc_constructor(void)
849 atexit(alc_destructor);
850 alc_init();
853 static void alc_destructor(void)
855 alc_deinit();
857 #elif defined(HAVE_GCC_DESTRUCTOR)
858 static void alc_init(void) __attribute__((constructor));
859 static void alc_deinit(void) __attribute__((destructor));
860 #else
861 #error "No static initialization available on this platform!"
862 #endif
864 #elif defined(HAVE_GCC_DESTRUCTOR)
866 static void alc_init(void) __attribute__((constructor));
867 static void alc_deinit(void) __attribute__((destructor));
869 #else
870 #error "No global initialization available on this platform!"
871 #endif
873 static void ReleaseThreadCtx(void *ptr);
874 static void alc_init(void)
876 const char *str;
877 int ret;
879 LogFile = stderr;
881 AL_STRING_INIT(alcAllDevicesList);
882 AL_STRING_INIT(alcCaptureDeviceList);
884 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
885 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
886 ConeScale *= 0.5f;
888 str = getenv("__ALSOFT_REVERSE_Z");
889 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
890 ZScale *= -1.0f;
892 str = getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
893 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
894 OverrideReverbSpeedOfSound = AL_TRUE;
896 ret = altss_create(&LocalContext, ReleaseThreadCtx);
897 assert(ret == althrd_success);
899 ret = almtx_init(&ListLock, almtx_recursive);
900 assert(ret == althrd_success);
903 static void alc_initconfig(void)
905 const char *devs, *str;
906 int capfilter;
907 float valf;
908 int i, n;
910 str = getenv("ALSOFT_LOGLEVEL");
911 if(str)
913 long lvl = strtol(str, NULL, 0);
914 if(lvl >= NoLog && lvl <= LogRef)
915 LogLevel = lvl;
918 str = getenv("ALSOFT_LOGFILE");
919 if(str && str[0])
921 FILE *logfile = al_fopen(str, "wt");
922 if(logfile) LogFile = logfile;
923 else ERR("Failed to open log file '%s'\n", str);
926 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION,
927 ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH);
929 char buf[1024] = "";
930 int len = 0;
932 if(BackendListSize > 0)
933 len += snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
934 for(i = 1;i < BackendListSize;i++)
935 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
936 TRACE("Supported backends: %s\n", buf);
938 ReadALConfig();
940 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
941 if(str && *str)
943 if(strcasecmp(str, "ignore") == 0)
945 SuspendDefers = ALC_FALSE;
946 TRACE("Selected context suspend behavior, \"ignore\"\n");
948 else
949 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
952 capfilter = 0;
953 #if defined(HAVE_SSE4_1)
954 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
955 #elif defined(HAVE_SSE3)
956 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
957 #elif defined(HAVE_SSE2)
958 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
959 #elif defined(HAVE_SSE)
960 capfilter |= CPU_CAP_SSE;
961 #endif
962 #ifdef HAVE_NEON
963 capfilter |= CPU_CAP_NEON;
964 #endif
965 if(ConfigValueStr(NULL, NULL, "disable-cpu-exts", &str))
967 if(strcasecmp(str, "all") == 0)
968 capfilter = 0;
969 else
971 size_t len;
972 const char *next = str;
974 do {
975 str = next;
976 while(isspace(str[0]))
977 str++;
978 next = strchr(str, ',');
980 if(!str[0] || str[0] == ',')
981 continue;
983 len = (next ? ((size_t)(next-str)) : strlen(str));
984 while(len > 0 && isspace(str[len-1]))
985 len--;
986 if(len == 3 && strncasecmp(str, "sse", len) == 0)
987 capfilter &= ~CPU_CAP_SSE;
988 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
989 capfilter &= ~CPU_CAP_SSE2;
990 else if(len == 4 && strncasecmp(str, "sse3", len) == 0)
991 capfilter &= ~CPU_CAP_SSE3;
992 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
993 capfilter &= ~CPU_CAP_SSE4_1;
994 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
995 capfilter &= ~CPU_CAP_NEON;
996 else
997 WARN("Invalid CPU extension \"%s\"\n", str);
998 } while(next++);
1001 FillCPUCaps(capfilter);
1003 #ifdef _WIN32
1004 RTPrioLevel = 1;
1005 #else
1006 RTPrioLevel = 0;
1007 #endif
1008 ConfigValueInt(NULL, NULL, "rt-prio", &RTPrioLevel);
1010 aluInit();
1011 aluInitMixer();
1013 str = getenv("ALSOFT_TRAP_ERROR");
1014 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1016 TrapALError = AL_TRUE;
1017 TrapALCError = AL_TRUE;
1019 else
1021 str = getenv("ALSOFT_TRAP_AL_ERROR");
1022 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1023 TrapALError = AL_TRUE;
1024 TrapALError = GetConfigValueBool(NULL, NULL, "trap-al-error", TrapALError);
1026 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1027 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1028 TrapALCError = ALC_TRUE;
1029 TrapALCError = GetConfigValueBool(NULL, NULL, "trap-alc-error", TrapALCError);
1032 if(ConfigValueFloat(NULL, "reverb", "boost", &valf))
1033 ReverbBoost *= powf(10.0f, valf / 20.0f);
1035 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1036 ConfigValueStr(NULL, NULL, "drivers", &devs))
1038 int n;
1039 size_t len;
1040 const char *next = devs;
1041 int endlist, delitem;
1043 i = 0;
1044 do {
1045 devs = next;
1046 while(isspace(devs[0]))
1047 devs++;
1048 next = strchr(devs, ',');
1050 delitem = (devs[0] == '-');
1051 if(devs[0] == '-') devs++;
1053 if(!devs[0] || devs[0] == ',')
1055 endlist = 0;
1056 continue;
1058 endlist = 1;
1060 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1061 while(len > 0 && isspace(devs[len-1]))
1062 len--;
1063 #ifdef HAVE_WASAPI
1064 /* HACK: For backwards compatibility, convert backend references of
1065 * mmdevapi to wasapi. This should eventually be removed.
1067 if(len == 8 && strncmp(devs, "mmdevapi", len) == 0)
1069 devs = "wasapi";
1070 len = 6;
1072 #endif
1073 for(n = i;n < BackendListSize;n++)
1075 if(len == strlen(BackendList[n].name) &&
1076 strncmp(BackendList[n].name, devs, len) == 0)
1078 if(delitem)
1080 for(;n+1 < BackendListSize;n++)
1081 BackendList[n] = BackendList[n+1];
1082 BackendListSize--;
1084 else
1086 struct BackendInfo Bkp = BackendList[n];
1087 for(;n > i;n--)
1088 BackendList[n] = BackendList[n-1];
1089 BackendList[n] = Bkp;
1091 i++;
1093 break;
1096 } while(next++);
1098 if(endlist)
1099 BackendListSize = i;
1102 for(n = i = 0;i < BackendListSize && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1104 ALCbackendFactory *factory;
1105 BackendList[n] = BackendList[i];
1107 factory = BackendList[n].getFactory();
1108 if(!V0(factory,init)())
1110 WARN("Failed to initialize backend \"%s\"\n", BackendList[n].name);
1111 continue;
1114 TRACE("Initialized backend \"%s\"\n", BackendList[n].name);
1115 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1117 PlaybackBackend = BackendList[n];
1118 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1120 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1122 CaptureBackend = BackendList[n];
1123 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1125 n++;
1127 BackendListSize = n;
1130 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1131 V0(factory,init)();
1134 if(!PlaybackBackend.name)
1135 WARN("No playback backend available!\n");
1136 if(!CaptureBackend.name)
1137 WARN("No capture backend available!\n");
1139 if(ConfigValueStr(NULL, NULL, "excludefx", &str))
1141 size_t len;
1142 const char *next = str;
1144 do {
1145 str = next;
1146 next = strchr(str, ',');
1148 if(!str[0] || next == str)
1149 continue;
1151 len = (next ? ((size_t)(next-str)) : strlen(str));
1152 for(n = 0;n < EFFECTLIST_SIZE;n++)
1154 if(len == strlen(EffectList[n].name) &&
1155 strncmp(EffectList[n].name, str, len) == 0)
1156 DisabledEffects[EffectList[n].type] = AL_TRUE;
1158 } while(next++);
1161 InitEffect(&DefaultEffect);
1162 str = getenv("ALSOFT_DEFAULT_REVERB");
1163 if((str && str[0]) || ConfigValueStr(NULL, NULL, "default-reverb", &str))
1164 LoadReverbPreset(str, &DefaultEffect);
1166 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1169 /************************************************
1170 * Library deinitialization
1171 ************************************************/
1172 static void alc_cleanup(void)
1174 ALCdevice *dev;
1176 AL_STRING_DEINIT(alcAllDevicesList);
1177 AL_STRING_DEINIT(alcCaptureDeviceList);
1179 free(alcDefaultAllDevicesSpecifier);
1180 alcDefaultAllDevicesSpecifier = NULL;
1181 free(alcCaptureDefaultDeviceSpecifier);
1182 alcCaptureDefaultDeviceSpecifier = NULL;
1184 if((dev=ATOMIC_EXCHANGE_PTR_SEQ(&DeviceList, NULL)) != NULL)
1186 ALCuint num = 0;
1187 do {
1188 num++;
1189 dev = ATOMIC_LOAD(&dev->next, almemory_order_relaxed);
1190 } while(dev != NULL);
1191 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1195 static void alc_deinit_safe(void)
1197 alc_cleanup();
1199 FreeHrtfs();
1200 FreeALConfig();
1202 almtx_destroy(&ListLock);
1203 altss_delete(LocalContext);
1205 if(LogFile != stderr)
1206 fclose(LogFile);
1207 LogFile = NULL;
1209 althrd_deinit();
1212 static void alc_deinit(void)
1214 int i;
1216 alc_cleanup();
1218 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1219 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1221 for(i = 0;i < BackendListSize;i++)
1223 ALCbackendFactory *factory = BackendList[i].getFactory();
1224 V0(factory,deinit)();
1227 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1228 V0(factory,deinit)();
1231 alc_deinit_safe();
1235 /************************************************
1236 * Device enumeration
1237 ************************************************/
1238 static void ProbeDevices(al_string *list, struct BackendInfo *backendinfo, enum DevProbe type)
1240 DO_INITCONFIG();
1242 LockLists();
1243 alstr_clear(list);
1245 if(backendinfo->getFactory)
1247 ALCbackendFactory *factory = backendinfo->getFactory();
1248 V(factory,probe)(type, list);
1251 UnlockLists();
1253 static void ProbeAllDevicesList(void)
1254 { ProbeDevices(&alcAllDevicesList, &PlaybackBackend, ALL_DEVICE_PROBE); }
1255 static void ProbeCaptureDeviceList(void)
1256 { ProbeDevices(&alcCaptureDeviceList, &CaptureBackend, CAPTURE_DEVICE_PROBE); }
1259 /************************************************
1260 * Device format information
1261 ************************************************/
1262 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1264 switch(type)
1266 case DevFmtByte: return "Signed Byte";
1267 case DevFmtUByte: return "Unsigned Byte";
1268 case DevFmtShort: return "Signed Short";
1269 case DevFmtUShort: return "Unsigned Short";
1270 case DevFmtInt: return "Signed Int";
1271 case DevFmtUInt: return "Unsigned Int";
1272 case DevFmtFloat: return "Float";
1274 return "(unknown type)";
1276 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1278 switch(chans)
1280 case DevFmtMono: return "Mono";
1281 case DevFmtStereo: return "Stereo";
1282 case DevFmtQuad: return "Quadraphonic";
1283 case DevFmtX51: return "5.1 Surround";
1284 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1285 case DevFmtX61: return "6.1 Surround";
1286 case DevFmtX71: return "7.1 Surround";
1287 case DevFmtAmbi3D: return "Ambisonic 3D";
1289 return "(unknown channels)";
1292 extern inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type, ALsizei ambiorder);
1293 ALsizei BytesFromDevFmt(enum DevFmtType type)
1295 switch(type)
1297 case DevFmtByte: return sizeof(ALbyte);
1298 case DevFmtUByte: return sizeof(ALubyte);
1299 case DevFmtShort: return sizeof(ALshort);
1300 case DevFmtUShort: return sizeof(ALushort);
1301 case DevFmtInt: return sizeof(ALint);
1302 case DevFmtUInt: return sizeof(ALuint);
1303 case DevFmtFloat: return sizeof(ALfloat);
1305 return 0;
1307 ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans, ALsizei ambiorder)
1309 switch(chans)
1311 case DevFmtMono: return 1;
1312 case DevFmtStereo: return 2;
1313 case DevFmtQuad: return 4;
1314 case DevFmtX51: return 6;
1315 case DevFmtX51Rear: return 6;
1316 case DevFmtX61: return 7;
1317 case DevFmtX71: return 8;
1318 case DevFmtAmbi3D: return (ambiorder >= 3) ? 16 :
1319 (ambiorder == 2) ? 9 :
1320 (ambiorder == 1) ? 4 : 1;
1322 return 0;
1325 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1326 enum DevFmtType *type)
1328 static const struct {
1329 ALenum format;
1330 enum DevFmtChannels channels;
1331 enum DevFmtType type;
1332 } list[] = {
1333 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1334 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1335 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1337 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1338 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1339 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1341 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1342 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1343 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1345 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1346 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1347 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1349 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1350 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1351 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1353 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1354 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1355 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1357 ALuint i;
1359 for(i = 0;i < COUNTOF(list);i++)
1361 if(list[i].format == format)
1363 *chans = list[i].channels;
1364 *type = list[i].type;
1365 return AL_TRUE;
1369 return AL_FALSE;
1372 static ALCboolean IsValidALCType(ALCenum type)
1374 switch(type)
1376 case ALC_BYTE_SOFT:
1377 case ALC_UNSIGNED_BYTE_SOFT:
1378 case ALC_SHORT_SOFT:
1379 case ALC_UNSIGNED_SHORT_SOFT:
1380 case ALC_INT_SOFT:
1381 case ALC_UNSIGNED_INT_SOFT:
1382 case ALC_FLOAT_SOFT:
1383 return ALC_TRUE;
1385 return ALC_FALSE;
1388 static ALCboolean IsValidALCChannels(ALCenum channels)
1390 switch(channels)
1392 case ALC_MONO_SOFT:
1393 case ALC_STEREO_SOFT:
1394 case ALC_QUAD_SOFT:
1395 case ALC_5POINT1_SOFT:
1396 case ALC_6POINT1_SOFT:
1397 case ALC_7POINT1_SOFT:
1398 case ALC_BFORMAT3D_SOFT:
1399 return ALC_TRUE;
1401 return ALC_FALSE;
1404 static ALCboolean IsValidAmbiLayout(ALCenum layout)
1406 switch(layout)
1408 case ALC_ACN_SOFT:
1409 case ALC_FUMA_SOFT:
1410 return ALC_TRUE;
1412 return ALC_FALSE;
1415 static ALCboolean IsValidAmbiScaling(ALCenum scaling)
1417 switch(scaling)
1419 case ALC_N3D_SOFT:
1420 case ALC_SN3D_SOFT:
1421 case ALC_FUMA_SOFT:
1422 return ALC_TRUE;
1424 return ALC_FALSE;
1427 /************************************************
1428 * Miscellaneous ALC helpers
1429 ************************************************/
1431 /* SetDefaultWFXChannelOrder
1433 * Sets the default channel order used by WaveFormatEx.
1435 void SetDefaultWFXChannelOrder(ALCdevice *device)
1437 ALsizei i;
1439 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1440 device->RealOut.ChannelName[i] = InvalidChannel;
1442 switch(device->FmtChans)
1444 case DevFmtMono:
1445 device->RealOut.ChannelName[0] = FrontCenter;
1446 break;
1447 case DevFmtStereo:
1448 device->RealOut.ChannelName[0] = FrontLeft;
1449 device->RealOut.ChannelName[1] = FrontRight;
1450 break;
1451 case DevFmtQuad:
1452 device->RealOut.ChannelName[0] = FrontLeft;
1453 device->RealOut.ChannelName[1] = FrontRight;
1454 device->RealOut.ChannelName[2] = BackLeft;
1455 device->RealOut.ChannelName[3] = BackRight;
1456 break;
1457 case DevFmtX51:
1458 device->RealOut.ChannelName[0] = FrontLeft;
1459 device->RealOut.ChannelName[1] = FrontRight;
1460 device->RealOut.ChannelName[2] = FrontCenter;
1461 device->RealOut.ChannelName[3] = LFE;
1462 device->RealOut.ChannelName[4] = SideLeft;
1463 device->RealOut.ChannelName[5] = SideRight;
1464 break;
1465 case DevFmtX51Rear:
1466 device->RealOut.ChannelName[0] = FrontLeft;
1467 device->RealOut.ChannelName[1] = FrontRight;
1468 device->RealOut.ChannelName[2] = FrontCenter;
1469 device->RealOut.ChannelName[3] = LFE;
1470 device->RealOut.ChannelName[4] = BackLeft;
1471 device->RealOut.ChannelName[5] = BackRight;
1472 break;
1473 case DevFmtX61:
1474 device->RealOut.ChannelName[0] = FrontLeft;
1475 device->RealOut.ChannelName[1] = FrontRight;
1476 device->RealOut.ChannelName[2] = FrontCenter;
1477 device->RealOut.ChannelName[3] = LFE;
1478 device->RealOut.ChannelName[4] = BackCenter;
1479 device->RealOut.ChannelName[5] = SideLeft;
1480 device->RealOut.ChannelName[6] = SideRight;
1481 break;
1482 case DevFmtX71:
1483 device->RealOut.ChannelName[0] = FrontLeft;
1484 device->RealOut.ChannelName[1] = FrontRight;
1485 device->RealOut.ChannelName[2] = FrontCenter;
1486 device->RealOut.ChannelName[3] = LFE;
1487 device->RealOut.ChannelName[4] = BackLeft;
1488 device->RealOut.ChannelName[5] = BackRight;
1489 device->RealOut.ChannelName[6] = SideLeft;
1490 device->RealOut.ChannelName[7] = SideRight;
1491 break;
1492 case DevFmtAmbi3D:
1493 device->RealOut.ChannelName[0] = Aux0;
1494 if(device->AmbiOrder > 0)
1496 device->RealOut.ChannelName[1] = Aux1;
1497 device->RealOut.ChannelName[2] = Aux2;
1498 device->RealOut.ChannelName[3] = Aux3;
1500 if(device->AmbiOrder > 1)
1502 device->RealOut.ChannelName[4] = Aux4;
1503 device->RealOut.ChannelName[5] = Aux5;
1504 device->RealOut.ChannelName[6] = Aux6;
1505 device->RealOut.ChannelName[7] = Aux7;
1506 device->RealOut.ChannelName[8] = Aux8;
1508 if(device->AmbiOrder > 2)
1510 device->RealOut.ChannelName[9] = Aux9;
1511 device->RealOut.ChannelName[10] = Aux10;
1512 device->RealOut.ChannelName[11] = Aux11;
1513 device->RealOut.ChannelName[12] = Aux12;
1514 device->RealOut.ChannelName[13] = Aux13;
1515 device->RealOut.ChannelName[14] = Aux14;
1516 device->RealOut.ChannelName[15] = Aux15;
1518 break;
1522 /* SetDefaultChannelOrder
1524 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1526 void SetDefaultChannelOrder(ALCdevice *device)
1528 ALsizei i;
1530 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1531 device->RealOut.ChannelName[i] = InvalidChannel;
1533 switch(device->FmtChans)
1535 case DevFmtX51Rear:
1536 device->RealOut.ChannelName[0] = FrontLeft;
1537 device->RealOut.ChannelName[1] = FrontRight;
1538 device->RealOut.ChannelName[2] = BackLeft;
1539 device->RealOut.ChannelName[3] = BackRight;
1540 device->RealOut.ChannelName[4] = FrontCenter;
1541 device->RealOut.ChannelName[5] = LFE;
1542 return;
1543 case DevFmtX71:
1544 device->RealOut.ChannelName[0] = FrontLeft;
1545 device->RealOut.ChannelName[1] = FrontRight;
1546 device->RealOut.ChannelName[2] = BackLeft;
1547 device->RealOut.ChannelName[3] = BackRight;
1548 device->RealOut.ChannelName[4] = FrontCenter;
1549 device->RealOut.ChannelName[5] = LFE;
1550 device->RealOut.ChannelName[6] = SideLeft;
1551 device->RealOut.ChannelName[7] = SideRight;
1552 return;
1554 /* Same as WFX order */
1555 case DevFmtMono:
1556 case DevFmtStereo:
1557 case DevFmtQuad:
1558 case DevFmtX51:
1559 case DevFmtX61:
1560 case DevFmtAmbi3D:
1561 SetDefaultWFXChannelOrder(device);
1562 break;
1566 extern inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan);
1567 extern inline ALint GetChannelIdxByName(const RealMixParams *real, enum Channel chan);
1570 /* ALCcontext_DeferUpdates
1572 * Defers/suspends updates for the given context's listener and sources. This
1573 * does *NOT* stop mixing, but rather prevents certain property changes from
1574 * taking effect.
1576 void ALCcontext_DeferUpdates(ALCcontext *context)
1578 ATOMIC_STORE_SEQ(&context->DeferUpdates, AL_TRUE);
1581 /* ALCcontext_ProcessUpdates
1583 * Resumes update processing after being deferred.
1585 void ALCcontext_ProcessUpdates(ALCcontext *context)
1587 almtx_lock(&context->PropLock);
1588 if(ATOMIC_EXCHANGE_SEQ(&context->DeferUpdates, AL_FALSE))
1590 /* Tell the mixer to stop applying updates, then wait for any active
1591 * updating to finish, before providing updates.
1593 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_TRUE);
1594 while((ATOMIC_LOAD(&context->UpdateCount, almemory_order_acquire)&1) != 0)
1595 althrd_yield();
1597 if(!ATOMIC_FLAG_TEST_AND_SET(&context->PropsClean, almemory_order_acq_rel))
1598 UpdateContextProps(context);
1599 if(!ATOMIC_FLAG_TEST_AND_SET(&context->Listener->PropsClean, almemory_order_acq_rel))
1600 UpdateListenerProps(context);
1601 UpdateAllEffectSlotProps(context);
1602 UpdateAllSourceProps(context);
1604 /* Now with all updates declared, let the mixer continue applying them
1605 * so they all happen at once.
1607 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_FALSE);
1609 almtx_unlock(&context->PropLock);
1613 /* alcSetError
1615 * Stores the latest ALC device error
1617 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1619 WARN("Error generated on device %p, code 0x%04x\n", device, errorCode);
1620 if(TrapALCError)
1622 #ifdef _WIN32
1623 /* DebugBreak() will cause an exception if there is no debugger */
1624 if(IsDebuggerPresent())
1625 DebugBreak();
1626 #elif defined(SIGTRAP)
1627 raise(SIGTRAP);
1628 #endif
1631 if(device)
1632 ATOMIC_STORE_SEQ(&device->LastError, errorCode);
1633 else
1634 ATOMIC_STORE_SEQ(&LastNullDeviceError, errorCode);
1638 static struct Compressor *CreateDeviceLimiter(const ALCdevice *device, const ALfloat threshold)
1640 return CompressorInit(device->RealOut.NumChannels, device->Frequency,
1641 AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, 0.001f, 0.002f,
1642 0.0f, 0.0f, threshold, INFINITY, 0.0f, 0.020f, 0.200f);
1645 /* UpdateClockBase
1647 * Updates the device's base clock time with however many samples have been
1648 * done. This is used so frequency changes on the device don't cause the time
1649 * to jump forward or back. Must not be called while the device is running/
1650 * mixing.
1652 static inline void UpdateClockBase(ALCdevice *device)
1654 IncrementRef(&device->MixCount);
1655 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1656 device->SamplesDone = 0;
1657 IncrementRef(&device->MixCount);
1660 /* UpdateDeviceParams
1662 * Updates device parameters according to the attribute list (caller is
1663 * responsible for holding the list lock).
1665 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1667 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1668 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1669 ALCenum gainLimiter = device->LimiterState;
1670 const ALsizei old_sends = device->NumAuxSends;
1671 ALsizei new_sends = device->NumAuxSends;
1672 enum DevFmtChannels oldChans;
1673 enum DevFmtType oldType;
1674 ALboolean update_failed;
1675 ALCsizei hrtf_id = -1;
1676 ALCcontext *context;
1677 ALCuint oldFreq;
1678 size_t size;
1679 ALCsizei i;
1680 int val;
1682 // Check for attributes
1683 if(device->Type == Loopback)
1685 ALCsizei numMono, numStereo, numSends;
1686 ALCenum alayout = AL_NONE;
1687 ALCenum ascale = AL_NONE;
1688 ALCenum schans = AL_NONE;
1689 ALCenum stype = AL_NONE;
1690 ALCsizei attrIdx = 0;
1691 ALCsizei aorder = 0;
1692 ALCuint freq = 0;
1694 if(!attrList)
1696 WARN("Missing attributes for loopback device\n");
1697 return ALC_INVALID_VALUE;
1700 numMono = device->NumMonoSources;
1701 numStereo = device->NumStereoSources;
1702 numSends = old_sends;
1704 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1705 while(attrList[attrIdx])
1707 switch(attrList[attrIdx])
1709 case ALC_FORMAT_CHANNELS_SOFT:
1710 schans = attrList[attrIdx + 1];
1711 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1712 if(!IsValidALCChannels(schans))
1713 return ALC_INVALID_VALUE;
1714 break;
1716 case ALC_FORMAT_TYPE_SOFT:
1717 stype = attrList[attrIdx + 1];
1718 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1719 if(!IsValidALCType(stype))
1720 return ALC_INVALID_VALUE;
1721 break;
1723 case ALC_FREQUENCY:
1724 freq = attrList[attrIdx + 1];
1725 TRACE_ATTR(ALC_FREQUENCY, freq);
1726 if(freq < MIN_OUTPUT_RATE)
1727 return ALC_INVALID_VALUE;
1728 break;
1730 case ALC_AMBISONIC_LAYOUT_SOFT:
1731 alayout = attrList[attrIdx + 1];
1732 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1733 if(!IsValidAmbiLayout(alayout))
1734 return ALC_INVALID_VALUE;
1735 break;
1737 case ALC_AMBISONIC_SCALING_SOFT:
1738 ascale = attrList[attrIdx + 1];
1739 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1740 if(!IsValidAmbiScaling(ascale))
1741 return ALC_INVALID_VALUE;
1742 break;
1744 case ALC_AMBISONIC_ORDER_SOFT:
1745 aorder = attrList[attrIdx + 1];
1746 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1747 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1748 return ALC_INVALID_VALUE;
1749 break;
1751 case ALC_MONO_SOURCES:
1752 numMono = attrList[attrIdx + 1];
1753 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1754 numMono = maxi(numMono, 0);
1755 break;
1757 case ALC_STEREO_SOURCES:
1758 numStereo = attrList[attrIdx + 1];
1759 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1760 numStereo = maxi(numStereo, 0);
1761 break;
1763 case ALC_MAX_AUXILIARY_SENDS:
1764 numSends = attrList[attrIdx + 1];
1765 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1766 numSends = clampi(numSends, 0, MAX_SENDS);
1767 break;
1769 case ALC_HRTF_SOFT:
1770 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1771 if(attrList[attrIdx + 1] == ALC_FALSE)
1772 hrtf_appreq = Hrtf_Disable;
1773 else if(attrList[attrIdx + 1] == ALC_TRUE)
1774 hrtf_appreq = Hrtf_Enable;
1775 else
1776 hrtf_appreq = Hrtf_Default;
1777 break;
1779 case ALC_HRTF_ID_SOFT:
1780 hrtf_id = attrList[attrIdx + 1];
1781 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1782 break;
1784 case ALC_OUTPUT_LIMITER_SOFT:
1785 gainLimiter = attrList[attrIdx + 1];
1786 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1787 break;
1789 default:
1790 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList[attrIdx],
1791 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1792 break;
1795 attrIdx += 2;
1797 #undef TRACE_ATTR
1799 if(!schans || !stype || !freq)
1801 WARN("Missing format for loopback device\n");
1802 return ALC_INVALID_VALUE;
1804 if(schans == ALC_BFORMAT3D_SOFT && (!alayout || !ascale || !aorder))
1806 WARN("Missing ambisonic info for loopback device\n");
1807 return ALC_INVALID_VALUE;
1810 if((device->Flags&DEVICE_RUNNING))
1811 V0(device->Backend,stop)();
1812 device->Flags &= ~DEVICE_RUNNING;
1814 UpdateClockBase(device);
1816 device->Frequency = freq;
1817 device->FmtChans = schans;
1818 device->FmtType = stype;
1819 if(schans == ALC_BFORMAT3D_SOFT)
1821 device->AmbiOrder = aorder;
1822 device->AmbiLayout = alayout;
1823 device->AmbiScale = ascale;
1826 if(numMono > INT_MAX-numStereo)
1827 numMono = INT_MAX-numStereo;
1828 numMono += numStereo;
1829 if(ConfigValueInt(NULL, NULL, "sources", &numMono))
1831 if(numMono <= 0)
1832 numMono = 256;
1834 else
1835 numMono = maxi(numMono, 256);
1836 numStereo = mini(numStereo, numMono);
1837 numMono -= numStereo;
1838 device->SourcesMax = numMono + numStereo;
1840 device->NumMonoSources = numMono;
1841 device->NumStereoSources = numStereo;
1843 if(ConfigValueInt(NULL, NULL, "sends", &new_sends))
1844 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1845 else
1846 new_sends = numSends;
1848 else if(attrList && attrList[0])
1850 ALCsizei numMono, numStereo, numSends;
1851 ALCsizei attrIdx = 0;
1852 ALCuint freq;
1854 /* If a context is already running on the device, stop playback so the
1855 * device attributes can be updated. */
1856 if((device->Flags&DEVICE_RUNNING))
1857 V0(device->Backend,stop)();
1858 device->Flags &= ~DEVICE_RUNNING;
1860 UpdateClockBase(device);
1862 freq = device->Frequency;
1863 numMono = device->NumMonoSources;
1864 numStereo = device->NumStereoSources;
1865 numSends = old_sends;
1867 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1868 while(attrList[attrIdx])
1870 switch(attrList[attrIdx])
1872 case ALC_FREQUENCY:
1873 freq = attrList[attrIdx + 1];
1874 TRACE_ATTR(ALC_FREQUENCY, freq);
1875 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1876 break;
1878 case ALC_MONO_SOURCES:
1879 numMono = attrList[attrIdx + 1];
1880 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1881 numMono = maxi(numMono, 0);
1882 break;
1884 case ALC_STEREO_SOURCES:
1885 numStereo = attrList[attrIdx + 1];
1886 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1887 numStereo = maxi(numStereo, 0);
1888 break;
1890 case ALC_MAX_AUXILIARY_SENDS:
1891 numSends = attrList[attrIdx + 1];
1892 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1893 numSends = clampi(numSends, 0, MAX_SENDS);
1894 break;
1896 case ALC_HRTF_SOFT:
1897 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1898 if(attrList[attrIdx + 1] == ALC_FALSE)
1899 hrtf_appreq = Hrtf_Disable;
1900 else if(attrList[attrIdx + 1] == ALC_TRUE)
1901 hrtf_appreq = Hrtf_Enable;
1902 else
1903 hrtf_appreq = Hrtf_Default;
1904 break;
1906 case ALC_HRTF_ID_SOFT:
1907 hrtf_id = attrList[attrIdx + 1];
1908 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1909 break;
1911 case ALC_OUTPUT_LIMITER_SOFT:
1912 gainLimiter = attrList[attrIdx + 1];
1913 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1914 break;
1916 default:
1917 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1918 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1919 break;
1922 attrIdx += 2;
1924 #undef TRACE_ATTR
1926 ConfigValueUInt(alstr_get_cstr(device->DeviceName), NULL, "frequency", &freq);
1927 freq = maxu(freq, MIN_OUTPUT_RATE);
1929 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1930 device->Frequency;
1931 /* SSE and Neon do best with the update size being a multiple of 4 */
1932 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1933 device->UpdateSize = (device->UpdateSize+3)&~3;
1935 device->Frequency = freq;
1937 if(numMono > INT_MAX-numStereo)
1938 numMono = INT_MAX-numStereo;
1939 numMono += numStereo;
1940 if(ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "sources", &numMono))
1942 if(numMono <= 0)
1943 numMono = 256;
1945 else
1946 numMono = maxi(numMono, 256);
1947 numStereo = mini(numStereo, numMono);
1948 numMono -= numStereo;
1949 device->SourcesMax = numMono + numStereo;
1951 device->NumMonoSources = numMono;
1952 device->NumStereoSources = numStereo;
1954 if(ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "sends", &new_sends))
1955 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1956 else
1957 new_sends = numSends;
1960 if((device->Flags&DEVICE_RUNNING))
1961 return ALC_NO_ERROR;
1963 al_free(device->Uhj_Encoder);
1964 device->Uhj_Encoder = NULL;
1966 al_free(device->Bs2b);
1967 device->Bs2b = NULL;
1969 al_free(device->ChannelDelay[0].Buffer);
1970 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1972 device->ChannelDelay[i].Length = 0;
1973 device->ChannelDelay[i].Buffer = NULL;
1976 al_free(device->Dry.Buffer);
1977 device->Dry.Buffer = NULL;
1978 device->Dry.NumChannels = 0;
1979 device->FOAOut.Buffer = NULL;
1980 device->FOAOut.NumChannels = 0;
1981 device->RealOut.Buffer = NULL;
1982 device->RealOut.NumChannels = 0;
1984 UpdateClockBase(device);
1985 device->FixedLatency = 0;
1987 device->DitherSeed = DITHER_RNG_SEED;
1989 /*************************************************************************
1990 * Update device format request if HRTF is requested
1992 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
1993 if(device->Type != Loopback)
1995 const char *hrtf;
1996 if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "hrtf", &hrtf))
1998 if(strcasecmp(hrtf, "true") == 0)
1999 hrtf_userreq = Hrtf_Enable;
2000 else if(strcasecmp(hrtf, "false") == 0)
2001 hrtf_userreq = Hrtf_Disable;
2002 else if(strcasecmp(hrtf, "auto") != 0)
2003 ERR("Unexpected hrtf value: %s\n", hrtf);
2006 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
2008 struct Hrtf *hrtf = NULL;
2009 if(VECTOR_SIZE(device->HrtfList) == 0)
2011 VECTOR_DEINIT(device->HrtfList);
2012 device->HrtfList = EnumerateHrtf(device->DeviceName);
2014 if(VECTOR_SIZE(device->HrtfList) > 0)
2016 if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->HrtfList))
2017 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, hrtf_id).hrtf);
2018 else
2019 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, 0).hrtf);
2022 if(hrtf)
2024 device->FmtChans = DevFmtStereo;
2025 device->Frequency = hrtf->sampleRate;
2026 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
2027 if(device->HrtfHandle)
2028 Hrtf_DecRef(device->HrtfHandle);
2029 device->HrtfHandle = hrtf;
2031 else
2033 hrtf_userreq = Hrtf_Default;
2034 hrtf_appreq = Hrtf_Disable;
2035 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2040 oldFreq = device->Frequency;
2041 oldChans = device->FmtChans;
2042 oldType = device->FmtType;
2044 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2045 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
2046 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
2047 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
2048 device->UpdateSize, device->NumUpdates
2051 if(V0(device->Backend,reset)() == ALC_FALSE)
2052 return ALC_INVALID_DEVICE;
2054 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
2056 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2057 DevFmtChannelsString(device->FmtChans));
2058 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2060 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2062 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2063 DevFmtTypeString(device->FmtType));
2064 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2066 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2068 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2069 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2072 if((device->UpdateSize&3) != 0)
2074 if((CPUCapFlags&CPU_CAP_SSE))
2075 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2076 if((CPUCapFlags&CPU_CAP_NEON))
2077 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2080 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2081 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2082 device->Frequency, device->UpdateSize, device->NumUpdates
2085 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2086 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device->Dry.NumChannels,
2087 device->FOAOut.NumChannels, device->RealOut.NumChannels);
2089 /* Allocate extra channels for any post-filter output. */
2090 size = (device->Dry.NumChannels + device->FOAOut.NumChannels +
2091 device->RealOut.NumChannels)*sizeof(device->Dry.Buffer[0]);
2093 TRACE("Allocating "SZFMT" channels, "SZFMT" bytes\n", size/sizeof(device->Dry.Buffer[0]), size);
2094 device->Dry.Buffer = al_calloc(16, size);
2095 if(!device->Dry.Buffer)
2097 ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
2098 return ALC_INVALID_DEVICE;
2101 if(device->RealOut.NumChannels != 0)
2102 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels +
2103 device->FOAOut.NumChannels;
2104 else
2106 device->RealOut.Buffer = device->Dry.Buffer;
2107 device->RealOut.NumChannels = device->Dry.NumChannels;
2110 if(device->FOAOut.NumChannels != 0)
2111 device->FOAOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2112 else
2114 device->FOAOut.Buffer = device->Dry.Buffer;
2115 device->FOAOut.NumChannels = device->Dry.NumChannels;
2118 device->NumAuxSends = new_sends;
2119 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2120 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
2121 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
2123 device->DitherDepth = 0.0f;
2124 if(GetConfigValueBool(alstr_get_cstr(device->DeviceName), NULL, "dither", 1))
2126 ALint depth = 0;
2127 ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "dither-depth", &depth);
2128 if(depth <= 0)
2130 switch(device->FmtType)
2132 case DevFmtByte:
2133 case DevFmtUByte:
2134 depth = 8;
2135 break;
2136 case DevFmtShort:
2137 case DevFmtUShort:
2138 depth = 16;
2139 break;
2140 case DevFmtInt:
2141 case DevFmtUInt:
2142 case DevFmtFloat:
2143 break;
2147 if(depth > 0)
2149 depth = clampi(depth, 2, 24);
2150 device->DitherDepth = powf(2.0f, (ALfloat)(depth-1));
2153 if(!(device->DitherDepth > 0.0f))
2154 TRACE("Dithering disabled\n");
2155 else
2156 TRACE("Dithering enabled (%g-bit, %g)\n", log2f(device->DitherDepth)+1.0f,
2157 device->DitherDepth);
2159 device->LimiterState = gainLimiter;
2160 if(ConfigValueBool(alstr_get_cstr(device->DeviceName), NULL, "output-limiter", &val))
2161 gainLimiter = val ? ALC_TRUE : ALC_FALSE;
2163 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2164 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2165 * output (where samples must be clamped), and don't for floating-point
2166 * (which can take unclamped samples).
2168 if(gainLimiter == ALC_DONT_CARE_SOFT)
2170 switch(device->FmtType)
2172 case DevFmtByte:
2173 case DevFmtUByte:
2174 case DevFmtShort:
2175 case DevFmtUShort:
2176 case DevFmtInt:
2177 case DevFmtUInt:
2178 gainLimiter = ALC_TRUE;
2179 break;
2180 case DevFmtFloat:
2181 gainLimiter = ALC_FALSE;
2182 break;
2185 if(gainLimiter != ALC_FALSE)
2187 ALfloat thrshld = 1.0f;
2188 switch(device->FmtType)
2190 case DevFmtByte:
2191 case DevFmtUByte:
2192 thrshld = 127.0f / 128.0f;
2193 break;
2194 case DevFmtShort:
2195 case DevFmtUShort:
2196 thrshld = 32767.0f / 32768.0f;
2197 break;
2198 case DevFmtInt:
2199 case DevFmtUInt:
2200 case DevFmtFloat:
2201 break;
2203 if(device->DitherDepth > 0.0f)
2204 thrshld -= 1.0f / device->DitherDepth;
2206 al_free(device->Limiter);
2207 device->Limiter = CreateDeviceLimiter(device, log10f(thrshld) * 20.0f);
2208 device->FixedLatency += (ALuint)(GetCompressorLookAhead(device->Limiter) *
2209 DEVICE_CLOCK_RES / device->Frequency);
2211 else
2213 al_free(device->Limiter);
2214 device->Limiter = NULL;
2216 TRACE("Output limiter %s\n", device->Limiter ? "enabled" : "disabled");
2218 aluSelectPostProcess(device);
2220 TRACE("Fixed device latency: %uns\n", device->FixedLatency);
2222 /* Need to delay returning failure until replacement Send arrays have been
2223 * allocated with the appropriate size.
2225 update_failed = AL_FALSE;
2226 START_MIXER_MODE();
2227 context = ATOMIC_LOAD_SEQ(&device->ContextList);
2228 while(context)
2230 SourceSubList *sublist, *subend;
2231 struct ALvoiceProps *vprops;
2232 ALsizei pos;
2234 if(context->DefaultSlot)
2236 ALeffectslot *slot = context->DefaultSlot;
2237 ALeffectState *state = slot->Effect.State;
2239 state->OutBuffer = device->Dry.Buffer;
2240 state->OutChannels = device->Dry.NumChannels;
2241 if(V(state,deviceUpdate)(device) == AL_FALSE)
2242 update_failed = AL_TRUE;
2243 else
2244 UpdateEffectSlotProps(slot, context);
2247 almtx_lock(&context->PropLock);
2248 almtx_lock(&context->EffectSlotLock);
2249 for(pos = 0;pos < (ALsizei)VECTOR_SIZE(context->EffectSlotList);pos++)
2251 ALeffectslot *slot = VECTOR_ELEM(context->EffectSlotList, pos);
2252 ALeffectState *state = slot->Effect.State;
2254 state->OutBuffer = device->Dry.Buffer;
2255 state->OutChannels = device->Dry.NumChannels;
2256 if(V(state,deviceUpdate)(device) == AL_FALSE)
2257 update_failed = AL_TRUE;
2258 else
2259 UpdateEffectSlotProps(slot, context);
2261 almtx_unlock(&context->EffectSlotLock);
2263 almtx_lock(&context->SourceLock);
2264 sublist = VECTOR_BEGIN(context->SourceList);
2265 subend = VECTOR_END(context->SourceList);
2266 for(;sublist != subend;++sublist)
2268 ALuint64 usemask = ~sublist->FreeMask;
2269 while(usemask)
2271 ALsizei idx = CTZ64(usemask);
2272 ALsource *source = sublist->Sources + idx;
2274 usemask &= ~(U64(1) << idx);
2276 if(old_sends != device->NumAuxSends)
2278 ALvoid *sends = al_calloc(16, device->NumAuxSends*sizeof(source->Send[0]));
2279 ALsizei s;
2281 memcpy(sends, source->Send,
2282 mini(device->NumAuxSends, old_sends)*sizeof(source->Send[0])
2284 for(s = device->NumAuxSends;s < old_sends;s++)
2286 if(source->Send[s].Slot)
2287 DecrementRef(&source->Send[s].Slot->ref);
2288 source->Send[s].Slot = NULL;
2290 al_free(source->Send);
2291 source->Send = sends;
2292 for(s = old_sends;s < device->NumAuxSends;s++)
2294 source->Send[s].Slot = NULL;
2295 source->Send[s].Gain = 1.0f;
2296 source->Send[s].GainHF = 1.0f;
2297 source->Send[s].HFReference = LOWPASSFREQREF;
2298 source->Send[s].GainLF = 1.0f;
2299 source->Send[s].LFReference = HIGHPASSFREQREF;
2303 ATOMIC_FLAG_CLEAR(&source->PropsClean, almemory_order_release);
2307 /* Clear any pre-existing voice property structs, in case the number of
2308 * auxiliary sends is changing. Active sources will have updates
2309 * respecified in UpdateAllSourceProps.
2311 vprops = ATOMIC_EXCHANGE_PTR(&context->FreeVoiceProps, NULL, almemory_order_acq_rel);
2312 while(vprops)
2314 struct ALvoiceProps *next = ATOMIC_LOAD(&vprops->next, almemory_order_relaxed);
2315 al_free(vprops);
2316 vprops = next;
2319 AllocateVoices(context, context->MaxVoices, old_sends);
2320 for(pos = 0;pos < context->VoiceCount;pos++)
2322 ALvoice *voice = context->Voices[pos];
2324 al_free(ATOMIC_EXCHANGE_PTR(&voice->Update, NULL, almemory_order_acq_rel));
2326 if(ATOMIC_LOAD(&voice->Source, almemory_order_acquire) == NULL)
2327 continue;
2329 if(device->AvgSpeakerDist > 0.0f)
2331 /* Reinitialize the NFC filters for new parameters. */
2332 ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
2333 (device->AvgSpeakerDist * device->Frequency);
2334 for(i = 0;i < voice->NumChannels;i++)
2335 NfcFilterCreate(&voice->Direct.Params[i].NFCtrlFilter, 0.0f, w1);
2338 almtx_unlock(&context->SourceLock);
2340 ATOMIC_FLAG_TEST_AND_SET(&context->PropsClean, almemory_order_release);
2341 UpdateContextProps(context);
2342 ATOMIC_FLAG_TEST_AND_SET(&context->Listener->PropsClean, almemory_order_release);
2343 UpdateListenerProps(context);
2344 UpdateAllSourceProps(context);
2345 almtx_unlock(&context->PropLock);
2347 context = ATOMIC_LOAD(&context->next, almemory_order_relaxed);
2349 END_MIXER_MODE();
2350 if(update_failed)
2351 return ALC_INVALID_DEVICE;
2353 if(!(device->Flags&DEVICE_PAUSED))
2355 if(V0(device->Backend,start)() == ALC_FALSE)
2356 return ALC_INVALID_DEVICE;
2357 device->Flags |= DEVICE_RUNNING;
2360 return ALC_NO_ERROR;
2364 static void InitDevice(ALCdevice *device, enum DeviceType type)
2366 ALsizei i;
2368 InitRef(&device->ref, 1);
2369 ATOMIC_INIT(&device->Connected, ALC_TRUE);
2370 device->Type = type;
2371 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
2373 device->Flags = 0;
2374 device->Render_Mode = NormalRender;
2375 device->AvgSpeakerDist = 0.0f;
2376 device->LimiterState = ALC_DONT_CARE_SOFT;
2378 ATOMIC_INIT(&device->ContextList, NULL);
2380 device->ClockBase = 0;
2381 device->SamplesDone = 0;
2382 device->FixedLatency = 0;
2384 device->SourcesMax = 0;
2385 device->AuxiliaryEffectSlotMax = 0;
2386 device->NumAuxSends = 0;
2388 device->Dry.Buffer = NULL;
2389 device->Dry.NumChannels = 0;
2390 device->FOAOut.Buffer = NULL;
2391 device->FOAOut.NumChannels = 0;
2392 device->RealOut.Buffer = NULL;
2393 device->RealOut.NumChannels = 0;
2395 AL_STRING_INIT(device->DeviceName);
2397 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2399 device->ChannelDelay[i].Gain = 1.0f;
2400 device->ChannelDelay[i].Length = 0;
2401 device->ChannelDelay[i].Buffer = NULL;
2404 AL_STRING_INIT(device->HrtfName);
2405 VECTOR_INIT(device->HrtfList);
2406 device->HrtfHandle = NULL;
2407 device->Hrtf = NULL;
2408 device->Bs2b = NULL;
2409 device->Uhj_Encoder = NULL;
2410 device->AmbiDecoder = NULL;
2411 device->AmbiUp = NULL;
2412 device->Stablizer = NULL;
2413 device->Limiter = NULL;
2415 VECTOR_INIT(device->BufferList);
2416 almtx_init(&device->BufferLock, almtx_plain);
2418 VECTOR_INIT(device->EffectList);
2419 almtx_init(&device->EffectLock, almtx_plain);
2421 VECTOR_INIT(device->FilterList);
2422 almtx_init(&device->FilterLock, almtx_plain);
2424 almtx_init(&device->BackendLock, almtx_plain);
2425 device->Backend = NULL;
2427 ATOMIC_INIT(&device->next, NULL);
2430 /* FreeDevice
2432 * Frees the device structure, and destroys any objects the app failed to
2433 * delete. Called once there's no more references on the device.
2435 static ALCvoid FreeDevice(ALCdevice *device)
2437 ALsizei i;
2439 TRACE("%p\n", device);
2441 if(device->Backend)
2442 DELETE_OBJ(device->Backend);
2443 device->Backend = NULL;
2445 almtx_destroy(&device->BackendLock);
2447 ReleaseALBuffers(device);
2448 #define FREE_BUFFERSUBLIST(x) al_free((x)->Buffers)
2449 VECTOR_FOR_EACH(BufferSubList, device->BufferList, FREE_BUFFERSUBLIST);
2450 #undef FREE_BUFFERSUBLIST
2451 VECTOR_DEINIT(device->BufferList);
2452 almtx_destroy(&device->BufferLock);
2454 ReleaseALEffects(device);
2455 #define FREE_EFFECTSUBLIST(x) al_free((x)->Effects)
2456 VECTOR_FOR_EACH(EffectSubList, device->EffectList, FREE_EFFECTSUBLIST);
2457 #undef FREE_EFFECTSUBLIST
2458 VECTOR_DEINIT(device->EffectList);
2459 almtx_destroy(&device->EffectLock);
2461 ReleaseALFilters(device);
2462 #define FREE_FILTERSUBLIST(x) al_free((x)->Filters)
2463 VECTOR_FOR_EACH(FilterSubList, device->FilterList, FREE_FILTERSUBLIST);
2464 #undef FREE_FILTERSUBLIST
2465 VECTOR_DEINIT(device->FilterList);
2466 almtx_destroy(&device->FilterLock);
2468 AL_STRING_DEINIT(device->HrtfName);
2469 FreeHrtfList(&device->HrtfList);
2470 if(device->HrtfHandle)
2471 Hrtf_DecRef(device->HrtfHandle);
2472 device->HrtfHandle = NULL;
2473 al_free(device->Hrtf);
2474 device->Hrtf = NULL;
2476 al_free(device->Bs2b);
2477 device->Bs2b = NULL;
2479 al_free(device->Uhj_Encoder);
2480 device->Uhj_Encoder = NULL;
2482 bformatdec_free(&device->AmbiDecoder);
2483 ambiup_free(&device->AmbiUp);
2485 al_free(device->Stablizer);
2486 device->Stablizer = NULL;
2488 al_free(device->Limiter);
2489 device->Limiter = NULL;
2491 al_free(device->ChannelDelay[0].Buffer);
2492 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2494 device->ChannelDelay[i].Gain = 1.0f;
2495 device->ChannelDelay[i].Length = 0;
2496 device->ChannelDelay[i].Buffer = NULL;
2499 AL_STRING_DEINIT(device->DeviceName);
2501 al_free(device->Dry.Buffer);
2502 device->Dry.Buffer = NULL;
2503 device->Dry.NumChannels = 0;
2504 device->FOAOut.Buffer = NULL;
2505 device->FOAOut.NumChannels = 0;
2506 device->RealOut.Buffer = NULL;
2507 device->RealOut.NumChannels = 0;
2509 al_free(device);
2513 void ALCdevice_IncRef(ALCdevice *device)
2515 uint ref;
2516 ref = IncrementRef(&device->ref);
2517 TRACEREF("%p increasing refcount to %u\n", device, ref);
2520 void ALCdevice_DecRef(ALCdevice *device)
2522 uint ref;
2523 ref = DecrementRef(&device->ref);
2524 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2525 if(ref == 0) FreeDevice(device);
2528 /* VerifyDevice
2530 * Checks if the device handle is valid, and increments its ref count if so.
2532 static ALCboolean VerifyDevice(ALCdevice **device)
2534 ALCdevice *tmpDevice;
2536 LockLists();
2537 tmpDevice = ATOMIC_LOAD_SEQ(&DeviceList);
2538 while(tmpDevice)
2540 if(tmpDevice == *device)
2542 ALCdevice_IncRef(tmpDevice);
2543 UnlockLists();
2544 return ALC_TRUE;
2546 tmpDevice = ATOMIC_LOAD(&tmpDevice->next, almemory_order_relaxed);
2548 UnlockLists();
2550 *device = NULL;
2551 return ALC_FALSE;
2555 /* InitContext
2557 * Initializes context fields
2559 static ALvoid InitContext(ALCcontext *Context)
2561 ALlistener *listener = Context->Listener;
2562 struct ALeffectslotArray *auxslots;
2564 //Initialise listener
2565 listener->Gain = 1.0f;
2566 listener->Position[0] = 0.0f;
2567 listener->Position[1] = 0.0f;
2568 listener->Position[2] = 0.0f;
2569 listener->Velocity[0] = 0.0f;
2570 listener->Velocity[1] = 0.0f;
2571 listener->Velocity[2] = 0.0f;
2572 listener->Forward[0] = 0.0f;
2573 listener->Forward[1] = 0.0f;
2574 listener->Forward[2] = -1.0f;
2575 listener->Up[0] = 0.0f;
2576 listener->Up[1] = 1.0f;
2577 listener->Up[2] = 0.0f;
2578 ATOMIC_FLAG_TEST_AND_SET(&listener->PropsClean, almemory_order_relaxed);
2580 ATOMIC_INIT(&listener->Update, NULL);
2582 //Validate Context
2583 InitRef(&Context->UpdateCount, 0);
2584 ATOMIC_INIT(&Context->HoldUpdates, AL_FALSE);
2585 Context->GainBoost = 1.0f;
2586 almtx_init(&Context->PropLock, almtx_plain);
2587 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2588 VECTOR_INIT(Context->SourceList);
2589 Context->NumSources = 0;
2590 almtx_init(&Context->SourceLock, almtx_plain);
2591 VECTOR_INIT(Context->EffectSlotList);
2592 almtx_init(&Context->EffectSlotLock, almtx_plain);
2594 if(Context->DefaultSlot)
2596 auxslots = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, 1));
2597 auxslots->count = 1;
2598 auxslots->slot[0] = Context->DefaultSlot;
2600 else
2602 auxslots = al_calloc(DEF_ALIGN, sizeof(struct ALeffectslotArray));
2603 auxslots->count = 0;
2605 ATOMIC_INIT(&Context->ActiveAuxSlots, auxslots);
2607 //Set globals
2608 Context->DistanceModel = DefaultDistanceModel;
2609 Context->SourceDistanceModel = AL_FALSE;
2610 Context->DopplerFactor = 1.0f;
2611 Context->DopplerVelocity = 1.0f;
2612 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2613 Context->MetersPerUnit = AL_DEFAULT_METERS_PER_UNIT;
2614 ATOMIC_FLAG_TEST_AND_SET(&Context->PropsClean, almemory_order_relaxed);
2615 ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
2616 alsem_init(&Context->EventSem, 0);
2617 Context->AsyncEvents = NULL;
2618 ATOMIC_INIT(&Context->EnabledEvts, 0);
2619 almtx_init(&Context->EventCbLock, almtx_plain);
2620 Context->EventCb = NULL;
2621 Context->EventParam = NULL;
2623 ATOMIC_INIT(&Context->Update, NULL);
2624 ATOMIC_INIT(&Context->FreeContextProps, NULL);
2625 ATOMIC_INIT(&Context->FreeListenerProps, NULL);
2626 ATOMIC_INIT(&Context->FreeVoiceProps, NULL);
2627 ATOMIC_INIT(&Context->FreeEffectslotProps, NULL);
2629 Context->ExtensionList = alExtList;
2632 listener->Params.Matrix = IdentityMatrixf;
2633 aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2634 listener->Params.Gain = listener->Gain;
2635 listener->Params.MetersPerUnit = Context->MetersPerUnit;
2636 listener->Params.DopplerFactor = Context->DopplerFactor;
2637 listener->Params.SpeedOfSound = Context->SpeedOfSound * Context->DopplerVelocity;
2638 listener->Params.ReverbSpeedOfSound = listener->Params.SpeedOfSound *
2639 listener->Params.MetersPerUnit;
2640 listener->Params.SourceDistanceModel = Context->SourceDistanceModel;
2641 listener->Params.DistanceModel = Context->DistanceModel;
2644 Context->AsyncEvents = ll_ringbuffer_create(63, sizeof(AsyncEvent), false);
2645 if(althrd_create(&Context->EventThread, EventThread, Context) != althrd_success)
2646 ERR("Failed to start event thread! Expect problems.\n");
2650 /* FreeContext
2652 * Cleans up the context, and destroys any remaining objects the app failed to
2653 * delete. Called once there's no more references on the context.
2655 static void FreeContext(ALCcontext *context)
2657 ALlistener *listener = context->Listener;
2658 struct ALeffectslotArray *auxslots;
2659 struct ALeffectslotProps *eprops;
2660 struct ALlistenerProps *lprops;
2661 struct ALcontextProps *cprops;
2662 struct ALvoiceProps *vprops;
2663 size_t count;
2664 ALsizei i;
2666 TRACE("%p\n", context);
2668 if((cprops=ATOMIC_LOAD(&context->Update, almemory_order_acquire)) != NULL)
2670 TRACE("Freed unapplied context update %p\n", cprops);
2671 al_free(cprops);
2674 count = 0;
2675 cprops = ATOMIC_LOAD(&context->FreeContextProps, almemory_order_acquire);
2676 while(cprops)
2678 struct ALcontextProps *next = ATOMIC_LOAD(&cprops->next, almemory_order_acquire);
2679 al_free(cprops);
2680 cprops = next;
2681 ++count;
2683 TRACE("Freed "SZFMT" context property object%s\n", count, (count==1)?"":"s");
2685 if(context->DefaultSlot)
2687 DeinitEffectSlot(context->DefaultSlot);
2688 context->DefaultSlot = NULL;
2691 auxslots = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, NULL, almemory_order_relaxed);
2692 al_free(auxslots);
2694 ReleaseALSources(context);
2695 #define FREE_SOURCESUBLIST(x) al_free((x)->Sources)
2696 VECTOR_FOR_EACH(SourceSubList, context->SourceList, FREE_SOURCESUBLIST);
2697 #undef FREE_SOURCESUBLIST
2698 VECTOR_DEINIT(context->SourceList);
2699 context->NumSources = 0;
2700 almtx_destroy(&context->SourceLock);
2702 count = 0;
2703 eprops = ATOMIC_LOAD(&context->FreeEffectslotProps, almemory_order_relaxed);
2704 while(eprops)
2706 struct ALeffectslotProps *next = ATOMIC_LOAD(&eprops->next, almemory_order_relaxed);
2707 if(eprops->State) ALeffectState_DecRef(eprops->State);
2708 al_free(eprops);
2709 eprops = next;
2710 ++count;
2712 TRACE("Freed "SZFMT" AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2714 ReleaseALAuxiliaryEffectSlots(context);
2715 #define FREE_EFFECTSLOTPTR(x) al_free(*(x))
2716 VECTOR_FOR_EACH(ALeffectslotPtr, context->EffectSlotList, FREE_EFFECTSLOTPTR);
2717 #undef FREE_EFFECTSLOTPTR
2718 VECTOR_DEINIT(context->EffectSlotList);
2719 almtx_destroy(&context->EffectSlotLock);
2721 count = 0;
2722 vprops = ATOMIC_LOAD(&context->FreeVoiceProps, almemory_order_relaxed);
2723 while(vprops)
2725 struct ALvoiceProps *next = ATOMIC_LOAD(&vprops->next, almemory_order_relaxed);
2726 al_free(vprops);
2727 vprops = next;
2728 ++count;
2730 TRACE("Freed "SZFMT" voice property object%s\n", count, (count==1)?"":"s");
2732 for(i = 0;i < context->VoiceCount;i++)
2733 DeinitVoice(context->Voices[i]);
2734 al_free(context->Voices);
2735 context->Voices = NULL;
2736 context->VoiceCount = 0;
2737 context->MaxVoices = 0;
2739 if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != NULL)
2741 TRACE("Freed unapplied listener update %p\n", lprops);
2742 al_free(lprops);
2744 count = 0;
2745 lprops = ATOMIC_LOAD(&context->FreeListenerProps, almemory_order_acquire);
2746 while(lprops)
2748 struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_acquire);
2749 al_free(lprops);
2750 lprops = next;
2751 ++count;
2753 TRACE("Freed "SZFMT" listener property object%s\n", count, (count==1)?"":"s");
2755 almtx_destroy(&context->EventCbLock);
2756 alsem_destroy(&context->EventSem);
2758 ll_ringbuffer_free(context->AsyncEvents);
2759 context->AsyncEvents = NULL;
2761 almtx_destroy(&context->PropLock);
2763 ALCdevice_DecRef(context->Device);
2764 context->Device = NULL;
2766 //Invalidate context
2767 memset(context, 0, sizeof(ALCcontext));
2768 al_free(context);
2771 /* ReleaseContext
2773 * Removes the context reference from the given device and removes it from
2774 * being current on the running thread or globally. Returns true if other
2775 * contexts still exist on the device.
2777 static bool ReleaseContext(ALCcontext *context, ALCdevice *device)
2779 static const AsyncEvent kill_evt = ASYNC_EVENT(EventType_KillThread);
2780 ALCcontext *origctx, *newhead;
2781 bool ret = true;
2783 if(altss_get(LocalContext) == context)
2785 WARN("%p released while current on thread\n", context);
2786 altss_set(LocalContext, NULL);
2787 ALCcontext_DecRef(context);
2790 origctx = context;
2791 if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext, &origctx, NULL))
2792 ALCcontext_DecRef(context);
2794 V0(device->Backend,lock)();
2795 origctx = context;
2796 newhead = ATOMIC_LOAD(&context->next, almemory_order_relaxed);
2797 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device->ContextList, &origctx, newhead))
2799 ALCcontext *list;
2800 do {
2801 /* origctx is what the desired context failed to match. Try
2802 * swapping out the next one in the list.
2804 list = origctx;
2805 origctx = context;
2806 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list->next, &origctx, newhead));
2808 else
2809 ret = !!newhead;
2810 V0(device->Backend,unlock)();
2812 while(ll_ringbuffer_write(context->AsyncEvents, (const char*)&kill_evt, 1) == 0)
2813 althrd_yield();
2814 alsem_post(&context->EventSem);
2815 althrd_join(context->EventThread, NULL);
2817 ALCcontext_DecRef(context);
2818 return ret;
2821 static void ALCcontext_IncRef(ALCcontext *context)
2823 uint ref = IncrementRef(&context->ref);
2824 TRACEREF("%p increasing refcount to %u\n", context, ref);
2827 void ALCcontext_DecRef(ALCcontext *context)
2829 uint ref = DecrementRef(&context->ref);
2830 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2831 if(ref == 0) FreeContext(context);
2834 static void ReleaseThreadCtx(void *ptr)
2836 ALCcontext *context = ptr;
2837 uint ref = DecrementRef(&context->ref);
2838 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2839 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2842 /* VerifyContext
2844 * Checks that the given context is valid, and increments its reference count.
2846 static ALCboolean VerifyContext(ALCcontext **context)
2848 ALCdevice *dev;
2850 LockLists();
2851 dev = ATOMIC_LOAD_SEQ(&DeviceList);
2852 while(dev)
2854 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList, almemory_order_acquire);
2855 while(ctx)
2857 if(ctx == *context)
2859 ALCcontext_IncRef(ctx);
2860 UnlockLists();
2861 return ALC_TRUE;
2863 ctx = ATOMIC_LOAD(&ctx->next, almemory_order_relaxed);
2865 dev = ATOMIC_LOAD(&dev->next, almemory_order_relaxed);
2867 UnlockLists();
2869 *context = NULL;
2870 return ALC_FALSE;
2874 /* GetContextRef
2876 * Returns the currently active context for this thread, and adds a reference
2877 * without locking it.
2879 ALCcontext *GetContextRef(void)
2881 ALCcontext *context;
2883 context = altss_get(LocalContext);
2884 if(context)
2885 ALCcontext_IncRef(context);
2886 else
2888 LockLists();
2889 context = ATOMIC_LOAD_SEQ(&GlobalContext);
2890 if(context)
2891 ALCcontext_IncRef(context);
2892 UnlockLists();
2895 return context;
2899 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
2901 ALCdevice *device = context->Device;
2902 ALsizei num_sends = device->NumAuxSends;
2903 struct ALvoiceProps *props;
2904 size_t sizeof_props;
2905 size_t sizeof_voice;
2906 ALvoice **voices;
2907 ALvoice *voice;
2908 ALsizei v = 0;
2909 size_t size;
2911 if(num_voices == context->MaxVoices && num_sends == old_sends)
2912 return;
2914 /* Allocate the voice pointers, voices, and the voices' stored source
2915 * property set (including the dynamically-sized Send[] array) in one
2916 * chunk.
2918 sizeof_voice = RoundUp(FAM_SIZE(ALvoice, Send, num_sends), 16);
2919 sizeof_props = RoundUp(FAM_SIZE(struct ALvoiceProps, Send, num_sends), 16);
2920 size = sizeof(ALvoice*) + sizeof_voice + sizeof_props;
2922 voices = al_calloc(16, RoundUp(size*num_voices, 16));
2923 /* The voice and property objects are stored interleaved since they're
2924 * paired together.
2926 voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
2927 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2929 if(context->Voices)
2931 const ALsizei v_count = mini(context->VoiceCount, num_voices);
2932 const ALsizei s_count = mini(old_sends, num_sends);
2934 for(;v < v_count;v++)
2936 ALvoice *old_voice = context->Voices[v];
2937 ALsizei i;
2939 /* Copy the old voice data and source property set to the new
2940 * storage.
2942 *voice = *old_voice;
2943 for(i = 0;i < s_count;i++)
2944 voice->Send[i] = old_voice->Send[i];
2945 *props = *(old_voice->Props);
2946 for(i = 0;i < s_count;i++)
2947 props->Send[i] = old_voice->Props->Send[i];
2949 /* Set this voice's property set pointer and voice reference. */
2950 voice->Props = props;
2951 voices[v] = voice;
2953 /* Increment pointers to the next storage space. */
2954 voice = (ALvoice*)((char*)props + sizeof_props);
2955 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2957 /* Deinit any left over voices that weren't copied over to the new
2958 * array. NOTE: If this does anything, v equals num_voices and
2959 * num_voices is less than VoiceCount, so the following loop won't do
2960 * anything.
2962 for(;v < context->VoiceCount;v++)
2963 DeinitVoice(context->Voices[v]);
2965 /* Finish setting the voices' property set pointers and references. */
2966 for(;v < num_voices;v++)
2968 ATOMIC_INIT(&voice->Update, NULL);
2970 voice->Props = props;
2971 voices[v] = voice;
2973 voice = (ALvoice*)((char*)props + sizeof_props);
2974 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2977 al_free(context->Voices);
2978 context->Voices = voices;
2979 context->MaxVoices = num_voices;
2980 context->VoiceCount = mini(context->VoiceCount, num_voices);
2984 /************************************************
2985 * Standard ALC functions
2986 ************************************************/
2988 /* alcGetError
2990 * Return last ALC generated error code for the given device
2992 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2994 ALCenum errorCode;
2996 if(VerifyDevice(&device))
2998 errorCode = ATOMIC_EXCHANGE_SEQ(&device->LastError, ALC_NO_ERROR);
2999 ALCdevice_DecRef(device);
3001 else
3002 errorCode = ATOMIC_EXCHANGE_SEQ(&LastNullDeviceError, ALC_NO_ERROR);
3004 return errorCode;
3008 /* alcSuspendContext
3010 * Suspends updates for the given context
3012 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
3014 if(!SuspendDefers)
3015 return;
3017 if(!VerifyContext(&context))
3018 alcSetError(NULL, ALC_INVALID_CONTEXT);
3019 else
3021 ALCcontext_DeferUpdates(context);
3022 ALCcontext_DecRef(context);
3026 /* alcProcessContext
3028 * Resumes processing updates for the given context
3030 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
3032 if(!SuspendDefers)
3033 return;
3035 if(!VerifyContext(&context))
3036 alcSetError(NULL, ALC_INVALID_CONTEXT);
3037 else
3039 ALCcontext_ProcessUpdates(context);
3040 ALCcontext_DecRef(context);
3045 /* alcGetString
3047 * Returns information about the device, and error strings
3049 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
3051 const ALCchar *value = NULL;
3053 switch(param)
3055 case ALC_NO_ERROR:
3056 value = alcNoError;
3057 break;
3059 case ALC_INVALID_ENUM:
3060 value = alcErrInvalidEnum;
3061 break;
3063 case ALC_INVALID_VALUE:
3064 value = alcErrInvalidValue;
3065 break;
3067 case ALC_INVALID_DEVICE:
3068 value = alcErrInvalidDevice;
3069 break;
3071 case ALC_INVALID_CONTEXT:
3072 value = alcErrInvalidContext;
3073 break;
3075 case ALC_OUT_OF_MEMORY:
3076 value = alcErrOutOfMemory;
3077 break;
3079 case ALC_DEVICE_SPECIFIER:
3080 value = alcDefaultName;
3081 break;
3083 case ALC_ALL_DEVICES_SPECIFIER:
3084 if(VerifyDevice(&Device))
3086 value = alstr_get_cstr(Device->DeviceName);
3087 ALCdevice_DecRef(Device);
3089 else
3091 ProbeAllDevicesList();
3092 value = alstr_get_cstr(alcAllDevicesList);
3094 break;
3096 case ALC_CAPTURE_DEVICE_SPECIFIER:
3097 if(VerifyDevice(&Device))
3099 value = alstr_get_cstr(Device->DeviceName);
3100 ALCdevice_DecRef(Device);
3102 else
3104 ProbeCaptureDeviceList();
3105 value = alstr_get_cstr(alcCaptureDeviceList);
3107 break;
3109 /* Default devices are always first in the list */
3110 case ALC_DEFAULT_DEVICE_SPECIFIER:
3111 value = alcDefaultName;
3112 break;
3114 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
3115 if(alstr_empty(alcAllDevicesList))
3116 ProbeAllDevicesList();
3118 VerifyDevice(&Device);
3120 free(alcDefaultAllDevicesSpecifier);
3121 alcDefaultAllDevicesSpecifier = strdup(alstr_get_cstr(alcAllDevicesList));
3122 if(!alcDefaultAllDevicesSpecifier)
3123 alcSetError(Device, ALC_OUT_OF_MEMORY);
3125 value = alcDefaultAllDevicesSpecifier;
3126 if(Device) ALCdevice_DecRef(Device);
3127 break;
3129 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
3130 if(alstr_empty(alcCaptureDeviceList))
3131 ProbeCaptureDeviceList();
3133 VerifyDevice(&Device);
3135 free(alcCaptureDefaultDeviceSpecifier);
3136 alcCaptureDefaultDeviceSpecifier = strdup(alstr_get_cstr(alcCaptureDeviceList));
3137 if(!alcCaptureDefaultDeviceSpecifier)
3138 alcSetError(Device, ALC_OUT_OF_MEMORY);
3140 value = alcCaptureDefaultDeviceSpecifier;
3141 if(Device) ALCdevice_DecRef(Device);
3142 break;
3144 case ALC_EXTENSIONS:
3145 if(!VerifyDevice(&Device))
3146 value = alcNoDeviceExtList;
3147 else
3149 value = alcExtensionList;
3150 ALCdevice_DecRef(Device);
3152 break;
3154 case ALC_HRTF_SPECIFIER_SOFT:
3155 if(!VerifyDevice(&Device))
3156 alcSetError(NULL, ALC_INVALID_DEVICE);
3157 else
3159 almtx_lock(&Device->BackendLock);
3160 value = (Device->HrtfHandle ? alstr_get_cstr(Device->HrtfName) : "");
3161 almtx_unlock(&Device->BackendLock);
3162 ALCdevice_DecRef(Device);
3164 break;
3166 default:
3167 VerifyDevice(&Device);
3168 alcSetError(Device, ALC_INVALID_ENUM);
3169 if(Device) ALCdevice_DecRef(Device);
3170 break;
3173 return value;
3177 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
3179 if(device->Type == Capture) return 9;
3180 if(device->Type != Loopback) return 29;
3181 if(device->FmtChans == DevFmtAmbi3D)
3182 return 35;
3183 return 29;
3186 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3188 ALCsizei i;
3190 if(size <= 0 || values == NULL)
3192 alcSetError(device, ALC_INVALID_VALUE);
3193 return 0;
3196 if(!device)
3198 switch(param)
3200 case ALC_MAJOR_VERSION:
3201 values[0] = alcMajorVersion;
3202 return 1;
3203 case ALC_MINOR_VERSION:
3204 values[0] = alcMinorVersion;
3205 return 1;
3207 case ALC_ATTRIBUTES_SIZE:
3208 case ALC_ALL_ATTRIBUTES:
3209 case ALC_FREQUENCY:
3210 case ALC_REFRESH:
3211 case ALC_SYNC:
3212 case ALC_MONO_SOURCES:
3213 case ALC_STEREO_SOURCES:
3214 case ALC_CAPTURE_SAMPLES:
3215 case ALC_FORMAT_CHANNELS_SOFT:
3216 case ALC_FORMAT_TYPE_SOFT:
3217 case ALC_AMBISONIC_LAYOUT_SOFT:
3218 case ALC_AMBISONIC_SCALING_SOFT:
3219 case ALC_AMBISONIC_ORDER_SOFT:
3220 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3221 alcSetError(NULL, ALC_INVALID_DEVICE);
3222 return 0;
3224 default:
3225 alcSetError(NULL, ALC_INVALID_ENUM);
3226 return 0;
3228 return 0;
3231 if(device->Type == Capture)
3233 switch(param)
3235 case ALC_ATTRIBUTES_SIZE:
3236 values[0] = NumAttrsForDevice(device);
3237 return 1;
3239 case ALC_ALL_ATTRIBUTES:
3240 if(size < NumAttrsForDevice(device))
3242 alcSetError(device, ALC_INVALID_VALUE);
3243 return 0;
3246 i = 0;
3247 almtx_lock(&device->BackendLock);
3248 values[i++] = ALC_MAJOR_VERSION;
3249 values[i++] = alcMajorVersion;
3250 values[i++] = ALC_MINOR_VERSION;
3251 values[i++] = alcMinorVersion;
3252 values[i++] = ALC_CAPTURE_SAMPLES;
3253 values[i++] = V0(device->Backend,availableSamples)();
3254 values[i++] = ALC_CONNECTED;
3255 values[i++] = ATOMIC_LOAD(&device->Connected, almemory_order_relaxed);
3256 almtx_unlock(&device->BackendLock);
3258 values[i++] = 0;
3259 return i;
3261 case ALC_MAJOR_VERSION:
3262 values[0] = alcMajorVersion;
3263 return 1;
3264 case ALC_MINOR_VERSION:
3265 values[0] = alcMinorVersion;
3266 return 1;
3268 case ALC_CAPTURE_SAMPLES:
3269 almtx_lock(&device->BackendLock);
3270 values[0] = V0(device->Backend,availableSamples)();
3271 almtx_unlock(&device->BackendLock);
3272 return 1;
3274 case ALC_CONNECTED:
3275 values[0] = ATOMIC_LOAD(&device->Connected, almemory_order_acquire);
3276 return 1;
3278 default:
3279 alcSetError(device, ALC_INVALID_ENUM);
3280 return 0;
3282 return 0;
3285 /* render device */
3286 switch(param)
3288 case ALC_ATTRIBUTES_SIZE:
3289 values[0] = NumAttrsForDevice(device);
3290 return 1;
3292 case ALC_ALL_ATTRIBUTES:
3293 if(size < NumAttrsForDevice(device))
3295 alcSetError(device, ALC_INVALID_VALUE);
3296 return 0;
3299 i = 0;
3300 almtx_lock(&device->BackendLock);
3301 values[i++] = ALC_MAJOR_VERSION;
3302 values[i++] = alcMajorVersion;
3303 values[i++] = ALC_MINOR_VERSION;
3304 values[i++] = alcMinorVersion;
3305 values[i++] = ALC_EFX_MAJOR_VERSION;
3306 values[i++] = alcEFXMajorVersion;
3307 values[i++] = ALC_EFX_MINOR_VERSION;
3308 values[i++] = alcEFXMinorVersion;
3310 values[i++] = ALC_FREQUENCY;
3311 values[i++] = device->Frequency;
3312 if(device->Type != Loopback)
3314 values[i++] = ALC_REFRESH;
3315 values[i++] = device->Frequency / device->UpdateSize;
3317 values[i++] = ALC_SYNC;
3318 values[i++] = ALC_FALSE;
3320 else
3322 if(device->FmtChans == DevFmtAmbi3D)
3324 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3325 values[i++] = device->AmbiLayout;
3327 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3328 values[i++] = device->AmbiScale;
3330 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3331 values[i++] = device->AmbiOrder;
3334 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3335 values[i++] = device->FmtChans;
3337 values[i++] = ALC_FORMAT_TYPE_SOFT;
3338 values[i++] = device->FmtType;
3341 values[i++] = ALC_MONO_SOURCES;
3342 values[i++] = device->NumMonoSources;
3344 values[i++] = ALC_STEREO_SOURCES;
3345 values[i++] = device->NumStereoSources;
3347 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3348 values[i++] = device->NumAuxSends;
3350 values[i++] = ALC_HRTF_SOFT;
3351 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3353 values[i++] = ALC_HRTF_STATUS_SOFT;
3354 values[i++] = device->HrtfStatus;
3356 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3357 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3359 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
3360 values[i++] = MAX_AMBI_ORDER;
3361 almtx_unlock(&device->BackendLock);
3363 values[i++] = 0;
3364 return i;
3366 case ALC_MAJOR_VERSION:
3367 values[0] = alcMajorVersion;
3368 return 1;
3370 case ALC_MINOR_VERSION:
3371 values[0] = alcMinorVersion;
3372 return 1;
3374 case ALC_EFX_MAJOR_VERSION:
3375 values[0] = alcEFXMajorVersion;
3376 return 1;
3378 case ALC_EFX_MINOR_VERSION:
3379 values[0] = alcEFXMinorVersion;
3380 return 1;
3382 case ALC_FREQUENCY:
3383 values[0] = device->Frequency;
3384 return 1;
3386 case ALC_REFRESH:
3387 if(device->Type == Loopback)
3389 alcSetError(device, ALC_INVALID_DEVICE);
3390 return 0;
3392 almtx_lock(&device->BackendLock);
3393 values[0] = device->Frequency / device->UpdateSize;
3394 almtx_unlock(&device->BackendLock);
3395 return 1;
3397 case ALC_SYNC:
3398 if(device->Type == Loopback)
3400 alcSetError(device, ALC_INVALID_DEVICE);
3401 return 0;
3403 values[0] = ALC_FALSE;
3404 return 1;
3406 case ALC_FORMAT_CHANNELS_SOFT:
3407 if(device->Type != Loopback)
3409 alcSetError(device, ALC_INVALID_DEVICE);
3410 return 0;
3412 values[0] = device->FmtChans;
3413 return 1;
3415 case ALC_FORMAT_TYPE_SOFT:
3416 if(device->Type != Loopback)
3418 alcSetError(device, ALC_INVALID_DEVICE);
3419 return 0;
3421 values[0] = device->FmtType;
3422 return 1;
3424 case ALC_AMBISONIC_LAYOUT_SOFT:
3425 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3427 alcSetError(device, ALC_INVALID_DEVICE);
3428 return 0;
3430 values[0] = device->AmbiLayout;
3431 return 1;
3433 case ALC_AMBISONIC_SCALING_SOFT:
3434 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3436 alcSetError(device, ALC_INVALID_DEVICE);
3437 return 0;
3439 values[0] = device->AmbiScale;
3440 return 1;
3442 case ALC_AMBISONIC_ORDER_SOFT:
3443 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3445 alcSetError(device, ALC_INVALID_DEVICE);
3446 return 0;
3448 values[0] = device->AmbiOrder;
3449 return 1;
3451 case ALC_MONO_SOURCES:
3452 values[0] = device->NumMonoSources;
3453 return 1;
3455 case ALC_STEREO_SOURCES:
3456 values[0] = device->NumStereoSources;
3457 return 1;
3459 case ALC_MAX_AUXILIARY_SENDS:
3460 values[0] = device->NumAuxSends;
3461 return 1;
3463 case ALC_CONNECTED:
3464 values[0] = ATOMIC_LOAD(&device->Connected, almemory_order_acquire);
3465 return 1;
3467 case ALC_HRTF_SOFT:
3468 values[0] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3469 return 1;
3471 case ALC_HRTF_STATUS_SOFT:
3472 values[0] = device->HrtfStatus;
3473 return 1;
3475 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3476 almtx_lock(&device->BackendLock);
3477 FreeHrtfList(&device->HrtfList);
3478 device->HrtfList = EnumerateHrtf(device->DeviceName);
3479 values[0] = (ALCint)VECTOR_SIZE(device->HrtfList);
3480 almtx_unlock(&device->BackendLock);
3481 return 1;
3483 case ALC_OUTPUT_LIMITER_SOFT:
3484 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3485 return 1;
3487 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3488 values[0] = MAX_AMBI_ORDER;
3489 return 1;
3491 default:
3492 alcSetError(device, ALC_INVALID_ENUM);
3493 return 0;
3495 return 0;
3498 /* alcGetIntegerv
3500 * Returns information about the device and the version of OpenAL
3502 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3504 VerifyDevice(&device);
3505 if(size <= 0 || values == NULL)
3506 alcSetError(device, ALC_INVALID_VALUE);
3507 else
3508 GetIntegerv(device, param, size, values);
3509 if(device) ALCdevice_DecRef(device);
3512 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3514 ALCint *ivals;
3515 ALsizei i;
3517 VerifyDevice(&device);
3518 if(size <= 0 || values == NULL)
3519 alcSetError(device, ALC_INVALID_VALUE);
3520 else if(!device || device->Type == Capture)
3522 ivals = malloc(size * sizeof(ALCint));
3523 size = GetIntegerv(device, pname, size, ivals);
3524 for(i = 0;i < size;i++)
3525 values[i] = ivals[i];
3526 free(ivals);
3528 else /* render device */
3530 ClockLatency clock;
3531 ALuint64 basecount;
3532 ALuint samplecount;
3533 ALuint refcount;
3535 switch(pname)
3537 case ALC_ATTRIBUTES_SIZE:
3538 *values = NumAttrsForDevice(device)+4;
3539 break;
3541 case ALC_ALL_ATTRIBUTES:
3542 if(size < NumAttrsForDevice(device)+4)
3543 alcSetError(device, ALC_INVALID_VALUE);
3544 else
3546 i = 0;
3547 almtx_lock(&device->BackendLock);
3548 values[i++] = ALC_FREQUENCY;
3549 values[i++] = device->Frequency;
3551 if(device->Type != Loopback)
3553 values[i++] = ALC_REFRESH;
3554 values[i++] = device->Frequency / device->UpdateSize;
3556 values[i++] = ALC_SYNC;
3557 values[i++] = ALC_FALSE;
3559 else
3561 if(device->FmtChans == DevFmtAmbi3D)
3563 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3564 values[i++] = device->AmbiLayout;
3566 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3567 values[i++] = device->AmbiScale;
3569 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3570 values[i++] = device->AmbiOrder;
3573 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3574 values[i++] = device->FmtChans;
3576 values[i++] = ALC_FORMAT_TYPE_SOFT;
3577 values[i++] = device->FmtType;
3580 values[i++] = ALC_MONO_SOURCES;
3581 values[i++] = device->NumMonoSources;
3583 values[i++] = ALC_STEREO_SOURCES;
3584 values[i++] = device->NumStereoSources;
3586 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3587 values[i++] = device->NumAuxSends;
3589 values[i++] = ALC_HRTF_SOFT;
3590 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3592 values[i++] = ALC_HRTF_STATUS_SOFT;
3593 values[i++] = device->HrtfStatus;
3595 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3596 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3598 clock = GetClockLatency(device);
3599 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3600 values[i++] = clock.ClockTime;
3602 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3603 values[i++] = clock.Latency;
3604 almtx_unlock(&device->BackendLock);
3606 values[i++] = 0;
3608 break;
3610 case ALC_DEVICE_CLOCK_SOFT:
3611 almtx_lock(&device->BackendLock);
3612 do {
3613 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3614 althrd_yield();
3615 basecount = device->ClockBase;
3616 samplecount = device->SamplesDone;
3617 } while(refcount != ReadRef(&device->MixCount));
3618 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3619 almtx_unlock(&device->BackendLock);
3620 break;
3622 case ALC_DEVICE_LATENCY_SOFT:
3623 almtx_lock(&device->BackendLock);
3624 clock = GetClockLatency(device);
3625 almtx_unlock(&device->BackendLock);
3626 *values = clock.Latency;
3627 break;
3629 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3630 if(size < 2)
3631 alcSetError(device, ALC_INVALID_VALUE);
3632 else
3634 almtx_lock(&device->BackendLock);
3635 clock = GetClockLatency(device);
3636 almtx_unlock(&device->BackendLock);
3637 values[0] = clock.ClockTime;
3638 values[1] = clock.Latency;
3640 break;
3642 default:
3643 ivals = malloc(size * sizeof(ALCint));
3644 size = GetIntegerv(device, pname, size, ivals);
3645 for(i = 0;i < size;i++)
3646 values[i] = ivals[i];
3647 free(ivals);
3648 break;
3651 if(device)
3652 ALCdevice_DecRef(device);
3656 /* alcIsExtensionPresent
3658 * Determines if there is support for a particular extension
3660 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3662 ALCboolean bResult = ALC_FALSE;
3664 VerifyDevice(&device);
3666 if(!extName)
3667 alcSetError(device, ALC_INVALID_VALUE);
3668 else
3670 size_t len = strlen(extName);
3671 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3672 while(ptr && *ptr)
3674 if(strncasecmp(ptr, extName, len) == 0 &&
3675 (ptr[len] == '\0' || isspace(ptr[len])))
3677 bResult = ALC_TRUE;
3678 break;
3680 if((ptr=strchr(ptr, ' ')) != NULL)
3682 do {
3683 ++ptr;
3684 } while(isspace(*ptr));
3688 if(device)
3689 ALCdevice_DecRef(device);
3690 return bResult;
3694 /* alcGetProcAddress
3696 * Retrieves the function address for a particular extension function
3698 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3700 ALCvoid *ptr = NULL;
3702 if(!funcName)
3704 VerifyDevice(&device);
3705 alcSetError(device, ALC_INVALID_VALUE);
3706 if(device) ALCdevice_DecRef(device);
3708 else
3710 size_t i = 0;
3711 for(i = 0;i < COUNTOF(alcFunctions);i++)
3713 if(strcmp(alcFunctions[i].funcName, funcName) == 0)
3715 ptr = alcFunctions[i].address;
3716 break;
3721 return ptr;
3725 /* alcGetEnumValue
3727 * Get the value for a particular ALC enumeration name
3729 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3731 ALCenum val = 0;
3733 if(!enumName)
3735 VerifyDevice(&device);
3736 alcSetError(device, ALC_INVALID_VALUE);
3737 if(device) ALCdevice_DecRef(device);
3739 else
3741 size_t i = 0;
3742 for(i = 0;i < COUNTOF(alcEnumerations);i++)
3744 if(strcmp(alcEnumerations[i].enumName, enumName) == 0)
3746 val = alcEnumerations[i].value;
3747 break;
3752 return val;
3756 /* alcCreateContext
3758 * Create and attach a context to the given device.
3760 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3762 ALCcontext *ALContext;
3763 ALfloat valf;
3764 ALCenum err;
3766 /* Explicitly hold the list lock while taking the BackendLock in case the
3767 * device is asynchronously destropyed, to ensure this new context is
3768 * properly cleaned up after being made.
3770 LockLists();
3771 if(!VerifyDevice(&device) || device->Type == Capture ||
3772 !ATOMIC_LOAD(&device->Connected, almemory_order_relaxed))
3774 UnlockLists();
3775 alcSetError(device, ALC_INVALID_DEVICE);
3776 if(device) ALCdevice_DecRef(device);
3777 return NULL;
3779 almtx_lock(&device->BackendLock);
3780 UnlockLists();
3782 ATOMIC_STORE_SEQ(&device->LastError, ALC_NO_ERROR);
3784 if(device->Type == Playback && DefaultEffect.type != AL_EFFECT_NULL)
3785 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener)+sizeof(ALeffectslot));
3786 else
3787 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3788 if(!ALContext)
3790 almtx_unlock(&device->BackendLock);
3792 alcSetError(device, ALC_OUT_OF_MEMORY);
3793 ALCdevice_DecRef(device);
3794 return NULL;
3797 InitRef(&ALContext->ref, 1);
3798 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3799 ALContext->DefaultSlot = NULL;
3801 ALContext->Voices = NULL;
3802 ALContext->VoiceCount = 0;
3803 ALContext->MaxVoices = 0;
3804 ATOMIC_INIT(&ALContext->ActiveAuxSlots, NULL);
3805 ALContext->Device = device;
3806 ATOMIC_INIT(&ALContext->next, NULL);
3808 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3810 almtx_unlock(&device->BackendLock);
3812 al_free(ALContext);
3813 ALContext = NULL;
3815 alcSetError(device, err);
3816 if(err == ALC_INVALID_DEVICE)
3818 V0(device->Backend,lock)();
3819 aluHandleDisconnect(device, "Device update failure");
3820 V0(device->Backend,unlock)();
3822 ALCdevice_DecRef(device);
3823 return NULL;
3825 AllocateVoices(ALContext, 256, device->NumAuxSends);
3827 if(DefaultEffect.type != AL_EFFECT_NULL && device->Type == Playback)
3829 ALContext->DefaultSlot = (ALeffectslot*)(ALContext->_listener_mem + sizeof(ALlistener));
3830 if(InitEffectSlot(ALContext->DefaultSlot) == AL_NO_ERROR)
3831 aluInitEffectPanning(ALContext->DefaultSlot);
3832 else
3834 ALContext->DefaultSlot = NULL;
3835 ERR("Failed to initialize the default effect slot\n");
3839 ALCdevice_IncRef(ALContext->Device);
3840 InitContext(ALContext);
3842 if(ConfigValueFloat(alstr_get_cstr(device->DeviceName), NULL, "volume-adjust", &valf))
3844 if(!isfinite(valf))
3845 ERR("volume-adjust must be finite: %f\n", valf);
3846 else
3848 ALfloat db = clampf(valf, -24.0f, 24.0f);
3849 if(db != valf)
3850 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3851 ALContext->GainBoost = powf(10.0f, db/20.0f);
3852 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3855 UpdateListenerProps(ALContext);
3858 ALCcontext *head = ATOMIC_LOAD_SEQ(&device->ContextList);
3859 do {
3860 ATOMIC_STORE(&ALContext->next, head, almemory_order_relaxed);
3861 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device->ContextList, &head,
3862 ALContext) == 0);
3864 almtx_unlock(&device->BackendLock);
3866 if(ALContext->DefaultSlot)
3868 if(InitializeEffect(ALContext, ALContext->DefaultSlot, &DefaultEffect) == AL_NO_ERROR)
3869 UpdateEffectSlotProps(ALContext->DefaultSlot, ALContext);
3870 else
3871 ERR("Failed to initialize the default effect\n");
3874 ALCdevice_DecRef(device);
3876 TRACE("Created context %p\n", ALContext);
3877 return ALContext;
3880 /* alcDestroyContext
3882 * Remove a context from its device
3884 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3886 ALCdevice *Device;
3888 LockLists();
3889 if(!VerifyContext(&context))
3891 UnlockLists();
3892 alcSetError(NULL, ALC_INVALID_CONTEXT);
3893 return;
3896 Device = context->Device;
3897 if(Device)
3899 almtx_lock(&Device->BackendLock);
3900 if(!ReleaseContext(context, Device))
3902 V0(Device->Backend,stop)();
3903 Device->Flags &= ~DEVICE_RUNNING;
3905 almtx_unlock(&Device->BackendLock);
3907 UnlockLists();
3909 ALCcontext_DecRef(context);
3913 /* alcGetCurrentContext
3915 * Returns the currently active context on the calling thread
3917 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3919 ALCcontext *Context = altss_get(LocalContext);
3920 if(!Context) Context = ATOMIC_LOAD_SEQ(&GlobalContext);
3921 return Context;
3924 /* alcGetThreadContext
3926 * Returns the currently active thread-local context
3928 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3930 return altss_get(LocalContext);
3934 /* alcMakeContextCurrent
3936 * Makes the given context the active process-wide context, and removes the
3937 * thread-local context for the calling thread.
3939 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3941 /* context must be valid or NULL */
3942 if(context && !VerifyContext(&context))
3944 alcSetError(NULL, ALC_INVALID_CONTEXT);
3945 return ALC_FALSE;
3947 /* context's reference count is already incremented */
3948 context = ATOMIC_EXCHANGE_PTR_SEQ(&GlobalContext, context);
3949 if(context) ALCcontext_DecRef(context);
3951 if((context=altss_get(LocalContext)) != NULL)
3953 altss_set(LocalContext, NULL);
3954 ALCcontext_DecRef(context);
3957 return ALC_TRUE;
3960 /* alcSetThreadContext
3962 * Makes the given context the active context for the current thread
3964 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3966 ALCcontext *old;
3968 /* context must be valid or NULL */
3969 if(context && !VerifyContext(&context))
3971 alcSetError(NULL, ALC_INVALID_CONTEXT);
3972 return ALC_FALSE;
3974 /* context's reference count is already incremented */
3975 old = altss_get(LocalContext);
3976 altss_set(LocalContext, context);
3977 if(old) ALCcontext_DecRef(old);
3979 return ALC_TRUE;
3983 /* alcGetContextsDevice
3985 * Returns the device that a particular context is attached to
3987 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3989 ALCdevice *Device;
3991 if(!VerifyContext(&Context))
3993 alcSetError(NULL, ALC_INVALID_CONTEXT);
3994 return NULL;
3996 Device = Context->Device;
3997 ALCcontext_DecRef(Context);
3999 return Device;
4003 /* alcOpenDevice
4005 * Opens the named device.
4007 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
4009 ALCbackendFactory *factory;
4010 const ALCchar *fmt;
4011 ALCdevice *device;
4012 ALCenum err;
4014 DO_INITCONFIG();
4016 if(!PlaybackBackend.name)
4018 alcSetError(NULL, ALC_INVALID_VALUE);
4019 return NULL;
4022 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
4023 #ifdef _WIN32
4024 /* Some old Windows apps hardcode these expecting OpenAL to use a
4025 * specific audio API, even when they're not enumerated. Creative's
4026 * router effectively ignores them too.
4028 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
4029 || strcasecmp(deviceName, "MMSYSTEM") == 0
4030 #endif
4032 deviceName = NULL;
4034 device = al_calloc(16, sizeof(ALCdevice));
4035 if(!device)
4037 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4038 return NULL;
4041 //Validate device
4042 InitDevice(device, Playback);
4044 //Set output format
4045 device->FmtChans = DevFmtChannelsDefault;
4046 device->FmtType = DevFmtTypeDefault;
4047 device->Frequency = DEFAULT_OUTPUT_RATE;
4048 device->IsHeadphones = AL_FALSE;
4049 device->AmbiLayout = AmbiLayout_Default;
4050 device->AmbiScale = AmbiNorm_Default;
4051 device->LimiterState = ALC_TRUE;
4052 device->NumUpdates = 3;
4053 device->UpdateSize = 1024;
4055 device->SourcesMax = 256;
4056 device->AuxiliaryEffectSlotMax = 64;
4057 device->NumAuxSends = DEFAULT_SENDS;
4059 if(ConfigValueStr(deviceName, NULL, "channels", &fmt))
4061 static const struct {
4062 const char name[16];
4063 enum DevFmtChannels chans;
4064 ALsizei order;
4065 } chanlist[] = {
4066 { "mono", DevFmtMono, 0 },
4067 { "stereo", DevFmtStereo, 0 },
4068 { "quad", DevFmtQuad, 0 },
4069 { "surround51", DevFmtX51, 0 },
4070 { "surround61", DevFmtX61, 0 },
4071 { "surround71", DevFmtX71, 0 },
4072 { "surround51rear", DevFmtX51Rear, 0 },
4073 { "ambi1", DevFmtAmbi3D, 1 },
4074 { "ambi2", DevFmtAmbi3D, 2 },
4075 { "ambi3", DevFmtAmbi3D, 3 },
4077 size_t i;
4079 for(i = 0;i < COUNTOF(chanlist);i++)
4081 if(strcasecmp(chanlist[i].name, fmt) == 0)
4083 device->FmtChans = chanlist[i].chans;
4084 device->AmbiOrder = chanlist[i].order;
4085 device->Flags |= DEVICE_CHANNELS_REQUEST;
4086 break;
4089 if(i == COUNTOF(chanlist))
4090 ERR("Unsupported channels: %s\n", fmt);
4092 if(ConfigValueStr(deviceName, NULL, "sample-type", &fmt))
4094 static const struct {
4095 const char name[16];
4096 enum DevFmtType type;
4097 } typelist[] = {
4098 { "int8", DevFmtByte },
4099 { "uint8", DevFmtUByte },
4100 { "int16", DevFmtShort },
4101 { "uint16", DevFmtUShort },
4102 { "int32", DevFmtInt },
4103 { "uint32", DevFmtUInt },
4104 { "float32", DevFmtFloat },
4106 size_t i;
4108 for(i = 0;i < COUNTOF(typelist);i++)
4110 if(strcasecmp(typelist[i].name, fmt) == 0)
4112 device->FmtType = typelist[i].type;
4113 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
4114 break;
4117 if(i == COUNTOF(typelist))
4118 ERR("Unsupported sample-type: %s\n", fmt);
4121 if(ConfigValueUInt(deviceName, NULL, "frequency", &device->Frequency))
4123 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4124 if(device->Frequency < MIN_OUTPUT_RATE)
4125 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
4126 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
4129 ConfigValueUInt(deviceName, NULL, "periods", &device->NumUpdates);
4130 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
4132 ConfigValueUInt(deviceName, NULL, "period_size", &device->UpdateSize);
4133 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
4134 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
4135 device->UpdateSize = (device->UpdateSize+3)&~3;
4137 ConfigValueUInt(deviceName, NULL, "sources", &device->SourcesMax);
4138 if(device->SourcesMax == 0) device->SourcesMax = 256;
4140 ConfigValueUInt(deviceName, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4141 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4142 else device->AuxiliaryEffectSlotMax = minu(device->AuxiliaryEffectSlotMax, INT_MAX);
4144 if(ConfigValueInt(deviceName, NULL, "sends", &device->NumAuxSends))
4145 device->NumAuxSends = clampi(
4146 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4149 device->NumStereoSources = 1;
4150 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4152 factory = PlaybackBackend.getFactory();
4153 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
4154 if(!device->Backend)
4156 FreeDevice(device);
4157 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4158 return NULL;
4161 // Find a playback device to open
4162 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4164 FreeDevice(device);
4165 alcSetError(NULL, err);
4166 return NULL;
4169 if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt))
4171 if(strcasecmp(fmt, "fuma") == 0)
4173 device->AmbiLayout = AmbiLayout_FuMa;
4174 device->AmbiScale = AmbiNorm_FuMa;
4176 else if(strcasecmp(fmt, "acn+sn3d") == 0)
4178 device->AmbiLayout = AmbiLayout_ACN;
4179 device->AmbiScale = AmbiNorm_SN3D;
4181 else if(strcasecmp(fmt, "acn+n3d") == 0)
4183 device->AmbiLayout = AmbiLayout_ACN;
4184 device->AmbiScale = AmbiNorm_N3D;
4186 else
4187 ERR("Unsupported ambi-format: %s\n", fmt);
4191 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4192 do {
4193 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4194 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4197 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
4198 return device;
4201 /* alcCloseDevice
4203 * Closes the given device.
4205 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
4207 ALCdevice *iter, *origdev, *nextdev;
4208 ALCcontext *ctx;
4210 LockLists();
4211 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4212 do {
4213 if(iter == device)
4214 break;
4215 iter = ATOMIC_LOAD(&iter->next, almemory_order_relaxed);
4216 } while(iter != NULL);
4217 if(!iter || iter->Type == Capture)
4219 alcSetError(iter, ALC_INVALID_DEVICE);
4220 UnlockLists();
4221 return ALC_FALSE;
4223 almtx_lock(&device->BackendLock);
4225 origdev = device;
4226 nextdev = ATOMIC_LOAD(&device->next, almemory_order_relaxed);
4227 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, nextdev))
4229 ALCdevice *list;
4230 do {
4231 list = origdev;
4232 origdev = device;
4233 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list->next, &origdev, nextdev));
4235 UnlockLists();
4237 ctx = ATOMIC_LOAD_SEQ(&device->ContextList);
4238 while(ctx != NULL)
4240 ALCcontext *next = ATOMIC_LOAD(&ctx->next, almemory_order_relaxed);
4241 WARN("Releasing context %p\n", ctx);
4242 ReleaseContext(ctx, device);
4243 ctx = next;
4245 if((device->Flags&DEVICE_RUNNING))
4246 V0(device->Backend,stop)();
4247 device->Flags &= ~DEVICE_RUNNING;
4248 almtx_unlock(&device->BackendLock);
4250 ALCdevice_DecRef(device);
4252 return ALC_TRUE;
4256 /************************************************
4257 * ALC capture functions
4258 ************************************************/
4259 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
4261 ALCbackendFactory *factory;
4262 ALCdevice *device = NULL;
4263 ALCenum err;
4265 DO_INITCONFIG();
4267 if(!CaptureBackend.name)
4269 alcSetError(NULL, ALC_INVALID_VALUE);
4270 return NULL;
4273 if(samples <= 0)
4275 alcSetError(NULL, ALC_INVALID_VALUE);
4276 return NULL;
4279 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
4280 deviceName = NULL;
4282 device = al_calloc(16, sizeof(ALCdevice));
4283 if(!device)
4285 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4286 return NULL;
4289 //Validate device
4290 InitDevice(device, Capture);
4292 device->Frequency = frequency;
4293 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4295 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
4297 FreeDevice(device);
4298 alcSetError(NULL, ALC_INVALID_ENUM);
4299 return NULL;
4301 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
4302 device->IsHeadphones = AL_FALSE;
4303 device->AmbiOrder = 0;
4304 device->AmbiLayout = AmbiLayout_Default;
4305 device->AmbiScale = AmbiNorm_Default;
4307 device->UpdateSize = samples;
4308 device->NumUpdates = 1;
4310 factory = CaptureBackend.getFactory();
4311 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
4312 if(!device->Backend)
4314 FreeDevice(device);
4315 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4316 return NULL;
4319 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4320 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
4321 device->Frequency, device->UpdateSize, device->NumUpdates
4323 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4325 FreeDevice(device);
4326 alcSetError(NULL, err);
4327 return NULL;
4331 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4332 do {
4333 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4334 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4337 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
4338 return device;
4341 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
4343 ALCdevice *iter, *origdev, *nextdev;
4345 LockLists();
4346 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4347 do {
4348 if(iter == device)
4349 break;
4350 iter = ATOMIC_LOAD(&iter->next, almemory_order_relaxed);
4351 } while(iter != NULL);
4352 if(!iter || iter->Type != Capture)
4354 alcSetError(iter, ALC_INVALID_DEVICE);
4355 UnlockLists();
4356 return ALC_FALSE;
4359 origdev = device;
4360 nextdev = ATOMIC_LOAD(&device->next, almemory_order_relaxed);
4361 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, nextdev))
4363 ALCdevice *list;
4364 do {
4365 list = origdev;
4366 origdev = device;
4367 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list->next, &origdev, nextdev));
4369 UnlockLists();
4371 almtx_lock(&device->BackendLock);
4372 if((device->Flags&DEVICE_RUNNING))
4373 V0(device->Backend,stop)();
4374 device->Flags &= ~DEVICE_RUNNING;
4375 almtx_unlock(&device->BackendLock);
4377 ALCdevice_DecRef(device);
4379 return ALC_TRUE;
4382 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
4384 if(!VerifyDevice(&device) || device->Type != Capture)
4385 alcSetError(device, ALC_INVALID_DEVICE);
4386 else
4388 almtx_lock(&device->BackendLock);
4389 if(!ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
4390 alcSetError(device, ALC_INVALID_DEVICE);
4391 else if(!(device->Flags&DEVICE_RUNNING))
4393 if(V0(device->Backend,start)())
4394 device->Flags |= DEVICE_RUNNING;
4395 else
4397 aluHandleDisconnect(device, "Device start failure");
4398 alcSetError(device, ALC_INVALID_DEVICE);
4401 almtx_unlock(&device->BackendLock);
4404 if(device) ALCdevice_DecRef(device);
4407 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
4409 if(!VerifyDevice(&device) || device->Type != Capture)
4410 alcSetError(device, ALC_INVALID_DEVICE);
4411 else
4413 almtx_lock(&device->BackendLock);
4414 if((device->Flags&DEVICE_RUNNING))
4415 V0(device->Backend,stop)();
4416 device->Flags &= ~DEVICE_RUNNING;
4417 almtx_unlock(&device->BackendLock);
4420 if(device) ALCdevice_DecRef(device);
4423 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4425 if(!VerifyDevice(&device) || device->Type != Capture)
4426 alcSetError(device, ALC_INVALID_DEVICE);
4427 else
4429 ALCenum err = ALC_INVALID_VALUE;
4431 almtx_lock(&device->BackendLock);
4432 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
4433 err = V(device->Backend,captureSamples)(buffer, samples);
4434 almtx_unlock(&device->BackendLock);
4436 if(err != ALC_NO_ERROR)
4437 alcSetError(device, err);
4439 if(device) ALCdevice_DecRef(device);
4443 /************************************************
4444 * ALC loopback functions
4445 ************************************************/
4447 /* alcLoopbackOpenDeviceSOFT
4449 * Open a loopback device, for manual rendering.
4451 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
4453 ALCbackendFactory *factory;
4454 ALCdevice *device;
4456 DO_INITCONFIG();
4458 /* Make sure the device name, if specified, is us. */
4459 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
4461 alcSetError(NULL, ALC_INVALID_VALUE);
4462 return NULL;
4465 device = al_calloc(16, sizeof(ALCdevice));
4466 if(!device)
4468 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4469 return NULL;
4472 //Validate device
4473 InitDevice(device, Loopback);
4475 device->SourcesMax = 256;
4476 device->AuxiliaryEffectSlotMax = 64;
4477 device->NumAuxSends = DEFAULT_SENDS;
4479 //Set output format
4480 device->NumUpdates = 0;
4481 device->UpdateSize = 0;
4483 device->Frequency = DEFAULT_OUTPUT_RATE;
4484 device->FmtChans = DevFmtChannelsDefault;
4485 device->FmtType = DevFmtTypeDefault;
4486 device->IsHeadphones = AL_FALSE;
4487 device->AmbiLayout = AmbiLayout_Default;
4488 device->AmbiScale = AmbiNorm_Default;
4490 ConfigValueUInt(NULL, NULL, "sources", &device->SourcesMax);
4491 if(device->SourcesMax == 0) device->SourcesMax = 256;
4493 ConfigValueUInt(NULL, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4494 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4495 else device->AuxiliaryEffectSlotMax = minu(device->AuxiliaryEffectSlotMax, INT_MAX);
4497 if(ConfigValueInt(NULL, NULL, "sends", &device->NumAuxSends))
4498 device->NumAuxSends = clampi(
4499 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4502 device->NumStereoSources = 1;
4503 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4505 factory = ALCloopbackFactory_getFactory();
4506 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
4507 if(!device->Backend)
4509 al_free(device);
4510 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4511 return NULL;
4514 // Open the "backend"
4515 V(device->Backend,open)("Loopback");
4518 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4519 do {
4520 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4521 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4524 TRACE("Created device %p\n", device);
4525 return device;
4528 /* alcIsRenderFormatSupportedSOFT
4530 * Determines if the loopback device supports the given format for rendering.
4532 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4534 ALCboolean ret = ALC_FALSE;
4536 if(!VerifyDevice(&device) || device->Type != Loopback)
4537 alcSetError(device, ALC_INVALID_DEVICE);
4538 else if(freq <= 0)
4539 alcSetError(device, ALC_INVALID_VALUE);
4540 else
4542 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4543 ret = ALC_TRUE;
4545 if(device) ALCdevice_DecRef(device);
4547 return ret;
4550 /* alcRenderSamplesSOFT
4552 * Renders some samples into a buffer, using the format last set by the
4553 * attributes given to alcCreateContext.
4555 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4557 if(!VerifyDevice(&device) || device->Type != Loopback)
4558 alcSetError(device, ALC_INVALID_DEVICE);
4559 else if(samples < 0 || (samples > 0 && buffer == NULL))
4560 alcSetError(device, ALC_INVALID_VALUE);
4561 else
4563 V0(device->Backend,lock)();
4564 aluMixData(device, buffer, samples);
4565 V0(device->Backend,unlock)();
4567 if(device) ALCdevice_DecRef(device);
4571 /************************************************
4572 * ALC DSP pause/resume functions
4573 ************************************************/
4575 /* alcDevicePauseSOFT
4577 * Pause the DSP to stop audio processing.
4579 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4581 if(!VerifyDevice(&device) || device->Type != Playback)
4582 alcSetError(device, ALC_INVALID_DEVICE);
4583 else
4585 almtx_lock(&device->BackendLock);
4586 if((device->Flags&DEVICE_RUNNING))
4587 V0(device->Backend,stop)();
4588 device->Flags &= ~DEVICE_RUNNING;
4589 device->Flags |= DEVICE_PAUSED;
4590 almtx_unlock(&device->BackendLock);
4592 if(device) ALCdevice_DecRef(device);
4595 /* alcDeviceResumeSOFT
4597 * Resume the DSP to restart audio processing.
4599 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4601 if(!VerifyDevice(&device) || device->Type != Playback)
4602 alcSetError(device, ALC_INVALID_DEVICE);
4603 else
4605 almtx_lock(&device->BackendLock);
4606 if((device->Flags&DEVICE_PAUSED))
4608 device->Flags &= ~DEVICE_PAUSED;
4609 if(ATOMIC_LOAD_SEQ(&device->ContextList) != NULL)
4611 if(V0(device->Backend,start)() != ALC_FALSE)
4612 device->Flags |= DEVICE_RUNNING;
4613 else
4615 V0(device->Backend,lock)();
4616 aluHandleDisconnect(device, "Device start failure");
4617 V0(device->Backend,unlock)();
4618 alcSetError(device, ALC_INVALID_DEVICE);
4622 almtx_unlock(&device->BackendLock);
4624 if(device) ALCdevice_DecRef(device);
4628 /************************************************
4629 * ALC HRTF functions
4630 ************************************************/
4632 /* alcGetStringiSOFT
4634 * Gets a string parameter at the given index.
4636 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4638 const ALCchar *str = NULL;
4640 if(!VerifyDevice(&device) || device->Type == Capture)
4641 alcSetError(device, ALC_INVALID_DEVICE);
4642 else switch(paramName)
4644 case ALC_HRTF_SPECIFIER_SOFT:
4645 if(index >= 0 && (size_t)index < VECTOR_SIZE(device->HrtfList))
4646 str = alstr_get_cstr(VECTOR_ELEM(device->HrtfList, index).name);
4647 else
4648 alcSetError(device, ALC_INVALID_VALUE);
4649 break;
4651 default:
4652 alcSetError(device, ALC_INVALID_ENUM);
4653 break;
4655 if(device) ALCdevice_DecRef(device);
4657 return str;
4660 /* alcResetDeviceSOFT
4662 * Resets the given device output, using the specified attribute list.
4664 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4666 ALCenum err;
4668 LockLists();
4669 if(!VerifyDevice(&device) || device->Type == Capture ||
4670 !ATOMIC_LOAD(&device->Connected, almemory_order_relaxed))
4672 UnlockLists();
4673 alcSetError(device, ALC_INVALID_DEVICE);
4674 if(device) ALCdevice_DecRef(device);
4675 return ALC_FALSE;
4677 almtx_lock(&device->BackendLock);
4678 UnlockLists();
4680 err = UpdateDeviceParams(device, attribs);
4681 almtx_unlock(&device->BackendLock);
4683 if(err != ALC_NO_ERROR)
4685 alcSetError(device, err);
4686 if(err == ALC_INVALID_DEVICE)
4688 V0(device->Backend,lock)();
4689 aluHandleDisconnect(device, "Device start failure");
4690 V0(device->Backend,unlock)();
4692 ALCdevice_DecRef(device);
4693 return ALC_FALSE;
4695 ALCdevice_DecRef(device);
4697 return ALC_TRUE;