Merge pull request #204 from jhasse/android-byte-order
[openal-soft.git] / Alc / ALc.c
blob2e9dc710c66dc50185e75afa2106989d456e96bb
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 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
554 #if 0
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_FREQUENCY_SHIFTER_FREQUENCY),
636 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION),
637 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION),
639 DECL(AL_RING_MODULATOR_FREQUENCY),
640 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
641 DECL(AL_RING_MODULATOR_WAVEFORM),
643 DECL(AL_PITCH_SHIFTER_COARSE_TUNE),
644 DECL(AL_PITCH_SHIFTER_FINE_TUNE),
646 DECL(AL_COMPRESSOR_ONOFF),
648 DECL(AL_EQUALIZER_LOW_GAIN),
649 DECL(AL_EQUALIZER_LOW_CUTOFF),
650 DECL(AL_EQUALIZER_MID1_GAIN),
651 DECL(AL_EQUALIZER_MID1_CENTER),
652 DECL(AL_EQUALIZER_MID1_WIDTH),
653 DECL(AL_EQUALIZER_MID2_GAIN),
654 DECL(AL_EQUALIZER_MID2_CENTER),
655 DECL(AL_EQUALIZER_MID2_WIDTH),
656 DECL(AL_EQUALIZER_HIGH_GAIN),
657 DECL(AL_EQUALIZER_HIGH_CUTOFF),
659 DECL(AL_DEDICATED_GAIN),
661 DECL(AL_NUM_RESAMPLERS_SOFT),
662 DECL(AL_DEFAULT_RESAMPLER_SOFT),
663 DECL(AL_SOURCE_RESAMPLER_SOFT),
664 DECL(AL_RESAMPLER_NAME_SOFT),
666 DECL(AL_SOURCE_SPATIALIZE_SOFT),
667 DECL(AL_AUTO_SOFT),
669 DECL(AL_MAP_READ_BIT_SOFT),
670 DECL(AL_MAP_WRITE_BIT_SOFT),
671 DECL(AL_MAP_PERSISTENT_BIT_SOFT),
672 DECL(AL_PRESERVE_DATA_BIT_SOFT),
674 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT),
675 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT),
676 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT),
677 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT),
678 DECL(AL_EVENT_TYPE_ERROR_SOFT),
679 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT),
680 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT),
682 #undef DECL
684 static const ALCchar alcNoError[] = "No Error";
685 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
686 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
687 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
688 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
689 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
692 /************************************************
693 * Global variables
694 ************************************************/
696 /* Enumerated device names */
697 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
699 static al_string alcAllDevicesList;
700 static al_string alcCaptureDeviceList;
702 /* Default is always the first in the list */
703 static ALCchar *alcDefaultAllDevicesSpecifier;
704 static ALCchar *alcCaptureDefaultDeviceSpecifier;
706 /* Default context extensions */
707 static const ALchar alExtList[] =
708 "AL_EXT_ALAW "
709 "AL_EXT_BFORMAT "
710 "AL_EXT_DOUBLE "
711 "AL_EXT_EXPONENT_DISTANCE "
712 "AL_EXT_FLOAT32 "
713 "AL_EXT_IMA4 "
714 "AL_EXT_LINEAR_DISTANCE "
715 "AL_EXT_MCFORMATS "
716 "AL_EXT_MULAW "
717 "AL_EXT_MULAW_BFORMAT "
718 "AL_EXT_MULAW_MCFORMATS "
719 "AL_EXT_OFFSET "
720 "AL_EXT_source_distance_model "
721 "AL_EXT_SOURCE_RADIUS "
722 "AL_EXT_STEREO_ANGLES "
723 "AL_LOKI_quadriphonic "
724 "AL_SOFT_block_alignment "
725 "AL_SOFT_deferred_updates "
726 "AL_SOFT_direct_channels "
727 "AL_SOFTX_events "
728 "AL_SOFT_gain_clamp_ex "
729 "AL_SOFT_loop_points "
730 "AL_SOFTX_map_buffer "
731 "AL_SOFT_MSADPCM "
732 "AL_SOFT_source_latency "
733 "AL_SOFT_source_length "
734 "AL_SOFT_source_resampler "
735 "AL_SOFT_source_spatialize";
737 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
739 /* Thread-local current context */
740 static altss_t LocalContext;
741 /* Process-wide current context */
742 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
744 /* Mixing thread piority level */
745 ALint RTPrioLevel;
747 FILE *LogFile;
748 #ifdef _DEBUG
749 enum LogLevel LogLevel = LogWarning;
750 #else
751 enum LogLevel LogLevel = LogError;
752 #endif
754 /* Flag to trap ALC device errors */
755 static ALCboolean TrapALCError = ALC_FALSE;
757 /* One-time configuration init control */
758 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
760 /* Default effect that applies to sources that don't have an effect on send 0 */
761 static ALeffect DefaultEffect;
763 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
764 * updates.
766 static ALCboolean SuspendDefers = ALC_TRUE;
769 /************************************************
770 * ALC information
771 ************************************************/
772 static const ALCchar alcNoDeviceExtList[] =
773 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
774 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
775 static const ALCchar alcExtensionList[] =
776 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
777 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
778 "ALC_EXT_thread_local_context ALC_SOFT_device_clock ALC_SOFT_HRTF "
779 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
780 static const ALCint alcMajorVersion = 1;
781 static const ALCint alcMinorVersion = 1;
783 static const ALCint alcEFXMajorVersion = 1;
784 static const ALCint alcEFXMinorVersion = 0;
787 /************************************************
788 * Device lists
789 ************************************************/
790 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
792 static almtx_t ListLock;
793 static inline void LockLists(void)
795 int ret = almtx_lock(&ListLock);
796 assert(ret == althrd_success);
798 static inline void UnlockLists(void)
800 int ret = almtx_unlock(&ListLock);
801 assert(ret == althrd_success);
804 /************************************************
805 * Library initialization
806 ************************************************/
807 #if defined(_WIN32)
808 static void alc_init(void);
809 static void alc_deinit(void);
810 static void alc_deinit_safe(void);
812 #ifndef AL_LIBTYPE_STATIC
813 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
815 switch(reason)
817 case DLL_PROCESS_ATTACH:
818 /* Pin the DLL so we won't get unloaded until the process terminates */
819 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
820 (WCHAR*)hModule, &hModule);
821 alc_init();
822 break;
824 case DLL_THREAD_DETACH:
825 althrd_thread_detach();
826 break;
828 case DLL_PROCESS_DETACH:
829 if(!lpReserved)
830 alc_deinit();
831 else
832 alc_deinit_safe();
833 break;
835 return TRUE;
837 #elif defined(_MSC_VER)
838 #pragma section(".CRT$XCU",read)
839 static void alc_constructor(void);
840 static void alc_destructor(void);
841 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
843 static void alc_constructor(void)
845 atexit(alc_destructor);
846 alc_init();
849 static void alc_destructor(void)
851 alc_deinit();
853 #elif defined(HAVE_GCC_DESTRUCTOR)
854 static void alc_init(void) __attribute__((constructor));
855 static void alc_deinit(void) __attribute__((destructor));
856 #else
857 #error "No static initialization available on this platform!"
858 #endif
860 #elif defined(HAVE_GCC_DESTRUCTOR)
862 static void alc_init(void) __attribute__((constructor));
863 static void alc_deinit(void) __attribute__((destructor));
865 #else
866 #error "No global initialization available on this platform!"
867 #endif
869 static void ReleaseThreadCtx(void *ptr);
870 static void alc_init(void)
872 const char *str;
873 int ret;
875 LogFile = stderr;
877 AL_STRING_INIT(alcAllDevicesList);
878 AL_STRING_INIT(alcCaptureDeviceList);
880 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
881 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
882 ConeScale *= 0.5f;
884 str = getenv("__ALSOFT_REVERSE_Z");
885 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
886 ZScale *= -1.0f;
888 str = getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
889 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
890 OverrideReverbSpeedOfSound = AL_TRUE;
892 ret = altss_create(&LocalContext, ReleaseThreadCtx);
893 assert(ret == althrd_success);
895 ret = almtx_init(&ListLock, almtx_recursive);
896 assert(ret == althrd_success);
899 static void alc_initconfig(void)
901 const char *devs, *str;
902 int capfilter;
903 float valf;
904 int i, n;
906 str = getenv("ALSOFT_LOGLEVEL");
907 if(str)
909 long lvl = strtol(str, NULL, 0);
910 if(lvl >= NoLog && lvl <= LogRef)
911 LogLevel = lvl;
914 str = getenv("ALSOFT_LOGFILE");
915 if(str && str[0])
917 FILE *logfile = al_fopen(str, "wt");
918 if(logfile) LogFile = logfile;
919 else ERR("Failed to open log file '%s'\n", str);
922 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION,
923 ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH);
925 char buf[1024] = "";
926 int len = 0;
928 if(BackendListSize > 0)
929 len += snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
930 for(i = 1;i < BackendListSize;i++)
931 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
932 TRACE("Supported backends: %s\n", buf);
934 ReadALConfig();
936 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
937 if(str && *str)
939 if(strcasecmp(str, "ignore") == 0)
941 SuspendDefers = ALC_FALSE;
942 TRACE("Selected context suspend behavior, \"ignore\"\n");
944 else
945 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
948 capfilter = 0;
949 #if defined(HAVE_SSE4_1)
950 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
951 #elif defined(HAVE_SSE3)
952 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
953 #elif defined(HAVE_SSE2)
954 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
955 #elif defined(HAVE_SSE)
956 capfilter |= CPU_CAP_SSE;
957 #endif
958 #ifdef HAVE_NEON
959 capfilter |= CPU_CAP_NEON;
960 #endif
961 if(ConfigValueStr(NULL, NULL, "disable-cpu-exts", &str))
963 if(strcasecmp(str, "all") == 0)
964 capfilter = 0;
965 else
967 size_t len;
968 const char *next = str;
970 do {
971 str = next;
972 while(isspace(str[0]))
973 str++;
974 next = strchr(str, ',');
976 if(!str[0] || str[0] == ',')
977 continue;
979 len = (next ? ((size_t)(next-str)) : strlen(str));
980 while(len > 0 && isspace(str[len-1]))
981 len--;
982 if(len == 3 && strncasecmp(str, "sse", len) == 0)
983 capfilter &= ~CPU_CAP_SSE;
984 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
985 capfilter &= ~CPU_CAP_SSE2;
986 else if(len == 4 && strncasecmp(str, "sse3", len) == 0)
987 capfilter &= ~CPU_CAP_SSE3;
988 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
989 capfilter &= ~CPU_CAP_SSE4_1;
990 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
991 capfilter &= ~CPU_CAP_NEON;
992 else
993 WARN("Invalid CPU extension \"%s\"\n", str);
994 } while(next++);
997 FillCPUCaps(capfilter);
999 #ifdef _WIN32
1000 RTPrioLevel = 1;
1001 #else
1002 RTPrioLevel = 0;
1003 #endif
1004 ConfigValueInt(NULL, NULL, "rt-prio", &RTPrioLevel);
1006 aluInit();
1007 aluInitMixer();
1009 str = getenv("ALSOFT_TRAP_ERROR");
1010 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1012 TrapALError = AL_TRUE;
1013 TrapALCError = AL_TRUE;
1015 else
1017 str = getenv("ALSOFT_TRAP_AL_ERROR");
1018 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1019 TrapALError = AL_TRUE;
1020 TrapALError = GetConfigValueBool(NULL, NULL, "trap-al-error", TrapALError);
1022 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1023 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1024 TrapALCError = ALC_TRUE;
1025 TrapALCError = GetConfigValueBool(NULL, NULL, "trap-alc-error", TrapALCError);
1028 if(ConfigValueFloat(NULL, "reverb", "boost", &valf))
1029 ReverbBoost *= powf(10.0f, valf / 20.0f);
1031 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1032 ConfigValueStr(NULL, NULL, "drivers", &devs))
1034 int n;
1035 size_t len;
1036 const char *next = devs;
1037 int endlist, delitem;
1039 i = 0;
1040 do {
1041 devs = next;
1042 while(isspace(devs[0]))
1043 devs++;
1044 next = strchr(devs, ',');
1046 delitem = (devs[0] == '-');
1047 if(devs[0] == '-') devs++;
1049 if(!devs[0] || devs[0] == ',')
1051 endlist = 0;
1052 continue;
1054 endlist = 1;
1056 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1057 while(len > 0 && isspace(devs[len-1]))
1058 len--;
1059 #ifdef HAVE_WASAPI
1060 /* HACK: For backwards compatibility, convert backend references of
1061 * mmdevapi to wasapi. This should eventually be removed.
1063 if(len == 8 && strncmp(devs, "mmdevapi", len) == 0)
1065 devs = "wasapi";
1066 len = 6;
1068 #endif
1069 for(n = i;n < BackendListSize;n++)
1071 if(len == strlen(BackendList[n].name) &&
1072 strncmp(BackendList[n].name, devs, len) == 0)
1074 if(delitem)
1076 for(;n+1 < BackendListSize;n++)
1077 BackendList[n] = BackendList[n+1];
1078 BackendListSize--;
1080 else
1082 struct BackendInfo Bkp = BackendList[n];
1083 for(;n > i;n--)
1084 BackendList[n] = BackendList[n-1];
1085 BackendList[n] = Bkp;
1087 i++;
1089 break;
1092 } while(next++);
1094 if(endlist)
1095 BackendListSize = i;
1098 for(n = i = 0;i < BackendListSize && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1100 ALCbackendFactory *factory;
1101 BackendList[n] = BackendList[i];
1103 factory = BackendList[n].getFactory();
1104 if(!V0(factory,init)())
1106 WARN("Failed to initialize backend \"%s\"\n", BackendList[n].name);
1107 continue;
1110 TRACE("Initialized backend \"%s\"\n", BackendList[n].name);
1111 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1113 PlaybackBackend = BackendList[n];
1114 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1116 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1118 CaptureBackend = BackendList[n];
1119 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1121 n++;
1123 BackendListSize = n;
1126 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1127 V0(factory,init)();
1130 if(!PlaybackBackend.name)
1131 WARN("No playback backend available!\n");
1132 if(!CaptureBackend.name)
1133 WARN("No capture backend available!\n");
1135 if(ConfigValueStr(NULL, NULL, "excludefx", &str))
1137 size_t len;
1138 const char *next = str;
1140 do {
1141 str = next;
1142 next = strchr(str, ',');
1144 if(!str[0] || next == str)
1145 continue;
1147 len = (next ? ((size_t)(next-str)) : strlen(str));
1148 for(n = 0;n < EFFECTLIST_SIZE;n++)
1150 if(len == strlen(EffectList[n].name) &&
1151 strncmp(EffectList[n].name, str, len) == 0)
1152 DisabledEffects[EffectList[n].type] = AL_TRUE;
1154 } while(next++);
1157 InitEffect(&DefaultEffect);
1158 str = getenv("ALSOFT_DEFAULT_REVERB");
1159 if((str && str[0]) || ConfigValueStr(NULL, NULL, "default-reverb", &str))
1160 LoadReverbPreset(str, &DefaultEffect);
1162 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1164 #ifdef __ANDROID__
1165 #include <jni.h>
1167 static JavaVM *gJavaVM;
1168 static pthread_key_t gJVMThreadKey;
1170 static void CleanupJNIEnv(void* UNUSED(ptr))
1172 JCALL0(gJavaVM,DetachCurrentThread)();
1175 void *Android_GetJNIEnv(void)
1177 if(!gJavaVM)
1179 WARN("gJavaVM is NULL!\n");
1180 return NULL;
1183 /* http://developer.android.com/guide/practices/jni.html
1185 * All threads are Linux threads, scheduled by the kernel. They're usually
1186 * started from managed code (using Thread.start), but they can also be
1187 * created elsewhere and then attached to the JavaVM. For example, a thread
1188 * started with pthread_create can be attached with the JNI
1189 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1190 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1191 * Attaching a natively-created thread causes a java.lang.Thread object to
1192 * be constructed and added to the "main" ThreadGroup, making it visible to
1193 * the debugger. Calling AttachCurrentThread on an already-attached thread
1194 * is a no-op.
1196 JNIEnv *env = pthread_getspecific(gJVMThreadKey);
1197 if(!env)
1199 int status = JCALL(gJavaVM,AttachCurrentThread)(&env, NULL);
1200 if(status < 0)
1202 ERR("Failed to attach current thread\n");
1203 return NULL;
1205 pthread_setspecific(gJVMThreadKey, env);
1207 return env;
1210 /* Automatically called by JNI. */
1211 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void* UNUSED(reserved))
1213 void *env;
1214 int err;
1216 gJavaVM = jvm;
1217 if(JCALL(gJavaVM,GetEnv)(&env, JNI_VERSION_1_4) != JNI_OK)
1219 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1220 return JNI_ERR;
1223 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1224 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1226 if((err=pthread_key_create(&gJVMThreadKey, CleanupJNIEnv)) != 0)
1227 ERR("pthread_key_create failed: %d\n", err);
1228 pthread_setspecific(gJVMThreadKey, env);
1229 return JNI_VERSION_1_4;
1231 #endif
1234 /************************************************
1235 * Library deinitialization
1236 ************************************************/
1237 static void alc_cleanup(void)
1239 ALCdevice *dev;
1241 AL_STRING_DEINIT(alcAllDevicesList);
1242 AL_STRING_DEINIT(alcCaptureDeviceList);
1244 free(alcDefaultAllDevicesSpecifier);
1245 alcDefaultAllDevicesSpecifier = NULL;
1246 free(alcCaptureDefaultDeviceSpecifier);
1247 alcCaptureDefaultDeviceSpecifier = NULL;
1249 if((dev=ATOMIC_EXCHANGE_PTR_SEQ(&DeviceList, NULL)) != NULL)
1251 ALCuint num = 0;
1252 do {
1253 num++;
1254 dev = ATOMIC_LOAD(&dev->next, almemory_order_relaxed);
1255 } while(dev != NULL);
1256 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1260 static void alc_deinit_safe(void)
1262 alc_cleanup();
1264 FreeHrtfs();
1265 FreeALConfig();
1267 almtx_destroy(&ListLock);
1268 altss_delete(LocalContext);
1270 if(LogFile != stderr)
1271 fclose(LogFile);
1272 LogFile = NULL;
1274 althrd_deinit();
1277 static void alc_deinit(void)
1279 int i;
1281 alc_cleanup();
1283 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1284 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1286 for(i = 0;i < BackendListSize;i++)
1288 ALCbackendFactory *factory = BackendList[i].getFactory();
1289 V0(factory,deinit)();
1292 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1293 V0(factory,deinit)();
1296 alc_deinit_safe();
1300 /************************************************
1301 * Device enumeration
1302 ************************************************/
1303 static void ProbeDevices(al_string *list, struct BackendInfo *backendinfo, enum DevProbe type)
1305 DO_INITCONFIG();
1307 LockLists();
1308 alstr_clear(list);
1310 if(backendinfo->getFactory)
1312 ALCbackendFactory *factory = backendinfo->getFactory();
1313 V(factory,probe)(type);
1316 UnlockLists();
1318 static void ProbeAllDevicesList(void)
1319 { ProbeDevices(&alcAllDevicesList, &PlaybackBackend, ALL_DEVICE_PROBE); }
1320 static void ProbeCaptureDeviceList(void)
1321 { ProbeDevices(&alcCaptureDeviceList, &CaptureBackend, CAPTURE_DEVICE_PROBE); }
1323 static void AppendDevice(const ALCchar *name, al_string *devnames)
1325 size_t len = strlen(name);
1326 if(len > 0)
1327 alstr_append_range(devnames, name, name+len+1);
1329 void AppendAllDevicesList(const ALCchar *name)
1330 { AppendDevice(name, &alcAllDevicesList); }
1331 void AppendCaptureDeviceList(const ALCchar *name)
1332 { AppendDevice(name, &alcCaptureDeviceList); }
1335 /************************************************
1336 * Device format information
1337 ************************************************/
1338 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1340 switch(type)
1342 case DevFmtByte: return "Signed Byte";
1343 case DevFmtUByte: return "Unsigned Byte";
1344 case DevFmtShort: return "Signed Short";
1345 case DevFmtUShort: return "Unsigned Short";
1346 case DevFmtInt: return "Signed Int";
1347 case DevFmtUInt: return "Unsigned Int";
1348 case DevFmtFloat: return "Float";
1350 return "(unknown type)";
1352 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1354 switch(chans)
1356 case DevFmtMono: return "Mono";
1357 case DevFmtStereo: return "Stereo";
1358 case DevFmtQuad: return "Quadraphonic";
1359 case DevFmtX51: return "5.1 Surround";
1360 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1361 case DevFmtX61: return "6.1 Surround";
1362 case DevFmtX71: return "7.1 Surround";
1363 case DevFmtAmbi3D: return "Ambisonic 3D";
1365 return "(unknown channels)";
1368 extern inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type, ALsizei ambiorder);
1369 ALsizei BytesFromDevFmt(enum DevFmtType type)
1371 switch(type)
1373 case DevFmtByte: return sizeof(ALbyte);
1374 case DevFmtUByte: return sizeof(ALubyte);
1375 case DevFmtShort: return sizeof(ALshort);
1376 case DevFmtUShort: return sizeof(ALushort);
1377 case DevFmtInt: return sizeof(ALint);
1378 case DevFmtUInt: return sizeof(ALuint);
1379 case DevFmtFloat: return sizeof(ALfloat);
1381 return 0;
1383 ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans, ALsizei ambiorder)
1385 switch(chans)
1387 case DevFmtMono: return 1;
1388 case DevFmtStereo: return 2;
1389 case DevFmtQuad: return 4;
1390 case DevFmtX51: return 6;
1391 case DevFmtX51Rear: return 6;
1392 case DevFmtX61: return 7;
1393 case DevFmtX71: return 8;
1394 case DevFmtAmbi3D: return (ambiorder >= 3) ? 16 :
1395 (ambiorder == 2) ? 9 :
1396 (ambiorder == 1) ? 4 : 1;
1398 return 0;
1401 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1402 enum DevFmtType *type)
1404 static const struct {
1405 ALenum format;
1406 enum DevFmtChannels channels;
1407 enum DevFmtType type;
1408 } list[] = {
1409 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1410 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1411 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1413 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1414 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1415 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1417 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1418 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1419 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1421 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1422 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1423 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1425 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1426 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1427 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1429 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1430 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1431 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1433 ALuint i;
1435 for(i = 0;i < COUNTOF(list);i++)
1437 if(list[i].format == format)
1439 *chans = list[i].channels;
1440 *type = list[i].type;
1441 return AL_TRUE;
1445 return AL_FALSE;
1448 static ALCboolean IsValidALCType(ALCenum type)
1450 switch(type)
1452 case ALC_BYTE_SOFT:
1453 case ALC_UNSIGNED_BYTE_SOFT:
1454 case ALC_SHORT_SOFT:
1455 case ALC_UNSIGNED_SHORT_SOFT:
1456 case ALC_INT_SOFT:
1457 case ALC_UNSIGNED_INT_SOFT:
1458 case ALC_FLOAT_SOFT:
1459 return ALC_TRUE;
1461 return ALC_FALSE;
1464 static ALCboolean IsValidALCChannels(ALCenum channels)
1466 switch(channels)
1468 case ALC_MONO_SOFT:
1469 case ALC_STEREO_SOFT:
1470 case ALC_QUAD_SOFT:
1471 case ALC_5POINT1_SOFT:
1472 case ALC_6POINT1_SOFT:
1473 case ALC_7POINT1_SOFT:
1474 case ALC_BFORMAT3D_SOFT:
1475 return ALC_TRUE;
1477 return ALC_FALSE;
1480 static ALCboolean IsValidAmbiLayout(ALCenum layout)
1482 switch(layout)
1484 case ALC_ACN_SOFT:
1485 case ALC_FUMA_SOFT:
1486 return ALC_TRUE;
1488 return ALC_FALSE;
1491 static ALCboolean IsValidAmbiScaling(ALCenum scaling)
1493 switch(scaling)
1495 case ALC_N3D_SOFT:
1496 case ALC_SN3D_SOFT:
1497 case ALC_FUMA_SOFT:
1498 return ALC_TRUE;
1500 return ALC_FALSE;
1503 /************************************************
1504 * Miscellaneous ALC helpers
1505 ************************************************/
1507 /* SetDefaultWFXChannelOrder
1509 * Sets the default channel order used by WaveFormatEx.
1511 void SetDefaultWFXChannelOrder(ALCdevice *device)
1513 ALsizei i;
1515 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1516 device->RealOut.ChannelName[i] = InvalidChannel;
1518 switch(device->FmtChans)
1520 case DevFmtMono:
1521 device->RealOut.ChannelName[0] = FrontCenter;
1522 break;
1523 case DevFmtStereo:
1524 device->RealOut.ChannelName[0] = FrontLeft;
1525 device->RealOut.ChannelName[1] = FrontRight;
1526 break;
1527 case DevFmtQuad:
1528 device->RealOut.ChannelName[0] = FrontLeft;
1529 device->RealOut.ChannelName[1] = FrontRight;
1530 device->RealOut.ChannelName[2] = BackLeft;
1531 device->RealOut.ChannelName[3] = BackRight;
1532 break;
1533 case DevFmtX51:
1534 device->RealOut.ChannelName[0] = FrontLeft;
1535 device->RealOut.ChannelName[1] = FrontRight;
1536 device->RealOut.ChannelName[2] = FrontCenter;
1537 device->RealOut.ChannelName[3] = LFE;
1538 device->RealOut.ChannelName[4] = SideLeft;
1539 device->RealOut.ChannelName[5] = SideRight;
1540 break;
1541 case DevFmtX51Rear:
1542 device->RealOut.ChannelName[0] = FrontLeft;
1543 device->RealOut.ChannelName[1] = FrontRight;
1544 device->RealOut.ChannelName[2] = FrontCenter;
1545 device->RealOut.ChannelName[3] = LFE;
1546 device->RealOut.ChannelName[4] = BackLeft;
1547 device->RealOut.ChannelName[5] = BackRight;
1548 break;
1549 case DevFmtX61:
1550 device->RealOut.ChannelName[0] = FrontLeft;
1551 device->RealOut.ChannelName[1] = FrontRight;
1552 device->RealOut.ChannelName[2] = FrontCenter;
1553 device->RealOut.ChannelName[3] = LFE;
1554 device->RealOut.ChannelName[4] = BackCenter;
1555 device->RealOut.ChannelName[5] = SideLeft;
1556 device->RealOut.ChannelName[6] = SideRight;
1557 break;
1558 case DevFmtX71:
1559 device->RealOut.ChannelName[0] = FrontLeft;
1560 device->RealOut.ChannelName[1] = FrontRight;
1561 device->RealOut.ChannelName[2] = FrontCenter;
1562 device->RealOut.ChannelName[3] = LFE;
1563 device->RealOut.ChannelName[4] = BackLeft;
1564 device->RealOut.ChannelName[5] = BackRight;
1565 device->RealOut.ChannelName[6] = SideLeft;
1566 device->RealOut.ChannelName[7] = SideRight;
1567 break;
1568 case DevFmtAmbi3D:
1569 device->RealOut.ChannelName[0] = Aux0;
1570 if(device->AmbiOrder > 0)
1572 device->RealOut.ChannelName[1] = Aux1;
1573 device->RealOut.ChannelName[2] = Aux2;
1574 device->RealOut.ChannelName[3] = Aux3;
1576 if(device->AmbiOrder > 1)
1578 device->RealOut.ChannelName[4] = Aux4;
1579 device->RealOut.ChannelName[5] = Aux5;
1580 device->RealOut.ChannelName[6] = Aux6;
1581 device->RealOut.ChannelName[7] = Aux7;
1582 device->RealOut.ChannelName[8] = Aux8;
1584 if(device->AmbiOrder > 2)
1586 device->RealOut.ChannelName[9] = Aux9;
1587 device->RealOut.ChannelName[10] = Aux10;
1588 device->RealOut.ChannelName[11] = Aux11;
1589 device->RealOut.ChannelName[12] = Aux12;
1590 device->RealOut.ChannelName[13] = Aux13;
1591 device->RealOut.ChannelName[14] = Aux14;
1592 device->RealOut.ChannelName[15] = Aux15;
1594 break;
1598 /* SetDefaultChannelOrder
1600 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1602 void SetDefaultChannelOrder(ALCdevice *device)
1604 ALsizei i;
1606 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1607 device->RealOut.ChannelName[i] = InvalidChannel;
1609 switch(device->FmtChans)
1611 case DevFmtX51Rear:
1612 device->RealOut.ChannelName[0] = FrontLeft;
1613 device->RealOut.ChannelName[1] = FrontRight;
1614 device->RealOut.ChannelName[2] = BackLeft;
1615 device->RealOut.ChannelName[3] = BackRight;
1616 device->RealOut.ChannelName[4] = FrontCenter;
1617 device->RealOut.ChannelName[5] = LFE;
1618 return;
1619 case DevFmtX71:
1620 device->RealOut.ChannelName[0] = FrontLeft;
1621 device->RealOut.ChannelName[1] = FrontRight;
1622 device->RealOut.ChannelName[2] = BackLeft;
1623 device->RealOut.ChannelName[3] = BackRight;
1624 device->RealOut.ChannelName[4] = FrontCenter;
1625 device->RealOut.ChannelName[5] = LFE;
1626 device->RealOut.ChannelName[6] = SideLeft;
1627 device->RealOut.ChannelName[7] = SideRight;
1628 return;
1630 /* Same as WFX order */
1631 case DevFmtMono:
1632 case DevFmtStereo:
1633 case DevFmtQuad:
1634 case DevFmtX51:
1635 case DevFmtX61:
1636 case DevFmtAmbi3D:
1637 SetDefaultWFXChannelOrder(device);
1638 break;
1642 extern inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan);
1643 extern inline ALint GetChannelIdxByName(const RealMixParams *real, enum Channel chan);
1646 /* ALCcontext_DeferUpdates
1648 * Defers/suspends updates for the given context's listener and sources. This
1649 * does *NOT* stop mixing, but rather prevents certain property changes from
1650 * taking effect.
1652 void ALCcontext_DeferUpdates(ALCcontext *context)
1654 ATOMIC_STORE_SEQ(&context->DeferUpdates, AL_TRUE);
1657 /* ALCcontext_ProcessUpdates
1659 * Resumes update processing after being deferred.
1661 void ALCcontext_ProcessUpdates(ALCcontext *context)
1663 almtx_lock(&context->PropLock);
1664 if(ATOMIC_EXCHANGE_SEQ(&context->DeferUpdates, AL_FALSE))
1666 /* Tell the mixer to stop applying updates, then wait for any active
1667 * updating to finish, before providing updates.
1669 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_TRUE);
1670 while((ATOMIC_LOAD(&context->UpdateCount, almemory_order_acquire)&1) != 0)
1671 althrd_yield();
1673 if(!ATOMIC_FLAG_TEST_AND_SET(&context->PropsClean, almemory_order_acq_rel))
1674 UpdateContextProps(context);
1675 if(!ATOMIC_FLAG_TEST_AND_SET(&context->Listener->PropsClean, almemory_order_acq_rel))
1676 UpdateListenerProps(context);
1677 UpdateAllEffectSlotProps(context);
1678 UpdateAllSourceProps(context);
1680 /* Now with all updates declared, let the mixer continue applying them
1681 * so they all happen at once.
1683 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_FALSE);
1685 almtx_unlock(&context->PropLock);
1689 /* alcSetError
1691 * Stores the latest ALC device error
1693 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1695 WARN("Error generated on device %p, code 0x%04x\n", device, errorCode);
1696 if(TrapALCError)
1698 #ifdef _WIN32
1699 /* DebugBreak() will cause an exception if there is no debugger */
1700 if(IsDebuggerPresent())
1701 DebugBreak();
1702 #elif defined(SIGTRAP)
1703 raise(SIGTRAP);
1704 #endif
1707 if(device)
1708 ATOMIC_STORE_SEQ(&device->LastError, errorCode);
1709 else
1710 ATOMIC_STORE_SEQ(&LastNullDeviceError, errorCode);
1714 struct Compressor *CreateDeviceLimiter(const ALCdevice *device)
1716 return CompressorInit(0.0f, 0.0f, AL_FALSE, AL_TRUE, 0.0f, 0.0f, 0.5f, 2.0f,
1717 0.0f, -3.0f, 3.0f, device->Frequency);
1720 /* UpdateClockBase
1722 * Updates the device's base clock time with however many samples have been
1723 * done. This is used so frequency changes on the device don't cause the time
1724 * to jump forward or back. Must not be called while the device is running/
1725 * mixing.
1727 static inline void UpdateClockBase(ALCdevice *device)
1729 IncrementRef(&device->MixCount);
1730 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1731 device->SamplesDone = 0;
1732 IncrementRef(&device->MixCount);
1735 /* UpdateDeviceParams
1737 * Updates device parameters according to the attribute list (caller is
1738 * responsible for holding the list lock).
1740 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1742 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1743 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1744 ALCenum gainLimiter = device->Limiter ? ALC_TRUE : ALC_FALSE;
1745 const ALsizei old_sends = device->NumAuxSends;
1746 ALsizei new_sends = device->NumAuxSends;
1747 enum DevFmtChannels oldChans;
1748 enum DevFmtType oldType;
1749 ALboolean update_failed;
1750 ALCsizei hrtf_id = -1;
1751 ALCcontext *context;
1752 ALCuint oldFreq;
1753 size_t size;
1754 ALCsizei i;
1755 int val;
1757 // Check for attributes
1758 if(device->Type == Loopback)
1760 ALCsizei numMono, numStereo, numSends;
1761 ALCenum alayout = AL_NONE;
1762 ALCenum ascale = AL_NONE;
1763 ALCenum schans = AL_NONE;
1764 ALCenum stype = AL_NONE;
1765 ALCsizei attrIdx = 0;
1766 ALCsizei aorder = 0;
1767 ALCuint freq = 0;
1769 if(!attrList)
1771 WARN("Missing attributes for loopback device\n");
1772 return ALC_INVALID_VALUE;
1775 numMono = device->NumMonoSources;
1776 numStereo = device->NumStereoSources;
1777 numSends = old_sends;
1779 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1780 while(attrList[attrIdx])
1782 switch(attrList[attrIdx])
1784 case ALC_FORMAT_CHANNELS_SOFT:
1785 schans = attrList[attrIdx + 1];
1786 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1787 if(!IsValidALCChannels(schans))
1788 return ALC_INVALID_VALUE;
1789 break;
1791 case ALC_FORMAT_TYPE_SOFT:
1792 stype = attrList[attrIdx + 1];
1793 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1794 if(!IsValidALCType(stype))
1795 return ALC_INVALID_VALUE;
1796 break;
1798 case ALC_FREQUENCY:
1799 freq = attrList[attrIdx + 1];
1800 TRACE_ATTR(ALC_FREQUENCY, freq);
1801 if(freq < MIN_OUTPUT_RATE)
1802 return ALC_INVALID_VALUE;
1803 break;
1805 case ALC_AMBISONIC_LAYOUT_SOFT:
1806 alayout = attrList[attrIdx + 1];
1807 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1808 if(!IsValidAmbiLayout(alayout))
1809 return ALC_INVALID_VALUE;
1810 break;
1812 case ALC_AMBISONIC_SCALING_SOFT:
1813 ascale = attrList[attrIdx + 1];
1814 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1815 if(!IsValidAmbiScaling(ascale))
1816 return ALC_INVALID_VALUE;
1817 break;
1819 case ALC_AMBISONIC_ORDER_SOFT:
1820 aorder = attrList[attrIdx + 1];
1821 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1822 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1823 return ALC_INVALID_VALUE;
1824 break;
1826 case ALC_MONO_SOURCES:
1827 numMono = attrList[attrIdx + 1];
1828 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1829 numMono = maxi(numMono, 0);
1830 break;
1832 case ALC_STEREO_SOURCES:
1833 numStereo = attrList[attrIdx + 1];
1834 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1835 numStereo = maxi(numStereo, 0);
1836 break;
1838 case ALC_MAX_AUXILIARY_SENDS:
1839 numSends = attrList[attrIdx + 1];
1840 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1841 numSends = clampi(numSends, 0, MAX_SENDS);
1842 break;
1844 case ALC_HRTF_SOFT:
1845 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1846 if(attrList[attrIdx + 1] == ALC_FALSE)
1847 hrtf_appreq = Hrtf_Disable;
1848 else if(attrList[attrIdx + 1] == ALC_TRUE)
1849 hrtf_appreq = Hrtf_Enable;
1850 else
1851 hrtf_appreq = Hrtf_Default;
1852 break;
1854 case ALC_HRTF_ID_SOFT:
1855 hrtf_id = attrList[attrIdx + 1];
1856 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1857 break;
1859 case ALC_OUTPUT_LIMITER_SOFT:
1860 gainLimiter = attrList[attrIdx + 1];
1861 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1862 break;
1864 default:
1865 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList[attrIdx],
1866 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1867 break;
1870 attrIdx += 2;
1872 #undef TRACE_ATTR
1874 if(!schans || !stype || !freq)
1876 WARN("Missing format for loopback device\n");
1877 return ALC_INVALID_VALUE;
1879 if(schans == ALC_BFORMAT3D_SOFT && (!alayout || !ascale || !aorder))
1881 WARN("Missing ambisonic info for loopback device\n");
1882 return ALC_INVALID_VALUE;
1885 if((device->Flags&DEVICE_RUNNING))
1886 V0(device->Backend,stop)();
1887 device->Flags &= ~DEVICE_RUNNING;
1889 UpdateClockBase(device);
1891 device->Frequency = freq;
1892 device->FmtChans = schans;
1893 device->FmtType = stype;
1894 if(schans == ALC_BFORMAT3D_SOFT)
1896 device->AmbiOrder = aorder;
1897 device->AmbiLayout = alayout;
1898 device->AmbiScale = ascale;
1901 if(numMono > INT_MAX-numStereo)
1902 numMono = INT_MAX-numStereo;
1903 numMono += numStereo;
1904 if(ConfigValueInt(NULL, NULL, "sources", &numMono))
1906 if(numMono <= 0)
1907 numMono = 256;
1909 else
1910 numMono = maxi(numMono, 256);
1911 numStereo = mini(numStereo, numMono);
1912 numMono -= numStereo;
1913 device->SourcesMax = numMono + numStereo;
1915 device->NumMonoSources = numMono;
1916 device->NumStereoSources = numStereo;
1918 if(ConfigValueInt(NULL, NULL, "sends", &new_sends))
1919 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1920 else
1921 new_sends = numSends;
1923 else if(attrList && attrList[0])
1925 ALCsizei numMono, numStereo, numSends;
1926 ALCsizei attrIdx = 0;
1927 ALCuint freq;
1929 /* If a context is already running on the device, stop playback so the
1930 * device attributes can be updated. */
1931 if((device->Flags&DEVICE_RUNNING))
1932 V0(device->Backend,stop)();
1933 device->Flags &= ~DEVICE_RUNNING;
1935 UpdateClockBase(device);
1937 freq = device->Frequency;
1938 numMono = device->NumMonoSources;
1939 numStereo = device->NumStereoSources;
1940 numSends = old_sends;
1942 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1943 while(attrList[attrIdx])
1945 switch(attrList[attrIdx])
1947 case ALC_FREQUENCY:
1948 freq = attrList[attrIdx + 1];
1949 TRACE_ATTR(ALC_FREQUENCY, freq);
1950 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1951 break;
1953 case ALC_MONO_SOURCES:
1954 numMono = attrList[attrIdx + 1];
1955 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1956 numMono = maxi(numMono, 0);
1957 break;
1959 case ALC_STEREO_SOURCES:
1960 numStereo = attrList[attrIdx + 1];
1961 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1962 numStereo = maxi(numStereo, 0);
1963 break;
1965 case ALC_MAX_AUXILIARY_SENDS:
1966 numSends = attrList[attrIdx + 1];
1967 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1968 numSends = clampi(numSends, 0, MAX_SENDS);
1969 break;
1971 case ALC_HRTF_SOFT:
1972 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1973 if(attrList[attrIdx + 1] == ALC_FALSE)
1974 hrtf_appreq = Hrtf_Disable;
1975 else if(attrList[attrIdx + 1] == ALC_TRUE)
1976 hrtf_appreq = Hrtf_Enable;
1977 else
1978 hrtf_appreq = Hrtf_Default;
1979 break;
1981 case ALC_HRTF_ID_SOFT:
1982 hrtf_id = attrList[attrIdx + 1];
1983 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1984 break;
1986 case ALC_OUTPUT_LIMITER_SOFT:
1987 gainLimiter = attrList[attrIdx + 1];
1988 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1989 break;
1991 default:
1992 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1993 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1994 break;
1997 attrIdx += 2;
1999 #undef TRACE_ATTR
2001 ConfigValueUInt(alstr_get_cstr(device->DeviceName), NULL, "frequency", &freq);
2002 freq = maxu(freq, MIN_OUTPUT_RATE);
2004 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
2005 device->Frequency;
2006 /* SSE and Neon do best with the update size being a multiple of 4 */
2007 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
2008 device->UpdateSize = (device->UpdateSize+3)&~3;
2010 device->Frequency = freq;
2012 if(numMono > INT_MAX-numStereo)
2013 numMono = INT_MAX-numStereo;
2014 numMono += numStereo;
2015 if(ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "sources", &numMono))
2017 if(numMono <= 0)
2018 numMono = 256;
2020 else
2021 numMono = maxi(numMono, 256);
2022 numStereo = mini(numStereo, numMono);
2023 numMono -= numStereo;
2024 device->SourcesMax = numMono + numStereo;
2026 device->NumMonoSources = numMono;
2027 device->NumStereoSources = numStereo;
2029 if(ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "sends", &new_sends))
2030 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
2031 else
2032 new_sends = numSends;
2035 if((device->Flags&DEVICE_RUNNING))
2036 return ALC_NO_ERROR;
2038 al_free(device->Uhj_Encoder);
2039 device->Uhj_Encoder = NULL;
2041 al_free(device->Bs2b);
2042 device->Bs2b = NULL;
2044 al_free(device->ChannelDelay[0].Buffer);
2045 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2047 device->ChannelDelay[i].Length = 0;
2048 device->ChannelDelay[i].Buffer = NULL;
2051 al_free(device->Dry.Buffer);
2052 device->Dry.Buffer = NULL;
2053 device->Dry.NumChannels = 0;
2054 device->FOAOut.Buffer = NULL;
2055 device->FOAOut.NumChannels = 0;
2056 device->RealOut.Buffer = NULL;
2057 device->RealOut.NumChannels = 0;
2059 UpdateClockBase(device);
2061 device->DitherSeed = DITHER_RNG_SEED;
2063 /*************************************************************************
2064 * Update device format request if HRTF is requested
2066 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
2067 if(device->Type != Loopback)
2069 const char *hrtf;
2070 if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "hrtf", &hrtf))
2072 if(strcasecmp(hrtf, "true") == 0)
2073 hrtf_userreq = Hrtf_Enable;
2074 else if(strcasecmp(hrtf, "false") == 0)
2075 hrtf_userreq = Hrtf_Disable;
2076 else if(strcasecmp(hrtf, "auto") != 0)
2077 ERR("Unexpected hrtf value: %s\n", hrtf);
2080 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
2082 struct Hrtf *hrtf = NULL;
2083 if(VECTOR_SIZE(device->HrtfList) == 0)
2085 VECTOR_DEINIT(device->HrtfList);
2086 device->HrtfList = EnumerateHrtf(device->DeviceName);
2088 if(VECTOR_SIZE(device->HrtfList) > 0)
2090 if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->HrtfList))
2091 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, hrtf_id).hrtf);
2092 else
2093 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, 0).hrtf);
2096 if(hrtf)
2098 device->FmtChans = DevFmtStereo;
2099 device->Frequency = hrtf->sampleRate;
2100 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
2101 if(device->HrtfHandle)
2102 Hrtf_DecRef(device->HrtfHandle);
2103 device->HrtfHandle = hrtf;
2105 else
2107 hrtf_userreq = Hrtf_Default;
2108 hrtf_appreq = Hrtf_Disable;
2109 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2114 oldFreq = device->Frequency;
2115 oldChans = device->FmtChans;
2116 oldType = device->FmtType;
2118 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2119 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
2120 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
2121 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
2122 device->UpdateSize, device->NumUpdates
2125 if(V0(device->Backend,reset)() == ALC_FALSE)
2126 return ALC_INVALID_DEVICE;
2128 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
2130 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2131 DevFmtChannelsString(device->FmtChans));
2132 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2134 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2136 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2137 DevFmtTypeString(device->FmtType));
2138 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2140 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2142 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2143 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2146 if((device->UpdateSize&3) != 0)
2148 if((CPUCapFlags&CPU_CAP_SSE))
2149 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2150 if((CPUCapFlags&CPU_CAP_NEON))
2151 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2154 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2155 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2156 device->Frequency, device->UpdateSize, device->NumUpdates
2159 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2160 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device->Dry.NumChannels,
2161 device->FOAOut.NumChannels, device->RealOut.NumChannels);
2163 /* Allocate extra channels for any post-filter output. */
2164 size = (device->Dry.NumChannels + device->FOAOut.NumChannels +
2165 device->RealOut.NumChannels)*sizeof(device->Dry.Buffer[0]);
2167 TRACE("Allocating "SZFMT" channels, "SZFMT" bytes\n", size/sizeof(device->Dry.Buffer[0]), size);
2168 device->Dry.Buffer = al_calloc(16, size);
2169 if(!device->Dry.Buffer)
2171 ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
2172 return ALC_INVALID_DEVICE;
2175 if(device->RealOut.NumChannels != 0)
2176 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels +
2177 device->FOAOut.NumChannels;
2178 else
2180 device->RealOut.Buffer = device->Dry.Buffer;
2181 device->RealOut.NumChannels = device->Dry.NumChannels;
2184 if(device->FOAOut.NumChannels != 0)
2185 device->FOAOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2186 else
2188 device->FOAOut.Buffer = device->Dry.Buffer;
2189 device->FOAOut.NumChannels = device->Dry.NumChannels;
2192 device->NumAuxSends = new_sends;
2193 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2194 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
2195 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
2197 device->DitherDepth = 0.0f;
2198 if(GetConfigValueBool(alstr_get_cstr(device->DeviceName), NULL, "dither", 1))
2200 ALint depth = 0;
2201 ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "dither-depth", &depth);
2202 if(depth <= 0)
2204 switch(device->FmtType)
2206 case DevFmtByte:
2207 case DevFmtUByte:
2208 depth = 8;
2209 break;
2210 case DevFmtShort:
2211 case DevFmtUShort:
2212 depth = 16;
2213 break;
2214 case DevFmtInt:
2215 case DevFmtUInt:
2216 case DevFmtFloat:
2217 break;
2221 if(depth > 0)
2223 depth = clampi(depth, 2, 20);
2224 device->DitherDepth = powf(2.0f, (ALfloat)(depth-1));
2227 if(!(device->DitherDepth > 0.0f))
2228 TRACE("Dithering disabled\n");
2229 else
2230 TRACE("Dithering enabled (%g-bit, %g)\n", log2f(device->DitherDepth)+1.0f,
2231 device->DitherDepth);
2233 if(ConfigValueBool(alstr_get_cstr(device->DeviceName), NULL, "output-limiter", &val))
2234 gainLimiter = val ? ALC_TRUE : ALC_FALSE;
2235 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2236 * ALC_FALSE. We default to on, so ALC_DONT_CARE_SOFT is the same as
2237 * ALC_TRUE.
2239 if(gainLimiter != ALC_FALSE)
2241 if(!device->Limiter || device->Frequency != GetCompressorSampleRate(device->Limiter))
2243 al_free(device->Limiter);
2244 device->Limiter = CreateDeviceLimiter(device);
2247 else
2249 al_free(device->Limiter);
2250 device->Limiter = NULL;
2252 TRACE("Output limiter %s\n", device->Limiter ? "enabled" : "disabled");
2254 aluSelectPostProcess(device);
2256 /* Need to delay returning failure until replacement Send arrays have been
2257 * allocated with the appropriate size.
2259 update_failed = AL_FALSE;
2260 START_MIXER_MODE();
2261 context = ATOMIC_LOAD_SEQ(&device->ContextList);
2262 while(context)
2264 SourceSubList *sublist, *subend;
2265 struct ALvoiceProps *vprops;
2266 ALsizei pos;
2268 if(context->DefaultSlot)
2270 ALeffectslot *slot = context->DefaultSlot;
2271 ALeffectState *state = slot->Effect.State;
2273 state->OutBuffer = device->Dry.Buffer;
2274 state->OutChannels = device->Dry.NumChannels;
2275 if(V(state,deviceUpdate)(device) == AL_FALSE)
2276 update_failed = AL_TRUE;
2277 else
2278 UpdateEffectSlotProps(slot, context);
2281 almtx_lock(&context->PropLock);
2282 almtx_lock(&context->EffectSlotLock);
2283 for(pos = 0;pos < (ALsizei)VECTOR_SIZE(context->EffectSlotList);pos++)
2285 ALeffectslot *slot = VECTOR_ELEM(context->EffectSlotList, pos);
2286 ALeffectState *state = slot->Effect.State;
2288 state->OutBuffer = device->Dry.Buffer;
2289 state->OutChannels = device->Dry.NumChannels;
2290 if(V(state,deviceUpdate)(device) == AL_FALSE)
2291 update_failed = AL_TRUE;
2292 else
2293 UpdateEffectSlotProps(slot, context);
2295 almtx_unlock(&context->EffectSlotLock);
2297 almtx_lock(&context->SourceLock);
2298 sublist = VECTOR_BEGIN(context->SourceList);
2299 subend = VECTOR_END(context->SourceList);
2300 for(;sublist != subend;++sublist)
2302 ALuint64 usemask = ~sublist->FreeMask;
2303 while(usemask)
2305 ALsizei idx = CTZ64(usemask);
2306 ALsource *source = sublist->Sources + idx;
2308 usemask &= ~(U64(1) << idx);
2310 if(old_sends != device->NumAuxSends)
2312 ALvoid *sends = al_calloc(16, device->NumAuxSends*sizeof(source->Send[0]));
2313 ALsizei s;
2315 memcpy(sends, source->Send,
2316 mini(device->NumAuxSends, old_sends)*sizeof(source->Send[0])
2318 for(s = device->NumAuxSends;s < old_sends;s++)
2320 if(source->Send[s].Slot)
2321 DecrementRef(&source->Send[s].Slot->ref);
2322 source->Send[s].Slot = NULL;
2324 al_free(source->Send);
2325 source->Send = sends;
2326 for(s = old_sends;s < device->NumAuxSends;s++)
2328 source->Send[s].Slot = NULL;
2329 source->Send[s].Gain = 1.0f;
2330 source->Send[s].GainHF = 1.0f;
2331 source->Send[s].HFReference = LOWPASSFREQREF;
2332 source->Send[s].GainLF = 1.0f;
2333 source->Send[s].LFReference = HIGHPASSFREQREF;
2337 ATOMIC_FLAG_CLEAR(&source->PropsClean, almemory_order_release);
2341 /* Clear any pre-existing voice property structs, in case the number of
2342 * auxiliary sends is changing. Active sources will have updates
2343 * respecified in UpdateAllSourceProps.
2345 vprops = ATOMIC_EXCHANGE_PTR(&context->FreeVoiceProps, NULL, almemory_order_acq_rel);
2346 while(vprops)
2348 struct ALvoiceProps *next = ATOMIC_LOAD(&vprops->next, almemory_order_relaxed);
2349 al_free(vprops);
2350 vprops = next;
2353 AllocateVoices(context, context->MaxVoices, old_sends);
2354 for(pos = 0;pos < context->VoiceCount;pos++)
2356 ALvoice *voice = context->Voices[pos];
2358 al_free(ATOMIC_EXCHANGE_PTR(&voice->Update, NULL, almemory_order_acq_rel));
2360 if(ATOMIC_LOAD(&voice->Source, almemory_order_acquire) == NULL)
2361 continue;
2363 if(device->AvgSpeakerDist > 0.0f)
2365 /* Reinitialize the NFC filters for new parameters. */
2366 ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
2367 (device->AvgSpeakerDist * device->Frequency);
2368 for(i = 0;i < voice->NumChannels;i++)
2369 NfcFilterCreate(&voice->Direct.Params[i].NFCtrlFilter, 0.0f, w1);
2372 almtx_unlock(&context->SourceLock);
2374 ATOMIC_FLAG_TEST_AND_SET(&context->PropsClean, almemory_order_release);
2375 UpdateContextProps(context);
2376 ATOMIC_FLAG_TEST_AND_SET(&context->Listener->PropsClean, almemory_order_release);
2377 UpdateListenerProps(context);
2378 UpdateAllSourceProps(context);
2379 almtx_unlock(&context->PropLock);
2381 context = ATOMIC_LOAD(&context->next, almemory_order_relaxed);
2383 END_MIXER_MODE();
2384 if(update_failed)
2385 return ALC_INVALID_DEVICE;
2387 if(!(device->Flags&DEVICE_PAUSED))
2389 if(V0(device->Backend,start)() == ALC_FALSE)
2390 return ALC_INVALID_DEVICE;
2391 device->Flags |= DEVICE_RUNNING;
2394 return ALC_NO_ERROR;
2398 static void InitDevice(ALCdevice *device, enum DeviceType type)
2400 ALsizei i;
2402 InitRef(&device->ref, 1);
2403 ATOMIC_INIT(&device->Connected, ALC_TRUE);
2404 device->Type = type;
2405 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
2407 device->Flags = 0;
2408 device->Render_Mode = NormalRender;
2409 device->AvgSpeakerDist = 0.0f;
2411 ATOMIC_INIT(&device->ContextList, NULL);
2413 device->ClockBase = 0;
2414 device->SamplesDone = 0;
2416 device->SourcesMax = 0;
2417 device->AuxiliaryEffectSlotMax = 0;
2418 device->NumAuxSends = 0;
2420 device->Dry.Buffer = NULL;
2421 device->Dry.NumChannels = 0;
2422 device->FOAOut.Buffer = NULL;
2423 device->FOAOut.NumChannels = 0;
2424 device->RealOut.Buffer = NULL;
2425 device->RealOut.NumChannels = 0;
2427 AL_STRING_INIT(device->DeviceName);
2429 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2431 device->ChannelDelay[i].Gain = 1.0f;
2432 device->ChannelDelay[i].Length = 0;
2433 device->ChannelDelay[i].Buffer = NULL;
2436 AL_STRING_INIT(device->HrtfName);
2437 VECTOR_INIT(device->HrtfList);
2438 device->HrtfHandle = NULL;
2439 device->Hrtf = NULL;
2440 device->Bs2b = NULL;
2441 device->Uhj_Encoder = NULL;
2442 device->AmbiDecoder = NULL;
2443 device->AmbiUp = NULL;
2444 device->Stablizer = NULL;
2445 device->Limiter = NULL;
2447 VECTOR_INIT(device->BufferList);
2448 almtx_init(&device->BufferLock, almtx_plain);
2450 VECTOR_INIT(device->EffectList);
2451 almtx_init(&device->EffectLock, almtx_plain);
2453 VECTOR_INIT(device->FilterList);
2454 almtx_init(&device->FilterLock, almtx_plain);
2456 almtx_init(&device->BackendLock, almtx_plain);
2457 device->Backend = NULL;
2459 ATOMIC_INIT(&device->next, NULL);
2462 /* FreeDevice
2464 * Frees the device structure, and destroys any objects the app failed to
2465 * delete. Called once there's no more references on the device.
2467 static ALCvoid FreeDevice(ALCdevice *device)
2469 ALsizei i;
2471 TRACE("%p\n", device);
2473 if(device->Backend)
2474 DELETE_OBJ(device->Backend);
2475 device->Backend = NULL;
2477 almtx_destroy(&device->BackendLock);
2479 ReleaseALBuffers(device);
2480 #define FREE_BUFFERSUBLIST(x) al_free((x)->Buffers)
2481 VECTOR_FOR_EACH(BufferSubList, device->BufferList, FREE_BUFFERSUBLIST);
2482 #undef FREE_BUFFERSUBLIST
2483 VECTOR_DEINIT(device->BufferList);
2484 almtx_destroy(&device->BufferLock);
2486 ReleaseALEffects(device);
2487 #define FREE_EFFECTSUBLIST(x) al_free((x)->Effects)
2488 VECTOR_FOR_EACH(EffectSubList, device->EffectList, FREE_EFFECTSUBLIST);
2489 #undef FREE_EFFECTSUBLIST
2490 VECTOR_DEINIT(device->EffectList);
2491 almtx_destroy(&device->EffectLock);
2493 ReleaseALFilters(device);
2494 #define FREE_FILTERSUBLIST(x) al_free((x)->Filters)
2495 VECTOR_FOR_EACH(FilterSubList, device->FilterList, FREE_FILTERSUBLIST);
2496 #undef FREE_FILTERSUBLIST
2497 VECTOR_DEINIT(device->FilterList);
2498 almtx_destroy(&device->FilterLock);
2500 AL_STRING_DEINIT(device->HrtfName);
2501 FreeHrtfList(&device->HrtfList);
2502 if(device->HrtfHandle)
2503 Hrtf_DecRef(device->HrtfHandle);
2504 device->HrtfHandle = NULL;
2505 al_free(device->Hrtf);
2506 device->Hrtf = NULL;
2508 al_free(device->Bs2b);
2509 device->Bs2b = NULL;
2511 al_free(device->Uhj_Encoder);
2512 device->Uhj_Encoder = NULL;
2514 bformatdec_free(&device->AmbiDecoder);
2515 ambiup_free(&device->AmbiUp);
2517 al_free(device->Stablizer);
2518 device->Stablizer = NULL;
2520 al_free(device->Limiter);
2521 device->Limiter = NULL;
2523 al_free(device->ChannelDelay[0].Buffer);
2524 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2526 device->ChannelDelay[i].Gain = 1.0f;
2527 device->ChannelDelay[i].Length = 0;
2528 device->ChannelDelay[i].Buffer = NULL;
2531 AL_STRING_DEINIT(device->DeviceName);
2533 al_free(device->Dry.Buffer);
2534 device->Dry.Buffer = NULL;
2535 device->Dry.NumChannels = 0;
2536 device->FOAOut.Buffer = NULL;
2537 device->FOAOut.NumChannels = 0;
2538 device->RealOut.Buffer = NULL;
2539 device->RealOut.NumChannels = 0;
2541 al_free(device);
2545 void ALCdevice_IncRef(ALCdevice *device)
2547 uint ref;
2548 ref = IncrementRef(&device->ref);
2549 TRACEREF("%p increasing refcount to %u\n", device, ref);
2552 void ALCdevice_DecRef(ALCdevice *device)
2554 uint ref;
2555 ref = DecrementRef(&device->ref);
2556 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2557 if(ref == 0) FreeDevice(device);
2560 /* VerifyDevice
2562 * Checks if the device handle is valid, and increments its ref count if so.
2564 static ALCboolean VerifyDevice(ALCdevice **device)
2566 ALCdevice *tmpDevice;
2568 LockLists();
2569 tmpDevice = ATOMIC_LOAD_SEQ(&DeviceList);
2570 while(tmpDevice)
2572 if(tmpDevice == *device)
2574 ALCdevice_IncRef(tmpDevice);
2575 UnlockLists();
2576 return ALC_TRUE;
2578 tmpDevice = ATOMIC_LOAD(&tmpDevice->next, almemory_order_relaxed);
2580 UnlockLists();
2582 *device = NULL;
2583 return ALC_FALSE;
2587 /* InitContext
2589 * Initializes context fields
2591 static ALvoid InitContext(ALCcontext *Context)
2593 ALlistener *listener = Context->Listener;
2594 struct ALeffectslotArray *auxslots;
2596 //Initialise listener
2597 listener->Gain = 1.0f;
2598 listener->Position[0] = 0.0f;
2599 listener->Position[1] = 0.0f;
2600 listener->Position[2] = 0.0f;
2601 listener->Velocity[0] = 0.0f;
2602 listener->Velocity[1] = 0.0f;
2603 listener->Velocity[2] = 0.0f;
2604 listener->Forward[0] = 0.0f;
2605 listener->Forward[1] = 0.0f;
2606 listener->Forward[2] = -1.0f;
2607 listener->Up[0] = 0.0f;
2608 listener->Up[1] = 1.0f;
2609 listener->Up[2] = 0.0f;
2610 ATOMIC_FLAG_TEST_AND_SET(&listener->PropsClean, almemory_order_relaxed);
2612 ATOMIC_INIT(&listener->Update, NULL);
2614 //Validate Context
2615 InitRef(&Context->UpdateCount, 0);
2616 ATOMIC_INIT(&Context->HoldUpdates, AL_FALSE);
2617 Context->GainBoost = 1.0f;
2618 almtx_init(&Context->PropLock, almtx_plain);
2619 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2620 VECTOR_INIT(Context->SourceList);
2621 Context->NumSources = 0;
2622 almtx_init(&Context->SourceLock, almtx_plain);
2623 VECTOR_INIT(Context->EffectSlotList);
2624 almtx_init(&Context->EffectSlotLock, almtx_plain);
2626 if(Context->DefaultSlot)
2628 auxslots = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, 1));
2629 auxslots->count = 1;
2630 auxslots->slot[0] = Context->DefaultSlot;
2632 else
2634 auxslots = al_calloc(DEF_ALIGN, sizeof(struct ALeffectslotArray));
2635 auxslots->count = 0;
2637 ATOMIC_INIT(&Context->ActiveAuxSlots, auxslots);
2639 //Set globals
2640 Context->DistanceModel = DefaultDistanceModel;
2641 Context->SourceDistanceModel = AL_FALSE;
2642 Context->DopplerFactor = 1.0f;
2643 Context->DopplerVelocity = 1.0f;
2644 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2645 Context->MetersPerUnit = AL_DEFAULT_METERS_PER_UNIT;
2646 ATOMIC_FLAG_TEST_AND_SET(&Context->PropsClean, almemory_order_relaxed);
2647 ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
2648 almtx_init(&Context->EventThrdLock, almtx_plain);
2649 alsem_init(&Context->EventSem, 0);
2650 Context->AsyncEvents = NULL;
2651 ATOMIC_INIT(&Context->EnabledEvts, 0);
2652 almtx_init(&Context->EventCbLock, almtx_plain);
2653 Context->EventCb = NULL;
2654 Context->EventParam = NULL;
2656 ATOMIC_INIT(&Context->Update, NULL);
2657 ATOMIC_INIT(&Context->FreeContextProps, NULL);
2658 ATOMIC_INIT(&Context->FreeListenerProps, NULL);
2659 ATOMIC_INIT(&Context->FreeVoiceProps, NULL);
2660 ATOMIC_INIT(&Context->FreeEffectslotProps, NULL);
2662 Context->ExtensionList = alExtList;
2665 listener->Params.Matrix = IdentityMatrixf;
2666 aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2667 listener->Params.Gain = listener->Gain;
2668 listener->Params.MetersPerUnit = Context->MetersPerUnit;
2669 listener->Params.DopplerFactor = Context->DopplerFactor;
2670 listener->Params.SpeedOfSound = Context->SpeedOfSound * Context->DopplerVelocity;
2671 listener->Params.ReverbSpeedOfSound = listener->Params.SpeedOfSound *
2672 listener->Params.MetersPerUnit;
2673 listener->Params.SourceDistanceModel = Context->SourceDistanceModel;
2674 listener->Params.DistanceModel = Context->DistanceModel;
2678 /* FreeContext
2680 * Cleans up the context, and destroys any remaining objects the app failed to
2681 * delete. Called once there's no more references on the context.
2683 static void FreeContext(ALCcontext *context)
2685 ALlistener *listener = context->Listener;
2686 struct ALeffectslotArray *auxslots;
2687 struct ALeffectslotProps *eprops;
2688 struct ALlistenerProps *lprops;
2689 struct ALcontextProps *cprops;
2690 struct ALvoiceProps *vprops;
2691 size_t count;
2692 ALsizei i;
2694 TRACE("%p\n", context);
2696 if((cprops=ATOMIC_LOAD(&context->Update, almemory_order_acquire)) != NULL)
2698 TRACE("Freed unapplied context update %p\n", cprops);
2699 al_free(cprops);
2702 count = 0;
2703 cprops = ATOMIC_LOAD(&context->FreeContextProps, almemory_order_acquire);
2704 while(cprops)
2706 struct ALcontextProps *next = ATOMIC_LOAD(&cprops->next, almemory_order_acquire);
2707 al_free(cprops);
2708 cprops = next;
2709 ++count;
2711 TRACE("Freed "SZFMT" context property object%s\n", count, (count==1)?"":"s");
2713 if(context->DefaultSlot)
2715 DeinitEffectSlot(context->DefaultSlot);
2716 context->DefaultSlot = NULL;
2719 auxslots = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, NULL, almemory_order_relaxed);
2720 al_free(auxslots);
2722 ReleaseALSources(context);
2723 #define FREE_SOURCESUBLIST(x) al_free((x)->Sources)
2724 VECTOR_FOR_EACH(SourceSubList, context->SourceList, FREE_SOURCESUBLIST);
2725 #undef FREE_SOURCESUBLIST
2726 VECTOR_DEINIT(context->SourceList);
2727 context->NumSources = 0;
2728 almtx_destroy(&context->SourceLock);
2730 count = 0;
2731 eprops = ATOMIC_LOAD(&context->FreeEffectslotProps, almemory_order_relaxed);
2732 while(eprops)
2734 struct ALeffectslotProps *next = ATOMIC_LOAD(&eprops->next, almemory_order_relaxed);
2735 if(eprops->State) ALeffectState_DecRef(eprops->State);
2736 al_free(eprops);
2737 eprops = next;
2738 ++count;
2740 TRACE("Freed "SZFMT" AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2742 ReleaseALAuxiliaryEffectSlots(context);
2743 #define FREE_EFFECTSLOTPTR(x) al_free(*(x))
2744 VECTOR_FOR_EACH(ALeffectslotPtr, context->EffectSlotList, FREE_EFFECTSLOTPTR);
2745 #undef FREE_EFFECTSLOTPTR
2746 VECTOR_DEINIT(context->EffectSlotList);
2747 almtx_destroy(&context->EffectSlotLock);
2749 count = 0;
2750 vprops = ATOMIC_LOAD(&context->FreeVoiceProps, almemory_order_relaxed);
2751 while(vprops)
2753 struct ALvoiceProps *next = ATOMIC_LOAD(&vprops->next, almemory_order_relaxed);
2754 al_free(vprops);
2755 vprops = next;
2756 ++count;
2758 TRACE("Freed "SZFMT" voice property object%s\n", count, (count==1)?"":"s");
2760 for(i = 0;i < context->VoiceCount;i++)
2761 DeinitVoice(context->Voices[i]);
2762 al_free(context->Voices);
2763 context->Voices = NULL;
2764 context->VoiceCount = 0;
2765 context->MaxVoices = 0;
2767 if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != NULL)
2769 TRACE("Freed unapplied listener update %p\n", lprops);
2770 al_free(lprops);
2772 count = 0;
2773 lprops = ATOMIC_LOAD(&context->FreeListenerProps, almemory_order_acquire);
2774 while(lprops)
2776 struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_acquire);
2777 al_free(lprops);
2778 lprops = next;
2779 ++count;
2781 TRACE("Freed "SZFMT" listener property object%s\n", count, (count==1)?"":"s");
2783 if(ATOMIC_EXCHANGE(&context->EnabledEvts, 0, almemory_order_acq_rel))
2785 static const AsyncEvent kill_evt = { 0 };
2786 while(ll_ringbuffer_write(context->AsyncEvents, (const char*)&kill_evt, 1) == 0)
2787 althrd_yield();
2788 alsem_post(&context->EventSem);
2789 althrd_join(context->EventThread, NULL);
2792 almtx_destroy(&context->EventCbLock);
2793 almtx_destroy(&context->EventThrdLock);
2794 alsem_destroy(&context->EventSem);
2796 ll_ringbuffer_free(context->AsyncEvents);
2797 context->AsyncEvents = NULL;
2799 almtx_destroy(&context->PropLock);
2801 ALCdevice_DecRef(context->Device);
2802 context->Device = NULL;
2804 //Invalidate context
2805 memset(context, 0, sizeof(ALCcontext));
2806 al_free(context);
2809 /* ReleaseContext
2811 * Removes the context reference from the given device and removes it from
2812 * being current on the running thread or globally. Returns true if other
2813 * contexts still exist on the device.
2815 static bool ReleaseContext(ALCcontext *context, ALCdevice *device)
2817 ALCcontext *origctx, *newhead;
2818 bool ret = true;
2820 if(altss_get(LocalContext) == context)
2822 WARN("%p released while current on thread\n", context);
2823 altss_set(LocalContext, NULL);
2824 ALCcontext_DecRef(context);
2827 origctx = context;
2828 if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext, &origctx, NULL))
2829 ALCcontext_DecRef(context);
2831 V0(device->Backend,lock)();
2832 origctx = context;
2833 newhead = ATOMIC_LOAD(&context->next, almemory_order_relaxed);
2834 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device->ContextList, &origctx, newhead))
2836 ALCcontext *list;
2837 do {
2838 /* origctx is what the desired context failed to match. Try
2839 * swapping out the next one in the list.
2841 list = origctx;
2842 origctx = context;
2843 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list->next, &origctx, newhead));
2845 else
2846 ret = !!newhead;
2847 V0(device->Backend,unlock)();
2849 ALCcontext_DecRef(context);
2850 return ret;
2853 static void ALCcontext_IncRef(ALCcontext *context)
2855 uint ref = IncrementRef(&context->ref);
2856 TRACEREF("%p increasing refcount to %u\n", context, ref);
2859 void ALCcontext_DecRef(ALCcontext *context)
2861 uint ref = DecrementRef(&context->ref);
2862 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2863 if(ref == 0) FreeContext(context);
2866 static void ReleaseThreadCtx(void *ptr)
2868 ALCcontext *context = ptr;
2869 uint ref = DecrementRef(&context->ref);
2870 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2871 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2874 /* VerifyContext
2876 * Checks that the given context is valid, and increments its reference count.
2878 static ALCboolean VerifyContext(ALCcontext **context)
2880 ALCdevice *dev;
2882 LockLists();
2883 dev = ATOMIC_LOAD_SEQ(&DeviceList);
2884 while(dev)
2886 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList, almemory_order_acquire);
2887 while(ctx)
2889 if(ctx == *context)
2891 ALCcontext_IncRef(ctx);
2892 UnlockLists();
2893 return ALC_TRUE;
2895 ctx = ATOMIC_LOAD(&ctx->next, almemory_order_relaxed);
2897 dev = ATOMIC_LOAD(&dev->next, almemory_order_relaxed);
2899 UnlockLists();
2901 *context = NULL;
2902 return ALC_FALSE;
2906 /* GetContextRef
2908 * Returns the currently active context for this thread, and adds a reference
2909 * without locking it.
2911 ALCcontext *GetContextRef(void)
2913 ALCcontext *context;
2915 context = altss_get(LocalContext);
2916 if(context)
2917 ALCcontext_IncRef(context);
2918 else
2920 LockLists();
2921 context = ATOMIC_LOAD_SEQ(&GlobalContext);
2922 if(context)
2923 ALCcontext_IncRef(context);
2924 UnlockLists();
2927 return context;
2931 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
2933 ALCdevice *device = context->Device;
2934 ALsizei num_sends = device->NumAuxSends;
2935 struct ALvoiceProps *props;
2936 size_t sizeof_props;
2937 size_t sizeof_voice;
2938 ALvoice **voices;
2939 ALvoice *voice;
2940 ALsizei v = 0;
2941 size_t size;
2943 if(num_voices == context->MaxVoices && num_sends == old_sends)
2944 return;
2946 /* Allocate the voice pointers, voices, and the voices' stored source
2947 * property set (including the dynamically-sized Send[] array) in one
2948 * chunk.
2950 sizeof_voice = RoundUp(FAM_SIZE(ALvoice, Send, num_sends), 16);
2951 sizeof_props = RoundUp(FAM_SIZE(struct ALvoiceProps, Send, num_sends), 16);
2952 size = sizeof(ALvoice*) + sizeof_voice + sizeof_props;
2954 voices = al_calloc(16, RoundUp(size*num_voices, 16));
2955 /* The voice and property objects are stored interleaved since they're
2956 * paired together.
2958 voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
2959 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2961 if(context->Voices)
2963 const ALsizei v_count = mini(context->VoiceCount, num_voices);
2964 const ALsizei s_count = mini(old_sends, num_sends);
2966 for(;v < v_count;v++)
2968 ALvoice *old_voice = context->Voices[v];
2969 ALsizei i;
2971 /* Copy the old voice data and source property set to the new
2972 * storage.
2974 *voice = *old_voice;
2975 for(i = 0;i < s_count;i++)
2976 voice->Send[i] = old_voice->Send[i];
2977 *props = *(old_voice->Props);
2978 for(i = 0;i < s_count;i++)
2979 props->Send[i] = old_voice->Props->Send[i];
2981 /* Set this voice's property set pointer and voice reference. */
2982 voice->Props = props;
2983 voices[v] = voice;
2985 /* Increment pointers to the next storage space. */
2986 voice = (ALvoice*)((char*)props + sizeof_props);
2987 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2989 /* Deinit any left over voices that weren't copied over to the new
2990 * array. NOTE: If this does anything, v equals num_voices and
2991 * num_voices is less than VoiceCount, so the following loop won't do
2992 * anything.
2994 for(;v < context->VoiceCount;v++)
2995 DeinitVoice(context->Voices[v]);
2997 /* Finish setting the voices' property set pointers and references. */
2998 for(;v < num_voices;v++)
3000 ATOMIC_INIT(&voice->Update, NULL);
3002 voice->Props = props;
3003 voices[v] = voice;
3005 voice = (ALvoice*)((char*)props + sizeof_props);
3006 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
3009 al_free(context->Voices);
3010 context->Voices = voices;
3011 context->MaxVoices = num_voices;
3012 context->VoiceCount = mini(context->VoiceCount, num_voices);
3016 /************************************************
3017 * Standard ALC functions
3018 ************************************************/
3020 /* alcGetError
3022 * Return last ALC generated error code for the given device
3024 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
3026 ALCenum errorCode;
3028 if(VerifyDevice(&device))
3030 errorCode = ATOMIC_EXCHANGE_SEQ(&device->LastError, ALC_NO_ERROR);
3031 ALCdevice_DecRef(device);
3033 else
3034 errorCode = ATOMIC_EXCHANGE_SEQ(&LastNullDeviceError, ALC_NO_ERROR);
3036 return errorCode;
3040 /* alcSuspendContext
3042 * Suspends updates for the given context
3044 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
3046 if(!SuspendDefers)
3047 return;
3049 if(!VerifyContext(&context))
3050 alcSetError(NULL, ALC_INVALID_CONTEXT);
3051 else
3053 ALCcontext_DeferUpdates(context);
3054 ALCcontext_DecRef(context);
3058 /* alcProcessContext
3060 * Resumes processing updates for the given context
3062 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
3064 if(!SuspendDefers)
3065 return;
3067 if(!VerifyContext(&context))
3068 alcSetError(NULL, ALC_INVALID_CONTEXT);
3069 else
3071 ALCcontext_ProcessUpdates(context);
3072 ALCcontext_DecRef(context);
3077 /* alcGetString
3079 * Returns information about the device, and error strings
3081 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
3083 const ALCchar *value = NULL;
3085 switch(param)
3087 case ALC_NO_ERROR:
3088 value = alcNoError;
3089 break;
3091 case ALC_INVALID_ENUM:
3092 value = alcErrInvalidEnum;
3093 break;
3095 case ALC_INVALID_VALUE:
3096 value = alcErrInvalidValue;
3097 break;
3099 case ALC_INVALID_DEVICE:
3100 value = alcErrInvalidDevice;
3101 break;
3103 case ALC_INVALID_CONTEXT:
3104 value = alcErrInvalidContext;
3105 break;
3107 case ALC_OUT_OF_MEMORY:
3108 value = alcErrOutOfMemory;
3109 break;
3111 case ALC_DEVICE_SPECIFIER:
3112 value = alcDefaultName;
3113 break;
3115 case ALC_ALL_DEVICES_SPECIFIER:
3116 if(VerifyDevice(&Device))
3118 value = alstr_get_cstr(Device->DeviceName);
3119 ALCdevice_DecRef(Device);
3121 else
3123 ProbeAllDevicesList();
3124 value = alstr_get_cstr(alcAllDevicesList);
3126 break;
3128 case ALC_CAPTURE_DEVICE_SPECIFIER:
3129 if(VerifyDevice(&Device))
3131 value = alstr_get_cstr(Device->DeviceName);
3132 ALCdevice_DecRef(Device);
3134 else
3136 ProbeCaptureDeviceList();
3137 value = alstr_get_cstr(alcCaptureDeviceList);
3139 break;
3141 /* Default devices are always first in the list */
3142 case ALC_DEFAULT_DEVICE_SPECIFIER:
3143 value = alcDefaultName;
3144 break;
3146 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
3147 if(alstr_empty(alcAllDevicesList))
3148 ProbeAllDevicesList();
3150 VerifyDevice(&Device);
3152 free(alcDefaultAllDevicesSpecifier);
3153 alcDefaultAllDevicesSpecifier = strdup(alstr_get_cstr(alcAllDevicesList));
3154 if(!alcDefaultAllDevicesSpecifier)
3155 alcSetError(Device, ALC_OUT_OF_MEMORY);
3157 value = alcDefaultAllDevicesSpecifier;
3158 if(Device) ALCdevice_DecRef(Device);
3159 break;
3161 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
3162 if(alstr_empty(alcCaptureDeviceList))
3163 ProbeCaptureDeviceList();
3165 VerifyDevice(&Device);
3167 free(alcCaptureDefaultDeviceSpecifier);
3168 alcCaptureDefaultDeviceSpecifier = strdup(alstr_get_cstr(alcCaptureDeviceList));
3169 if(!alcCaptureDefaultDeviceSpecifier)
3170 alcSetError(Device, ALC_OUT_OF_MEMORY);
3172 value = alcCaptureDefaultDeviceSpecifier;
3173 if(Device) ALCdevice_DecRef(Device);
3174 break;
3176 case ALC_EXTENSIONS:
3177 if(!VerifyDevice(&Device))
3178 value = alcNoDeviceExtList;
3179 else
3181 value = alcExtensionList;
3182 ALCdevice_DecRef(Device);
3184 break;
3186 case ALC_HRTF_SPECIFIER_SOFT:
3187 if(!VerifyDevice(&Device))
3188 alcSetError(NULL, ALC_INVALID_DEVICE);
3189 else
3191 almtx_lock(&Device->BackendLock);
3192 value = (Device->HrtfHandle ? alstr_get_cstr(Device->HrtfName) : "");
3193 almtx_unlock(&Device->BackendLock);
3194 ALCdevice_DecRef(Device);
3196 break;
3198 default:
3199 VerifyDevice(&Device);
3200 alcSetError(Device, ALC_INVALID_ENUM);
3201 if(Device) ALCdevice_DecRef(Device);
3202 break;
3205 return value;
3209 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
3211 if(device->Type == Capture) return 9;
3212 if(device->Type != Loopback) return 29;
3213 if(device->FmtChans == DevFmtAmbi3D)
3214 return 35;
3215 return 29;
3218 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3220 ALCsizei i;
3222 if(size <= 0 || values == NULL)
3224 alcSetError(device, ALC_INVALID_VALUE);
3225 return 0;
3228 if(!device)
3230 switch(param)
3232 case ALC_MAJOR_VERSION:
3233 values[0] = alcMajorVersion;
3234 return 1;
3235 case ALC_MINOR_VERSION:
3236 values[0] = alcMinorVersion;
3237 return 1;
3239 case ALC_ATTRIBUTES_SIZE:
3240 case ALC_ALL_ATTRIBUTES:
3241 case ALC_FREQUENCY:
3242 case ALC_REFRESH:
3243 case ALC_SYNC:
3244 case ALC_MONO_SOURCES:
3245 case ALC_STEREO_SOURCES:
3246 case ALC_CAPTURE_SAMPLES:
3247 case ALC_FORMAT_CHANNELS_SOFT:
3248 case ALC_FORMAT_TYPE_SOFT:
3249 case ALC_AMBISONIC_LAYOUT_SOFT:
3250 case ALC_AMBISONIC_SCALING_SOFT:
3251 case ALC_AMBISONIC_ORDER_SOFT:
3252 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3253 alcSetError(NULL, ALC_INVALID_DEVICE);
3254 return 0;
3256 default:
3257 alcSetError(NULL, ALC_INVALID_ENUM);
3258 return 0;
3260 return 0;
3263 if(device->Type == Capture)
3265 switch(param)
3267 case ALC_ATTRIBUTES_SIZE:
3268 values[0] = NumAttrsForDevice(device);
3269 return 1;
3271 case ALC_ALL_ATTRIBUTES:
3272 if(size < NumAttrsForDevice(device))
3274 alcSetError(device, ALC_INVALID_VALUE);
3275 return 0;
3278 i = 0;
3279 almtx_lock(&device->BackendLock);
3280 values[i++] = ALC_MAJOR_VERSION;
3281 values[i++] = alcMajorVersion;
3282 values[i++] = ALC_MINOR_VERSION;
3283 values[i++] = alcMinorVersion;
3284 values[i++] = ALC_CAPTURE_SAMPLES;
3285 values[i++] = V0(device->Backend,availableSamples)();
3286 values[i++] = ALC_CONNECTED;
3287 values[i++] = ATOMIC_LOAD(&device->Connected, almemory_order_relaxed);
3288 almtx_unlock(&device->BackendLock);
3290 values[i++] = 0;
3291 return i;
3293 case ALC_MAJOR_VERSION:
3294 values[0] = alcMajorVersion;
3295 return 1;
3296 case ALC_MINOR_VERSION:
3297 values[0] = alcMinorVersion;
3298 return 1;
3300 case ALC_CAPTURE_SAMPLES:
3301 almtx_lock(&device->BackendLock);
3302 values[0] = V0(device->Backend,availableSamples)();
3303 almtx_unlock(&device->BackendLock);
3304 return 1;
3306 case ALC_CONNECTED:
3307 values[0] = ATOMIC_LOAD(&device->Connected, almemory_order_acquire);
3308 return 1;
3310 default:
3311 alcSetError(device, ALC_INVALID_ENUM);
3312 return 0;
3314 return 0;
3317 /* render device */
3318 switch(param)
3320 case ALC_ATTRIBUTES_SIZE:
3321 values[0] = NumAttrsForDevice(device);
3322 return 1;
3324 case ALC_ALL_ATTRIBUTES:
3325 if(size < NumAttrsForDevice(device))
3327 alcSetError(device, ALC_INVALID_VALUE);
3328 return 0;
3331 i = 0;
3332 almtx_lock(&device->BackendLock);
3333 values[i++] = ALC_MAJOR_VERSION;
3334 values[i++] = alcMajorVersion;
3335 values[i++] = ALC_MINOR_VERSION;
3336 values[i++] = alcMinorVersion;
3337 values[i++] = ALC_EFX_MAJOR_VERSION;
3338 values[i++] = alcEFXMajorVersion;
3339 values[i++] = ALC_EFX_MINOR_VERSION;
3340 values[i++] = alcEFXMinorVersion;
3342 values[i++] = ALC_FREQUENCY;
3343 values[i++] = device->Frequency;
3344 if(device->Type != Loopback)
3346 values[i++] = ALC_REFRESH;
3347 values[i++] = device->Frequency / device->UpdateSize;
3349 values[i++] = ALC_SYNC;
3350 values[i++] = ALC_FALSE;
3352 else
3354 if(device->FmtChans == DevFmtAmbi3D)
3356 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3357 values[i++] = device->AmbiLayout;
3359 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3360 values[i++] = device->AmbiScale;
3362 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3363 values[i++] = device->AmbiOrder;
3366 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3367 values[i++] = device->FmtChans;
3369 values[i++] = ALC_FORMAT_TYPE_SOFT;
3370 values[i++] = device->FmtType;
3373 values[i++] = ALC_MONO_SOURCES;
3374 values[i++] = device->NumMonoSources;
3376 values[i++] = ALC_STEREO_SOURCES;
3377 values[i++] = device->NumStereoSources;
3379 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3380 values[i++] = device->NumAuxSends;
3382 values[i++] = ALC_HRTF_SOFT;
3383 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3385 values[i++] = ALC_HRTF_STATUS_SOFT;
3386 values[i++] = device->HrtfStatus;
3388 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3389 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3391 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
3392 values[i++] = MAX_AMBI_ORDER;
3393 almtx_unlock(&device->BackendLock);
3395 values[i++] = 0;
3396 return i;
3398 case ALC_MAJOR_VERSION:
3399 values[0] = alcMajorVersion;
3400 return 1;
3402 case ALC_MINOR_VERSION:
3403 values[0] = alcMinorVersion;
3404 return 1;
3406 case ALC_EFX_MAJOR_VERSION:
3407 values[0] = alcEFXMajorVersion;
3408 return 1;
3410 case ALC_EFX_MINOR_VERSION:
3411 values[0] = alcEFXMinorVersion;
3412 return 1;
3414 case ALC_FREQUENCY:
3415 values[0] = device->Frequency;
3416 return 1;
3418 case ALC_REFRESH:
3419 if(device->Type == Loopback)
3421 alcSetError(device, ALC_INVALID_DEVICE);
3422 return 0;
3424 almtx_lock(&device->BackendLock);
3425 values[0] = device->Frequency / device->UpdateSize;
3426 almtx_unlock(&device->BackendLock);
3427 return 1;
3429 case ALC_SYNC:
3430 if(device->Type == Loopback)
3432 alcSetError(device, ALC_INVALID_DEVICE);
3433 return 0;
3435 values[0] = ALC_FALSE;
3436 return 1;
3438 case ALC_FORMAT_CHANNELS_SOFT:
3439 if(device->Type != Loopback)
3441 alcSetError(device, ALC_INVALID_DEVICE);
3442 return 0;
3444 values[0] = device->FmtChans;
3445 return 1;
3447 case ALC_FORMAT_TYPE_SOFT:
3448 if(device->Type != Loopback)
3450 alcSetError(device, ALC_INVALID_DEVICE);
3451 return 0;
3453 values[0] = device->FmtType;
3454 return 1;
3456 case ALC_AMBISONIC_LAYOUT_SOFT:
3457 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3459 alcSetError(device, ALC_INVALID_DEVICE);
3460 return 0;
3462 values[0] = device->AmbiLayout;
3463 return 1;
3465 case ALC_AMBISONIC_SCALING_SOFT:
3466 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3468 alcSetError(device, ALC_INVALID_DEVICE);
3469 return 0;
3471 values[0] = device->AmbiScale;
3472 return 1;
3474 case ALC_AMBISONIC_ORDER_SOFT:
3475 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3477 alcSetError(device, ALC_INVALID_DEVICE);
3478 return 0;
3480 values[0] = device->AmbiOrder;
3481 return 1;
3483 case ALC_MONO_SOURCES:
3484 values[0] = device->NumMonoSources;
3485 return 1;
3487 case ALC_STEREO_SOURCES:
3488 values[0] = device->NumStereoSources;
3489 return 1;
3491 case ALC_MAX_AUXILIARY_SENDS:
3492 values[0] = device->NumAuxSends;
3493 return 1;
3495 case ALC_CONNECTED:
3496 values[0] = ATOMIC_LOAD(&device->Connected, almemory_order_acquire);
3497 return 1;
3499 case ALC_HRTF_SOFT:
3500 values[0] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3501 return 1;
3503 case ALC_HRTF_STATUS_SOFT:
3504 values[0] = device->HrtfStatus;
3505 return 1;
3507 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3508 almtx_lock(&device->BackendLock);
3509 FreeHrtfList(&device->HrtfList);
3510 device->HrtfList = EnumerateHrtf(device->DeviceName);
3511 values[0] = (ALCint)VECTOR_SIZE(device->HrtfList);
3512 almtx_unlock(&device->BackendLock);
3513 return 1;
3515 case ALC_OUTPUT_LIMITER_SOFT:
3516 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3517 return 1;
3519 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3520 values[0] = MAX_AMBI_ORDER;
3521 return 1;
3523 default:
3524 alcSetError(device, ALC_INVALID_ENUM);
3525 return 0;
3527 return 0;
3530 /* alcGetIntegerv
3532 * Returns information about the device and the version of OpenAL
3534 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3536 VerifyDevice(&device);
3537 if(size <= 0 || values == NULL)
3538 alcSetError(device, ALC_INVALID_VALUE);
3539 else
3540 GetIntegerv(device, param, size, values);
3541 if(device) ALCdevice_DecRef(device);
3544 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3546 ALCint *ivals;
3547 ALsizei i;
3549 VerifyDevice(&device);
3550 if(size <= 0 || values == NULL)
3551 alcSetError(device, ALC_INVALID_VALUE);
3552 else if(!device || device->Type == Capture)
3554 ivals = malloc(size * sizeof(ALCint));
3555 size = GetIntegerv(device, pname, size, ivals);
3556 for(i = 0;i < size;i++)
3557 values[i] = ivals[i];
3558 free(ivals);
3560 else /* render device */
3562 ClockLatency clock;
3563 ALuint64 basecount;
3564 ALuint samplecount;
3565 ALuint refcount;
3567 switch(pname)
3569 case ALC_ATTRIBUTES_SIZE:
3570 *values = NumAttrsForDevice(device)+4;
3571 break;
3573 case ALC_ALL_ATTRIBUTES:
3574 if(size < NumAttrsForDevice(device)+4)
3575 alcSetError(device, ALC_INVALID_VALUE);
3576 else
3578 i = 0;
3579 almtx_lock(&device->BackendLock);
3580 values[i++] = ALC_FREQUENCY;
3581 values[i++] = device->Frequency;
3583 if(device->Type != Loopback)
3585 values[i++] = ALC_REFRESH;
3586 values[i++] = device->Frequency / device->UpdateSize;
3588 values[i++] = ALC_SYNC;
3589 values[i++] = ALC_FALSE;
3591 else
3593 if(device->FmtChans == DevFmtAmbi3D)
3595 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3596 values[i++] = device->AmbiLayout;
3598 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3599 values[i++] = device->AmbiScale;
3601 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3602 values[i++] = device->AmbiOrder;
3605 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3606 values[i++] = device->FmtChans;
3608 values[i++] = ALC_FORMAT_TYPE_SOFT;
3609 values[i++] = device->FmtType;
3612 values[i++] = ALC_MONO_SOURCES;
3613 values[i++] = device->NumMonoSources;
3615 values[i++] = ALC_STEREO_SOURCES;
3616 values[i++] = device->NumStereoSources;
3618 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3619 values[i++] = device->NumAuxSends;
3621 values[i++] = ALC_HRTF_SOFT;
3622 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3624 values[i++] = ALC_HRTF_STATUS_SOFT;
3625 values[i++] = device->HrtfStatus;
3627 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3628 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3630 clock = V0(device->Backend,getClockLatency)();
3631 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3632 values[i++] = clock.ClockTime;
3634 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3635 values[i++] = clock.Latency;
3636 almtx_unlock(&device->BackendLock);
3638 values[i++] = 0;
3640 break;
3642 case ALC_DEVICE_CLOCK_SOFT:
3643 almtx_lock(&device->BackendLock);
3644 do {
3645 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3646 althrd_yield();
3647 basecount = device->ClockBase;
3648 samplecount = device->SamplesDone;
3649 } while(refcount != ReadRef(&device->MixCount));
3650 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3651 almtx_unlock(&device->BackendLock);
3652 break;
3654 case ALC_DEVICE_LATENCY_SOFT:
3655 almtx_lock(&device->BackendLock);
3656 clock = V0(device->Backend,getClockLatency)();
3657 almtx_unlock(&device->BackendLock);
3658 *values = clock.Latency;
3659 break;
3661 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3662 if(size < 2)
3663 alcSetError(device, ALC_INVALID_VALUE);
3664 else
3666 almtx_lock(&device->BackendLock);
3667 clock = V0(device->Backend,getClockLatency)();
3668 almtx_unlock(&device->BackendLock);
3669 values[0] = clock.ClockTime;
3670 values[1] = clock.Latency;
3672 break;
3674 default:
3675 ivals = malloc(size * sizeof(ALCint));
3676 size = GetIntegerv(device, pname, size, ivals);
3677 for(i = 0;i < size;i++)
3678 values[i] = ivals[i];
3679 free(ivals);
3680 break;
3683 if(device)
3684 ALCdevice_DecRef(device);
3688 /* alcIsExtensionPresent
3690 * Determines if there is support for a particular extension
3692 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3694 ALCboolean bResult = ALC_FALSE;
3696 VerifyDevice(&device);
3698 if(!extName)
3699 alcSetError(device, ALC_INVALID_VALUE);
3700 else
3702 size_t len = strlen(extName);
3703 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3704 while(ptr && *ptr)
3706 if(strncasecmp(ptr, extName, len) == 0 &&
3707 (ptr[len] == '\0' || isspace(ptr[len])))
3709 bResult = ALC_TRUE;
3710 break;
3712 if((ptr=strchr(ptr, ' ')) != NULL)
3714 do {
3715 ++ptr;
3716 } while(isspace(*ptr));
3720 if(device)
3721 ALCdevice_DecRef(device);
3722 return bResult;
3726 /* alcGetProcAddress
3728 * Retrieves the function address for a particular extension function
3730 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3732 ALCvoid *ptr = NULL;
3734 if(!funcName)
3736 VerifyDevice(&device);
3737 alcSetError(device, ALC_INVALID_VALUE);
3738 if(device) ALCdevice_DecRef(device);
3740 else
3742 size_t i = 0;
3743 for(i = 0;i < COUNTOF(alcFunctions);i++)
3745 if(strcmp(alcFunctions[i].funcName, funcName) == 0)
3747 ptr = alcFunctions[i].address;
3748 break;
3753 return ptr;
3757 /* alcGetEnumValue
3759 * Get the value for a particular ALC enumeration name
3761 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3763 ALCenum val = 0;
3765 if(!enumName)
3767 VerifyDevice(&device);
3768 alcSetError(device, ALC_INVALID_VALUE);
3769 if(device) ALCdevice_DecRef(device);
3771 else
3773 size_t i = 0;
3774 for(i = 0;i < COUNTOF(alcEnumerations);i++)
3776 if(strcmp(alcEnumerations[i].enumName, enumName) == 0)
3778 val = alcEnumerations[i].value;
3779 break;
3784 return val;
3788 /* alcCreateContext
3790 * Create and attach a context to the given device.
3792 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3794 ALCcontext *ALContext;
3795 ALfloat valf;
3796 ALCenum err;
3798 /* Explicitly hold the list lock while taking the BackendLock in case the
3799 * device is asynchronously destropyed, to ensure this new context is
3800 * properly cleaned up after being made.
3802 LockLists();
3803 if(!VerifyDevice(&device) || device->Type == Capture ||
3804 !ATOMIC_LOAD(&device->Connected, almemory_order_relaxed))
3806 UnlockLists();
3807 alcSetError(device, ALC_INVALID_DEVICE);
3808 if(device) ALCdevice_DecRef(device);
3809 return NULL;
3811 almtx_lock(&device->BackendLock);
3812 UnlockLists();
3814 ATOMIC_STORE_SEQ(&device->LastError, ALC_NO_ERROR);
3816 if(device->Type == Playback && DefaultEffect.type != AL_EFFECT_NULL)
3817 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener)+sizeof(ALeffectslot));
3818 else
3819 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3820 if(!ALContext)
3822 almtx_unlock(&device->BackendLock);
3824 alcSetError(device, ALC_OUT_OF_MEMORY);
3825 ALCdevice_DecRef(device);
3826 return NULL;
3829 InitRef(&ALContext->ref, 1);
3830 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3831 ALContext->DefaultSlot = NULL;
3833 ALContext->Voices = NULL;
3834 ALContext->VoiceCount = 0;
3835 ALContext->MaxVoices = 0;
3836 ATOMIC_INIT(&ALContext->ActiveAuxSlots, NULL);
3837 ALContext->Device = device;
3838 ATOMIC_INIT(&ALContext->next, NULL);
3840 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3842 almtx_unlock(&device->BackendLock);
3844 al_free(ALContext);
3845 ALContext = NULL;
3847 alcSetError(device, err);
3848 if(err == ALC_INVALID_DEVICE)
3850 V0(device->Backend,lock)();
3851 aluHandleDisconnect(device, "Device update failure");
3852 V0(device->Backend,unlock)();
3854 ALCdevice_DecRef(device);
3855 return NULL;
3857 AllocateVoices(ALContext, 256, device->NumAuxSends);
3859 if(DefaultEffect.type != AL_EFFECT_NULL && device->Type == Playback)
3861 ALContext->DefaultSlot = (ALeffectslot*)(ALContext->_listener_mem + sizeof(ALlistener));
3862 if(InitEffectSlot(ALContext->DefaultSlot) == AL_NO_ERROR)
3863 aluInitEffectPanning(ALContext->DefaultSlot);
3864 else
3866 ALContext->DefaultSlot = NULL;
3867 ERR("Failed to initialize the default effect slot\n");
3871 ALCdevice_IncRef(ALContext->Device);
3872 InitContext(ALContext);
3874 if(ConfigValueFloat(alstr_get_cstr(device->DeviceName), NULL, "volume-adjust", &valf))
3876 if(!isfinite(valf))
3877 ERR("volume-adjust must be finite: %f\n", valf);
3878 else
3880 ALfloat db = clampf(valf, -24.0f, 24.0f);
3881 if(db != valf)
3882 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3883 ALContext->GainBoost = powf(10.0f, db/20.0f);
3884 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3887 UpdateListenerProps(ALContext);
3890 ALCcontext *head = ATOMIC_LOAD_SEQ(&device->ContextList);
3891 do {
3892 ATOMIC_STORE(&ALContext->next, head, almemory_order_relaxed);
3893 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device->ContextList, &head,
3894 ALContext) == 0);
3896 almtx_unlock(&device->BackendLock);
3898 if(ALContext->DefaultSlot)
3900 if(InitializeEffect(ALContext, ALContext->DefaultSlot, &DefaultEffect) == AL_NO_ERROR)
3901 UpdateEffectSlotProps(ALContext->DefaultSlot, ALContext);
3902 else
3903 ERR("Failed to initialize the default effect\n");
3906 ALCdevice_DecRef(device);
3908 TRACE("Created context %p\n", ALContext);
3909 return ALContext;
3912 /* alcDestroyContext
3914 * Remove a context from its device
3916 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3918 ALCdevice *Device;
3920 LockLists();
3921 if(!VerifyContext(&context))
3923 UnlockLists();
3924 alcSetError(NULL, ALC_INVALID_CONTEXT);
3925 return;
3928 Device = context->Device;
3929 if(Device)
3931 almtx_lock(&Device->BackendLock);
3932 if(!ReleaseContext(context, Device))
3934 V0(Device->Backend,stop)();
3935 Device->Flags &= ~DEVICE_RUNNING;
3937 almtx_unlock(&Device->BackendLock);
3939 UnlockLists();
3941 ALCcontext_DecRef(context);
3945 /* alcGetCurrentContext
3947 * Returns the currently active context on the calling thread
3949 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3951 ALCcontext *Context = altss_get(LocalContext);
3952 if(!Context) Context = ATOMIC_LOAD_SEQ(&GlobalContext);
3953 return Context;
3956 /* alcGetThreadContext
3958 * Returns the currently active thread-local context
3960 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3962 return altss_get(LocalContext);
3966 /* alcMakeContextCurrent
3968 * Makes the given context the active process-wide context, and removes the
3969 * thread-local context for the calling thread.
3971 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3973 /* context must be valid or NULL */
3974 if(context && !VerifyContext(&context))
3976 alcSetError(NULL, ALC_INVALID_CONTEXT);
3977 return ALC_FALSE;
3979 /* context's reference count is already incremented */
3980 context = ATOMIC_EXCHANGE_PTR_SEQ(&GlobalContext, context);
3981 if(context) ALCcontext_DecRef(context);
3983 if((context=altss_get(LocalContext)) != NULL)
3985 altss_set(LocalContext, NULL);
3986 ALCcontext_DecRef(context);
3989 return ALC_TRUE;
3992 /* alcSetThreadContext
3994 * Makes the given context the active context for the current thread
3996 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3998 ALCcontext *old;
4000 /* context must be valid or NULL */
4001 if(context && !VerifyContext(&context))
4003 alcSetError(NULL, ALC_INVALID_CONTEXT);
4004 return ALC_FALSE;
4006 /* context's reference count is already incremented */
4007 old = altss_get(LocalContext);
4008 altss_set(LocalContext, context);
4009 if(old) ALCcontext_DecRef(old);
4011 return ALC_TRUE;
4015 /* alcGetContextsDevice
4017 * Returns the device that a particular context is attached to
4019 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
4021 ALCdevice *Device;
4023 if(!VerifyContext(&Context))
4025 alcSetError(NULL, ALC_INVALID_CONTEXT);
4026 return NULL;
4028 Device = Context->Device;
4029 ALCcontext_DecRef(Context);
4031 return Device;
4035 /* alcOpenDevice
4037 * Opens the named device.
4039 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
4041 ALCbackendFactory *factory;
4042 const ALCchar *fmt;
4043 ALCdevice *device;
4044 ALCenum err;
4046 DO_INITCONFIG();
4048 if(!PlaybackBackend.name)
4050 alcSetError(NULL, ALC_INVALID_VALUE);
4051 return NULL;
4054 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
4055 #ifdef _WIN32
4056 /* Some old Windows apps hardcode these expecting OpenAL to use a
4057 * specific audio API, even when they're not enumerated. Creative's
4058 * router effectively ignores them too.
4060 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
4061 || strcasecmp(deviceName, "MMSYSTEM") == 0
4062 #endif
4064 deviceName = NULL;
4066 device = al_calloc(16, sizeof(ALCdevice));
4067 if(!device)
4069 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4070 return NULL;
4073 //Validate device
4074 InitDevice(device, Playback);
4076 //Set output format
4077 device->FmtChans = DevFmtChannelsDefault;
4078 device->FmtType = DevFmtTypeDefault;
4079 device->Frequency = DEFAULT_OUTPUT_RATE;
4080 device->IsHeadphones = AL_FALSE;
4081 device->AmbiLayout = AmbiLayout_Default;
4082 device->AmbiScale = AmbiNorm_Default;
4083 device->NumUpdates = 3;
4084 device->UpdateSize = 1024;
4086 device->SourcesMax = 256;
4087 device->AuxiliaryEffectSlotMax = 64;
4088 device->NumAuxSends = DEFAULT_SENDS;
4090 if(ConfigValueStr(deviceName, NULL, "channels", &fmt))
4092 static const struct {
4093 const char name[16];
4094 enum DevFmtChannels chans;
4095 ALsizei order;
4096 } chanlist[] = {
4097 { "mono", DevFmtMono, 0 },
4098 { "stereo", DevFmtStereo, 0 },
4099 { "quad", DevFmtQuad, 0 },
4100 { "surround51", DevFmtX51, 0 },
4101 { "surround61", DevFmtX61, 0 },
4102 { "surround71", DevFmtX71, 0 },
4103 { "surround51rear", DevFmtX51Rear, 0 },
4104 { "ambi1", DevFmtAmbi3D, 1 },
4105 { "ambi2", DevFmtAmbi3D, 2 },
4106 { "ambi3", DevFmtAmbi3D, 3 },
4108 size_t i;
4110 for(i = 0;i < COUNTOF(chanlist);i++)
4112 if(strcasecmp(chanlist[i].name, fmt) == 0)
4114 device->FmtChans = chanlist[i].chans;
4115 device->AmbiOrder = chanlist[i].order;
4116 device->Flags |= DEVICE_CHANNELS_REQUEST;
4117 break;
4120 if(i == COUNTOF(chanlist))
4121 ERR("Unsupported channels: %s\n", fmt);
4123 if(ConfigValueStr(deviceName, NULL, "sample-type", &fmt))
4125 static const struct {
4126 const char name[16];
4127 enum DevFmtType type;
4128 } typelist[] = {
4129 { "int8", DevFmtByte },
4130 { "uint8", DevFmtUByte },
4131 { "int16", DevFmtShort },
4132 { "uint16", DevFmtUShort },
4133 { "int32", DevFmtInt },
4134 { "uint32", DevFmtUInt },
4135 { "float32", DevFmtFloat },
4137 size_t i;
4139 for(i = 0;i < COUNTOF(typelist);i++)
4141 if(strcasecmp(typelist[i].name, fmt) == 0)
4143 device->FmtType = typelist[i].type;
4144 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
4145 break;
4148 if(i == COUNTOF(typelist))
4149 ERR("Unsupported sample-type: %s\n", fmt);
4152 if(ConfigValueUInt(deviceName, NULL, "frequency", &device->Frequency))
4154 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4155 if(device->Frequency < MIN_OUTPUT_RATE)
4156 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
4157 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
4160 ConfigValueUInt(deviceName, NULL, "periods", &device->NumUpdates);
4161 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
4163 ConfigValueUInt(deviceName, NULL, "period_size", &device->UpdateSize);
4164 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
4165 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
4166 device->UpdateSize = (device->UpdateSize+3)&~3;
4168 ConfigValueUInt(deviceName, NULL, "sources", &device->SourcesMax);
4169 if(device->SourcesMax == 0) device->SourcesMax = 256;
4171 ConfigValueUInt(deviceName, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4172 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4173 else device->AuxiliaryEffectSlotMax = minu(device->AuxiliaryEffectSlotMax, INT_MAX);
4175 if(ConfigValueInt(deviceName, NULL, "sends", &device->NumAuxSends))
4176 device->NumAuxSends = clampi(
4177 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4180 device->NumStereoSources = 1;
4181 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4183 factory = PlaybackBackend.getFactory();
4184 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
4185 if(!device->Backend)
4187 FreeDevice(device);
4188 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4189 return NULL;
4192 // Find a playback device to open
4193 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4195 FreeDevice(device);
4196 alcSetError(NULL, err);
4197 return NULL;
4200 if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt))
4202 if(strcasecmp(fmt, "fuma") == 0)
4204 device->AmbiLayout = AmbiLayout_FuMa;
4205 device->AmbiScale = AmbiNorm_FuMa;
4207 else if(strcasecmp(fmt, "acn+sn3d") == 0)
4209 device->AmbiLayout = AmbiLayout_ACN;
4210 device->AmbiScale = AmbiNorm_SN3D;
4212 else if(strcasecmp(fmt, "acn+n3d") == 0)
4214 device->AmbiLayout = AmbiLayout_ACN;
4215 device->AmbiScale = AmbiNorm_N3D;
4217 else
4218 ERR("Unsupported ambi-format: %s\n", fmt);
4221 device->Limiter = CreateDeviceLimiter(device);
4224 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4225 do {
4226 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4227 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4230 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
4231 return device;
4234 /* alcCloseDevice
4236 * Closes the given device.
4238 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
4240 ALCdevice *iter, *origdev, *nextdev;
4241 ALCcontext *ctx;
4243 LockLists();
4244 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4245 do {
4246 if(iter == device)
4247 break;
4248 iter = ATOMIC_LOAD(&iter->next, almemory_order_relaxed);
4249 } while(iter != NULL);
4250 if(!iter || iter->Type == Capture)
4252 alcSetError(iter, ALC_INVALID_DEVICE);
4253 UnlockLists();
4254 return ALC_FALSE;
4256 almtx_lock(&device->BackendLock);
4258 origdev = device;
4259 nextdev = ATOMIC_LOAD(&device->next, almemory_order_relaxed);
4260 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, nextdev))
4262 ALCdevice *list;
4263 do {
4264 list = origdev;
4265 origdev = device;
4266 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list->next, &origdev, nextdev));
4268 UnlockLists();
4270 ctx = ATOMIC_LOAD_SEQ(&device->ContextList);
4271 while(ctx != NULL)
4273 ALCcontext *next = ATOMIC_LOAD(&ctx->next, almemory_order_relaxed);
4274 WARN("Releasing context %p\n", ctx);
4275 ReleaseContext(ctx, device);
4276 ctx = next;
4278 if((device->Flags&DEVICE_RUNNING))
4279 V0(device->Backend,stop)();
4280 device->Flags &= ~DEVICE_RUNNING;
4281 almtx_unlock(&device->BackendLock);
4283 ALCdevice_DecRef(device);
4285 return ALC_TRUE;
4289 /************************************************
4290 * ALC capture functions
4291 ************************************************/
4292 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
4294 ALCbackendFactory *factory;
4295 ALCdevice *device = NULL;
4296 ALCenum err;
4298 DO_INITCONFIG();
4300 if(!CaptureBackend.name)
4302 alcSetError(NULL, ALC_INVALID_VALUE);
4303 return NULL;
4306 if(samples <= 0)
4308 alcSetError(NULL, ALC_INVALID_VALUE);
4309 return NULL;
4312 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
4313 deviceName = NULL;
4315 device = al_calloc(16, sizeof(ALCdevice));
4316 if(!device)
4318 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4319 return NULL;
4322 //Validate device
4323 InitDevice(device, Capture);
4325 device->Frequency = frequency;
4326 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4328 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
4330 FreeDevice(device);
4331 alcSetError(NULL, ALC_INVALID_ENUM);
4332 return NULL;
4334 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
4335 device->IsHeadphones = AL_FALSE;
4336 device->AmbiOrder = 0;
4337 device->AmbiLayout = AmbiLayout_Default;
4338 device->AmbiScale = AmbiNorm_Default;
4340 device->UpdateSize = samples;
4341 device->NumUpdates = 1;
4343 factory = CaptureBackend.getFactory();
4344 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
4345 if(!device->Backend)
4347 FreeDevice(device);
4348 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4349 return NULL;
4352 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4353 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
4354 device->Frequency, device->UpdateSize, device->NumUpdates
4356 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4358 FreeDevice(device);
4359 alcSetError(NULL, err);
4360 return NULL;
4364 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4365 do {
4366 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4367 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4370 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
4371 return device;
4374 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
4376 ALCdevice *iter, *origdev, *nextdev;
4378 LockLists();
4379 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4380 do {
4381 if(iter == device)
4382 break;
4383 iter = ATOMIC_LOAD(&iter->next, almemory_order_relaxed);
4384 } while(iter != NULL);
4385 if(!iter || iter->Type != Capture)
4387 alcSetError(iter, ALC_INVALID_DEVICE);
4388 UnlockLists();
4389 return ALC_FALSE;
4392 origdev = device;
4393 nextdev = ATOMIC_LOAD(&device->next, almemory_order_relaxed);
4394 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, nextdev))
4396 ALCdevice *list;
4397 do {
4398 list = origdev;
4399 origdev = device;
4400 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list->next, &origdev, nextdev));
4402 UnlockLists();
4404 almtx_lock(&device->BackendLock);
4405 if((device->Flags&DEVICE_RUNNING))
4406 V0(device->Backend,stop)();
4407 device->Flags &= ~DEVICE_RUNNING;
4408 almtx_unlock(&device->BackendLock);
4410 ALCdevice_DecRef(device);
4412 return ALC_TRUE;
4415 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
4417 if(!VerifyDevice(&device) || device->Type != Capture)
4418 alcSetError(device, ALC_INVALID_DEVICE);
4419 else
4421 almtx_lock(&device->BackendLock);
4422 if(!ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
4423 alcSetError(device, ALC_INVALID_DEVICE);
4424 else if(!(device->Flags&DEVICE_RUNNING))
4426 if(V0(device->Backend,start)())
4427 device->Flags |= DEVICE_RUNNING;
4428 else
4430 aluHandleDisconnect(device, "Device start failure");
4431 alcSetError(device, ALC_INVALID_DEVICE);
4434 almtx_unlock(&device->BackendLock);
4437 if(device) ALCdevice_DecRef(device);
4440 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
4442 if(!VerifyDevice(&device) || device->Type != Capture)
4443 alcSetError(device, ALC_INVALID_DEVICE);
4444 else
4446 almtx_lock(&device->BackendLock);
4447 if((device->Flags&DEVICE_RUNNING))
4448 V0(device->Backend,stop)();
4449 device->Flags &= ~DEVICE_RUNNING;
4450 almtx_unlock(&device->BackendLock);
4453 if(device) ALCdevice_DecRef(device);
4456 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4458 if(!VerifyDevice(&device) || device->Type != Capture)
4459 alcSetError(device, ALC_INVALID_DEVICE);
4460 else
4462 ALCenum err = ALC_INVALID_VALUE;
4464 almtx_lock(&device->BackendLock);
4465 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
4466 err = V(device->Backend,captureSamples)(buffer, samples);
4467 almtx_unlock(&device->BackendLock);
4469 if(err != ALC_NO_ERROR)
4470 alcSetError(device, err);
4472 if(device) ALCdevice_DecRef(device);
4476 /************************************************
4477 * ALC loopback functions
4478 ************************************************/
4480 /* alcLoopbackOpenDeviceSOFT
4482 * Open a loopback device, for manual rendering.
4484 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
4486 ALCbackendFactory *factory;
4487 ALCdevice *device;
4489 DO_INITCONFIG();
4491 /* Make sure the device name, if specified, is us. */
4492 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
4494 alcSetError(NULL, ALC_INVALID_VALUE);
4495 return NULL;
4498 device = al_calloc(16, sizeof(ALCdevice));
4499 if(!device)
4501 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4502 return NULL;
4505 //Validate device
4506 InitDevice(device, Loopback);
4508 device->SourcesMax = 256;
4509 device->AuxiliaryEffectSlotMax = 64;
4510 device->NumAuxSends = DEFAULT_SENDS;
4512 //Set output format
4513 device->NumUpdates = 0;
4514 device->UpdateSize = 0;
4516 device->Frequency = DEFAULT_OUTPUT_RATE;
4517 device->FmtChans = DevFmtChannelsDefault;
4518 device->FmtType = DevFmtTypeDefault;
4519 device->IsHeadphones = AL_FALSE;
4520 device->AmbiLayout = AmbiLayout_Default;
4521 device->AmbiScale = AmbiNorm_Default;
4523 ConfigValueUInt(NULL, NULL, "sources", &device->SourcesMax);
4524 if(device->SourcesMax == 0) device->SourcesMax = 256;
4526 ConfigValueUInt(NULL, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4527 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4528 else device->AuxiliaryEffectSlotMax = minu(device->AuxiliaryEffectSlotMax, INT_MAX);
4530 if(ConfigValueInt(NULL, NULL, "sends", &device->NumAuxSends))
4531 device->NumAuxSends = clampi(
4532 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4535 device->NumStereoSources = 1;
4536 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4538 factory = ALCloopbackFactory_getFactory();
4539 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
4540 if(!device->Backend)
4542 al_free(device);
4543 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4544 return NULL;
4547 // Open the "backend"
4548 V(device->Backend,open)("Loopback");
4550 device->Limiter = CreateDeviceLimiter(device);
4553 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4554 do {
4555 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4556 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4559 TRACE("Created device %p\n", device);
4560 return device;
4563 /* alcIsRenderFormatSupportedSOFT
4565 * Determines if the loopback device supports the given format for rendering.
4567 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4569 ALCboolean ret = ALC_FALSE;
4571 if(!VerifyDevice(&device) || device->Type != Loopback)
4572 alcSetError(device, ALC_INVALID_DEVICE);
4573 else if(freq <= 0)
4574 alcSetError(device, ALC_INVALID_VALUE);
4575 else
4577 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4578 ret = ALC_TRUE;
4580 if(device) ALCdevice_DecRef(device);
4582 return ret;
4585 /* alcRenderSamplesSOFT
4587 * Renders some samples into a buffer, using the format last set by the
4588 * attributes given to alcCreateContext.
4590 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4592 if(!VerifyDevice(&device) || device->Type != Loopback)
4593 alcSetError(device, ALC_INVALID_DEVICE);
4594 else if(samples < 0 || (samples > 0 && buffer == NULL))
4595 alcSetError(device, ALC_INVALID_VALUE);
4596 else
4598 V0(device->Backend,lock)();
4599 aluMixData(device, buffer, samples);
4600 V0(device->Backend,unlock)();
4602 if(device) ALCdevice_DecRef(device);
4606 /************************************************
4607 * ALC DSP pause/resume functions
4608 ************************************************/
4610 /* alcDevicePauseSOFT
4612 * Pause the DSP to stop audio processing.
4614 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4616 if(!VerifyDevice(&device) || device->Type != Playback)
4617 alcSetError(device, ALC_INVALID_DEVICE);
4618 else
4620 almtx_lock(&device->BackendLock);
4621 if((device->Flags&DEVICE_RUNNING))
4622 V0(device->Backend,stop)();
4623 device->Flags &= ~DEVICE_RUNNING;
4624 device->Flags |= DEVICE_PAUSED;
4625 almtx_unlock(&device->BackendLock);
4627 if(device) ALCdevice_DecRef(device);
4630 /* alcDeviceResumeSOFT
4632 * Resume the DSP to restart audio processing.
4634 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4636 if(!VerifyDevice(&device) || device->Type != Playback)
4637 alcSetError(device, ALC_INVALID_DEVICE);
4638 else
4640 almtx_lock(&device->BackendLock);
4641 if((device->Flags&DEVICE_PAUSED))
4643 device->Flags &= ~DEVICE_PAUSED;
4644 if(ATOMIC_LOAD_SEQ(&device->ContextList) != NULL)
4646 if(V0(device->Backend,start)() != ALC_FALSE)
4647 device->Flags |= DEVICE_RUNNING;
4648 else
4650 V0(device->Backend,lock)();
4651 aluHandleDisconnect(device, "Device start failure");
4652 V0(device->Backend,unlock)();
4653 alcSetError(device, ALC_INVALID_DEVICE);
4657 almtx_unlock(&device->BackendLock);
4659 if(device) ALCdevice_DecRef(device);
4663 /************************************************
4664 * ALC HRTF functions
4665 ************************************************/
4667 /* alcGetStringiSOFT
4669 * Gets a string parameter at the given index.
4671 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4673 const ALCchar *str = NULL;
4675 if(!VerifyDevice(&device) || device->Type == Capture)
4676 alcSetError(device, ALC_INVALID_DEVICE);
4677 else switch(paramName)
4679 case ALC_HRTF_SPECIFIER_SOFT:
4680 if(index >= 0 && (size_t)index < VECTOR_SIZE(device->HrtfList))
4681 str = alstr_get_cstr(VECTOR_ELEM(device->HrtfList, index).name);
4682 else
4683 alcSetError(device, ALC_INVALID_VALUE);
4684 break;
4686 default:
4687 alcSetError(device, ALC_INVALID_ENUM);
4688 break;
4690 if(device) ALCdevice_DecRef(device);
4692 return str;
4695 /* alcResetDeviceSOFT
4697 * Resets the given device output, using the specified attribute list.
4699 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4701 ALCenum err;
4703 LockLists();
4704 if(!VerifyDevice(&device) || device->Type == Capture ||
4705 !ATOMIC_LOAD(&device->Connected, almemory_order_relaxed))
4707 UnlockLists();
4708 alcSetError(device, ALC_INVALID_DEVICE);
4709 if(device) ALCdevice_DecRef(device);
4710 return ALC_FALSE;
4712 almtx_lock(&device->BackendLock);
4713 UnlockLists();
4715 err = UpdateDeviceParams(device, attribs);
4716 almtx_unlock(&device->BackendLock);
4718 if(err != ALC_NO_ERROR)
4720 alcSetError(device, err);
4721 if(err == ALC_INVALID_DEVICE)
4723 V0(device->Backend,lock)();
4724 aluHandleDisconnect(device, "Device start failure");
4725 V0(device->Backend,unlock)();
4727 ALCdevice_DecRef(device);
4728 return ALC_FALSE;
4730 ALCdevice_DecRef(device);
4732 return ALC_TRUE;