Merge pull request #184 from hhyyrylainen/master
[openal-soft.git] / Alc / ALc.c
blob597cc890c2c6587874884363dca47828a6556126
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_OSS
79 { "oss", ALCossBackendFactory_getFactory },
80 #endif
81 #ifdef HAVE_SOLARIS
82 { "solaris", ALCsolarisBackendFactory_getFactory },
83 #endif
84 #ifdef HAVE_SNDIO
85 { "sndio", ALCsndioBackendFactory_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 #if 0
554 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
555 DECL(AL_EFFECT_VOCAL_MORPHER),
556 #endif
557 DECL(AL_EFFECT_RING_MODULATOR),
558 #if 0
559 DECL(AL_EFFECT_AUTOWAH),
560 #endif
561 DECL(AL_EFFECT_COMPRESSOR),
562 DECL(AL_EFFECT_EQUALIZER),
563 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
564 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
566 DECL(AL_EFFECTSLOT_EFFECT),
567 DECL(AL_EFFECTSLOT_GAIN),
568 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
569 DECL(AL_EFFECTSLOT_NULL),
571 DECL(AL_EAXREVERB_DENSITY),
572 DECL(AL_EAXREVERB_DIFFUSION),
573 DECL(AL_EAXREVERB_GAIN),
574 DECL(AL_EAXREVERB_GAINHF),
575 DECL(AL_EAXREVERB_GAINLF),
576 DECL(AL_EAXREVERB_DECAY_TIME),
577 DECL(AL_EAXREVERB_DECAY_HFRATIO),
578 DECL(AL_EAXREVERB_DECAY_LFRATIO),
579 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
580 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
581 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
582 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
583 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
584 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
585 DECL(AL_EAXREVERB_ECHO_TIME),
586 DECL(AL_EAXREVERB_ECHO_DEPTH),
587 DECL(AL_EAXREVERB_MODULATION_TIME),
588 DECL(AL_EAXREVERB_MODULATION_DEPTH),
589 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
590 DECL(AL_EAXREVERB_HFREFERENCE),
591 DECL(AL_EAXREVERB_LFREFERENCE),
592 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
593 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
595 DECL(AL_REVERB_DENSITY),
596 DECL(AL_REVERB_DIFFUSION),
597 DECL(AL_REVERB_GAIN),
598 DECL(AL_REVERB_GAINHF),
599 DECL(AL_REVERB_DECAY_TIME),
600 DECL(AL_REVERB_DECAY_HFRATIO),
601 DECL(AL_REVERB_REFLECTIONS_GAIN),
602 DECL(AL_REVERB_REFLECTIONS_DELAY),
603 DECL(AL_REVERB_LATE_REVERB_GAIN),
604 DECL(AL_REVERB_LATE_REVERB_DELAY),
605 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
606 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
607 DECL(AL_REVERB_DECAY_HFLIMIT),
609 DECL(AL_CHORUS_WAVEFORM),
610 DECL(AL_CHORUS_PHASE),
611 DECL(AL_CHORUS_RATE),
612 DECL(AL_CHORUS_DEPTH),
613 DECL(AL_CHORUS_FEEDBACK),
614 DECL(AL_CHORUS_DELAY),
616 DECL(AL_DISTORTION_EDGE),
617 DECL(AL_DISTORTION_GAIN),
618 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
619 DECL(AL_DISTORTION_EQCENTER),
620 DECL(AL_DISTORTION_EQBANDWIDTH),
622 DECL(AL_ECHO_DELAY),
623 DECL(AL_ECHO_LRDELAY),
624 DECL(AL_ECHO_DAMPING),
625 DECL(AL_ECHO_FEEDBACK),
626 DECL(AL_ECHO_SPREAD),
628 DECL(AL_FLANGER_WAVEFORM),
629 DECL(AL_FLANGER_PHASE),
630 DECL(AL_FLANGER_RATE),
631 DECL(AL_FLANGER_DEPTH),
632 DECL(AL_FLANGER_FEEDBACK),
633 DECL(AL_FLANGER_DELAY),
635 DECL(AL_RING_MODULATOR_FREQUENCY),
636 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
637 DECL(AL_RING_MODULATOR_WAVEFORM),
639 DECL(AL_PITCH_SHIFTER_COARSE_TUNE),
640 DECL(AL_PITCH_SHIFTER_FINE_TUNE),
642 DECL(AL_COMPRESSOR_ONOFF),
644 DECL(AL_EQUALIZER_LOW_GAIN),
645 DECL(AL_EQUALIZER_LOW_CUTOFF),
646 DECL(AL_EQUALIZER_MID1_GAIN),
647 DECL(AL_EQUALIZER_MID1_CENTER),
648 DECL(AL_EQUALIZER_MID1_WIDTH),
649 DECL(AL_EQUALIZER_MID2_GAIN),
650 DECL(AL_EQUALIZER_MID2_CENTER),
651 DECL(AL_EQUALIZER_MID2_WIDTH),
652 DECL(AL_EQUALIZER_HIGH_GAIN),
653 DECL(AL_EQUALIZER_HIGH_CUTOFF),
655 DECL(AL_DEDICATED_GAIN),
657 DECL(AL_NUM_RESAMPLERS_SOFT),
658 DECL(AL_DEFAULT_RESAMPLER_SOFT),
659 DECL(AL_SOURCE_RESAMPLER_SOFT),
660 DECL(AL_RESAMPLER_NAME_SOFT),
662 DECL(AL_SOURCE_SPATIALIZE_SOFT),
663 DECL(AL_AUTO_SOFT),
665 DECL(AL_MAP_READ_BIT_SOFT),
666 DECL(AL_MAP_WRITE_BIT_SOFT),
667 DECL(AL_MAP_PERSISTENT_BIT_SOFT),
668 DECL(AL_PRESERVE_DATA_BIT_SOFT),
670 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT),
671 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT),
672 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT),
673 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT),
674 DECL(AL_EVENT_TYPE_ERROR_SOFT),
675 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT),
676 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT),
678 #undef DECL
680 static const ALCchar alcNoError[] = "No Error";
681 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
682 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
683 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
684 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
685 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
688 /************************************************
689 * Global variables
690 ************************************************/
692 /* Enumerated device names */
693 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
695 static al_string alcAllDevicesList;
696 static al_string alcCaptureDeviceList;
698 /* Default is always the first in the list */
699 static ALCchar *alcDefaultAllDevicesSpecifier;
700 static ALCchar *alcCaptureDefaultDeviceSpecifier;
702 /* Default context extensions */
703 static const ALchar alExtList[] =
704 "AL_EXT_ALAW "
705 "AL_EXT_BFORMAT "
706 "AL_EXT_DOUBLE "
707 "AL_EXT_EXPONENT_DISTANCE "
708 "AL_EXT_FLOAT32 "
709 "AL_EXT_IMA4 "
710 "AL_EXT_LINEAR_DISTANCE "
711 "AL_EXT_MCFORMATS "
712 "AL_EXT_MULAW "
713 "AL_EXT_MULAW_BFORMAT "
714 "AL_EXT_MULAW_MCFORMATS "
715 "AL_EXT_OFFSET "
716 "AL_EXT_source_distance_model "
717 "AL_EXT_SOURCE_RADIUS "
718 "AL_EXT_STEREO_ANGLES "
719 "AL_LOKI_quadriphonic "
720 "AL_SOFT_block_alignment "
721 "AL_SOFT_deferred_updates "
722 "AL_SOFT_direct_channels "
723 "AL_SOFTX_events "
724 "AL_SOFT_gain_clamp_ex "
725 "AL_SOFT_loop_points "
726 "AL_SOFTX_map_buffer "
727 "AL_SOFT_MSADPCM "
728 "AL_SOFT_source_latency "
729 "AL_SOFT_source_length "
730 "AL_SOFT_source_resampler "
731 "AL_SOFT_source_spatialize";
733 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
735 /* Thread-local current context */
736 static altss_t LocalContext;
737 /* Process-wide current context */
738 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
740 /* Mixing thread piority level */
741 ALint RTPrioLevel;
743 FILE *LogFile;
744 #ifdef _DEBUG
745 enum LogLevel LogLevel = LogWarning;
746 #else
747 enum LogLevel LogLevel = LogError;
748 #endif
750 /* Flag to trap ALC device errors */
751 static ALCboolean TrapALCError = ALC_FALSE;
753 /* One-time configuration init control */
754 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
756 /* Default effect that applies to sources that don't have an effect on send 0 */
757 static ALeffect DefaultEffect;
759 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
760 * updates.
762 static ALCboolean SuspendDefers = ALC_TRUE;
765 /************************************************
766 * ALC information
767 ************************************************/
768 static const ALCchar alcNoDeviceExtList[] =
769 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
770 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
771 static const ALCchar alcExtensionList[] =
772 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
773 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
774 "ALC_EXT_thread_local_context ALC_SOFT_device_clock ALC_SOFT_HRTF "
775 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
776 static const ALCint alcMajorVersion = 1;
777 static const ALCint alcMinorVersion = 1;
779 static const ALCint alcEFXMajorVersion = 1;
780 static const ALCint alcEFXMinorVersion = 0;
783 /************************************************
784 * Device lists
785 ************************************************/
786 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
788 static almtx_t ListLock;
789 static inline void LockLists(void)
791 int ret = almtx_lock(&ListLock);
792 assert(ret == althrd_success);
794 static inline void UnlockLists(void)
796 int ret = almtx_unlock(&ListLock);
797 assert(ret == althrd_success);
800 /************************************************
801 * Library initialization
802 ************************************************/
803 #if defined(_WIN32)
804 static void alc_init(void);
805 static void alc_deinit(void);
806 static void alc_deinit_safe(void);
808 #ifndef AL_LIBTYPE_STATIC
809 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
811 switch(reason)
813 case DLL_PROCESS_ATTACH:
814 /* Pin the DLL so we won't get unloaded until the process terminates */
815 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
816 (WCHAR*)hModule, &hModule);
817 alc_init();
818 break;
820 case DLL_THREAD_DETACH:
821 althrd_thread_detach();
822 break;
824 case DLL_PROCESS_DETACH:
825 if(!lpReserved)
826 alc_deinit();
827 else
828 alc_deinit_safe();
829 break;
831 return TRUE;
833 #elif defined(_MSC_VER)
834 #pragma section(".CRT$XCU",read)
835 static void alc_constructor(void);
836 static void alc_destructor(void);
837 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
839 static void alc_constructor(void)
841 atexit(alc_destructor);
842 alc_init();
845 static void alc_destructor(void)
847 alc_deinit();
849 #elif defined(HAVE_GCC_DESTRUCTOR)
850 static void alc_init(void) __attribute__((constructor));
851 static void alc_deinit(void) __attribute__((destructor));
852 #else
853 #error "No static initialization available on this platform!"
854 #endif
856 #elif defined(HAVE_GCC_DESTRUCTOR)
858 static void alc_init(void) __attribute__((constructor));
859 static void alc_deinit(void) __attribute__((destructor));
861 #else
862 #error "No global initialization available on this platform!"
863 #endif
865 static void ReleaseThreadCtx(void *ptr);
866 static void alc_init(void)
868 const char *str;
869 int ret;
871 LogFile = stderr;
873 AL_STRING_INIT(alcAllDevicesList);
874 AL_STRING_INIT(alcCaptureDeviceList);
876 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
877 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
878 ConeScale *= 0.5f;
880 str = getenv("__ALSOFT_REVERSE_Z");
881 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
882 ZScale *= -1.0f;
884 str = getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
885 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
886 OverrideReverbSpeedOfSound = AL_TRUE;
888 ret = altss_create(&LocalContext, ReleaseThreadCtx);
889 assert(ret == althrd_success);
891 ret = almtx_init(&ListLock, almtx_recursive);
892 assert(ret == althrd_success);
895 static void alc_initconfig(void)
897 const char *devs, *str;
898 int capfilter;
899 float valf;
900 int i, n;
902 str = getenv("ALSOFT_LOGLEVEL");
903 if(str)
905 long lvl = strtol(str, NULL, 0);
906 if(lvl >= NoLog && lvl <= LogRef)
907 LogLevel = lvl;
910 str = getenv("ALSOFT_LOGFILE");
911 if(str && str[0])
913 FILE *logfile = al_fopen(str, "wt");
914 if(logfile) LogFile = logfile;
915 else ERR("Failed to open log file '%s'\n", str);
918 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION,
919 ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH);
921 char buf[1024] = "";
922 int len = 0;
924 if(BackendListSize > 0)
925 len += snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
926 for(i = 1;i < BackendListSize;i++)
927 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
928 TRACE("Supported backends: %s\n", buf);
930 ReadALConfig();
932 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
933 if(str && *str)
935 if(strcasecmp(str, "ignore") == 0)
937 SuspendDefers = ALC_FALSE;
938 TRACE("Selected context suspend behavior, \"ignore\"\n");
940 else
941 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
944 capfilter = 0;
945 #if defined(HAVE_SSE4_1)
946 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
947 #elif defined(HAVE_SSE3)
948 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
949 #elif defined(HAVE_SSE2)
950 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
951 #elif defined(HAVE_SSE)
952 capfilter |= CPU_CAP_SSE;
953 #endif
954 #ifdef HAVE_NEON
955 capfilter |= CPU_CAP_NEON;
956 #endif
957 if(ConfigValueStr(NULL, NULL, "disable-cpu-exts", &str))
959 if(strcasecmp(str, "all") == 0)
960 capfilter = 0;
961 else
963 size_t len;
964 const char *next = str;
966 do {
967 str = next;
968 while(isspace(str[0]))
969 str++;
970 next = strchr(str, ',');
972 if(!str[0] || str[0] == ',')
973 continue;
975 len = (next ? ((size_t)(next-str)) : strlen(str));
976 while(len > 0 && isspace(str[len-1]))
977 len--;
978 if(len == 3 && strncasecmp(str, "sse", len) == 0)
979 capfilter &= ~CPU_CAP_SSE;
980 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
981 capfilter &= ~CPU_CAP_SSE2;
982 else if(len == 4 && strncasecmp(str, "sse3", len) == 0)
983 capfilter &= ~CPU_CAP_SSE3;
984 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
985 capfilter &= ~CPU_CAP_SSE4_1;
986 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
987 capfilter &= ~CPU_CAP_NEON;
988 else
989 WARN("Invalid CPU extension \"%s\"\n", str);
990 } while(next++);
993 FillCPUCaps(capfilter);
995 #ifdef _WIN32
996 RTPrioLevel = 1;
997 #else
998 RTPrioLevel = 0;
999 #endif
1000 ConfigValueInt(NULL, NULL, "rt-prio", &RTPrioLevel);
1002 aluInit();
1003 aluInitMixer();
1005 str = getenv("ALSOFT_TRAP_ERROR");
1006 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1008 TrapALError = AL_TRUE;
1009 TrapALCError = AL_TRUE;
1011 else
1013 str = getenv("ALSOFT_TRAP_AL_ERROR");
1014 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1015 TrapALError = AL_TRUE;
1016 TrapALError = GetConfigValueBool(NULL, NULL, "trap-al-error", TrapALError);
1018 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1019 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1020 TrapALCError = ALC_TRUE;
1021 TrapALCError = GetConfigValueBool(NULL, NULL, "trap-alc-error", TrapALCError);
1024 if(ConfigValueFloat(NULL, "reverb", "boost", &valf))
1025 ReverbBoost *= powf(10.0f, valf / 20.0f);
1027 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1028 ConfigValueStr(NULL, NULL, "drivers", &devs))
1030 int n;
1031 size_t len;
1032 const char *next = devs;
1033 int endlist, delitem;
1035 i = 0;
1036 do {
1037 devs = next;
1038 while(isspace(devs[0]))
1039 devs++;
1040 next = strchr(devs, ',');
1042 delitem = (devs[0] == '-');
1043 if(devs[0] == '-') devs++;
1045 if(!devs[0] || devs[0] == ',')
1047 endlist = 0;
1048 continue;
1050 endlist = 1;
1052 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1053 while(len > 0 && isspace(devs[len-1]))
1054 len--;
1055 #ifdef HAVE_WASAPI
1056 /* HACK: For backwards compatibility, convert backend references of
1057 * mmdevapi to wasapi. This should eventually be removed.
1059 if(len == 8 && strncmp(devs, "mmdevapi", len) == 0)
1061 devs = "wasapi";
1062 len = 6;
1064 #endif
1065 for(n = i;n < BackendListSize;n++)
1067 if(len == strlen(BackendList[n].name) &&
1068 strncmp(BackendList[n].name, devs, len) == 0)
1070 if(delitem)
1072 for(;n+1 < BackendListSize;n++)
1073 BackendList[n] = BackendList[n+1];
1074 BackendListSize--;
1076 else
1078 struct BackendInfo Bkp = BackendList[n];
1079 for(;n > i;n--)
1080 BackendList[n] = BackendList[n-1];
1081 BackendList[n] = Bkp;
1083 i++;
1085 break;
1088 } while(next++);
1090 if(endlist)
1091 BackendListSize = i;
1094 for(n = i = 0;i < BackendListSize && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1096 ALCbackendFactory *factory;
1097 BackendList[n] = BackendList[i];
1099 factory = BackendList[n].getFactory();
1100 if(!V0(factory,init)())
1102 WARN("Failed to initialize backend \"%s\"\n", BackendList[n].name);
1103 continue;
1106 TRACE("Initialized backend \"%s\"\n", BackendList[n].name);
1107 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1109 PlaybackBackend = BackendList[n];
1110 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1112 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1114 CaptureBackend = BackendList[n];
1115 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1117 n++;
1119 BackendListSize = n;
1122 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1123 V0(factory,init)();
1126 if(!PlaybackBackend.name)
1127 WARN("No playback backend available!\n");
1128 if(!CaptureBackend.name)
1129 WARN("No capture backend available!\n");
1131 if(ConfigValueStr(NULL, NULL, "excludefx", &str))
1133 size_t len;
1134 const char *next = str;
1136 do {
1137 str = next;
1138 next = strchr(str, ',');
1140 if(!str[0] || next == str)
1141 continue;
1143 len = (next ? ((size_t)(next-str)) : strlen(str));
1144 for(n = 0;n < EFFECTLIST_SIZE;n++)
1146 if(len == strlen(EffectList[n].name) &&
1147 strncmp(EffectList[n].name, str, len) == 0)
1148 DisabledEffects[EffectList[n].type] = AL_TRUE;
1150 } while(next++);
1153 InitEffect(&DefaultEffect);
1154 str = getenv("ALSOFT_DEFAULT_REVERB");
1155 if((str && str[0]) || ConfigValueStr(NULL, NULL, "default-reverb", &str))
1156 LoadReverbPreset(str, &DefaultEffect);
1158 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1160 #ifdef __ANDROID__
1161 #include <jni.h>
1163 static JavaVM *gJavaVM;
1164 static pthread_key_t gJVMThreadKey;
1166 static void CleanupJNIEnv(void* UNUSED(ptr))
1168 JCALL0(gJavaVM,DetachCurrentThread)();
1171 void *Android_GetJNIEnv(void)
1173 if(!gJavaVM)
1175 WARN("gJavaVM is NULL!\n");
1176 return NULL;
1179 /* http://developer.android.com/guide/practices/jni.html
1181 * All threads are Linux threads, scheduled by the kernel. They're usually
1182 * started from managed code (using Thread.start), but they can also be
1183 * created elsewhere and then attached to the JavaVM. For example, a thread
1184 * started with pthread_create can be attached with the JNI
1185 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1186 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1187 * Attaching a natively-created thread causes a java.lang.Thread object to
1188 * be constructed and added to the "main" ThreadGroup, making it visible to
1189 * the debugger. Calling AttachCurrentThread on an already-attached thread
1190 * is a no-op.
1192 JNIEnv *env = pthread_getspecific(gJVMThreadKey);
1193 if(!env)
1195 int status = JCALL(gJavaVM,AttachCurrentThread)(&env, NULL);
1196 if(status < 0)
1198 ERR("Failed to attach current thread\n");
1199 return NULL;
1201 pthread_setspecific(gJVMThreadKey, env);
1203 return env;
1206 /* Automatically called by JNI. */
1207 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void* UNUSED(reserved))
1209 void *env;
1210 int err;
1212 gJavaVM = jvm;
1213 if(JCALL(gJavaVM,GetEnv)(&env, JNI_VERSION_1_4) != JNI_OK)
1215 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1216 return JNI_ERR;
1219 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1220 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1222 if((err=pthread_key_create(&gJVMThreadKey, CleanupJNIEnv)) != 0)
1223 ERR("pthread_key_create failed: %d\n", err);
1224 pthread_setspecific(gJVMThreadKey, env);
1225 return JNI_VERSION_1_4;
1227 #endif
1230 /************************************************
1231 * Library deinitialization
1232 ************************************************/
1233 static void alc_cleanup(void)
1235 ALCdevice *dev;
1237 AL_STRING_DEINIT(alcAllDevicesList);
1238 AL_STRING_DEINIT(alcCaptureDeviceList);
1240 free(alcDefaultAllDevicesSpecifier);
1241 alcDefaultAllDevicesSpecifier = NULL;
1242 free(alcCaptureDefaultDeviceSpecifier);
1243 alcCaptureDefaultDeviceSpecifier = NULL;
1245 if((dev=ATOMIC_EXCHANGE_PTR_SEQ(&DeviceList, NULL)) != NULL)
1247 ALCuint num = 0;
1248 do {
1249 num++;
1250 dev = ATOMIC_LOAD(&dev->next, almemory_order_relaxed);
1251 } while(dev != NULL);
1252 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1256 static void alc_deinit_safe(void)
1258 alc_cleanup();
1260 FreeHrtfs();
1261 FreeALConfig();
1263 almtx_destroy(&ListLock);
1264 altss_delete(LocalContext);
1266 if(LogFile != stderr)
1267 fclose(LogFile);
1268 LogFile = NULL;
1270 althrd_deinit();
1273 static void alc_deinit(void)
1275 int i;
1277 alc_cleanup();
1279 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1280 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1282 for(i = 0;i < BackendListSize;i++)
1284 ALCbackendFactory *factory = BackendList[i].getFactory();
1285 V0(factory,deinit)();
1288 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1289 V0(factory,deinit)();
1292 alc_deinit_safe();
1296 /************************************************
1297 * Device enumeration
1298 ************************************************/
1299 static void ProbeDevices(al_string *list, struct BackendInfo *backendinfo, enum DevProbe type)
1301 DO_INITCONFIG();
1303 LockLists();
1304 alstr_clear(list);
1306 if(backendinfo->getFactory)
1308 ALCbackendFactory *factory = backendinfo->getFactory();
1309 V(factory,probe)(type);
1312 UnlockLists();
1314 static void ProbeAllDevicesList(void)
1315 { ProbeDevices(&alcAllDevicesList, &PlaybackBackend, ALL_DEVICE_PROBE); }
1316 static void ProbeCaptureDeviceList(void)
1317 { ProbeDevices(&alcCaptureDeviceList, &CaptureBackend, CAPTURE_DEVICE_PROBE); }
1319 static void AppendDevice(const ALCchar *name, al_string *devnames)
1321 size_t len = strlen(name);
1322 if(len > 0)
1323 alstr_append_range(devnames, name, name+len+1);
1325 void AppendAllDevicesList(const ALCchar *name)
1326 { AppendDevice(name, &alcAllDevicesList); }
1327 void AppendCaptureDeviceList(const ALCchar *name)
1328 { AppendDevice(name, &alcCaptureDeviceList); }
1331 /************************************************
1332 * Device format information
1333 ************************************************/
1334 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1336 switch(type)
1338 case DevFmtByte: return "Signed Byte";
1339 case DevFmtUByte: return "Unsigned Byte";
1340 case DevFmtShort: return "Signed Short";
1341 case DevFmtUShort: return "Unsigned Short";
1342 case DevFmtInt: return "Signed Int";
1343 case DevFmtUInt: return "Unsigned Int";
1344 case DevFmtFloat: return "Float";
1346 return "(unknown type)";
1348 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1350 switch(chans)
1352 case DevFmtMono: return "Mono";
1353 case DevFmtStereo: return "Stereo";
1354 case DevFmtQuad: return "Quadraphonic";
1355 case DevFmtX51: return "5.1 Surround";
1356 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1357 case DevFmtX61: return "6.1 Surround";
1358 case DevFmtX71: return "7.1 Surround";
1359 case DevFmtAmbi3D: return "Ambisonic 3D";
1361 return "(unknown channels)";
1364 extern inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type, ALsizei ambiorder);
1365 ALsizei BytesFromDevFmt(enum DevFmtType type)
1367 switch(type)
1369 case DevFmtByte: return sizeof(ALbyte);
1370 case DevFmtUByte: return sizeof(ALubyte);
1371 case DevFmtShort: return sizeof(ALshort);
1372 case DevFmtUShort: return sizeof(ALushort);
1373 case DevFmtInt: return sizeof(ALint);
1374 case DevFmtUInt: return sizeof(ALuint);
1375 case DevFmtFloat: return sizeof(ALfloat);
1377 return 0;
1379 ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans, ALsizei ambiorder)
1381 switch(chans)
1383 case DevFmtMono: return 1;
1384 case DevFmtStereo: return 2;
1385 case DevFmtQuad: return 4;
1386 case DevFmtX51: return 6;
1387 case DevFmtX51Rear: return 6;
1388 case DevFmtX61: return 7;
1389 case DevFmtX71: return 8;
1390 case DevFmtAmbi3D: return (ambiorder >= 3) ? 16 :
1391 (ambiorder == 2) ? 9 :
1392 (ambiorder == 1) ? 4 : 1;
1394 return 0;
1397 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1398 enum DevFmtType *type)
1400 static const struct {
1401 ALenum format;
1402 enum DevFmtChannels channels;
1403 enum DevFmtType type;
1404 } list[] = {
1405 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1406 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1407 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1409 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1410 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1411 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1413 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1414 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1415 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1417 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1418 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1419 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1421 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1422 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1423 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1425 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1426 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1427 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1429 ALuint i;
1431 for(i = 0;i < COUNTOF(list);i++)
1433 if(list[i].format == format)
1435 *chans = list[i].channels;
1436 *type = list[i].type;
1437 return AL_TRUE;
1441 return AL_FALSE;
1444 static ALCboolean IsValidALCType(ALCenum type)
1446 switch(type)
1448 case ALC_BYTE_SOFT:
1449 case ALC_UNSIGNED_BYTE_SOFT:
1450 case ALC_SHORT_SOFT:
1451 case ALC_UNSIGNED_SHORT_SOFT:
1452 case ALC_INT_SOFT:
1453 case ALC_UNSIGNED_INT_SOFT:
1454 case ALC_FLOAT_SOFT:
1455 return ALC_TRUE;
1457 return ALC_FALSE;
1460 static ALCboolean IsValidALCChannels(ALCenum channels)
1462 switch(channels)
1464 case ALC_MONO_SOFT:
1465 case ALC_STEREO_SOFT:
1466 case ALC_QUAD_SOFT:
1467 case ALC_5POINT1_SOFT:
1468 case ALC_6POINT1_SOFT:
1469 case ALC_7POINT1_SOFT:
1470 case ALC_BFORMAT3D_SOFT:
1471 return ALC_TRUE;
1473 return ALC_FALSE;
1476 static ALCboolean IsValidAmbiLayout(ALCenum layout)
1478 switch(layout)
1480 case ALC_ACN_SOFT:
1481 case ALC_FUMA_SOFT:
1482 return ALC_TRUE;
1484 return ALC_FALSE;
1487 static ALCboolean IsValidAmbiScaling(ALCenum scaling)
1489 switch(scaling)
1491 case ALC_N3D_SOFT:
1492 case ALC_SN3D_SOFT:
1493 case ALC_FUMA_SOFT:
1494 return ALC_TRUE;
1496 return ALC_FALSE;
1499 /************************************************
1500 * Miscellaneous ALC helpers
1501 ************************************************/
1503 /* SetDefaultWFXChannelOrder
1505 * Sets the default channel order used by WaveFormatEx.
1507 void SetDefaultWFXChannelOrder(ALCdevice *device)
1509 ALsizei i;
1511 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1512 device->RealOut.ChannelName[i] = InvalidChannel;
1514 switch(device->FmtChans)
1516 case DevFmtMono:
1517 device->RealOut.ChannelName[0] = FrontCenter;
1518 break;
1519 case DevFmtStereo:
1520 device->RealOut.ChannelName[0] = FrontLeft;
1521 device->RealOut.ChannelName[1] = FrontRight;
1522 break;
1523 case DevFmtQuad:
1524 device->RealOut.ChannelName[0] = FrontLeft;
1525 device->RealOut.ChannelName[1] = FrontRight;
1526 device->RealOut.ChannelName[2] = BackLeft;
1527 device->RealOut.ChannelName[3] = BackRight;
1528 break;
1529 case DevFmtX51:
1530 device->RealOut.ChannelName[0] = FrontLeft;
1531 device->RealOut.ChannelName[1] = FrontRight;
1532 device->RealOut.ChannelName[2] = FrontCenter;
1533 device->RealOut.ChannelName[3] = LFE;
1534 device->RealOut.ChannelName[4] = SideLeft;
1535 device->RealOut.ChannelName[5] = SideRight;
1536 break;
1537 case DevFmtX51Rear:
1538 device->RealOut.ChannelName[0] = FrontLeft;
1539 device->RealOut.ChannelName[1] = FrontRight;
1540 device->RealOut.ChannelName[2] = FrontCenter;
1541 device->RealOut.ChannelName[3] = LFE;
1542 device->RealOut.ChannelName[4] = BackLeft;
1543 device->RealOut.ChannelName[5] = BackRight;
1544 break;
1545 case DevFmtX61:
1546 device->RealOut.ChannelName[0] = FrontLeft;
1547 device->RealOut.ChannelName[1] = FrontRight;
1548 device->RealOut.ChannelName[2] = FrontCenter;
1549 device->RealOut.ChannelName[3] = LFE;
1550 device->RealOut.ChannelName[4] = BackCenter;
1551 device->RealOut.ChannelName[5] = SideLeft;
1552 device->RealOut.ChannelName[6] = SideRight;
1553 break;
1554 case DevFmtX71:
1555 device->RealOut.ChannelName[0] = FrontLeft;
1556 device->RealOut.ChannelName[1] = FrontRight;
1557 device->RealOut.ChannelName[2] = FrontCenter;
1558 device->RealOut.ChannelName[3] = LFE;
1559 device->RealOut.ChannelName[4] = BackLeft;
1560 device->RealOut.ChannelName[5] = BackRight;
1561 device->RealOut.ChannelName[6] = SideLeft;
1562 device->RealOut.ChannelName[7] = SideRight;
1563 break;
1564 case DevFmtAmbi3D:
1565 device->RealOut.ChannelName[0] = Aux0;
1566 if(device->AmbiOrder > 0)
1568 device->RealOut.ChannelName[1] = Aux1;
1569 device->RealOut.ChannelName[2] = Aux2;
1570 device->RealOut.ChannelName[3] = Aux3;
1572 if(device->AmbiOrder > 1)
1574 device->RealOut.ChannelName[4] = Aux4;
1575 device->RealOut.ChannelName[5] = Aux5;
1576 device->RealOut.ChannelName[6] = Aux6;
1577 device->RealOut.ChannelName[7] = Aux7;
1578 device->RealOut.ChannelName[8] = Aux8;
1580 if(device->AmbiOrder > 2)
1582 device->RealOut.ChannelName[9] = Aux9;
1583 device->RealOut.ChannelName[10] = Aux10;
1584 device->RealOut.ChannelName[11] = Aux11;
1585 device->RealOut.ChannelName[12] = Aux12;
1586 device->RealOut.ChannelName[13] = Aux13;
1587 device->RealOut.ChannelName[14] = Aux14;
1588 device->RealOut.ChannelName[15] = Aux15;
1590 break;
1594 /* SetDefaultChannelOrder
1596 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1598 void SetDefaultChannelOrder(ALCdevice *device)
1600 ALsizei i;
1602 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1603 device->RealOut.ChannelName[i] = InvalidChannel;
1605 switch(device->FmtChans)
1607 case DevFmtX51Rear:
1608 device->RealOut.ChannelName[0] = FrontLeft;
1609 device->RealOut.ChannelName[1] = FrontRight;
1610 device->RealOut.ChannelName[2] = BackLeft;
1611 device->RealOut.ChannelName[3] = BackRight;
1612 device->RealOut.ChannelName[4] = FrontCenter;
1613 device->RealOut.ChannelName[5] = LFE;
1614 return;
1615 case DevFmtX71:
1616 device->RealOut.ChannelName[0] = FrontLeft;
1617 device->RealOut.ChannelName[1] = FrontRight;
1618 device->RealOut.ChannelName[2] = BackLeft;
1619 device->RealOut.ChannelName[3] = BackRight;
1620 device->RealOut.ChannelName[4] = FrontCenter;
1621 device->RealOut.ChannelName[5] = LFE;
1622 device->RealOut.ChannelName[6] = SideLeft;
1623 device->RealOut.ChannelName[7] = SideRight;
1624 return;
1626 /* Same as WFX order */
1627 case DevFmtMono:
1628 case DevFmtStereo:
1629 case DevFmtQuad:
1630 case DevFmtX51:
1631 case DevFmtX61:
1632 case DevFmtAmbi3D:
1633 SetDefaultWFXChannelOrder(device);
1634 break;
1638 extern inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan);
1639 extern inline ALint GetChannelIdxByName(const RealMixParams *real, enum Channel chan);
1642 /* ALCcontext_DeferUpdates
1644 * Defers/suspends updates for the given context's listener and sources. This
1645 * does *NOT* stop mixing, but rather prevents certain property changes from
1646 * taking effect.
1648 void ALCcontext_DeferUpdates(ALCcontext *context)
1650 ATOMIC_STORE_SEQ(&context->DeferUpdates, AL_TRUE);
1653 /* ALCcontext_ProcessUpdates
1655 * Resumes update processing after being deferred.
1657 void ALCcontext_ProcessUpdates(ALCcontext *context)
1659 almtx_lock(&context->PropLock);
1660 if(ATOMIC_EXCHANGE_SEQ(&context->DeferUpdates, AL_FALSE))
1662 /* Tell the mixer to stop applying updates, then wait for any active
1663 * updating to finish, before providing updates.
1665 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_TRUE);
1666 while((ATOMIC_LOAD(&context->UpdateCount, almemory_order_acquire)&1) != 0)
1667 althrd_yield();
1669 if(!ATOMIC_FLAG_TEST_AND_SET(&context->PropsClean, almemory_order_acq_rel))
1670 UpdateContextProps(context);
1671 if(!ATOMIC_FLAG_TEST_AND_SET(&context->Listener->PropsClean, almemory_order_acq_rel))
1672 UpdateListenerProps(context);
1673 UpdateAllEffectSlotProps(context);
1674 UpdateAllSourceProps(context);
1676 /* Now with all updates declared, let the mixer continue applying them
1677 * so they all happen at once.
1679 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_FALSE);
1681 almtx_unlock(&context->PropLock);
1685 /* alcSetError
1687 * Stores the latest ALC device error
1689 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1691 WARN("Error generated on device %p, code 0x%04x\n", device, errorCode);
1692 if(TrapALCError)
1694 #ifdef _WIN32
1695 /* DebugBreak() will cause an exception if there is no debugger */
1696 if(IsDebuggerPresent())
1697 DebugBreak();
1698 #elif defined(SIGTRAP)
1699 raise(SIGTRAP);
1700 #endif
1703 if(device)
1704 ATOMIC_STORE_SEQ(&device->LastError, errorCode);
1705 else
1706 ATOMIC_STORE_SEQ(&LastNullDeviceError, errorCode);
1710 struct Compressor *CreateDeviceLimiter(const ALCdevice *device)
1712 return CompressorInit(0.0f, 0.0f, AL_FALSE, AL_TRUE, 0.0f, 0.0f, 0.5f, 2.0f,
1713 0.0f, -3.0f, 3.0f, device->Frequency);
1716 /* UpdateClockBase
1718 * Updates the device's base clock time with however many samples have been
1719 * done. This is used so frequency changes on the device don't cause the time
1720 * to jump forward or back. Must not be called while the device is running/
1721 * mixing.
1723 static inline void UpdateClockBase(ALCdevice *device)
1725 IncrementRef(&device->MixCount);
1726 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1727 device->SamplesDone = 0;
1728 IncrementRef(&device->MixCount);
1731 /* UpdateDeviceParams
1733 * Updates device parameters according to the attribute list (caller is
1734 * responsible for holding the list lock).
1736 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1738 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1739 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1740 ALCenum gainLimiter = device->Limiter ? ALC_TRUE : ALC_FALSE;
1741 const ALsizei old_sends = device->NumAuxSends;
1742 ALsizei new_sends = device->NumAuxSends;
1743 enum DevFmtChannels oldChans;
1744 enum DevFmtType oldType;
1745 ALboolean update_failed;
1746 ALCsizei hrtf_id = -1;
1747 ALCcontext *context;
1748 ALCuint oldFreq;
1749 size_t size;
1750 ALCsizei i;
1751 int val;
1753 // Check for attributes
1754 if(device->Type == Loopback)
1756 ALCsizei numMono, numStereo, numSends;
1757 ALCenum alayout = AL_NONE;
1758 ALCenum ascale = AL_NONE;
1759 ALCenum schans = AL_NONE;
1760 ALCenum stype = AL_NONE;
1761 ALCsizei attrIdx = 0;
1762 ALCsizei aorder = 0;
1763 ALCuint freq = 0;
1765 if(!attrList)
1767 WARN("Missing attributes for loopback device\n");
1768 return ALC_INVALID_VALUE;
1771 numMono = device->NumMonoSources;
1772 numStereo = device->NumStereoSources;
1773 numSends = old_sends;
1775 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1776 while(attrList[attrIdx])
1778 switch(attrList[attrIdx])
1780 case ALC_FORMAT_CHANNELS_SOFT:
1781 schans = attrList[attrIdx + 1];
1782 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1783 if(!IsValidALCChannels(schans))
1784 return ALC_INVALID_VALUE;
1785 break;
1787 case ALC_FORMAT_TYPE_SOFT:
1788 stype = attrList[attrIdx + 1];
1789 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1790 if(!IsValidALCType(stype))
1791 return ALC_INVALID_VALUE;
1792 break;
1794 case ALC_FREQUENCY:
1795 freq = attrList[attrIdx + 1];
1796 TRACE_ATTR(ALC_FREQUENCY, freq);
1797 if(freq < MIN_OUTPUT_RATE)
1798 return ALC_INVALID_VALUE;
1799 break;
1801 case ALC_AMBISONIC_LAYOUT_SOFT:
1802 alayout = attrList[attrIdx + 1];
1803 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1804 if(!IsValidAmbiLayout(alayout))
1805 return ALC_INVALID_VALUE;
1806 break;
1808 case ALC_AMBISONIC_SCALING_SOFT:
1809 ascale = attrList[attrIdx + 1];
1810 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1811 if(!IsValidAmbiScaling(ascale))
1812 return ALC_INVALID_VALUE;
1813 break;
1815 case ALC_AMBISONIC_ORDER_SOFT:
1816 aorder = attrList[attrIdx + 1];
1817 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1818 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1819 return ALC_INVALID_VALUE;
1820 break;
1822 case ALC_MONO_SOURCES:
1823 numMono = attrList[attrIdx + 1];
1824 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1825 numMono = maxi(numMono, 0);
1826 break;
1828 case ALC_STEREO_SOURCES:
1829 numStereo = attrList[attrIdx + 1];
1830 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1831 numStereo = maxi(numStereo, 0);
1832 break;
1834 case ALC_MAX_AUXILIARY_SENDS:
1835 numSends = attrList[attrIdx + 1];
1836 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1837 numSends = clampi(numSends, 0, MAX_SENDS);
1838 break;
1840 case ALC_HRTF_SOFT:
1841 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1842 if(attrList[attrIdx + 1] == ALC_FALSE)
1843 hrtf_appreq = Hrtf_Disable;
1844 else if(attrList[attrIdx + 1] == ALC_TRUE)
1845 hrtf_appreq = Hrtf_Enable;
1846 else
1847 hrtf_appreq = Hrtf_Default;
1848 break;
1850 case ALC_HRTF_ID_SOFT:
1851 hrtf_id = attrList[attrIdx + 1];
1852 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1853 break;
1855 case ALC_OUTPUT_LIMITER_SOFT:
1856 gainLimiter = attrList[attrIdx + 1];
1857 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1858 break;
1860 default:
1861 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList[attrIdx],
1862 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1863 break;
1866 attrIdx += 2;
1868 #undef TRACE_ATTR
1870 if(!schans || !stype || !freq)
1872 WARN("Missing format for loopback device\n");
1873 return ALC_INVALID_VALUE;
1875 if(schans == ALC_BFORMAT3D_SOFT && (!alayout || !ascale || !aorder))
1877 WARN("Missing ambisonic info for loopback device\n");
1878 return ALC_INVALID_VALUE;
1881 if((device->Flags&DEVICE_RUNNING))
1882 V0(device->Backend,stop)();
1883 device->Flags &= ~DEVICE_RUNNING;
1885 UpdateClockBase(device);
1887 device->Frequency = freq;
1888 device->FmtChans = schans;
1889 device->FmtType = stype;
1890 if(schans == ALC_BFORMAT3D_SOFT)
1892 device->AmbiOrder = aorder;
1893 device->AmbiLayout = alayout;
1894 device->AmbiScale = ascale;
1897 if(numMono > INT_MAX-numStereo)
1898 numMono = INT_MAX-numStereo;
1899 numMono += numStereo;
1900 if(ConfigValueInt(NULL, NULL, "sources", &numMono))
1902 if(numMono <= 0)
1903 numMono = 256;
1905 else
1906 numMono = maxi(numMono, 256);
1907 numStereo = mini(numStereo, numMono);
1908 numMono -= numStereo;
1909 device->SourcesMax = numMono + numStereo;
1911 device->NumMonoSources = numMono;
1912 device->NumStereoSources = numStereo;
1914 if(ConfigValueInt(NULL, NULL, "sends", &new_sends))
1915 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1916 else
1917 new_sends = numSends;
1919 else if(attrList && attrList[0])
1921 ALCsizei numMono, numStereo, numSends;
1922 ALCsizei attrIdx = 0;
1923 ALCuint freq;
1925 /* If a context is already running on the device, stop playback so the
1926 * device attributes can be updated. */
1927 if((device->Flags&DEVICE_RUNNING))
1928 V0(device->Backend,stop)();
1929 device->Flags &= ~DEVICE_RUNNING;
1931 UpdateClockBase(device);
1933 freq = device->Frequency;
1934 numMono = device->NumMonoSources;
1935 numStereo = device->NumStereoSources;
1936 numSends = old_sends;
1938 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1939 while(attrList[attrIdx])
1941 switch(attrList[attrIdx])
1943 case ALC_FREQUENCY:
1944 freq = attrList[attrIdx + 1];
1945 TRACE_ATTR(ALC_FREQUENCY, freq);
1946 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1947 break;
1949 case ALC_MONO_SOURCES:
1950 numMono = attrList[attrIdx + 1];
1951 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1952 numMono = maxi(numMono, 0);
1953 break;
1955 case ALC_STEREO_SOURCES:
1956 numStereo = attrList[attrIdx + 1];
1957 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1958 numStereo = maxi(numStereo, 0);
1959 break;
1961 case ALC_MAX_AUXILIARY_SENDS:
1962 numSends = attrList[attrIdx + 1];
1963 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1964 numSends = clampi(numSends, 0, MAX_SENDS);
1965 break;
1967 case ALC_HRTF_SOFT:
1968 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1969 if(attrList[attrIdx + 1] == ALC_FALSE)
1970 hrtf_appreq = Hrtf_Disable;
1971 else if(attrList[attrIdx + 1] == ALC_TRUE)
1972 hrtf_appreq = Hrtf_Enable;
1973 else
1974 hrtf_appreq = Hrtf_Default;
1975 break;
1977 case ALC_HRTF_ID_SOFT:
1978 hrtf_id = attrList[attrIdx + 1];
1979 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1980 break;
1982 case ALC_OUTPUT_LIMITER_SOFT:
1983 gainLimiter = attrList[attrIdx + 1];
1984 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1985 break;
1987 default:
1988 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1989 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1990 break;
1993 attrIdx += 2;
1995 #undef TRACE_ATTR
1997 ConfigValueUInt(alstr_get_cstr(device->DeviceName), NULL, "frequency", &freq);
1998 freq = maxu(freq, MIN_OUTPUT_RATE);
2000 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
2001 device->Frequency;
2002 /* SSE and Neon do best with the update size being a multiple of 4 */
2003 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
2004 device->UpdateSize = (device->UpdateSize+3)&~3;
2006 device->Frequency = freq;
2008 if(numMono > INT_MAX-numStereo)
2009 numMono = INT_MAX-numStereo;
2010 numMono += numStereo;
2011 if(ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "sources", &numMono))
2013 if(numMono <= 0)
2014 numMono = 256;
2016 else
2017 numMono = maxi(numMono, 256);
2018 numStereo = mini(numStereo, numMono);
2019 numMono -= numStereo;
2020 device->SourcesMax = numMono + numStereo;
2022 device->NumMonoSources = numMono;
2023 device->NumStereoSources = numStereo;
2025 if(ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "sends", &new_sends))
2026 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
2027 else
2028 new_sends = numSends;
2031 if((device->Flags&DEVICE_RUNNING))
2032 return ALC_NO_ERROR;
2034 al_free(device->Uhj_Encoder);
2035 device->Uhj_Encoder = NULL;
2037 al_free(device->Bs2b);
2038 device->Bs2b = NULL;
2040 al_free(device->ChannelDelay[0].Buffer);
2041 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2043 device->ChannelDelay[i].Length = 0;
2044 device->ChannelDelay[i].Buffer = NULL;
2047 al_free(device->Dry.Buffer);
2048 device->Dry.Buffer = NULL;
2049 device->Dry.NumChannels = 0;
2050 device->FOAOut.Buffer = NULL;
2051 device->FOAOut.NumChannels = 0;
2052 device->RealOut.Buffer = NULL;
2053 device->RealOut.NumChannels = 0;
2055 UpdateClockBase(device);
2057 device->DitherSeed = DITHER_RNG_SEED;
2059 /*************************************************************************
2060 * Update device format request if HRTF is requested
2062 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
2063 if(device->Type != Loopback)
2065 const char *hrtf;
2066 if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "hrtf", &hrtf))
2068 if(strcasecmp(hrtf, "true") == 0)
2069 hrtf_userreq = Hrtf_Enable;
2070 else if(strcasecmp(hrtf, "false") == 0)
2071 hrtf_userreq = Hrtf_Disable;
2072 else if(strcasecmp(hrtf, "auto") != 0)
2073 ERR("Unexpected hrtf value: %s\n", hrtf);
2076 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
2078 struct Hrtf *hrtf = NULL;
2079 if(VECTOR_SIZE(device->HrtfList) == 0)
2081 VECTOR_DEINIT(device->HrtfList);
2082 device->HrtfList = EnumerateHrtf(device->DeviceName);
2084 if(VECTOR_SIZE(device->HrtfList) > 0)
2086 if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->HrtfList))
2087 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, hrtf_id).hrtf);
2088 else
2089 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, 0).hrtf);
2092 if(hrtf)
2094 device->FmtChans = DevFmtStereo;
2095 device->Frequency = hrtf->sampleRate;
2096 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
2097 if(device->HrtfHandle)
2098 Hrtf_DecRef(device->HrtfHandle);
2099 device->HrtfHandle = hrtf;
2101 else
2103 hrtf_userreq = Hrtf_Default;
2104 hrtf_appreq = Hrtf_Disable;
2105 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2110 oldFreq = device->Frequency;
2111 oldChans = device->FmtChans;
2112 oldType = device->FmtType;
2114 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2115 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
2116 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
2117 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
2118 device->UpdateSize, device->NumUpdates
2121 if(V0(device->Backend,reset)() == ALC_FALSE)
2122 return ALC_INVALID_DEVICE;
2124 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
2126 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2127 DevFmtChannelsString(device->FmtChans));
2128 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2130 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2132 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2133 DevFmtTypeString(device->FmtType));
2134 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2136 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2138 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2139 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2142 if((device->UpdateSize&3) != 0)
2144 if((CPUCapFlags&CPU_CAP_SSE))
2145 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2146 if((CPUCapFlags&CPU_CAP_NEON))
2147 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2150 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2151 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2152 device->Frequency, device->UpdateSize, device->NumUpdates
2155 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2156 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device->Dry.NumChannels,
2157 device->FOAOut.NumChannels, device->RealOut.NumChannels);
2159 /* Allocate extra channels for any post-filter output. */
2160 size = (device->Dry.NumChannels + device->FOAOut.NumChannels +
2161 device->RealOut.NumChannels)*sizeof(device->Dry.Buffer[0]);
2163 TRACE("Allocating "SZFMT" channels, "SZFMT" bytes\n", size/sizeof(device->Dry.Buffer[0]), size);
2164 device->Dry.Buffer = al_calloc(16, size);
2165 if(!device->Dry.Buffer)
2167 ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
2168 return ALC_INVALID_DEVICE;
2171 if(device->RealOut.NumChannels != 0)
2172 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels +
2173 device->FOAOut.NumChannels;
2174 else
2176 device->RealOut.Buffer = device->Dry.Buffer;
2177 device->RealOut.NumChannels = device->Dry.NumChannels;
2180 if(device->FOAOut.NumChannels != 0)
2181 device->FOAOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2182 else
2184 device->FOAOut.Buffer = device->Dry.Buffer;
2185 device->FOAOut.NumChannels = device->Dry.NumChannels;
2188 device->NumAuxSends = new_sends;
2189 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2190 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
2191 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
2193 device->DitherDepth = 0.0f;
2194 if(GetConfigValueBool(alstr_get_cstr(device->DeviceName), NULL, "dither", 1))
2196 ALint depth = 0;
2197 ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "dither-depth", &depth);
2198 if(depth <= 0)
2200 switch(device->FmtType)
2202 case DevFmtByte:
2203 case DevFmtUByte:
2204 depth = 8;
2205 break;
2206 case DevFmtShort:
2207 case DevFmtUShort:
2208 depth = 16;
2209 break;
2210 case DevFmtInt:
2211 case DevFmtUInt:
2212 case DevFmtFloat:
2213 break;
2216 else if(depth > 24)
2217 depth = 24;
2218 device->DitherDepth = (depth > 0) ? powf(2.0f, (ALfloat)(depth-1)) : 0.0f;
2220 if(!(device->DitherDepth > 0.0f))
2221 TRACE("Dithering disabled\n");
2222 else
2223 TRACE("Dithering enabled (%g-bit, %g)\n", log2f(device->DitherDepth)+1.0f,
2224 device->DitherDepth);
2226 if(ConfigValueBool(alstr_get_cstr(device->DeviceName), NULL, "output-limiter", &val))
2227 gainLimiter = val ? ALC_TRUE : ALC_FALSE;
2228 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2229 * ALC_FALSE. We default to on, so ALC_DONT_CARE_SOFT is the same as
2230 * ALC_TRUE.
2232 if(gainLimiter != ALC_FALSE)
2234 if(!device->Limiter || device->Frequency != GetCompressorSampleRate(device->Limiter))
2236 al_free(device->Limiter);
2237 device->Limiter = CreateDeviceLimiter(device);
2240 else
2242 al_free(device->Limiter);
2243 device->Limiter = NULL;
2245 TRACE("Output limiter %s\n", device->Limiter ? "enabled" : "disabled");
2247 aluSelectPostProcess(device);
2249 /* Need to delay returning failure until replacement Send arrays have been
2250 * allocated with the appropriate size.
2252 update_failed = AL_FALSE;
2253 START_MIXER_MODE();
2254 context = ATOMIC_LOAD_SEQ(&device->ContextList);
2255 while(context)
2257 SourceSubList *sublist, *subend;
2258 struct ALvoiceProps *vprops;
2259 ALsizei pos;
2261 if(context->DefaultSlot)
2263 ALeffectslot *slot = context->DefaultSlot;
2264 ALeffectState *state = slot->Effect.State;
2266 state->OutBuffer = device->Dry.Buffer;
2267 state->OutChannels = device->Dry.NumChannels;
2268 if(V(state,deviceUpdate)(device) == AL_FALSE)
2269 update_failed = AL_TRUE;
2270 else
2271 UpdateEffectSlotProps(slot, context);
2274 almtx_lock(&context->PropLock);
2275 almtx_lock(&context->EffectSlotLock);
2276 for(pos = 0;pos < (ALsizei)VECTOR_SIZE(context->EffectSlotList);pos++)
2278 ALeffectslot *slot = VECTOR_ELEM(context->EffectSlotList, pos);
2279 ALeffectState *state = slot->Effect.State;
2281 state->OutBuffer = device->Dry.Buffer;
2282 state->OutChannels = device->Dry.NumChannels;
2283 if(V(state,deviceUpdate)(device) == AL_FALSE)
2284 update_failed = AL_TRUE;
2285 else
2286 UpdateEffectSlotProps(slot, context);
2288 almtx_unlock(&context->EffectSlotLock);
2290 almtx_lock(&context->SourceLock);
2291 sublist = VECTOR_BEGIN(context->SourceList);
2292 subend = VECTOR_END(context->SourceList);
2293 for(;sublist != subend;++sublist)
2295 ALuint64 usemask = ~sublist->FreeMask;
2296 while(usemask)
2298 ALsizei idx = CTZ64(usemask);
2299 ALsource *source = sublist->Sources + idx;
2301 usemask &= ~(U64(1) << idx);
2303 if(old_sends != device->NumAuxSends)
2305 ALvoid *sends = al_calloc(16, device->NumAuxSends*sizeof(source->Send[0]));
2306 ALsizei s;
2308 memcpy(sends, source->Send,
2309 mini(device->NumAuxSends, old_sends)*sizeof(source->Send[0])
2311 for(s = device->NumAuxSends;s < old_sends;s++)
2313 if(source->Send[s].Slot)
2314 DecrementRef(&source->Send[s].Slot->ref);
2315 source->Send[s].Slot = NULL;
2317 al_free(source->Send);
2318 source->Send = sends;
2319 for(s = old_sends;s < device->NumAuxSends;s++)
2321 source->Send[s].Slot = NULL;
2322 source->Send[s].Gain = 1.0f;
2323 source->Send[s].GainHF = 1.0f;
2324 source->Send[s].HFReference = LOWPASSFREQREF;
2325 source->Send[s].GainLF = 1.0f;
2326 source->Send[s].LFReference = HIGHPASSFREQREF;
2330 ATOMIC_FLAG_CLEAR(&source->PropsClean, almemory_order_release);
2334 /* Clear any pre-existing voice property structs, in case the number of
2335 * auxiliary sends is changing. Active sources will have updates
2336 * respecified in UpdateAllSourceProps.
2338 vprops = ATOMIC_EXCHANGE_PTR(&context->FreeVoiceProps, NULL, almemory_order_acq_rel);
2339 while(vprops)
2341 struct ALvoiceProps *next = ATOMIC_LOAD(&vprops->next, almemory_order_relaxed);
2342 al_free(vprops);
2343 vprops = next;
2346 AllocateVoices(context, context->MaxVoices, old_sends);
2347 for(pos = 0;pos < context->VoiceCount;pos++)
2349 ALvoice *voice = context->Voices[pos];
2351 al_free(ATOMIC_EXCHANGE_PTR(&voice->Update, NULL, almemory_order_acq_rel));
2353 if(ATOMIC_LOAD(&voice->Source, almemory_order_acquire) == NULL)
2354 continue;
2356 if(device->AvgSpeakerDist > 0.0f)
2358 /* Reinitialize the NFC filters for new parameters. */
2359 ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
2360 (device->AvgSpeakerDist * device->Frequency);
2361 for(i = 0;i < voice->NumChannels;i++)
2362 NfcFilterCreate(&voice->Direct.Params[i].NFCtrlFilter, 0.0f, w1);
2365 almtx_unlock(&context->SourceLock);
2367 ATOMIC_FLAG_TEST_AND_SET(&context->PropsClean, almemory_order_release);
2368 UpdateContextProps(context);
2369 ATOMIC_FLAG_TEST_AND_SET(&context->Listener->PropsClean, almemory_order_release);
2370 UpdateListenerProps(context);
2371 UpdateAllSourceProps(context);
2372 almtx_unlock(&context->PropLock);
2374 context = ATOMIC_LOAD(&context->next, almemory_order_relaxed);
2376 END_MIXER_MODE();
2377 if(update_failed)
2378 return ALC_INVALID_DEVICE;
2380 if(!(device->Flags&DEVICE_PAUSED))
2382 if(V0(device->Backend,start)() == ALC_FALSE)
2383 return ALC_INVALID_DEVICE;
2384 device->Flags |= DEVICE_RUNNING;
2387 return ALC_NO_ERROR;
2391 static void InitDevice(ALCdevice *device, enum DeviceType type)
2393 ALsizei i;
2395 InitRef(&device->ref, 1);
2396 ATOMIC_INIT(&device->Connected, ALC_TRUE);
2397 device->Type = type;
2398 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
2400 device->Flags = 0;
2401 device->Render_Mode = NormalRender;
2402 device->AvgSpeakerDist = 0.0f;
2404 ATOMIC_INIT(&device->ContextList, NULL);
2406 device->ClockBase = 0;
2407 device->SamplesDone = 0;
2409 device->SourcesMax = 0;
2410 device->AuxiliaryEffectSlotMax = 0;
2411 device->NumAuxSends = 0;
2413 device->Dry.Buffer = NULL;
2414 device->Dry.NumChannels = 0;
2415 device->FOAOut.Buffer = NULL;
2416 device->FOAOut.NumChannels = 0;
2417 device->RealOut.Buffer = NULL;
2418 device->RealOut.NumChannels = 0;
2420 AL_STRING_INIT(device->DeviceName);
2422 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2424 device->ChannelDelay[i].Gain = 1.0f;
2425 device->ChannelDelay[i].Length = 0;
2426 device->ChannelDelay[i].Buffer = NULL;
2429 AL_STRING_INIT(device->HrtfName);
2430 VECTOR_INIT(device->HrtfList);
2431 device->HrtfHandle = NULL;
2432 device->Hrtf = NULL;
2433 device->Bs2b = NULL;
2434 device->Uhj_Encoder = NULL;
2435 device->AmbiDecoder = NULL;
2436 device->AmbiUp = NULL;
2437 device->Stablizer = NULL;
2438 device->Limiter = NULL;
2440 VECTOR_INIT(device->BufferList);
2441 almtx_init(&device->BufferLock, almtx_plain);
2443 VECTOR_INIT(device->EffectList);
2444 almtx_init(&device->EffectLock, almtx_plain);
2446 VECTOR_INIT(device->FilterList);
2447 almtx_init(&device->FilterLock, almtx_plain);
2449 almtx_init(&device->BackendLock, almtx_plain);
2450 device->Backend = NULL;
2452 ATOMIC_INIT(&device->next, NULL);
2455 /* FreeDevice
2457 * Frees the device structure, and destroys any objects the app failed to
2458 * delete. Called once there's no more references on the device.
2460 static ALCvoid FreeDevice(ALCdevice *device)
2462 ALsizei i;
2464 TRACE("%p\n", device);
2466 if(device->Backend)
2467 DELETE_OBJ(device->Backend);
2468 device->Backend = NULL;
2470 almtx_destroy(&device->BackendLock);
2472 ReleaseALBuffers(device);
2473 #define FREE_BUFFERSUBLIST(x) al_free((x)->Buffers)
2474 VECTOR_FOR_EACH(BufferSubList, device->BufferList, FREE_BUFFERSUBLIST);
2475 #undef FREE_BUFFERSUBLIST
2476 VECTOR_DEINIT(device->BufferList);
2477 almtx_destroy(&device->BufferLock);
2479 ReleaseALEffects(device);
2480 #define FREE_EFFECTSUBLIST(x) al_free((x)->Effects)
2481 VECTOR_FOR_EACH(EffectSubList, device->EffectList, FREE_EFFECTSUBLIST);
2482 #undef FREE_EFFECTSUBLIST
2483 VECTOR_DEINIT(device->EffectList);
2484 almtx_destroy(&device->EffectLock);
2486 ReleaseALFilters(device);
2487 #define FREE_FILTERSUBLIST(x) al_free((x)->Filters)
2488 VECTOR_FOR_EACH(FilterSubList, device->FilterList, FREE_FILTERSUBLIST);
2489 #undef FREE_FILTERSUBLIST
2490 VECTOR_DEINIT(device->FilterList);
2491 almtx_destroy(&device->FilterLock);
2493 AL_STRING_DEINIT(device->HrtfName);
2494 FreeHrtfList(&device->HrtfList);
2495 if(device->HrtfHandle)
2496 Hrtf_DecRef(device->HrtfHandle);
2497 device->HrtfHandle = NULL;
2498 al_free(device->Hrtf);
2499 device->Hrtf = NULL;
2501 al_free(device->Bs2b);
2502 device->Bs2b = NULL;
2504 al_free(device->Uhj_Encoder);
2505 device->Uhj_Encoder = NULL;
2507 bformatdec_free(&device->AmbiDecoder);
2508 ambiup_free(&device->AmbiUp);
2510 al_free(device->Stablizer);
2511 device->Stablizer = NULL;
2513 al_free(device->Limiter);
2514 device->Limiter = NULL;
2516 al_free(device->ChannelDelay[0].Buffer);
2517 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2519 device->ChannelDelay[i].Gain = 1.0f;
2520 device->ChannelDelay[i].Length = 0;
2521 device->ChannelDelay[i].Buffer = NULL;
2524 AL_STRING_DEINIT(device->DeviceName);
2526 al_free(device->Dry.Buffer);
2527 device->Dry.Buffer = NULL;
2528 device->Dry.NumChannels = 0;
2529 device->FOAOut.Buffer = NULL;
2530 device->FOAOut.NumChannels = 0;
2531 device->RealOut.Buffer = NULL;
2532 device->RealOut.NumChannels = 0;
2534 al_free(device);
2538 void ALCdevice_IncRef(ALCdevice *device)
2540 uint ref;
2541 ref = IncrementRef(&device->ref);
2542 TRACEREF("%p increasing refcount to %u\n", device, ref);
2545 void ALCdevice_DecRef(ALCdevice *device)
2547 uint ref;
2548 ref = DecrementRef(&device->ref);
2549 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2550 if(ref == 0) FreeDevice(device);
2553 /* VerifyDevice
2555 * Checks if the device handle is valid, and increments its ref count if so.
2557 static ALCboolean VerifyDevice(ALCdevice **device)
2559 ALCdevice *tmpDevice;
2561 LockLists();
2562 tmpDevice = ATOMIC_LOAD_SEQ(&DeviceList);
2563 while(tmpDevice)
2565 if(tmpDevice == *device)
2567 ALCdevice_IncRef(tmpDevice);
2568 UnlockLists();
2569 return ALC_TRUE;
2571 tmpDevice = ATOMIC_LOAD(&tmpDevice->next, almemory_order_relaxed);
2573 UnlockLists();
2575 *device = NULL;
2576 return ALC_FALSE;
2580 /* InitContext
2582 * Initializes context fields
2584 static ALvoid InitContext(ALCcontext *Context)
2586 ALlistener *listener = Context->Listener;
2587 struct ALeffectslotArray *auxslots;
2589 //Initialise listener
2590 listener->Gain = 1.0f;
2591 listener->Position[0] = 0.0f;
2592 listener->Position[1] = 0.0f;
2593 listener->Position[2] = 0.0f;
2594 listener->Velocity[0] = 0.0f;
2595 listener->Velocity[1] = 0.0f;
2596 listener->Velocity[2] = 0.0f;
2597 listener->Forward[0] = 0.0f;
2598 listener->Forward[1] = 0.0f;
2599 listener->Forward[2] = -1.0f;
2600 listener->Up[0] = 0.0f;
2601 listener->Up[1] = 1.0f;
2602 listener->Up[2] = 0.0f;
2603 ATOMIC_FLAG_TEST_AND_SET(&listener->PropsClean, almemory_order_relaxed);
2605 ATOMIC_INIT(&listener->Update, NULL);
2607 //Validate Context
2608 InitRef(&Context->UpdateCount, 0);
2609 ATOMIC_INIT(&Context->HoldUpdates, AL_FALSE);
2610 Context->GainBoost = 1.0f;
2611 almtx_init(&Context->PropLock, almtx_plain);
2612 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2613 VECTOR_INIT(Context->SourceList);
2614 Context->NumSources = 0;
2615 almtx_init(&Context->SourceLock, almtx_plain);
2616 VECTOR_INIT(Context->EffectSlotList);
2617 almtx_init(&Context->EffectSlotLock, almtx_plain);
2619 if(Context->DefaultSlot)
2621 auxslots = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, 1));
2622 auxslots->count = 1;
2623 auxslots->slot[0] = Context->DefaultSlot;
2625 else
2627 auxslots = al_calloc(DEF_ALIGN, sizeof(struct ALeffectslotArray));
2628 auxslots->count = 0;
2630 ATOMIC_INIT(&Context->ActiveAuxSlots, auxslots);
2632 //Set globals
2633 Context->DistanceModel = DefaultDistanceModel;
2634 Context->SourceDistanceModel = AL_FALSE;
2635 Context->DopplerFactor = 1.0f;
2636 Context->DopplerVelocity = 1.0f;
2637 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2638 Context->MetersPerUnit = AL_DEFAULT_METERS_PER_UNIT;
2639 ATOMIC_FLAG_TEST_AND_SET(&Context->PropsClean, almemory_order_relaxed);
2640 ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
2641 almtx_init(&Context->EventThrdLock, almtx_plain);
2642 alsem_init(&Context->EventSem, 0);
2643 Context->AsyncEvents = NULL;
2644 ATOMIC_INIT(&Context->EnabledEvts, 0);
2645 almtx_init(&Context->EventCbLock, almtx_plain);
2646 Context->EventCb = NULL;
2647 Context->EventParam = NULL;
2649 ATOMIC_INIT(&Context->Update, NULL);
2650 ATOMIC_INIT(&Context->FreeContextProps, NULL);
2651 ATOMIC_INIT(&Context->FreeListenerProps, NULL);
2652 ATOMIC_INIT(&Context->FreeVoiceProps, NULL);
2653 ATOMIC_INIT(&Context->FreeEffectslotProps, NULL);
2655 Context->ExtensionList = alExtList;
2658 listener->Params.Matrix = IdentityMatrixf;
2659 aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2660 listener->Params.Gain = listener->Gain;
2661 listener->Params.MetersPerUnit = Context->MetersPerUnit;
2662 listener->Params.DopplerFactor = Context->DopplerFactor;
2663 listener->Params.SpeedOfSound = Context->SpeedOfSound * Context->DopplerVelocity;
2664 listener->Params.ReverbSpeedOfSound = listener->Params.SpeedOfSound *
2665 listener->Params.MetersPerUnit;
2666 listener->Params.SourceDistanceModel = Context->SourceDistanceModel;
2667 listener->Params.DistanceModel = Context->DistanceModel;
2671 /* FreeContext
2673 * Cleans up the context, and destroys any remaining objects the app failed to
2674 * delete. Called once there's no more references on the context.
2676 static void FreeContext(ALCcontext *context)
2678 ALlistener *listener = context->Listener;
2679 struct ALeffectslotArray *auxslots;
2680 struct ALeffectslotProps *eprops;
2681 struct ALlistenerProps *lprops;
2682 struct ALcontextProps *cprops;
2683 struct ALvoiceProps *vprops;
2684 size_t count;
2685 ALsizei i;
2687 TRACE("%p\n", context);
2689 if((cprops=ATOMIC_LOAD(&context->Update, almemory_order_acquire)) != NULL)
2691 TRACE("Freed unapplied context update %p\n", cprops);
2692 al_free(cprops);
2695 count = 0;
2696 cprops = ATOMIC_LOAD(&context->FreeContextProps, almemory_order_acquire);
2697 while(cprops)
2699 struct ALcontextProps *next = ATOMIC_LOAD(&cprops->next, almemory_order_acquire);
2700 al_free(cprops);
2701 cprops = next;
2702 ++count;
2704 TRACE("Freed "SZFMT" context property object%s\n", count, (count==1)?"":"s");
2706 if(context->DefaultSlot)
2708 DeinitEffectSlot(context->DefaultSlot);
2709 context->DefaultSlot = NULL;
2712 auxslots = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, NULL, almemory_order_relaxed);
2713 al_free(auxslots);
2715 ReleaseALSources(context);
2716 #define FREE_SOURCESUBLIST(x) al_free((x)->Sources)
2717 VECTOR_FOR_EACH(SourceSubList, context->SourceList, FREE_SOURCESUBLIST);
2718 #undef FREE_SOURCESUBLIST
2719 VECTOR_DEINIT(context->SourceList);
2720 context->NumSources = 0;
2721 almtx_destroy(&context->SourceLock);
2723 count = 0;
2724 eprops = ATOMIC_LOAD(&context->FreeEffectslotProps, almemory_order_relaxed);
2725 while(eprops)
2727 struct ALeffectslotProps *next = ATOMIC_LOAD(&eprops->next, almemory_order_relaxed);
2728 if(eprops->State) ALeffectState_DecRef(eprops->State);
2729 al_free(eprops);
2730 eprops = next;
2731 ++count;
2733 TRACE("Freed "SZFMT" AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2735 ReleaseALAuxiliaryEffectSlots(context);
2736 #define FREE_EFFECTSLOTPTR(x) al_free(*(x))
2737 VECTOR_FOR_EACH(ALeffectslotPtr, context->EffectSlotList, FREE_EFFECTSLOTPTR);
2738 #undef FREE_EFFECTSLOTPTR
2739 VECTOR_DEINIT(context->EffectSlotList);
2740 almtx_destroy(&context->EffectSlotLock);
2742 count = 0;
2743 vprops = ATOMIC_LOAD(&context->FreeVoiceProps, almemory_order_relaxed);
2744 while(vprops)
2746 struct ALvoiceProps *next = ATOMIC_LOAD(&vprops->next, almemory_order_relaxed);
2747 al_free(vprops);
2748 vprops = next;
2749 ++count;
2751 TRACE("Freed "SZFMT" voice property object%s\n", count, (count==1)?"":"s");
2753 for(i = 0;i < context->VoiceCount;i++)
2754 DeinitVoice(context->Voices[i]);
2755 al_free(context->Voices);
2756 context->Voices = NULL;
2757 context->VoiceCount = 0;
2758 context->MaxVoices = 0;
2760 if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != NULL)
2762 TRACE("Freed unapplied listener update %p\n", lprops);
2763 al_free(lprops);
2765 count = 0;
2766 lprops = ATOMIC_LOAD(&context->FreeListenerProps, almemory_order_acquire);
2767 while(lprops)
2769 struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_acquire);
2770 al_free(lprops);
2771 lprops = next;
2772 ++count;
2774 TRACE("Freed "SZFMT" listener property object%s\n", count, (count==1)?"":"s");
2776 if(ATOMIC_EXCHANGE(&context->EnabledEvts, 0, almemory_order_acq_rel))
2778 static const AsyncEvent kill_evt = { 0 };
2779 while(ll_ringbuffer_write(context->AsyncEvents, (const char*)&kill_evt, 1) == 0)
2780 althrd_yield();
2781 alsem_post(&context->EventSem);
2782 althrd_join(context->EventThread, NULL);
2785 almtx_destroy(&context->EventCbLock);
2786 almtx_destroy(&context->EventThrdLock);
2787 alsem_destroy(&context->EventSem);
2789 ll_ringbuffer_free(context->AsyncEvents);
2790 context->AsyncEvents = NULL;
2792 almtx_destroy(&context->PropLock);
2794 ALCdevice_DecRef(context->Device);
2795 context->Device = NULL;
2797 //Invalidate context
2798 memset(context, 0, sizeof(ALCcontext));
2799 al_free(context);
2802 /* ReleaseContext
2804 * Removes the context reference from the given device and removes it from
2805 * being current on the running thread or globally. Returns true if other
2806 * contexts still exist on the device.
2808 static bool ReleaseContext(ALCcontext *context, ALCdevice *device)
2810 ALCcontext *origctx, *newhead;
2811 bool ret = true;
2813 if(altss_get(LocalContext) == context)
2815 WARN("%p released while current on thread\n", context);
2816 altss_set(LocalContext, NULL);
2817 ALCcontext_DecRef(context);
2820 origctx = context;
2821 if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext, &origctx, NULL))
2822 ALCcontext_DecRef(context);
2824 V0(device->Backend,lock)();
2825 origctx = context;
2826 newhead = ATOMIC_LOAD(&context->next, almemory_order_relaxed);
2827 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device->ContextList, &origctx, newhead))
2829 ALCcontext *list;
2830 do {
2831 /* origctx is what the desired context failed to match. Try
2832 * swapping out the next one in the list.
2834 list = origctx;
2835 origctx = context;
2836 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list->next, &origctx, newhead));
2838 else
2839 ret = !!newhead;
2840 V0(device->Backend,unlock)();
2842 ALCcontext_DecRef(context);
2843 return ret;
2846 static void ALCcontext_IncRef(ALCcontext *context)
2848 uint ref = IncrementRef(&context->ref);
2849 TRACEREF("%p increasing refcount to %u\n", context, ref);
2852 void ALCcontext_DecRef(ALCcontext *context)
2854 uint ref = DecrementRef(&context->ref);
2855 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2856 if(ref == 0) FreeContext(context);
2859 static void ReleaseThreadCtx(void *ptr)
2861 ALCcontext *context = ptr;
2862 uint ref = DecrementRef(&context->ref);
2863 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2864 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2867 /* VerifyContext
2869 * Checks that the given context is valid, and increments its reference count.
2871 static ALCboolean VerifyContext(ALCcontext **context)
2873 ALCdevice *dev;
2875 LockLists();
2876 dev = ATOMIC_LOAD_SEQ(&DeviceList);
2877 while(dev)
2879 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList, almemory_order_acquire);
2880 while(ctx)
2882 if(ctx == *context)
2884 ALCcontext_IncRef(ctx);
2885 UnlockLists();
2886 return ALC_TRUE;
2888 ctx = ATOMIC_LOAD(&ctx->next, almemory_order_relaxed);
2890 dev = ATOMIC_LOAD(&dev->next, almemory_order_relaxed);
2892 UnlockLists();
2894 *context = NULL;
2895 return ALC_FALSE;
2899 /* GetContextRef
2901 * Returns the currently active context for this thread, and adds a reference
2902 * without locking it.
2904 ALCcontext *GetContextRef(void)
2906 ALCcontext *context;
2908 context = altss_get(LocalContext);
2909 if(context)
2910 ALCcontext_IncRef(context);
2911 else
2913 LockLists();
2914 context = ATOMIC_LOAD_SEQ(&GlobalContext);
2915 if(context)
2916 ALCcontext_IncRef(context);
2917 UnlockLists();
2920 return context;
2924 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
2926 ALCdevice *device = context->Device;
2927 ALsizei num_sends = device->NumAuxSends;
2928 struct ALvoiceProps *props;
2929 size_t sizeof_props;
2930 size_t sizeof_voice;
2931 ALvoice **voices;
2932 ALvoice *voice;
2933 ALsizei v = 0;
2934 size_t size;
2936 if(num_voices == context->MaxVoices && num_sends == old_sends)
2937 return;
2939 /* Allocate the voice pointers, voices, and the voices' stored source
2940 * property set (including the dynamically-sized Send[] array) in one
2941 * chunk.
2943 sizeof_voice = RoundUp(FAM_SIZE(ALvoice, Send, num_sends), 16);
2944 sizeof_props = RoundUp(FAM_SIZE(struct ALvoiceProps, Send, num_sends), 16);
2945 size = sizeof(ALvoice*) + sizeof_voice + sizeof_props;
2947 voices = al_calloc(16, RoundUp(size*num_voices, 16));
2948 /* The voice and property objects are stored interleaved since they're
2949 * paired together.
2951 voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
2952 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2954 if(context->Voices)
2956 const ALsizei v_count = mini(context->VoiceCount, num_voices);
2957 const ALsizei s_count = mini(old_sends, num_sends);
2959 for(;v < v_count;v++)
2961 ALvoice *old_voice = context->Voices[v];
2962 ALsizei i;
2964 /* Copy the old voice data and source property set to the new
2965 * storage.
2967 *voice = *old_voice;
2968 for(i = 0;i < s_count;i++)
2969 voice->Send[i] = old_voice->Send[i];
2970 *props = *(old_voice->Props);
2971 for(i = 0;i < s_count;i++)
2972 props->Send[i] = old_voice->Props->Send[i];
2974 /* Set this voice's property set pointer and voice reference. */
2975 voice->Props = props;
2976 voices[v] = voice;
2978 /* Increment pointers to the next storage space. */
2979 voice = (ALvoice*)((char*)props + sizeof_props);
2980 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2982 /* Deinit any left over voices that weren't copied over to the new
2983 * array. NOTE: If this does anything, v equals num_voices and
2984 * num_voices is less than VoiceCount, so the following loop won't do
2985 * anything.
2987 for(;v < context->VoiceCount;v++)
2988 DeinitVoice(context->Voices[v]);
2990 /* Finish setting the voices' property set pointers and references. */
2991 for(;v < num_voices;v++)
2993 ATOMIC_INIT(&voice->Update, NULL);
2995 voice->Props = props;
2996 voices[v] = voice;
2998 voice = (ALvoice*)((char*)props + sizeof_props);
2999 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
3002 al_free(context->Voices);
3003 context->Voices = voices;
3004 context->MaxVoices = num_voices;
3005 context->VoiceCount = mini(context->VoiceCount, num_voices);
3009 /************************************************
3010 * Standard ALC functions
3011 ************************************************/
3013 /* alcGetError
3015 * Return last ALC generated error code for the given device
3017 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
3019 ALCenum errorCode;
3021 if(VerifyDevice(&device))
3023 errorCode = ATOMIC_EXCHANGE_SEQ(&device->LastError, ALC_NO_ERROR);
3024 ALCdevice_DecRef(device);
3026 else
3027 errorCode = ATOMIC_EXCHANGE_SEQ(&LastNullDeviceError, ALC_NO_ERROR);
3029 return errorCode;
3033 /* alcSuspendContext
3035 * Suspends updates for the given context
3037 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
3039 if(!SuspendDefers)
3040 return;
3042 if(!VerifyContext(&context))
3043 alcSetError(NULL, ALC_INVALID_CONTEXT);
3044 else
3046 ALCcontext_DeferUpdates(context);
3047 ALCcontext_DecRef(context);
3051 /* alcProcessContext
3053 * Resumes processing updates for the given context
3055 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
3057 if(!SuspendDefers)
3058 return;
3060 if(!VerifyContext(&context))
3061 alcSetError(NULL, ALC_INVALID_CONTEXT);
3062 else
3064 ALCcontext_ProcessUpdates(context);
3065 ALCcontext_DecRef(context);
3070 /* alcGetString
3072 * Returns information about the device, and error strings
3074 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
3076 const ALCchar *value = NULL;
3078 switch(param)
3080 case ALC_NO_ERROR:
3081 value = alcNoError;
3082 break;
3084 case ALC_INVALID_ENUM:
3085 value = alcErrInvalidEnum;
3086 break;
3088 case ALC_INVALID_VALUE:
3089 value = alcErrInvalidValue;
3090 break;
3092 case ALC_INVALID_DEVICE:
3093 value = alcErrInvalidDevice;
3094 break;
3096 case ALC_INVALID_CONTEXT:
3097 value = alcErrInvalidContext;
3098 break;
3100 case ALC_OUT_OF_MEMORY:
3101 value = alcErrOutOfMemory;
3102 break;
3104 case ALC_DEVICE_SPECIFIER:
3105 value = alcDefaultName;
3106 break;
3108 case ALC_ALL_DEVICES_SPECIFIER:
3109 if(VerifyDevice(&Device))
3111 value = alstr_get_cstr(Device->DeviceName);
3112 ALCdevice_DecRef(Device);
3114 else
3116 ProbeAllDevicesList();
3117 value = alstr_get_cstr(alcAllDevicesList);
3119 break;
3121 case ALC_CAPTURE_DEVICE_SPECIFIER:
3122 if(VerifyDevice(&Device))
3124 value = alstr_get_cstr(Device->DeviceName);
3125 ALCdevice_DecRef(Device);
3127 else
3129 ProbeCaptureDeviceList();
3130 value = alstr_get_cstr(alcCaptureDeviceList);
3132 break;
3134 /* Default devices are always first in the list */
3135 case ALC_DEFAULT_DEVICE_SPECIFIER:
3136 value = alcDefaultName;
3137 break;
3139 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
3140 if(alstr_empty(alcAllDevicesList))
3141 ProbeAllDevicesList();
3143 VerifyDevice(&Device);
3145 free(alcDefaultAllDevicesSpecifier);
3146 alcDefaultAllDevicesSpecifier = strdup(alstr_get_cstr(alcAllDevicesList));
3147 if(!alcDefaultAllDevicesSpecifier)
3148 alcSetError(Device, ALC_OUT_OF_MEMORY);
3150 value = alcDefaultAllDevicesSpecifier;
3151 if(Device) ALCdevice_DecRef(Device);
3152 break;
3154 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
3155 if(alstr_empty(alcCaptureDeviceList))
3156 ProbeCaptureDeviceList();
3158 VerifyDevice(&Device);
3160 free(alcCaptureDefaultDeviceSpecifier);
3161 alcCaptureDefaultDeviceSpecifier = strdup(alstr_get_cstr(alcCaptureDeviceList));
3162 if(!alcCaptureDefaultDeviceSpecifier)
3163 alcSetError(Device, ALC_OUT_OF_MEMORY);
3165 value = alcCaptureDefaultDeviceSpecifier;
3166 if(Device) ALCdevice_DecRef(Device);
3167 break;
3169 case ALC_EXTENSIONS:
3170 if(!VerifyDevice(&Device))
3171 value = alcNoDeviceExtList;
3172 else
3174 value = alcExtensionList;
3175 ALCdevice_DecRef(Device);
3177 break;
3179 case ALC_HRTF_SPECIFIER_SOFT:
3180 if(!VerifyDevice(&Device))
3181 alcSetError(NULL, ALC_INVALID_DEVICE);
3182 else
3184 almtx_lock(&Device->BackendLock);
3185 value = (Device->HrtfHandle ? alstr_get_cstr(Device->HrtfName) : "");
3186 almtx_unlock(&Device->BackendLock);
3187 ALCdevice_DecRef(Device);
3189 break;
3191 default:
3192 VerifyDevice(&Device);
3193 alcSetError(Device, ALC_INVALID_ENUM);
3194 if(Device) ALCdevice_DecRef(Device);
3195 break;
3198 return value;
3202 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
3204 if(device->Type == Capture) return 9;
3205 if(device->Type != Loopback) return 29;
3206 if(device->FmtChans == DevFmtAmbi3D)
3207 return 35;
3208 return 29;
3211 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3213 ALCsizei i;
3215 if(size <= 0 || values == NULL)
3217 alcSetError(device, ALC_INVALID_VALUE);
3218 return 0;
3221 if(!device)
3223 switch(param)
3225 case ALC_MAJOR_VERSION:
3226 values[0] = alcMajorVersion;
3227 return 1;
3228 case ALC_MINOR_VERSION:
3229 values[0] = alcMinorVersion;
3230 return 1;
3232 case ALC_ATTRIBUTES_SIZE:
3233 case ALC_ALL_ATTRIBUTES:
3234 case ALC_FREQUENCY:
3235 case ALC_REFRESH:
3236 case ALC_SYNC:
3237 case ALC_MONO_SOURCES:
3238 case ALC_STEREO_SOURCES:
3239 case ALC_CAPTURE_SAMPLES:
3240 case ALC_FORMAT_CHANNELS_SOFT:
3241 case ALC_FORMAT_TYPE_SOFT:
3242 case ALC_AMBISONIC_LAYOUT_SOFT:
3243 case ALC_AMBISONIC_SCALING_SOFT:
3244 case ALC_AMBISONIC_ORDER_SOFT:
3245 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3246 alcSetError(NULL, ALC_INVALID_DEVICE);
3247 return 0;
3249 default:
3250 alcSetError(NULL, ALC_INVALID_ENUM);
3251 return 0;
3253 return 0;
3256 if(device->Type == Capture)
3258 switch(param)
3260 case ALC_ATTRIBUTES_SIZE:
3261 values[0] = NumAttrsForDevice(device);
3262 return 1;
3264 case ALC_ALL_ATTRIBUTES:
3265 if(size < NumAttrsForDevice(device))
3267 alcSetError(device, ALC_INVALID_VALUE);
3268 return 0;
3271 i = 0;
3272 almtx_lock(&device->BackendLock);
3273 values[i++] = ALC_MAJOR_VERSION;
3274 values[i++] = alcMajorVersion;
3275 values[i++] = ALC_MINOR_VERSION;
3276 values[i++] = alcMinorVersion;
3277 values[i++] = ALC_CAPTURE_SAMPLES;
3278 values[i++] = V0(device->Backend,availableSamples)();
3279 values[i++] = ALC_CONNECTED;
3280 values[i++] = ATOMIC_LOAD(&device->Connected, almemory_order_relaxed);
3281 almtx_unlock(&device->BackendLock);
3283 values[i++] = 0;
3284 return i;
3286 case ALC_MAJOR_VERSION:
3287 values[0] = alcMajorVersion;
3288 return 1;
3289 case ALC_MINOR_VERSION:
3290 values[0] = alcMinorVersion;
3291 return 1;
3293 case ALC_CAPTURE_SAMPLES:
3294 almtx_lock(&device->BackendLock);
3295 values[0] = V0(device->Backend,availableSamples)();
3296 almtx_unlock(&device->BackendLock);
3297 return 1;
3299 case ALC_CONNECTED:
3300 values[0] = ATOMIC_LOAD(&device->Connected, almemory_order_acquire);
3301 return 1;
3303 default:
3304 alcSetError(device, ALC_INVALID_ENUM);
3305 return 0;
3307 return 0;
3310 /* render device */
3311 switch(param)
3313 case ALC_ATTRIBUTES_SIZE:
3314 values[0] = NumAttrsForDevice(device);
3315 return 1;
3317 case ALC_ALL_ATTRIBUTES:
3318 if(size < NumAttrsForDevice(device))
3320 alcSetError(device, ALC_INVALID_VALUE);
3321 return 0;
3324 i = 0;
3325 almtx_lock(&device->BackendLock);
3326 values[i++] = ALC_MAJOR_VERSION;
3327 values[i++] = alcMajorVersion;
3328 values[i++] = ALC_MINOR_VERSION;
3329 values[i++] = alcMinorVersion;
3330 values[i++] = ALC_EFX_MAJOR_VERSION;
3331 values[i++] = alcEFXMajorVersion;
3332 values[i++] = ALC_EFX_MINOR_VERSION;
3333 values[i++] = alcEFXMinorVersion;
3335 values[i++] = ALC_FREQUENCY;
3336 values[i++] = device->Frequency;
3337 if(device->Type != Loopback)
3339 values[i++] = ALC_REFRESH;
3340 values[i++] = device->Frequency / device->UpdateSize;
3342 values[i++] = ALC_SYNC;
3343 values[i++] = ALC_FALSE;
3345 else
3347 if(device->FmtChans == DevFmtAmbi3D)
3349 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3350 values[i++] = device->AmbiLayout;
3352 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3353 values[i++] = device->AmbiScale;
3355 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3356 values[i++] = device->AmbiOrder;
3359 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3360 values[i++] = device->FmtChans;
3362 values[i++] = ALC_FORMAT_TYPE_SOFT;
3363 values[i++] = device->FmtType;
3366 values[i++] = ALC_MONO_SOURCES;
3367 values[i++] = device->NumMonoSources;
3369 values[i++] = ALC_STEREO_SOURCES;
3370 values[i++] = device->NumStereoSources;
3372 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3373 values[i++] = device->NumAuxSends;
3375 values[i++] = ALC_HRTF_SOFT;
3376 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3378 values[i++] = ALC_HRTF_STATUS_SOFT;
3379 values[i++] = device->HrtfStatus;
3381 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3382 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3384 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
3385 values[i++] = MAX_AMBI_ORDER;
3386 almtx_unlock(&device->BackendLock);
3388 values[i++] = 0;
3389 return i;
3391 case ALC_MAJOR_VERSION:
3392 values[0] = alcMajorVersion;
3393 return 1;
3395 case ALC_MINOR_VERSION:
3396 values[0] = alcMinorVersion;
3397 return 1;
3399 case ALC_EFX_MAJOR_VERSION:
3400 values[0] = alcEFXMajorVersion;
3401 return 1;
3403 case ALC_EFX_MINOR_VERSION:
3404 values[0] = alcEFXMinorVersion;
3405 return 1;
3407 case ALC_FREQUENCY:
3408 values[0] = device->Frequency;
3409 return 1;
3411 case ALC_REFRESH:
3412 if(device->Type == Loopback)
3414 alcSetError(device, ALC_INVALID_DEVICE);
3415 return 0;
3417 almtx_lock(&device->BackendLock);
3418 values[0] = device->Frequency / device->UpdateSize;
3419 almtx_unlock(&device->BackendLock);
3420 return 1;
3422 case ALC_SYNC:
3423 if(device->Type == Loopback)
3425 alcSetError(device, ALC_INVALID_DEVICE);
3426 return 0;
3428 values[0] = ALC_FALSE;
3429 return 1;
3431 case ALC_FORMAT_CHANNELS_SOFT:
3432 if(device->Type != Loopback)
3434 alcSetError(device, ALC_INVALID_DEVICE);
3435 return 0;
3437 values[0] = device->FmtChans;
3438 return 1;
3440 case ALC_FORMAT_TYPE_SOFT:
3441 if(device->Type != Loopback)
3443 alcSetError(device, ALC_INVALID_DEVICE);
3444 return 0;
3446 values[0] = device->FmtType;
3447 return 1;
3449 case ALC_AMBISONIC_LAYOUT_SOFT:
3450 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3452 alcSetError(device, ALC_INVALID_DEVICE);
3453 return 0;
3455 values[0] = device->AmbiLayout;
3456 return 1;
3458 case ALC_AMBISONIC_SCALING_SOFT:
3459 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3461 alcSetError(device, ALC_INVALID_DEVICE);
3462 return 0;
3464 values[0] = device->AmbiScale;
3465 return 1;
3467 case ALC_AMBISONIC_ORDER_SOFT:
3468 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3470 alcSetError(device, ALC_INVALID_DEVICE);
3471 return 0;
3473 values[0] = device->AmbiOrder;
3474 return 1;
3476 case ALC_MONO_SOURCES:
3477 values[0] = device->NumMonoSources;
3478 return 1;
3480 case ALC_STEREO_SOURCES:
3481 values[0] = device->NumStereoSources;
3482 return 1;
3484 case ALC_MAX_AUXILIARY_SENDS:
3485 values[0] = device->NumAuxSends;
3486 return 1;
3488 case ALC_CONNECTED:
3489 values[0] = ATOMIC_LOAD(&device->Connected, almemory_order_acquire);
3490 return 1;
3492 case ALC_HRTF_SOFT:
3493 values[0] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3494 return 1;
3496 case ALC_HRTF_STATUS_SOFT:
3497 values[0] = device->HrtfStatus;
3498 return 1;
3500 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3501 almtx_lock(&device->BackendLock);
3502 FreeHrtfList(&device->HrtfList);
3503 device->HrtfList = EnumerateHrtf(device->DeviceName);
3504 values[0] = (ALCint)VECTOR_SIZE(device->HrtfList);
3505 almtx_unlock(&device->BackendLock);
3506 return 1;
3508 case ALC_OUTPUT_LIMITER_SOFT:
3509 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3510 return 1;
3512 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3513 values[0] = MAX_AMBI_ORDER;
3514 return 1;
3516 default:
3517 alcSetError(device, ALC_INVALID_ENUM);
3518 return 0;
3520 return 0;
3523 /* alcGetIntegerv
3525 * Returns information about the device and the version of OpenAL
3527 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3529 VerifyDevice(&device);
3530 if(size <= 0 || values == NULL)
3531 alcSetError(device, ALC_INVALID_VALUE);
3532 else
3533 GetIntegerv(device, param, size, values);
3534 if(device) ALCdevice_DecRef(device);
3537 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3539 ALCint *ivals;
3540 ALsizei i;
3542 VerifyDevice(&device);
3543 if(size <= 0 || values == NULL)
3544 alcSetError(device, ALC_INVALID_VALUE);
3545 else if(!device || device->Type == Capture)
3547 ivals = malloc(size * sizeof(ALCint));
3548 size = GetIntegerv(device, pname, size, ivals);
3549 for(i = 0;i < size;i++)
3550 values[i] = ivals[i];
3551 free(ivals);
3553 else /* render device */
3555 ClockLatency clock;
3556 ALuint64 basecount;
3557 ALuint samplecount;
3558 ALuint refcount;
3560 switch(pname)
3562 case ALC_ATTRIBUTES_SIZE:
3563 *values = NumAttrsForDevice(device)+4;
3564 break;
3566 case ALC_ALL_ATTRIBUTES:
3567 if(size < NumAttrsForDevice(device)+4)
3568 alcSetError(device, ALC_INVALID_VALUE);
3569 else
3571 i = 0;
3572 almtx_lock(&device->BackendLock);
3573 values[i++] = ALC_FREQUENCY;
3574 values[i++] = device->Frequency;
3576 if(device->Type != Loopback)
3578 values[i++] = ALC_REFRESH;
3579 values[i++] = device->Frequency / device->UpdateSize;
3581 values[i++] = ALC_SYNC;
3582 values[i++] = ALC_FALSE;
3584 else
3586 if(device->FmtChans == DevFmtAmbi3D)
3588 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3589 values[i++] = device->AmbiLayout;
3591 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3592 values[i++] = device->AmbiScale;
3594 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3595 values[i++] = device->AmbiOrder;
3598 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3599 values[i++] = device->FmtChans;
3601 values[i++] = ALC_FORMAT_TYPE_SOFT;
3602 values[i++] = device->FmtType;
3605 values[i++] = ALC_MONO_SOURCES;
3606 values[i++] = device->NumMonoSources;
3608 values[i++] = ALC_STEREO_SOURCES;
3609 values[i++] = device->NumStereoSources;
3611 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3612 values[i++] = device->NumAuxSends;
3614 values[i++] = ALC_HRTF_SOFT;
3615 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3617 values[i++] = ALC_HRTF_STATUS_SOFT;
3618 values[i++] = device->HrtfStatus;
3620 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3621 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3623 clock = V0(device->Backend,getClockLatency)();
3624 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3625 values[i++] = clock.ClockTime;
3627 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3628 values[i++] = clock.Latency;
3629 almtx_unlock(&device->BackendLock);
3631 values[i++] = 0;
3633 break;
3635 case ALC_DEVICE_CLOCK_SOFT:
3636 almtx_lock(&device->BackendLock);
3637 do {
3638 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3639 althrd_yield();
3640 basecount = device->ClockBase;
3641 samplecount = device->SamplesDone;
3642 } while(refcount != ReadRef(&device->MixCount));
3643 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3644 almtx_unlock(&device->BackendLock);
3645 break;
3647 case ALC_DEVICE_LATENCY_SOFT:
3648 almtx_lock(&device->BackendLock);
3649 clock = V0(device->Backend,getClockLatency)();
3650 almtx_unlock(&device->BackendLock);
3651 *values = clock.Latency;
3652 break;
3654 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3655 if(size < 2)
3656 alcSetError(device, ALC_INVALID_VALUE);
3657 else
3659 almtx_lock(&device->BackendLock);
3660 clock = V0(device->Backend,getClockLatency)();
3661 almtx_unlock(&device->BackendLock);
3662 values[0] = clock.ClockTime;
3663 values[1] = clock.Latency;
3665 break;
3667 default:
3668 ivals = malloc(size * sizeof(ALCint));
3669 size = GetIntegerv(device, pname, size, ivals);
3670 for(i = 0;i < size;i++)
3671 values[i] = ivals[i];
3672 free(ivals);
3673 break;
3676 if(device)
3677 ALCdevice_DecRef(device);
3681 /* alcIsExtensionPresent
3683 * Determines if there is support for a particular extension
3685 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3687 ALCboolean bResult = ALC_FALSE;
3689 VerifyDevice(&device);
3691 if(!extName)
3692 alcSetError(device, ALC_INVALID_VALUE);
3693 else
3695 size_t len = strlen(extName);
3696 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3697 while(ptr && *ptr)
3699 if(strncasecmp(ptr, extName, len) == 0 &&
3700 (ptr[len] == '\0' || isspace(ptr[len])))
3702 bResult = ALC_TRUE;
3703 break;
3705 if((ptr=strchr(ptr, ' ')) != NULL)
3707 do {
3708 ++ptr;
3709 } while(isspace(*ptr));
3713 if(device)
3714 ALCdevice_DecRef(device);
3715 return bResult;
3719 /* alcGetProcAddress
3721 * Retrieves the function address for a particular extension function
3723 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3725 ALCvoid *ptr = NULL;
3727 if(!funcName)
3729 VerifyDevice(&device);
3730 alcSetError(device, ALC_INVALID_VALUE);
3731 if(device) ALCdevice_DecRef(device);
3733 else
3735 size_t i = 0;
3736 for(i = 0;i < COUNTOF(alcFunctions);i++)
3738 if(strcmp(alcFunctions[i].funcName, funcName) == 0)
3740 ptr = alcFunctions[i].address;
3741 break;
3746 return ptr;
3750 /* alcGetEnumValue
3752 * Get the value for a particular ALC enumeration name
3754 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3756 ALCenum val = 0;
3758 if(!enumName)
3760 VerifyDevice(&device);
3761 alcSetError(device, ALC_INVALID_VALUE);
3762 if(device) ALCdevice_DecRef(device);
3764 else
3766 size_t i = 0;
3767 for(i = 0;i < COUNTOF(alcEnumerations);i++)
3769 if(strcmp(alcEnumerations[i].enumName, enumName) == 0)
3771 val = alcEnumerations[i].value;
3772 break;
3777 return val;
3781 /* alcCreateContext
3783 * Create and attach a context to the given device.
3785 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3787 ALCcontext *ALContext;
3788 ALfloat valf;
3789 ALCenum err;
3791 /* Explicitly hold the list lock while taking the BackendLock in case the
3792 * device is asynchronously destropyed, to ensure this new context is
3793 * properly cleaned up after being made.
3795 LockLists();
3796 if(!VerifyDevice(&device) || device->Type == Capture ||
3797 !ATOMIC_LOAD(&device->Connected, almemory_order_relaxed))
3799 UnlockLists();
3800 alcSetError(device, ALC_INVALID_DEVICE);
3801 if(device) ALCdevice_DecRef(device);
3802 return NULL;
3804 almtx_lock(&device->BackendLock);
3805 UnlockLists();
3807 ATOMIC_STORE_SEQ(&device->LastError, ALC_NO_ERROR);
3809 if(device->Type == Playback && DefaultEffect.type != AL_EFFECT_NULL)
3810 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener)+sizeof(ALeffectslot));
3811 else
3812 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3813 if(!ALContext)
3815 almtx_unlock(&device->BackendLock);
3817 alcSetError(device, ALC_OUT_OF_MEMORY);
3818 ALCdevice_DecRef(device);
3819 return NULL;
3822 InitRef(&ALContext->ref, 1);
3823 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3824 ALContext->DefaultSlot = NULL;
3826 ALContext->Voices = NULL;
3827 ALContext->VoiceCount = 0;
3828 ALContext->MaxVoices = 0;
3829 ATOMIC_INIT(&ALContext->ActiveAuxSlots, NULL);
3830 ALContext->Device = device;
3831 ATOMIC_INIT(&ALContext->next, NULL);
3833 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3835 almtx_unlock(&device->BackendLock);
3837 al_free(ALContext);
3838 ALContext = NULL;
3840 alcSetError(device, err);
3841 if(err == ALC_INVALID_DEVICE)
3843 V0(device->Backend,lock)();
3844 aluHandleDisconnect(device, "Device update failure");
3845 V0(device->Backend,unlock)();
3847 ALCdevice_DecRef(device);
3848 return NULL;
3850 AllocateVoices(ALContext, 256, device->NumAuxSends);
3852 if(DefaultEffect.type != AL_EFFECT_NULL && device->Type == Playback)
3854 ALContext->DefaultSlot = (ALeffectslot*)(ALContext->_listener_mem + sizeof(ALlistener));
3855 if(InitEffectSlot(ALContext->DefaultSlot) == AL_NO_ERROR)
3856 aluInitEffectPanning(ALContext->DefaultSlot);
3857 else
3859 ALContext->DefaultSlot = NULL;
3860 ERR("Failed to initialize the default effect slot\n");
3864 ALCdevice_IncRef(ALContext->Device);
3865 InitContext(ALContext);
3867 if(ConfigValueFloat(alstr_get_cstr(device->DeviceName), NULL, "volume-adjust", &valf))
3869 if(!isfinite(valf))
3870 ERR("volume-adjust must be finite: %f\n", valf);
3871 else
3873 ALfloat db = clampf(valf, -24.0f, 24.0f);
3874 if(db != valf)
3875 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3876 ALContext->GainBoost = powf(10.0f, db/20.0f);
3877 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3880 UpdateListenerProps(ALContext);
3883 ALCcontext *head = ATOMIC_LOAD_SEQ(&device->ContextList);
3884 do {
3885 ATOMIC_STORE(&ALContext->next, head, almemory_order_relaxed);
3886 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device->ContextList, &head,
3887 ALContext) == 0);
3889 almtx_unlock(&device->BackendLock);
3891 if(ALContext->DefaultSlot)
3893 if(InitializeEffect(ALContext, ALContext->DefaultSlot, &DefaultEffect) == AL_NO_ERROR)
3894 UpdateEffectSlotProps(ALContext->DefaultSlot, ALContext);
3895 else
3896 ERR("Failed to initialize the default effect\n");
3899 ALCdevice_DecRef(device);
3901 TRACE("Created context %p\n", ALContext);
3902 return ALContext;
3905 /* alcDestroyContext
3907 * Remove a context from its device
3909 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3911 ALCdevice *Device;
3913 LockLists();
3914 if(!VerifyContext(&context))
3916 UnlockLists();
3917 alcSetError(NULL, ALC_INVALID_CONTEXT);
3918 return;
3921 Device = context->Device;
3922 if(Device)
3924 almtx_lock(&Device->BackendLock);
3925 if(!ReleaseContext(context, Device))
3927 V0(Device->Backend,stop)();
3928 Device->Flags &= ~DEVICE_RUNNING;
3930 almtx_unlock(&Device->BackendLock);
3932 UnlockLists();
3934 ALCcontext_DecRef(context);
3938 /* alcGetCurrentContext
3940 * Returns the currently active context on the calling thread
3942 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3944 ALCcontext *Context = altss_get(LocalContext);
3945 if(!Context) Context = ATOMIC_LOAD_SEQ(&GlobalContext);
3946 return Context;
3949 /* alcGetThreadContext
3951 * Returns the currently active thread-local context
3953 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3955 return altss_get(LocalContext);
3959 /* alcMakeContextCurrent
3961 * Makes the given context the active process-wide context, and removes the
3962 * thread-local context for the calling thread.
3964 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3966 /* context must be valid or NULL */
3967 if(context && !VerifyContext(&context))
3969 alcSetError(NULL, ALC_INVALID_CONTEXT);
3970 return ALC_FALSE;
3972 /* context's reference count is already incremented */
3973 context = ATOMIC_EXCHANGE_PTR_SEQ(&GlobalContext, context);
3974 if(context) ALCcontext_DecRef(context);
3976 if((context=altss_get(LocalContext)) != NULL)
3978 altss_set(LocalContext, NULL);
3979 ALCcontext_DecRef(context);
3982 return ALC_TRUE;
3985 /* alcSetThreadContext
3987 * Makes the given context the active context for the current thread
3989 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3991 ALCcontext *old;
3993 /* context must be valid or NULL */
3994 if(context && !VerifyContext(&context))
3996 alcSetError(NULL, ALC_INVALID_CONTEXT);
3997 return ALC_FALSE;
3999 /* context's reference count is already incremented */
4000 old = altss_get(LocalContext);
4001 altss_set(LocalContext, context);
4002 if(old) ALCcontext_DecRef(old);
4004 return ALC_TRUE;
4008 /* alcGetContextsDevice
4010 * Returns the device that a particular context is attached to
4012 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
4014 ALCdevice *Device;
4016 if(!VerifyContext(&Context))
4018 alcSetError(NULL, ALC_INVALID_CONTEXT);
4019 return NULL;
4021 Device = Context->Device;
4022 ALCcontext_DecRef(Context);
4024 return Device;
4028 /* alcOpenDevice
4030 * Opens the named device.
4032 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
4034 ALCbackendFactory *factory;
4035 const ALCchar *fmt;
4036 ALCdevice *device;
4037 ALCenum err;
4039 DO_INITCONFIG();
4041 if(!PlaybackBackend.name)
4043 alcSetError(NULL, ALC_INVALID_VALUE);
4044 return NULL;
4047 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
4048 #ifdef _WIN32
4049 /* Some old Windows apps hardcode these expecting OpenAL to use a
4050 * specific audio API, even when they're not enumerated. Creative's
4051 * router effectively ignores them too.
4053 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
4054 || strcasecmp(deviceName, "MMSYSTEM") == 0
4055 #endif
4057 deviceName = NULL;
4059 device = al_calloc(16, sizeof(ALCdevice));
4060 if(!device)
4062 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4063 return NULL;
4066 //Validate device
4067 InitDevice(device, Playback);
4069 //Set output format
4070 device->FmtChans = DevFmtChannelsDefault;
4071 device->FmtType = DevFmtTypeDefault;
4072 device->Frequency = DEFAULT_OUTPUT_RATE;
4073 device->IsHeadphones = AL_FALSE;
4074 device->AmbiLayout = AmbiLayout_Default;
4075 device->AmbiScale = AmbiNorm_Default;
4076 device->NumUpdates = 3;
4077 device->UpdateSize = 1024;
4079 device->SourcesMax = 256;
4080 device->AuxiliaryEffectSlotMax = 64;
4081 device->NumAuxSends = DEFAULT_SENDS;
4083 if(ConfigValueStr(deviceName, NULL, "channels", &fmt))
4085 static const struct {
4086 const char name[16];
4087 enum DevFmtChannels chans;
4088 ALsizei order;
4089 } chanlist[] = {
4090 { "mono", DevFmtMono, 0 },
4091 { "stereo", DevFmtStereo, 0 },
4092 { "quad", DevFmtQuad, 0 },
4093 { "surround51", DevFmtX51, 0 },
4094 { "surround61", DevFmtX61, 0 },
4095 { "surround71", DevFmtX71, 0 },
4096 { "surround51rear", DevFmtX51Rear, 0 },
4097 { "ambi1", DevFmtAmbi3D, 1 },
4098 { "ambi2", DevFmtAmbi3D, 2 },
4099 { "ambi3", DevFmtAmbi3D, 3 },
4101 size_t i;
4103 for(i = 0;i < COUNTOF(chanlist);i++)
4105 if(strcasecmp(chanlist[i].name, fmt) == 0)
4107 device->FmtChans = chanlist[i].chans;
4108 device->AmbiOrder = chanlist[i].order;
4109 device->Flags |= DEVICE_CHANNELS_REQUEST;
4110 break;
4113 if(i == COUNTOF(chanlist))
4114 ERR("Unsupported channels: %s\n", fmt);
4116 if(ConfigValueStr(deviceName, NULL, "sample-type", &fmt))
4118 static const struct {
4119 const char name[16];
4120 enum DevFmtType type;
4121 } typelist[] = {
4122 { "int8", DevFmtByte },
4123 { "uint8", DevFmtUByte },
4124 { "int16", DevFmtShort },
4125 { "uint16", DevFmtUShort },
4126 { "int32", DevFmtInt },
4127 { "uint32", DevFmtUInt },
4128 { "float32", DevFmtFloat },
4130 size_t i;
4132 for(i = 0;i < COUNTOF(typelist);i++)
4134 if(strcasecmp(typelist[i].name, fmt) == 0)
4136 device->FmtType = typelist[i].type;
4137 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
4138 break;
4141 if(i == COUNTOF(typelist))
4142 ERR("Unsupported sample-type: %s\n", fmt);
4145 if(ConfigValueUInt(deviceName, NULL, "frequency", &device->Frequency))
4147 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4148 if(device->Frequency < MIN_OUTPUT_RATE)
4149 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
4150 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
4153 ConfigValueUInt(deviceName, NULL, "periods", &device->NumUpdates);
4154 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
4156 ConfigValueUInt(deviceName, NULL, "period_size", &device->UpdateSize);
4157 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
4158 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
4159 device->UpdateSize = (device->UpdateSize+3)&~3;
4161 ConfigValueUInt(deviceName, NULL, "sources", &device->SourcesMax);
4162 if(device->SourcesMax == 0) device->SourcesMax = 256;
4164 ConfigValueUInt(deviceName, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4165 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4166 else device->AuxiliaryEffectSlotMax = minu(device->AuxiliaryEffectSlotMax, INT_MAX);
4168 if(ConfigValueInt(deviceName, NULL, "sends", &device->NumAuxSends))
4169 device->NumAuxSends = clampi(
4170 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4173 device->NumStereoSources = 1;
4174 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4176 factory = PlaybackBackend.getFactory();
4177 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
4178 if(!device->Backend)
4180 FreeDevice(device);
4181 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4182 return NULL;
4185 // Find a playback device to open
4186 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4188 FreeDevice(device);
4189 alcSetError(NULL, err);
4190 return NULL;
4193 if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt))
4195 if(strcasecmp(fmt, "fuma") == 0)
4197 device->AmbiLayout = AmbiLayout_FuMa;
4198 device->AmbiScale = AmbiNorm_FuMa;
4200 else if(strcasecmp(fmt, "acn+sn3d") == 0)
4202 device->AmbiLayout = AmbiLayout_ACN;
4203 device->AmbiScale = AmbiNorm_SN3D;
4205 else if(strcasecmp(fmt, "acn+n3d") == 0)
4207 device->AmbiLayout = AmbiLayout_ACN;
4208 device->AmbiScale = AmbiNorm_N3D;
4210 else
4211 ERR("Unsupported ambi-format: %s\n", fmt);
4214 device->Limiter = CreateDeviceLimiter(device);
4217 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4218 do {
4219 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4220 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4223 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
4224 return device;
4227 /* alcCloseDevice
4229 * Closes the given device.
4231 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
4233 ALCdevice *iter, *origdev, *nextdev;
4234 ALCcontext *ctx;
4236 LockLists();
4237 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4238 do {
4239 if(iter == device)
4240 break;
4241 iter = ATOMIC_LOAD(&iter->next, almemory_order_relaxed);
4242 } while(iter != NULL);
4243 if(!iter || iter->Type == Capture)
4245 alcSetError(iter, ALC_INVALID_DEVICE);
4246 UnlockLists();
4247 return ALC_FALSE;
4249 almtx_lock(&device->BackendLock);
4251 origdev = device;
4252 nextdev = ATOMIC_LOAD(&device->next, almemory_order_relaxed);
4253 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, nextdev))
4255 ALCdevice *list;
4256 do {
4257 list = origdev;
4258 origdev = device;
4259 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list->next, &origdev, nextdev));
4261 UnlockLists();
4263 ctx = ATOMIC_LOAD_SEQ(&device->ContextList);
4264 while(ctx != NULL)
4266 ALCcontext *next = ATOMIC_LOAD(&ctx->next, almemory_order_relaxed);
4267 WARN("Releasing context %p\n", ctx);
4268 ReleaseContext(ctx, device);
4269 ctx = next;
4271 if((device->Flags&DEVICE_RUNNING))
4272 V0(device->Backend,stop)();
4273 device->Flags &= ~DEVICE_RUNNING;
4274 almtx_unlock(&device->BackendLock);
4276 ALCdevice_DecRef(device);
4278 return ALC_TRUE;
4282 /************************************************
4283 * ALC capture functions
4284 ************************************************/
4285 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
4287 ALCbackendFactory *factory;
4288 ALCdevice *device = NULL;
4289 ALCenum err;
4291 DO_INITCONFIG();
4293 if(!CaptureBackend.name)
4295 alcSetError(NULL, ALC_INVALID_VALUE);
4296 return NULL;
4299 if(samples <= 0)
4301 alcSetError(NULL, ALC_INVALID_VALUE);
4302 return NULL;
4305 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
4306 deviceName = NULL;
4308 device = al_calloc(16, sizeof(ALCdevice));
4309 if(!device)
4311 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4312 return NULL;
4315 //Validate device
4316 InitDevice(device, Capture);
4318 device->Frequency = frequency;
4319 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4321 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
4323 FreeDevice(device);
4324 alcSetError(NULL, ALC_INVALID_ENUM);
4325 return NULL;
4327 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
4328 device->IsHeadphones = AL_FALSE;
4329 device->AmbiOrder = 0;
4330 device->AmbiLayout = AmbiLayout_Default;
4331 device->AmbiScale = AmbiNorm_Default;
4333 device->UpdateSize = samples;
4334 device->NumUpdates = 1;
4336 factory = CaptureBackend.getFactory();
4337 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
4338 if(!device->Backend)
4340 FreeDevice(device);
4341 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4342 return NULL;
4345 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4346 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
4347 device->Frequency, device->UpdateSize, device->NumUpdates
4349 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4351 FreeDevice(device);
4352 alcSetError(NULL, err);
4353 return NULL;
4357 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4358 do {
4359 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4360 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4363 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
4364 return device;
4367 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
4369 ALCdevice *iter, *origdev, *nextdev;
4371 LockLists();
4372 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4373 do {
4374 if(iter == device)
4375 break;
4376 iter = ATOMIC_LOAD(&iter->next, almemory_order_relaxed);
4377 } while(iter != NULL);
4378 if(!iter || iter->Type != Capture)
4380 alcSetError(iter, ALC_INVALID_DEVICE);
4381 UnlockLists();
4382 return ALC_FALSE;
4385 origdev = device;
4386 nextdev = ATOMIC_LOAD(&device->next, almemory_order_relaxed);
4387 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, nextdev))
4389 ALCdevice *list;
4390 do {
4391 list = origdev;
4392 origdev = device;
4393 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list->next, &origdev, nextdev));
4395 UnlockLists();
4397 ALCdevice_DecRef(device);
4399 return ALC_TRUE;
4402 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
4404 if(!VerifyDevice(&device) || device->Type != Capture)
4405 alcSetError(device, ALC_INVALID_DEVICE);
4406 else
4408 almtx_lock(&device->BackendLock);
4409 if(!ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
4410 alcSetError(device, ALC_INVALID_DEVICE);
4411 else if(!(device->Flags&DEVICE_RUNNING))
4413 if(V0(device->Backend,start)())
4414 device->Flags |= DEVICE_RUNNING;
4415 else
4417 aluHandleDisconnect(device, "Device start failure");
4418 alcSetError(device, ALC_INVALID_DEVICE);
4421 almtx_unlock(&device->BackendLock);
4424 if(device) ALCdevice_DecRef(device);
4427 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
4429 if(!VerifyDevice(&device) || device->Type != Capture)
4430 alcSetError(device, ALC_INVALID_DEVICE);
4431 else
4433 almtx_lock(&device->BackendLock);
4434 if((device->Flags&DEVICE_RUNNING))
4435 V0(device->Backend,stop)();
4436 device->Flags &= ~DEVICE_RUNNING;
4437 almtx_unlock(&device->BackendLock);
4440 if(device) ALCdevice_DecRef(device);
4443 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4445 if(!VerifyDevice(&device) || device->Type != Capture)
4446 alcSetError(device, ALC_INVALID_DEVICE);
4447 else
4449 ALCenum err = ALC_INVALID_VALUE;
4451 almtx_lock(&device->BackendLock);
4452 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
4453 err = V(device->Backend,captureSamples)(buffer, samples);
4454 almtx_unlock(&device->BackendLock);
4456 if(err != ALC_NO_ERROR)
4457 alcSetError(device, err);
4459 if(device) ALCdevice_DecRef(device);
4463 /************************************************
4464 * ALC loopback functions
4465 ************************************************/
4467 /* alcLoopbackOpenDeviceSOFT
4469 * Open a loopback device, for manual rendering.
4471 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
4473 ALCbackendFactory *factory;
4474 ALCdevice *device;
4476 DO_INITCONFIG();
4478 /* Make sure the device name, if specified, is us. */
4479 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
4481 alcSetError(NULL, ALC_INVALID_VALUE);
4482 return NULL;
4485 device = al_calloc(16, sizeof(ALCdevice));
4486 if(!device)
4488 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4489 return NULL;
4492 //Validate device
4493 InitDevice(device, Loopback);
4495 device->SourcesMax = 256;
4496 device->AuxiliaryEffectSlotMax = 64;
4497 device->NumAuxSends = DEFAULT_SENDS;
4499 //Set output format
4500 device->NumUpdates = 0;
4501 device->UpdateSize = 0;
4503 device->Frequency = DEFAULT_OUTPUT_RATE;
4504 device->FmtChans = DevFmtChannelsDefault;
4505 device->FmtType = DevFmtTypeDefault;
4506 device->IsHeadphones = AL_FALSE;
4507 device->AmbiLayout = AmbiLayout_Default;
4508 device->AmbiScale = AmbiNorm_Default;
4510 ConfigValueUInt(NULL, NULL, "sources", &device->SourcesMax);
4511 if(device->SourcesMax == 0) device->SourcesMax = 256;
4513 ConfigValueUInt(NULL, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4514 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4515 else device->AuxiliaryEffectSlotMax = minu(device->AuxiliaryEffectSlotMax, INT_MAX);
4517 if(ConfigValueInt(NULL, NULL, "sends", &device->NumAuxSends))
4518 device->NumAuxSends = clampi(
4519 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4522 device->NumStereoSources = 1;
4523 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4525 factory = ALCloopbackFactory_getFactory();
4526 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
4527 if(!device->Backend)
4529 al_free(device);
4530 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4531 return NULL;
4534 // Open the "backend"
4535 V(device->Backend,open)("Loopback");
4537 device->Limiter = CreateDeviceLimiter(device);
4540 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4541 do {
4542 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4543 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4546 TRACE("Created device %p\n", device);
4547 return device;
4550 /* alcIsRenderFormatSupportedSOFT
4552 * Determines if the loopback device supports the given format for rendering.
4554 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4556 ALCboolean ret = ALC_FALSE;
4558 if(!VerifyDevice(&device) || device->Type != Loopback)
4559 alcSetError(device, ALC_INVALID_DEVICE);
4560 else if(freq <= 0)
4561 alcSetError(device, ALC_INVALID_VALUE);
4562 else
4564 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4565 ret = ALC_TRUE;
4567 if(device) ALCdevice_DecRef(device);
4569 return ret;
4572 /* alcRenderSamplesSOFT
4574 * Renders some samples into a buffer, using the format last set by the
4575 * attributes given to alcCreateContext.
4577 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4579 if(!VerifyDevice(&device) || device->Type != Loopback)
4580 alcSetError(device, ALC_INVALID_DEVICE);
4581 else if(samples < 0 || (samples > 0 && buffer == NULL))
4582 alcSetError(device, ALC_INVALID_VALUE);
4583 else
4585 V0(device->Backend,lock)();
4586 aluMixData(device, buffer, samples);
4587 V0(device->Backend,unlock)();
4589 if(device) ALCdevice_DecRef(device);
4593 /************************************************
4594 * ALC DSP pause/resume functions
4595 ************************************************/
4597 /* alcDevicePauseSOFT
4599 * Pause the DSP to stop audio processing.
4601 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4603 if(!VerifyDevice(&device) || device->Type != Playback)
4604 alcSetError(device, ALC_INVALID_DEVICE);
4605 else
4607 almtx_lock(&device->BackendLock);
4608 if((device->Flags&DEVICE_RUNNING))
4609 V0(device->Backend,stop)();
4610 device->Flags &= ~DEVICE_RUNNING;
4611 device->Flags |= DEVICE_PAUSED;
4612 almtx_unlock(&device->BackendLock);
4614 if(device) ALCdevice_DecRef(device);
4617 /* alcDeviceResumeSOFT
4619 * Resume the DSP to restart audio processing.
4621 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4623 if(!VerifyDevice(&device) || device->Type != Playback)
4624 alcSetError(device, ALC_INVALID_DEVICE);
4625 else
4627 almtx_lock(&device->BackendLock);
4628 if((device->Flags&DEVICE_PAUSED))
4630 device->Flags &= ~DEVICE_PAUSED;
4631 if(ATOMIC_LOAD_SEQ(&device->ContextList) != NULL)
4633 if(V0(device->Backend,start)() != ALC_FALSE)
4634 device->Flags |= DEVICE_RUNNING;
4635 else
4637 V0(device->Backend,lock)();
4638 aluHandleDisconnect(device, "Device start failure");
4639 V0(device->Backend,unlock)();
4640 alcSetError(device, ALC_INVALID_DEVICE);
4644 almtx_unlock(&device->BackendLock);
4646 if(device) ALCdevice_DecRef(device);
4650 /************************************************
4651 * ALC HRTF functions
4652 ************************************************/
4654 /* alcGetStringiSOFT
4656 * Gets a string parameter at the given index.
4658 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4660 const ALCchar *str = NULL;
4662 if(!VerifyDevice(&device) || device->Type == Capture)
4663 alcSetError(device, ALC_INVALID_DEVICE);
4664 else switch(paramName)
4666 case ALC_HRTF_SPECIFIER_SOFT:
4667 if(index >= 0 && (size_t)index < VECTOR_SIZE(device->HrtfList))
4668 str = alstr_get_cstr(VECTOR_ELEM(device->HrtfList, index).name);
4669 else
4670 alcSetError(device, ALC_INVALID_VALUE);
4671 break;
4673 default:
4674 alcSetError(device, ALC_INVALID_ENUM);
4675 break;
4677 if(device) ALCdevice_DecRef(device);
4679 return str;
4682 /* alcResetDeviceSOFT
4684 * Resets the given device output, using the specified attribute list.
4686 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4688 ALCenum err;
4690 LockLists();
4691 if(!VerifyDevice(&device) || device->Type == Capture ||
4692 !ATOMIC_LOAD(&device->Connected, almemory_order_relaxed))
4694 UnlockLists();
4695 alcSetError(device, ALC_INVALID_DEVICE);
4696 if(device) ALCdevice_DecRef(device);
4697 return ALC_FALSE;
4699 almtx_lock(&device->BackendLock);
4700 UnlockLists();
4702 err = UpdateDeviceParams(device, attribs);
4703 almtx_unlock(&device->BackendLock);
4705 if(err != ALC_NO_ERROR)
4707 alcSetError(device, err);
4708 if(err == ALC_INVALID_DEVICE)
4710 V0(device->Backend,lock)();
4711 aluHandleDisconnect(device, "Device start failure");
4712 V0(device->Backend,unlock)();
4714 ALCdevice_DecRef(device);
4715 return ALC_FALSE;
4717 ALCdevice_DecRef(device);
4719 return ALC_TRUE;