Make bformatdec_free and ambiup_free clear the freed pointer
[openal-soft.git] / Alc / ALc.c
blob8c7438381a3d4a0cfaf0a185247e2d95cd733b6b
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 "alAuxEffectSlot.h"
38 #include "alError.h"
39 #include "mastering.h"
40 #include "bformatdec.h"
41 #include "alu.h"
42 #include "alconfig.h"
43 #include "ringbuffer.h"
45 #include "fpu_modes.h"
46 #include "cpu_caps.h"
47 #include "compat.h"
48 #include "threads.h"
49 #include "alstring.h"
50 #include "almalloc.h"
52 #include "backends/base.h"
55 /************************************************
56 * Backends
57 ************************************************/
58 struct BackendInfo {
59 const char *name;
60 ALCbackendFactory* (*getFactory)(void);
63 static struct BackendInfo BackendList[] = {
64 #ifdef HAVE_JACK
65 { "jack", ALCjackBackendFactory_getFactory },
66 #endif
67 #ifdef HAVE_PULSEAUDIO
68 { "pulse", ALCpulseBackendFactory_getFactory },
69 #endif
70 #ifdef HAVE_ALSA
71 { "alsa", ALCalsaBackendFactory_getFactory },
72 #endif
73 #ifdef HAVE_COREAUDIO
74 { "core", ALCcoreAudioBackendFactory_getFactory },
75 #endif
76 #ifdef HAVE_OSS
77 { "oss", ALCossBackendFactory_getFactory },
78 #endif
79 #ifdef HAVE_SOLARIS
80 { "solaris", ALCsolarisBackendFactory_getFactory },
81 #endif
82 #ifdef HAVE_SNDIO
83 { "sndio", ALCsndioBackendFactory_getFactory },
84 #endif
85 #ifdef HAVE_QSA
86 { "qsa", ALCqsaBackendFactory_getFactory },
87 #endif
88 #ifdef HAVE_MMDEVAPI
89 { "mmdevapi", ALCmmdevBackendFactory_getFactory },
90 #endif
91 #ifdef HAVE_DSOUND
92 { "dsound", ALCdsoundBackendFactory_getFactory },
93 #endif
94 #ifdef HAVE_WINMM
95 { "winmm", ALCwinmmBackendFactory_getFactory },
96 #endif
97 #ifdef HAVE_PORTAUDIO
98 { "port", ALCportBackendFactory_getFactory },
99 #endif
100 #ifdef HAVE_OPENSL
101 { "opensl", ALCopenslBackendFactory_getFactory },
102 #endif
104 { "null", ALCnullBackendFactory_getFactory },
105 #ifdef HAVE_WAVE
106 { "wave", ALCwaveBackendFactory_getFactory },
107 #endif
109 static ALsizei BackendListSize = COUNTOF(BackendList);
110 #undef EmptyFuncs
112 static struct BackendInfo PlaybackBackend;
113 static struct BackendInfo CaptureBackend;
116 /************************************************
117 * Functions, enums, and errors
118 ************************************************/
119 #define DECL(x) { #x, (ALCvoid*)(x) }
120 static const struct {
121 const ALCchar *funcName;
122 ALCvoid *address;
123 } alcFunctions[] = {
124 DECL(alcCreateContext),
125 DECL(alcMakeContextCurrent),
126 DECL(alcProcessContext),
127 DECL(alcSuspendContext),
128 DECL(alcDestroyContext),
129 DECL(alcGetCurrentContext),
130 DECL(alcGetContextsDevice),
131 DECL(alcOpenDevice),
132 DECL(alcCloseDevice),
133 DECL(alcGetError),
134 DECL(alcIsExtensionPresent),
135 DECL(alcGetProcAddress),
136 DECL(alcGetEnumValue),
137 DECL(alcGetString),
138 DECL(alcGetIntegerv),
139 DECL(alcCaptureOpenDevice),
140 DECL(alcCaptureCloseDevice),
141 DECL(alcCaptureStart),
142 DECL(alcCaptureStop),
143 DECL(alcCaptureSamples),
145 DECL(alcSetThreadContext),
146 DECL(alcGetThreadContext),
148 DECL(alcLoopbackOpenDeviceSOFT),
149 DECL(alcIsRenderFormatSupportedSOFT),
150 DECL(alcRenderSamplesSOFT),
152 DECL(alcDevicePauseSOFT),
153 DECL(alcDeviceResumeSOFT),
155 DECL(alcGetStringiSOFT),
156 DECL(alcResetDeviceSOFT),
158 DECL(alcGetInteger64vSOFT),
160 DECL(alEnable),
161 DECL(alDisable),
162 DECL(alIsEnabled),
163 DECL(alGetString),
164 DECL(alGetBooleanv),
165 DECL(alGetIntegerv),
166 DECL(alGetFloatv),
167 DECL(alGetDoublev),
168 DECL(alGetBoolean),
169 DECL(alGetInteger),
170 DECL(alGetFloat),
171 DECL(alGetDouble),
172 DECL(alGetError),
173 DECL(alIsExtensionPresent),
174 DECL(alGetProcAddress),
175 DECL(alGetEnumValue),
176 DECL(alListenerf),
177 DECL(alListener3f),
178 DECL(alListenerfv),
179 DECL(alListeneri),
180 DECL(alListener3i),
181 DECL(alListeneriv),
182 DECL(alGetListenerf),
183 DECL(alGetListener3f),
184 DECL(alGetListenerfv),
185 DECL(alGetListeneri),
186 DECL(alGetListener3i),
187 DECL(alGetListeneriv),
188 DECL(alGenSources),
189 DECL(alDeleteSources),
190 DECL(alIsSource),
191 DECL(alSourcef),
192 DECL(alSource3f),
193 DECL(alSourcefv),
194 DECL(alSourcei),
195 DECL(alSource3i),
196 DECL(alSourceiv),
197 DECL(alGetSourcef),
198 DECL(alGetSource3f),
199 DECL(alGetSourcefv),
200 DECL(alGetSourcei),
201 DECL(alGetSource3i),
202 DECL(alGetSourceiv),
203 DECL(alSourcePlayv),
204 DECL(alSourceStopv),
205 DECL(alSourceRewindv),
206 DECL(alSourcePausev),
207 DECL(alSourcePlay),
208 DECL(alSourceStop),
209 DECL(alSourceRewind),
210 DECL(alSourcePause),
211 DECL(alSourceQueueBuffers),
212 DECL(alSourceUnqueueBuffers),
213 DECL(alGenBuffers),
214 DECL(alDeleteBuffers),
215 DECL(alIsBuffer),
216 DECL(alBufferData),
217 DECL(alBufferf),
218 DECL(alBuffer3f),
219 DECL(alBufferfv),
220 DECL(alBufferi),
221 DECL(alBuffer3i),
222 DECL(alBufferiv),
223 DECL(alGetBufferf),
224 DECL(alGetBuffer3f),
225 DECL(alGetBufferfv),
226 DECL(alGetBufferi),
227 DECL(alGetBuffer3i),
228 DECL(alGetBufferiv),
229 DECL(alDopplerFactor),
230 DECL(alDopplerVelocity),
231 DECL(alSpeedOfSound),
232 DECL(alDistanceModel),
234 DECL(alGenFilters),
235 DECL(alDeleteFilters),
236 DECL(alIsFilter),
237 DECL(alFilteri),
238 DECL(alFilteriv),
239 DECL(alFilterf),
240 DECL(alFilterfv),
241 DECL(alGetFilteri),
242 DECL(alGetFilteriv),
243 DECL(alGetFilterf),
244 DECL(alGetFilterfv),
245 DECL(alGenEffects),
246 DECL(alDeleteEffects),
247 DECL(alIsEffect),
248 DECL(alEffecti),
249 DECL(alEffectiv),
250 DECL(alEffectf),
251 DECL(alEffectfv),
252 DECL(alGetEffecti),
253 DECL(alGetEffectiv),
254 DECL(alGetEffectf),
255 DECL(alGetEffectfv),
256 DECL(alGenAuxiliaryEffectSlots),
257 DECL(alDeleteAuxiliaryEffectSlots),
258 DECL(alIsAuxiliaryEffectSlot),
259 DECL(alAuxiliaryEffectSloti),
260 DECL(alAuxiliaryEffectSlotiv),
261 DECL(alAuxiliaryEffectSlotf),
262 DECL(alAuxiliaryEffectSlotfv),
263 DECL(alGetAuxiliaryEffectSloti),
264 DECL(alGetAuxiliaryEffectSlotiv),
265 DECL(alGetAuxiliaryEffectSlotf),
266 DECL(alGetAuxiliaryEffectSlotfv),
268 DECL(alDeferUpdatesSOFT),
269 DECL(alProcessUpdatesSOFT),
271 DECL(alSourcedSOFT),
272 DECL(alSource3dSOFT),
273 DECL(alSourcedvSOFT),
274 DECL(alGetSourcedSOFT),
275 DECL(alGetSource3dSOFT),
276 DECL(alGetSourcedvSOFT),
277 DECL(alSourcei64SOFT),
278 DECL(alSource3i64SOFT),
279 DECL(alSourcei64vSOFT),
280 DECL(alGetSourcei64SOFT),
281 DECL(alGetSource3i64SOFT),
282 DECL(alGetSourcei64vSOFT),
284 DECL(alGetStringiSOFT),
286 DECL(alBufferStorageSOFT),
287 DECL(alMapBufferSOFT),
288 DECL(alUnmapBufferSOFT),
289 DECL(alFlushMappedBufferSOFT),
291 DECL(alEventControlSOFT),
292 DECL(alEventCallbackSOFT),
293 DECL(alGetPointerSOFT),
294 DECL(alGetPointervSOFT),
296 #undef DECL
298 #define DECL(x) { #x, (x) }
299 static const struct {
300 const ALCchar *enumName;
301 ALCenum value;
302 } alcEnumerations[] = {
303 DECL(ALC_INVALID),
304 DECL(ALC_FALSE),
305 DECL(ALC_TRUE),
307 DECL(ALC_MAJOR_VERSION),
308 DECL(ALC_MINOR_VERSION),
309 DECL(ALC_ATTRIBUTES_SIZE),
310 DECL(ALC_ALL_ATTRIBUTES),
311 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
312 DECL(ALC_DEVICE_SPECIFIER),
313 DECL(ALC_ALL_DEVICES_SPECIFIER),
314 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
315 DECL(ALC_EXTENSIONS),
316 DECL(ALC_FREQUENCY),
317 DECL(ALC_REFRESH),
318 DECL(ALC_SYNC),
319 DECL(ALC_MONO_SOURCES),
320 DECL(ALC_STEREO_SOURCES),
321 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
322 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
323 DECL(ALC_CAPTURE_SAMPLES),
324 DECL(ALC_CONNECTED),
326 DECL(ALC_EFX_MAJOR_VERSION),
327 DECL(ALC_EFX_MINOR_VERSION),
328 DECL(ALC_MAX_AUXILIARY_SENDS),
330 DECL(ALC_FORMAT_CHANNELS_SOFT),
331 DECL(ALC_FORMAT_TYPE_SOFT),
333 DECL(ALC_MONO_SOFT),
334 DECL(ALC_STEREO_SOFT),
335 DECL(ALC_QUAD_SOFT),
336 DECL(ALC_5POINT1_SOFT),
337 DECL(ALC_6POINT1_SOFT),
338 DECL(ALC_7POINT1_SOFT),
339 DECL(ALC_BFORMAT3D_SOFT),
341 DECL(ALC_BYTE_SOFT),
342 DECL(ALC_UNSIGNED_BYTE_SOFT),
343 DECL(ALC_SHORT_SOFT),
344 DECL(ALC_UNSIGNED_SHORT_SOFT),
345 DECL(ALC_INT_SOFT),
346 DECL(ALC_UNSIGNED_INT_SOFT),
347 DECL(ALC_FLOAT_SOFT),
349 DECL(ALC_HRTF_SOFT),
350 DECL(ALC_DONT_CARE_SOFT),
351 DECL(ALC_HRTF_STATUS_SOFT),
352 DECL(ALC_HRTF_DISABLED_SOFT),
353 DECL(ALC_HRTF_ENABLED_SOFT),
354 DECL(ALC_HRTF_DENIED_SOFT),
355 DECL(ALC_HRTF_REQUIRED_SOFT),
356 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
357 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
358 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
359 DECL(ALC_HRTF_SPECIFIER_SOFT),
360 DECL(ALC_HRTF_ID_SOFT),
362 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
363 DECL(ALC_AMBISONIC_SCALING_SOFT),
364 DECL(ALC_AMBISONIC_ORDER_SOFT),
365 DECL(ALC_ACN_SOFT),
366 DECL(ALC_FUMA_SOFT),
367 DECL(ALC_N3D_SOFT),
368 DECL(ALC_SN3D_SOFT),
370 DECL(ALC_OUTPUT_LIMITER_SOFT),
372 DECL(ALC_NO_ERROR),
373 DECL(ALC_INVALID_DEVICE),
374 DECL(ALC_INVALID_CONTEXT),
375 DECL(ALC_INVALID_ENUM),
376 DECL(ALC_INVALID_VALUE),
377 DECL(ALC_OUT_OF_MEMORY),
380 DECL(AL_INVALID),
381 DECL(AL_NONE),
382 DECL(AL_FALSE),
383 DECL(AL_TRUE),
385 DECL(AL_SOURCE_RELATIVE),
386 DECL(AL_CONE_INNER_ANGLE),
387 DECL(AL_CONE_OUTER_ANGLE),
388 DECL(AL_PITCH),
389 DECL(AL_POSITION),
390 DECL(AL_DIRECTION),
391 DECL(AL_VELOCITY),
392 DECL(AL_LOOPING),
393 DECL(AL_BUFFER),
394 DECL(AL_GAIN),
395 DECL(AL_MIN_GAIN),
396 DECL(AL_MAX_GAIN),
397 DECL(AL_ORIENTATION),
398 DECL(AL_REFERENCE_DISTANCE),
399 DECL(AL_ROLLOFF_FACTOR),
400 DECL(AL_CONE_OUTER_GAIN),
401 DECL(AL_MAX_DISTANCE),
402 DECL(AL_SEC_OFFSET),
403 DECL(AL_SAMPLE_OFFSET),
404 DECL(AL_BYTE_OFFSET),
405 DECL(AL_SOURCE_TYPE),
406 DECL(AL_STATIC),
407 DECL(AL_STREAMING),
408 DECL(AL_UNDETERMINED),
409 DECL(AL_METERS_PER_UNIT),
410 DECL(AL_LOOP_POINTS_SOFT),
411 DECL(AL_DIRECT_CHANNELS_SOFT),
413 DECL(AL_DIRECT_FILTER),
414 DECL(AL_AUXILIARY_SEND_FILTER),
415 DECL(AL_AIR_ABSORPTION_FACTOR),
416 DECL(AL_ROOM_ROLLOFF_FACTOR),
417 DECL(AL_CONE_OUTER_GAINHF),
418 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
419 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
420 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
422 DECL(AL_SOURCE_STATE),
423 DECL(AL_INITIAL),
424 DECL(AL_PLAYING),
425 DECL(AL_PAUSED),
426 DECL(AL_STOPPED),
428 DECL(AL_BUFFERS_QUEUED),
429 DECL(AL_BUFFERS_PROCESSED),
431 DECL(AL_FORMAT_MONO8),
432 DECL(AL_FORMAT_MONO16),
433 DECL(AL_FORMAT_MONO_FLOAT32),
434 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
435 DECL(AL_FORMAT_STEREO8),
436 DECL(AL_FORMAT_STEREO16),
437 DECL(AL_FORMAT_STEREO_FLOAT32),
438 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
439 DECL(AL_FORMAT_MONO_IMA4),
440 DECL(AL_FORMAT_STEREO_IMA4),
441 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
442 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
443 DECL(AL_FORMAT_QUAD8_LOKI),
444 DECL(AL_FORMAT_QUAD16_LOKI),
445 DECL(AL_FORMAT_QUAD8),
446 DECL(AL_FORMAT_QUAD16),
447 DECL(AL_FORMAT_QUAD32),
448 DECL(AL_FORMAT_51CHN8),
449 DECL(AL_FORMAT_51CHN16),
450 DECL(AL_FORMAT_51CHN32),
451 DECL(AL_FORMAT_61CHN8),
452 DECL(AL_FORMAT_61CHN16),
453 DECL(AL_FORMAT_61CHN32),
454 DECL(AL_FORMAT_71CHN8),
455 DECL(AL_FORMAT_71CHN16),
456 DECL(AL_FORMAT_71CHN32),
457 DECL(AL_FORMAT_REAR8),
458 DECL(AL_FORMAT_REAR16),
459 DECL(AL_FORMAT_REAR32),
460 DECL(AL_FORMAT_MONO_MULAW),
461 DECL(AL_FORMAT_MONO_MULAW_EXT),
462 DECL(AL_FORMAT_STEREO_MULAW),
463 DECL(AL_FORMAT_STEREO_MULAW_EXT),
464 DECL(AL_FORMAT_QUAD_MULAW),
465 DECL(AL_FORMAT_51CHN_MULAW),
466 DECL(AL_FORMAT_61CHN_MULAW),
467 DECL(AL_FORMAT_71CHN_MULAW),
468 DECL(AL_FORMAT_REAR_MULAW),
469 DECL(AL_FORMAT_MONO_ALAW_EXT),
470 DECL(AL_FORMAT_STEREO_ALAW_EXT),
472 DECL(AL_FORMAT_BFORMAT2D_8),
473 DECL(AL_FORMAT_BFORMAT2D_16),
474 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
475 DECL(AL_FORMAT_BFORMAT2D_MULAW),
476 DECL(AL_FORMAT_BFORMAT3D_8),
477 DECL(AL_FORMAT_BFORMAT3D_16),
478 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
479 DECL(AL_FORMAT_BFORMAT3D_MULAW),
481 DECL(AL_FREQUENCY),
482 DECL(AL_BITS),
483 DECL(AL_CHANNELS),
484 DECL(AL_SIZE),
485 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
486 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
488 DECL(AL_SOURCE_RADIUS),
490 DECL(AL_STEREO_ANGLES),
492 DECL(AL_UNUSED),
493 DECL(AL_PENDING),
494 DECL(AL_PROCESSED),
496 DECL(AL_NO_ERROR),
497 DECL(AL_INVALID_NAME),
498 DECL(AL_INVALID_ENUM),
499 DECL(AL_INVALID_VALUE),
500 DECL(AL_INVALID_OPERATION),
501 DECL(AL_OUT_OF_MEMORY),
503 DECL(AL_VENDOR),
504 DECL(AL_VERSION),
505 DECL(AL_RENDERER),
506 DECL(AL_EXTENSIONS),
508 DECL(AL_DOPPLER_FACTOR),
509 DECL(AL_DOPPLER_VELOCITY),
510 DECL(AL_DISTANCE_MODEL),
511 DECL(AL_SPEED_OF_SOUND),
512 DECL(AL_SOURCE_DISTANCE_MODEL),
513 DECL(AL_DEFERRED_UPDATES_SOFT),
514 DECL(AL_GAIN_LIMIT_SOFT),
516 DECL(AL_INVERSE_DISTANCE),
517 DECL(AL_INVERSE_DISTANCE_CLAMPED),
518 DECL(AL_LINEAR_DISTANCE),
519 DECL(AL_LINEAR_DISTANCE_CLAMPED),
520 DECL(AL_EXPONENT_DISTANCE),
521 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
523 DECL(AL_FILTER_TYPE),
524 DECL(AL_FILTER_NULL),
525 DECL(AL_FILTER_LOWPASS),
526 DECL(AL_FILTER_HIGHPASS),
527 DECL(AL_FILTER_BANDPASS),
529 DECL(AL_LOWPASS_GAIN),
530 DECL(AL_LOWPASS_GAINHF),
532 DECL(AL_HIGHPASS_GAIN),
533 DECL(AL_HIGHPASS_GAINLF),
535 DECL(AL_BANDPASS_GAIN),
536 DECL(AL_BANDPASS_GAINHF),
537 DECL(AL_BANDPASS_GAINLF),
539 DECL(AL_EFFECT_TYPE),
540 DECL(AL_EFFECT_NULL),
541 DECL(AL_EFFECT_REVERB),
542 DECL(AL_EFFECT_EAXREVERB),
543 DECL(AL_EFFECT_CHORUS),
544 DECL(AL_EFFECT_DISTORTION),
545 DECL(AL_EFFECT_ECHO),
546 DECL(AL_EFFECT_FLANGER),
547 #if 0
548 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
549 DECL(AL_EFFECT_VOCAL_MORPHER),
550 DECL(AL_EFFECT_PITCH_SHIFTER),
551 #endif
552 DECL(AL_EFFECT_RING_MODULATOR),
553 #if 0
554 DECL(AL_EFFECT_AUTOWAH),
555 #endif
556 DECL(AL_EFFECT_COMPRESSOR),
557 DECL(AL_EFFECT_EQUALIZER),
558 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
559 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
561 DECL(AL_EFFECTSLOT_EFFECT),
562 DECL(AL_EFFECTSLOT_GAIN),
563 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
564 DECL(AL_EFFECTSLOT_NULL),
566 DECL(AL_EAXREVERB_DENSITY),
567 DECL(AL_EAXREVERB_DIFFUSION),
568 DECL(AL_EAXREVERB_GAIN),
569 DECL(AL_EAXREVERB_GAINHF),
570 DECL(AL_EAXREVERB_GAINLF),
571 DECL(AL_EAXREVERB_DECAY_TIME),
572 DECL(AL_EAXREVERB_DECAY_HFRATIO),
573 DECL(AL_EAXREVERB_DECAY_LFRATIO),
574 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
575 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
576 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
577 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
578 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
579 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
580 DECL(AL_EAXREVERB_ECHO_TIME),
581 DECL(AL_EAXREVERB_ECHO_DEPTH),
582 DECL(AL_EAXREVERB_MODULATION_TIME),
583 DECL(AL_EAXREVERB_MODULATION_DEPTH),
584 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
585 DECL(AL_EAXREVERB_HFREFERENCE),
586 DECL(AL_EAXREVERB_LFREFERENCE),
587 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
588 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
590 DECL(AL_REVERB_DENSITY),
591 DECL(AL_REVERB_DIFFUSION),
592 DECL(AL_REVERB_GAIN),
593 DECL(AL_REVERB_GAINHF),
594 DECL(AL_REVERB_DECAY_TIME),
595 DECL(AL_REVERB_DECAY_HFRATIO),
596 DECL(AL_REVERB_REFLECTIONS_GAIN),
597 DECL(AL_REVERB_REFLECTIONS_DELAY),
598 DECL(AL_REVERB_LATE_REVERB_GAIN),
599 DECL(AL_REVERB_LATE_REVERB_DELAY),
600 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
601 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
602 DECL(AL_REVERB_DECAY_HFLIMIT),
604 DECL(AL_CHORUS_WAVEFORM),
605 DECL(AL_CHORUS_PHASE),
606 DECL(AL_CHORUS_RATE),
607 DECL(AL_CHORUS_DEPTH),
608 DECL(AL_CHORUS_FEEDBACK),
609 DECL(AL_CHORUS_DELAY),
611 DECL(AL_DISTORTION_EDGE),
612 DECL(AL_DISTORTION_GAIN),
613 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
614 DECL(AL_DISTORTION_EQCENTER),
615 DECL(AL_DISTORTION_EQBANDWIDTH),
617 DECL(AL_ECHO_DELAY),
618 DECL(AL_ECHO_LRDELAY),
619 DECL(AL_ECHO_DAMPING),
620 DECL(AL_ECHO_FEEDBACK),
621 DECL(AL_ECHO_SPREAD),
623 DECL(AL_FLANGER_WAVEFORM),
624 DECL(AL_FLANGER_PHASE),
625 DECL(AL_FLANGER_RATE),
626 DECL(AL_FLANGER_DEPTH),
627 DECL(AL_FLANGER_FEEDBACK),
628 DECL(AL_FLANGER_DELAY),
630 DECL(AL_RING_MODULATOR_FREQUENCY),
631 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
632 DECL(AL_RING_MODULATOR_WAVEFORM),
634 DECL(AL_COMPRESSOR_ONOFF),
636 DECL(AL_EQUALIZER_LOW_GAIN),
637 DECL(AL_EQUALIZER_LOW_CUTOFF),
638 DECL(AL_EQUALIZER_MID1_GAIN),
639 DECL(AL_EQUALIZER_MID1_CENTER),
640 DECL(AL_EQUALIZER_MID1_WIDTH),
641 DECL(AL_EQUALIZER_MID2_GAIN),
642 DECL(AL_EQUALIZER_MID2_CENTER),
643 DECL(AL_EQUALIZER_MID2_WIDTH),
644 DECL(AL_EQUALIZER_HIGH_GAIN),
645 DECL(AL_EQUALIZER_HIGH_CUTOFF),
647 DECL(AL_DEDICATED_GAIN),
649 DECL(AL_NUM_RESAMPLERS_SOFT),
650 DECL(AL_DEFAULT_RESAMPLER_SOFT),
651 DECL(AL_SOURCE_RESAMPLER_SOFT),
652 DECL(AL_RESAMPLER_NAME_SOFT),
654 DECL(AL_SOURCE_SPATIALIZE_SOFT),
655 DECL(AL_AUTO_SOFT),
657 DECL(AL_MAP_READ_BIT_SOFT),
658 DECL(AL_MAP_WRITE_BIT_SOFT),
659 DECL(AL_MAP_PERSISTENT_BIT_SOFT),
660 DECL(AL_PRESERVE_DATA_BIT_SOFT),
662 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT),
663 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT),
664 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT),
665 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT),
666 DECL(AL_EVENT_TYPE_ERROR_SOFT),
667 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT),
668 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT),
670 #undef DECL
672 static const ALCchar alcNoError[] = "No Error";
673 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
674 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
675 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
676 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
677 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
680 /************************************************
681 * Global variables
682 ************************************************/
684 /* Enumerated device names */
685 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
687 static al_string alcAllDevicesList;
688 static al_string alcCaptureDeviceList;
690 /* Default is always the first in the list */
691 static ALCchar *alcDefaultAllDevicesSpecifier;
692 static ALCchar *alcCaptureDefaultDeviceSpecifier;
694 /* Default context extensions */
695 static const ALchar alExtList[] =
696 "AL_EXT_ALAW "
697 "AL_EXT_BFORMAT "
698 "AL_EXT_DOUBLE "
699 "AL_EXT_EXPONENT_DISTANCE "
700 "AL_EXT_FLOAT32 "
701 "AL_EXT_IMA4 "
702 "AL_EXT_LINEAR_DISTANCE "
703 "AL_EXT_MCFORMATS "
704 "AL_EXT_MULAW "
705 "AL_EXT_MULAW_BFORMAT "
706 "AL_EXT_MULAW_MCFORMATS "
707 "AL_EXT_OFFSET "
708 "AL_EXT_source_distance_model "
709 "AL_EXT_SOURCE_RADIUS "
710 "AL_EXT_STEREO_ANGLES "
711 "AL_LOKI_quadriphonic "
712 "AL_SOFT_block_alignment "
713 "AL_SOFT_deferred_updates "
714 "AL_SOFT_direct_channels "
715 "AL_SOFTX_events "
716 "AL_SOFT_gain_clamp_ex "
717 "AL_SOFT_loop_points "
718 "AL_SOFTX_map_buffer "
719 "AL_SOFT_MSADPCM "
720 "AL_SOFT_source_latency "
721 "AL_SOFT_source_length "
722 "AL_SOFT_source_resampler "
723 "AL_SOFT_source_spatialize";
725 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
727 /* Thread-local current context */
728 static altss_t LocalContext;
729 /* Process-wide current context */
730 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
732 /* Mixing thread piority level */
733 ALint RTPrioLevel;
735 FILE *LogFile;
736 #ifdef _DEBUG
737 enum LogLevel LogLevel = LogWarning;
738 #else
739 enum LogLevel LogLevel = LogError;
740 #endif
742 /* Flag to trap ALC device errors */
743 static ALCboolean TrapALCError = ALC_FALSE;
745 /* One-time configuration init control */
746 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
748 /* Default effect that applies to sources that don't have an effect on send 0 */
749 static ALeffect DefaultEffect;
751 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
752 * updates.
754 static ALCboolean SuspendDefers = ALC_TRUE;
757 /************************************************
758 * ALC information
759 ************************************************/
760 static const ALCchar alcNoDeviceExtList[] =
761 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
762 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
763 static const ALCchar alcExtensionList[] =
764 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
765 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
766 "ALC_EXT_thread_local_context ALC_SOFT_device_clock ALC_SOFT_HRTF "
767 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
768 static const ALCint alcMajorVersion = 1;
769 static const ALCint alcMinorVersion = 1;
771 static const ALCint alcEFXMajorVersion = 1;
772 static const ALCint alcEFXMinorVersion = 0;
775 /************************************************
776 * Device lists
777 ************************************************/
778 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
780 static almtx_t ListLock;
781 static inline void LockLists(void)
783 int ret = almtx_lock(&ListLock);
784 assert(ret == althrd_success);
786 static inline void UnlockLists(void)
788 int ret = almtx_unlock(&ListLock);
789 assert(ret == althrd_success);
792 /************************************************
793 * Library initialization
794 ************************************************/
795 #if defined(_WIN32)
796 static void alc_init(void);
797 static void alc_deinit(void);
798 static void alc_deinit_safe(void);
800 #ifndef AL_LIBTYPE_STATIC
801 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
803 switch(reason)
805 case DLL_PROCESS_ATTACH:
806 /* Pin the DLL so we won't get unloaded until the process terminates */
807 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
808 (WCHAR*)hModule, &hModule);
809 alc_init();
810 break;
812 case DLL_THREAD_DETACH:
813 break;
815 case DLL_PROCESS_DETACH:
816 if(!lpReserved)
817 alc_deinit();
818 else
819 alc_deinit_safe();
820 break;
822 return TRUE;
824 #elif defined(_MSC_VER)
825 #pragma section(".CRT$XCU",read)
826 static void alc_constructor(void);
827 static void alc_destructor(void);
828 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
830 static void alc_constructor(void)
832 atexit(alc_destructor);
833 alc_init();
836 static void alc_destructor(void)
838 alc_deinit();
840 #elif defined(HAVE_GCC_DESTRUCTOR)
841 static void alc_init(void) __attribute__((constructor));
842 static void alc_deinit(void) __attribute__((destructor));
843 #else
844 #error "No static initialization available on this platform!"
845 #endif
847 #elif defined(HAVE_GCC_DESTRUCTOR)
849 static void alc_init(void) __attribute__((constructor));
850 static void alc_deinit(void) __attribute__((destructor));
852 #else
853 #error "No global initialization available on this platform!"
854 #endif
856 static void ReleaseThreadCtx(void *ptr);
857 static void alc_init(void)
859 const char *str;
860 int ret;
862 LogFile = stderr;
864 AL_STRING_INIT(alcAllDevicesList);
865 AL_STRING_INIT(alcCaptureDeviceList);
867 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
868 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
869 ConeScale *= 0.5f;
871 str = getenv("__ALSOFT_REVERSE_Z");
872 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
873 ZScale *= -1.0f;
875 str = getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
876 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
877 OverrideReverbSpeedOfSound = AL_TRUE;
879 ret = altss_create(&LocalContext, ReleaseThreadCtx);
880 assert(ret == althrd_success);
882 ret = almtx_init(&ListLock, almtx_recursive);
883 assert(ret == althrd_success);
886 static void alc_initconfig(void)
888 const char *devs, *str;
889 int capfilter;
890 float valf;
891 int i, n;
893 str = getenv("ALSOFT_LOGLEVEL");
894 if(str)
896 long lvl = strtol(str, NULL, 0);
897 if(lvl >= NoLog && lvl <= LogRef)
898 LogLevel = lvl;
901 str = getenv("ALSOFT_LOGFILE");
902 if(str && str[0])
904 FILE *logfile = al_fopen(str, "wt");
905 if(logfile) LogFile = logfile;
906 else ERR("Failed to open log file '%s'\n", str);
909 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION,
910 ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH);
912 char buf[1024] = "";
913 int len = 0;
915 if(BackendListSize > 0)
916 len += snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
917 for(i = 1;i < BackendListSize;i++)
918 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
919 TRACE("Supported backends: %s\n", buf);
921 ReadALConfig();
923 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
924 if(str && *str)
926 if(strcasecmp(str, "ignore") == 0)
928 SuspendDefers = ALC_FALSE;
929 TRACE("Selected context suspend behavior, \"ignore\"\n");
931 else
932 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
935 capfilter = 0;
936 #if defined(HAVE_SSE4_1)
937 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
938 #elif defined(HAVE_SSE3)
939 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
940 #elif defined(HAVE_SSE2)
941 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
942 #elif defined(HAVE_SSE)
943 capfilter |= CPU_CAP_SSE;
944 #endif
945 #ifdef HAVE_NEON
946 capfilter |= CPU_CAP_NEON;
947 #endif
948 if(ConfigValueStr(NULL, NULL, "disable-cpu-exts", &str))
950 if(strcasecmp(str, "all") == 0)
951 capfilter = 0;
952 else
954 size_t len;
955 const char *next = str;
957 do {
958 str = next;
959 while(isspace(str[0]))
960 str++;
961 next = strchr(str, ',');
963 if(!str[0] || str[0] == ',')
964 continue;
966 len = (next ? ((size_t)(next-str)) : strlen(str));
967 while(len > 0 && isspace(str[len-1]))
968 len--;
969 if(len == 3 && strncasecmp(str, "sse", len) == 0)
970 capfilter &= ~CPU_CAP_SSE;
971 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
972 capfilter &= ~CPU_CAP_SSE2;
973 else if(len == 4 && strncasecmp(str, "sse3", len) == 0)
974 capfilter &= ~CPU_CAP_SSE3;
975 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
976 capfilter &= ~CPU_CAP_SSE4_1;
977 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
978 capfilter &= ~CPU_CAP_NEON;
979 else
980 WARN("Invalid CPU extension \"%s\"\n", str);
981 } while(next++);
984 FillCPUCaps(capfilter);
986 #ifdef _WIN32
987 RTPrioLevel = 1;
988 #else
989 RTPrioLevel = 0;
990 #endif
991 ConfigValueInt(NULL, NULL, "rt-prio", &RTPrioLevel);
993 aluInit();
994 aluInitMixer();
996 str = getenv("ALSOFT_TRAP_ERROR");
997 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
999 TrapALError = AL_TRUE;
1000 TrapALCError = AL_TRUE;
1002 else
1004 str = getenv("ALSOFT_TRAP_AL_ERROR");
1005 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1006 TrapALError = AL_TRUE;
1007 TrapALError = GetConfigValueBool(NULL, NULL, "trap-al-error", TrapALError);
1009 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1010 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1011 TrapALCError = ALC_TRUE;
1012 TrapALCError = GetConfigValueBool(NULL, NULL, "trap-alc-error", TrapALCError);
1015 if(ConfigValueFloat(NULL, "reverb", "boost", &valf))
1016 ReverbBoost *= powf(10.0f, valf / 20.0f);
1018 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1019 ConfigValueStr(NULL, NULL, "drivers", &devs))
1021 int n;
1022 size_t len;
1023 const char *next = devs;
1024 int endlist, delitem;
1026 i = 0;
1027 do {
1028 devs = next;
1029 while(isspace(devs[0]))
1030 devs++;
1031 next = strchr(devs, ',');
1033 delitem = (devs[0] == '-');
1034 if(devs[0] == '-') devs++;
1036 if(!devs[0] || devs[0] == ',')
1038 endlist = 0;
1039 continue;
1041 endlist = 1;
1043 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1044 while(len > 0 && isspace(devs[len-1]))
1045 len--;
1046 for(n = i;n < BackendListSize;n++)
1048 if(len == strlen(BackendList[n].name) &&
1049 strncmp(BackendList[n].name, devs, len) == 0)
1051 if(delitem)
1053 for(;n+1 < BackendListSize;n++)
1054 BackendList[n] = BackendList[n+1];
1055 BackendListSize--;
1057 else
1059 struct BackendInfo Bkp = BackendList[n];
1060 for(;n > i;n--)
1061 BackendList[n] = BackendList[n-1];
1062 BackendList[n] = Bkp;
1064 i++;
1066 break;
1069 } while(next++);
1071 if(endlist)
1072 BackendListSize = i;
1075 for(i = 0;i < BackendListSize && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1077 ALCbackendFactory *factory = BackendList[i].getFactory();
1078 if(!V0(factory,init)())
1080 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1081 continue;
1084 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1085 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1087 PlaybackBackend = BackendList[i];
1088 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1090 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1092 CaptureBackend = BackendList[i];
1093 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1097 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1098 V0(factory,init)();
1101 if(!PlaybackBackend.name)
1102 WARN("No playback backend available!\n");
1103 if(!CaptureBackend.name)
1104 WARN("No capture backend available!\n");
1106 if(ConfigValueStr(NULL, NULL, "excludefx", &str))
1108 size_t len;
1109 const char *next = str;
1111 do {
1112 str = next;
1113 next = strchr(str, ',');
1115 if(!str[0] || next == str)
1116 continue;
1118 len = (next ? ((size_t)(next-str)) : strlen(str));
1119 for(n = 0;n < EFFECTLIST_SIZE;n++)
1121 if(len == strlen(EffectList[n].name) &&
1122 strncmp(EffectList[n].name, str, len) == 0)
1123 DisabledEffects[EffectList[n].type] = AL_TRUE;
1125 } while(next++);
1128 InitEffect(&DefaultEffect);
1129 str = getenv("ALSOFT_DEFAULT_REVERB");
1130 if((str && str[0]) || ConfigValueStr(NULL, NULL, "default-reverb", &str))
1131 LoadReverbPreset(str, &DefaultEffect);
1133 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1135 #ifdef __ANDROID__
1136 #include <jni.h>
1138 static JavaVM *gJavaVM;
1139 static pthread_key_t gJVMThreadKey;
1141 static void CleanupJNIEnv(void* UNUSED(ptr))
1143 JCALL0(gJavaVM,DetachCurrentThread)();
1146 void *Android_GetJNIEnv(void)
1148 if(!gJavaVM)
1150 WARN("gJavaVM is NULL!\n");
1151 return NULL;
1154 /* http://developer.android.com/guide/practices/jni.html
1156 * All threads are Linux threads, scheduled by the kernel. They're usually
1157 * started from managed code (using Thread.start), but they can also be
1158 * created elsewhere and then attached to the JavaVM. For example, a thread
1159 * started with pthread_create can be attached with the JNI
1160 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1161 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1162 * Attaching a natively-created thread causes a java.lang.Thread object to
1163 * be constructed and added to the "main" ThreadGroup, making it visible to
1164 * the debugger. Calling AttachCurrentThread on an already-attached thread
1165 * is a no-op.
1167 JNIEnv *env = pthread_getspecific(gJVMThreadKey);
1168 if(!env)
1170 int status = JCALL(gJavaVM,AttachCurrentThread)(&env, NULL);
1171 if(status < 0)
1173 ERR("Failed to attach current thread\n");
1174 return NULL;
1176 pthread_setspecific(gJVMThreadKey, env);
1178 return env;
1181 /* Automatically called by JNI. */
1182 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void* UNUSED(reserved))
1184 void *env;
1185 int err;
1187 gJavaVM = jvm;
1188 if(JCALL(gJavaVM,GetEnv)(&env, JNI_VERSION_1_4) != JNI_OK)
1190 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1191 return JNI_ERR;
1194 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1195 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1197 if((err=pthread_key_create(&gJVMThreadKey, CleanupJNIEnv)) != 0)
1198 ERR("pthread_key_create failed: %d\n", err);
1199 pthread_setspecific(gJVMThreadKey, env);
1200 return JNI_VERSION_1_4;
1202 #endif
1205 /************************************************
1206 * Library deinitialization
1207 ************************************************/
1208 static void alc_cleanup(void)
1210 ALCdevice *dev;
1212 AL_STRING_DEINIT(alcAllDevicesList);
1213 AL_STRING_DEINIT(alcCaptureDeviceList);
1215 free(alcDefaultAllDevicesSpecifier);
1216 alcDefaultAllDevicesSpecifier = NULL;
1217 free(alcCaptureDefaultDeviceSpecifier);
1218 alcCaptureDefaultDeviceSpecifier = NULL;
1220 if((dev=ATOMIC_EXCHANGE_PTR_SEQ(&DeviceList, NULL)) != NULL)
1222 ALCuint num = 0;
1223 do {
1224 num++;
1225 } while((dev=dev->next) != NULL);
1226 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1230 static void alc_deinit_safe(void)
1232 alc_cleanup();
1234 FreeHrtfs();
1235 FreeALConfig();
1237 almtx_destroy(&ListLock);
1238 altss_delete(LocalContext);
1240 if(LogFile != stderr)
1241 fclose(LogFile);
1242 LogFile = NULL;
1245 static void alc_deinit(void)
1247 int i;
1249 alc_cleanup();
1251 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1252 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1254 for(i = 0;i < BackendListSize;i++)
1256 ALCbackendFactory *factory = BackendList[i].getFactory();
1257 V0(factory,deinit)();
1260 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1261 V0(factory,deinit)();
1264 alc_deinit_safe();
1268 /************************************************
1269 * Device enumeration
1270 ************************************************/
1271 static void ProbeDevices(al_string *list, struct BackendInfo *backendinfo, enum DevProbe type)
1273 DO_INITCONFIG();
1275 LockLists();
1276 alstr_clear(list);
1278 if(backendinfo->getFactory)
1280 ALCbackendFactory *factory = backendinfo->getFactory();
1281 V(factory,probe)(type);
1284 UnlockLists();
1286 static void ProbeAllDevicesList(void)
1287 { ProbeDevices(&alcAllDevicesList, &PlaybackBackend, ALL_DEVICE_PROBE); }
1288 static void ProbeCaptureDeviceList(void)
1289 { ProbeDevices(&alcCaptureDeviceList, &CaptureBackend, CAPTURE_DEVICE_PROBE); }
1291 static void AppendDevice(const ALCchar *name, al_string *devnames)
1293 size_t len = strlen(name);
1294 if(len > 0)
1295 alstr_append_range(devnames, name, name+len+1);
1297 void AppendAllDevicesList(const ALCchar *name)
1298 { AppendDevice(name, &alcAllDevicesList); }
1299 void AppendCaptureDeviceList(const ALCchar *name)
1300 { AppendDevice(name, &alcCaptureDeviceList); }
1303 /************************************************
1304 * Device format information
1305 ************************************************/
1306 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1308 switch(type)
1310 case DevFmtByte: return "Signed Byte";
1311 case DevFmtUByte: return "Unsigned Byte";
1312 case DevFmtShort: return "Signed Short";
1313 case DevFmtUShort: return "Unsigned Short";
1314 case DevFmtInt: return "Signed Int";
1315 case DevFmtUInt: return "Unsigned Int";
1316 case DevFmtFloat: return "Float";
1318 return "(unknown type)";
1320 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1322 switch(chans)
1324 case DevFmtMono: return "Mono";
1325 case DevFmtStereo: return "Stereo";
1326 case DevFmtQuad: return "Quadraphonic";
1327 case DevFmtX51: return "5.1 Surround";
1328 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1329 case DevFmtX61: return "6.1 Surround";
1330 case DevFmtX71: return "7.1 Surround";
1331 case DevFmtAmbi3D: return "Ambisonic 3D";
1333 return "(unknown channels)";
1336 extern inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type, ALsizei ambiorder);
1337 ALsizei BytesFromDevFmt(enum DevFmtType type)
1339 switch(type)
1341 case DevFmtByte: return sizeof(ALbyte);
1342 case DevFmtUByte: return sizeof(ALubyte);
1343 case DevFmtShort: return sizeof(ALshort);
1344 case DevFmtUShort: return sizeof(ALushort);
1345 case DevFmtInt: return sizeof(ALint);
1346 case DevFmtUInt: return sizeof(ALuint);
1347 case DevFmtFloat: return sizeof(ALfloat);
1349 return 0;
1351 ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans, ALsizei ambiorder)
1353 switch(chans)
1355 case DevFmtMono: return 1;
1356 case DevFmtStereo: return 2;
1357 case DevFmtQuad: return 4;
1358 case DevFmtX51: return 6;
1359 case DevFmtX51Rear: return 6;
1360 case DevFmtX61: return 7;
1361 case DevFmtX71: return 8;
1362 case DevFmtAmbi3D: return (ambiorder >= 3) ? 16 :
1363 (ambiorder == 2) ? 9 :
1364 (ambiorder == 1) ? 4 : 1;
1366 return 0;
1369 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1370 enum DevFmtType *type)
1372 static const struct {
1373 ALenum format;
1374 enum DevFmtChannels channels;
1375 enum DevFmtType type;
1376 } list[] = {
1377 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1378 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1379 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1381 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1382 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1383 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1385 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1386 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1387 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1389 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1390 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1391 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1393 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1394 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1395 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1397 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1398 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1399 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1401 ALuint i;
1403 for(i = 0;i < COUNTOF(list);i++)
1405 if(list[i].format == format)
1407 *chans = list[i].channels;
1408 *type = list[i].type;
1409 return AL_TRUE;
1413 return AL_FALSE;
1416 static ALCboolean IsValidALCType(ALCenum type)
1418 switch(type)
1420 case ALC_BYTE_SOFT:
1421 case ALC_UNSIGNED_BYTE_SOFT:
1422 case ALC_SHORT_SOFT:
1423 case ALC_UNSIGNED_SHORT_SOFT:
1424 case ALC_INT_SOFT:
1425 case ALC_UNSIGNED_INT_SOFT:
1426 case ALC_FLOAT_SOFT:
1427 return ALC_TRUE;
1429 return ALC_FALSE;
1432 static ALCboolean IsValidALCChannels(ALCenum channels)
1434 switch(channels)
1436 case ALC_MONO_SOFT:
1437 case ALC_STEREO_SOFT:
1438 case ALC_QUAD_SOFT:
1439 case ALC_5POINT1_SOFT:
1440 case ALC_6POINT1_SOFT:
1441 case ALC_7POINT1_SOFT:
1442 case ALC_BFORMAT3D_SOFT:
1443 return ALC_TRUE;
1445 return ALC_FALSE;
1448 static ALCboolean IsValidAmbiLayout(ALCenum layout)
1450 switch(layout)
1452 case ALC_ACN_SOFT:
1453 case ALC_FUMA_SOFT:
1454 return ALC_TRUE;
1456 return ALC_FALSE;
1459 static ALCboolean IsValidAmbiScaling(ALCenum scaling)
1461 switch(scaling)
1463 case ALC_N3D_SOFT:
1464 case ALC_SN3D_SOFT:
1465 case ALC_FUMA_SOFT:
1466 return ALC_TRUE;
1468 return ALC_FALSE;
1471 /************************************************
1472 * Miscellaneous ALC helpers
1473 ************************************************/
1475 /* SetDefaultWFXChannelOrder
1477 * Sets the default channel order used by WaveFormatEx.
1479 void SetDefaultWFXChannelOrder(ALCdevice *device)
1481 ALsizei i;
1483 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1484 device->RealOut.ChannelName[i] = InvalidChannel;
1486 switch(device->FmtChans)
1488 case DevFmtMono:
1489 device->RealOut.ChannelName[0] = FrontCenter;
1490 break;
1491 case DevFmtStereo:
1492 device->RealOut.ChannelName[0] = FrontLeft;
1493 device->RealOut.ChannelName[1] = FrontRight;
1494 break;
1495 case DevFmtQuad:
1496 device->RealOut.ChannelName[0] = FrontLeft;
1497 device->RealOut.ChannelName[1] = FrontRight;
1498 device->RealOut.ChannelName[2] = BackLeft;
1499 device->RealOut.ChannelName[3] = BackRight;
1500 break;
1501 case DevFmtX51:
1502 device->RealOut.ChannelName[0] = FrontLeft;
1503 device->RealOut.ChannelName[1] = FrontRight;
1504 device->RealOut.ChannelName[2] = FrontCenter;
1505 device->RealOut.ChannelName[3] = LFE;
1506 device->RealOut.ChannelName[4] = SideLeft;
1507 device->RealOut.ChannelName[5] = SideRight;
1508 break;
1509 case DevFmtX51Rear:
1510 device->RealOut.ChannelName[0] = FrontLeft;
1511 device->RealOut.ChannelName[1] = FrontRight;
1512 device->RealOut.ChannelName[2] = FrontCenter;
1513 device->RealOut.ChannelName[3] = LFE;
1514 device->RealOut.ChannelName[4] = BackLeft;
1515 device->RealOut.ChannelName[5] = BackRight;
1516 break;
1517 case DevFmtX61:
1518 device->RealOut.ChannelName[0] = FrontLeft;
1519 device->RealOut.ChannelName[1] = FrontRight;
1520 device->RealOut.ChannelName[2] = FrontCenter;
1521 device->RealOut.ChannelName[3] = LFE;
1522 device->RealOut.ChannelName[4] = BackCenter;
1523 device->RealOut.ChannelName[5] = SideLeft;
1524 device->RealOut.ChannelName[6] = SideRight;
1525 break;
1526 case DevFmtX71:
1527 device->RealOut.ChannelName[0] = FrontLeft;
1528 device->RealOut.ChannelName[1] = FrontRight;
1529 device->RealOut.ChannelName[2] = FrontCenter;
1530 device->RealOut.ChannelName[3] = LFE;
1531 device->RealOut.ChannelName[4] = BackLeft;
1532 device->RealOut.ChannelName[5] = BackRight;
1533 device->RealOut.ChannelName[6] = SideLeft;
1534 device->RealOut.ChannelName[7] = SideRight;
1535 break;
1536 case DevFmtAmbi3D:
1537 device->RealOut.ChannelName[0] = Aux0;
1538 if(device->AmbiOrder > 0)
1540 device->RealOut.ChannelName[1] = Aux1;
1541 device->RealOut.ChannelName[2] = Aux2;
1542 device->RealOut.ChannelName[3] = Aux3;
1544 if(device->AmbiOrder > 1)
1546 device->RealOut.ChannelName[4] = Aux4;
1547 device->RealOut.ChannelName[5] = Aux5;
1548 device->RealOut.ChannelName[6] = Aux6;
1549 device->RealOut.ChannelName[7] = Aux7;
1550 device->RealOut.ChannelName[8] = Aux8;
1552 if(device->AmbiOrder > 2)
1554 device->RealOut.ChannelName[9] = Aux9;
1555 device->RealOut.ChannelName[10] = Aux10;
1556 device->RealOut.ChannelName[11] = Aux11;
1557 device->RealOut.ChannelName[12] = Aux12;
1558 device->RealOut.ChannelName[13] = Aux13;
1559 device->RealOut.ChannelName[14] = Aux14;
1560 device->RealOut.ChannelName[15] = Aux15;
1562 break;
1566 /* SetDefaultChannelOrder
1568 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1570 void SetDefaultChannelOrder(ALCdevice *device)
1572 ALsizei i;
1574 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1575 device->RealOut.ChannelName[i] = InvalidChannel;
1577 switch(device->FmtChans)
1579 case DevFmtX51Rear:
1580 device->RealOut.ChannelName[0] = FrontLeft;
1581 device->RealOut.ChannelName[1] = FrontRight;
1582 device->RealOut.ChannelName[2] = BackLeft;
1583 device->RealOut.ChannelName[3] = BackRight;
1584 device->RealOut.ChannelName[4] = FrontCenter;
1585 device->RealOut.ChannelName[5] = LFE;
1586 return;
1587 case DevFmtX71:
1588 device->RealOut.ChannelName[0] = FrontLeft;
1589 device->RealOut.ChannelName[1] = FrontRight;
1590 device->RealOut.ChannelName[2] = BackLeft;
1591 device->RealOut.ChannelName[3] = BackRight;
1592 device->RealOut.ChannelName[4] = FrontCenter;
1593 device->RealOut.ChannelName[5] = LFE;
1594 device->RealOut.ChannelName[6] = SideLeft;
1595 device->RealOut.ChannelName[7] = SideRight;
1596 return;
1598 /* Same as WFX order */
1599 case DevFmtMono:
1600 case DevFmtStereo:
1601 case DevFmtQuad:
1602 case DevFmtX51:
1603 case DevFmtX61:
1604 case DevFmtAmbi3D:
1605 SetDefaultWFXChannelOrder(device);
1606 break;
1610 extern inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan);
1611 extern inline ALint GetChannelIdxByName(const RealMixParams *real, enum Channel chan);
1614 /* ALCcontext_DeferUpdates
1616 * Defers/suspends updates for the given context's listener and sources. This
1617 * does *NOT* stop mixing, but rather prevents certain property changes from
1618 * taking effect.
1620 void ALCcontext_DeferUpdates(ALCcontext *context)
1622 ATOMIC_STORE_SEQ(&context->DeferUpdates, AL_TRUE);
1625 /* ALCcontext_ProcessUpdates
1627 * Resumes update processing after being deferred.
1629 void ALCcontext_ProcessUpdates(ALCcontext *context)
1631 ReadLock(&context->PropLock);
1632 if(ATOMIC_EXCHANGE_SEQ(&context->DeferUpdates, AL_FALSE))
1634 /* Tell the mixer to stop applying updates, then wait for any active
1635 * updating to finish, before providing updates.
1637 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_TRUE);
1638 while((ATOMIC_LOAD(&context->UpdateCount, almemory_order_acquire)&1) != 0)
1639 althrd_yield();
1641 if(!ATOMIC_FLAG_TEST_AND_SET(&context->PropsClean, almemory_order_acq_rel))
1642 UpdateContextProps(context);
1643 if(!ATOMIC_FLAG_TEST_AND_SET(&context->Listener->PropsClean, almemory_order_acq_rel))
1644 UpdateListenerProps(context);
1645 UpdateAllEffectSlotProps(context);
1646 UpdateAllSourceProps(context);
1648 /* Now with all updates declared, let the mixer continue applying them
1649 * so they all happen at once.
1651 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_FALSE);
1653 ReadUnlock(&context->PropLock);
1657 /* alcSetError
1659 * Stores the latest ALC device error
1661 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1663 WARN("Error generated on device %p, code 0x%04x\n", device, errorCode);
1664 if(TrapALCError)
1666 #ifdef _WIN32
1667 /* DebugBreak() will cause an exception if there is no debugger */
1668 if(IsDebuggerPresent())
1669 DebugBreak();
1670 #elif defined(SIGTRAP)
1671 raise(SIGTRAP);
1672 #endif
1675 if(device)
1676 ATOMIC_STORE_SEQ(&device->LastError, errorCode);
1677 else
1678 ATOMIC_STORE_SEQ(&LastNullDeviceError, errorCode);
1682 struct Compressor *CreateDeviceLimiter(const ALCdevice *device)
1684 return CompressorInit(0.0f, 0.0f, AL_FALSE, AL_TRUE, 0.0f, 0.0f, 0.5f, 2.0f,
1685 0.0f, -3.0f, 3.0f, device->Frequency);
1688 /* UpdateClockBase
1690 * Updates the device's base clock time with however many samples have been
1691 * done. This is used so frequency changes on the device don't cause the time
1692 * to jump forward or back. Must not be called while the device is running/
1693 * mixing.
1695 static inline void UpdateClockBase(ALCdevice *device)
1697 IncrementRef(&device->MixCount);
1698 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1699 device->SamplesDone = 0;
1700 IncrementRef(&device->MixCount);
1703 /* UpdateDeviceParams
1705 * Updates device parameters according to the attribute list (caller is
1706 * responsible for holding the list lock).
1708 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1710 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1711 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1712 ALCenum gainLimiter = device->Limiter ? ALC_TRUE : ALC_FALSE;
1713 const ALsizei old_sends = device->NumAuxSends;
1714 ALsizei new_sends = device->NumAuxSends;
1715 enum DevFmtChannels oldChans;
1716 enum DevFmtType oldType;
1717 ALboolean update_failed;
1718 ALCsizei hrtf_id = -1;
1719 ALCcontext *context;
1720 ALCuint oldFreq;
1721 size_t size;
1722 ALCsizei i;
1723 int val;
1725 // Check for attributes
1726 if(device->Type == Loopback)
1728 ALCsizei numMono, numStereo, numSends;
1729 ALCenum alayout = AL_NONE;
1730 ALCenum ascale = AL_NONE;
1731 ALCenum schans = AL_NONE;
1732 ALCenum stype = AL_NONE;
1733 ALCsizei attrIdx = 0;
1734 ALCsizei aorder = 0;
1735 ALCuint freq = 0;
1737 if(!attrList)
1739 WARN("Missing attributes for loopback device\n");
1740 return ALC_INVALID_VALUE;
1743 numMono = device->NumMonoSources;
1744 numStereo = device->NumStereoSources;
1745 numSends = old_sends;
1747 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1748 while(attrList[attrIdx])
1750 switch(attrList[attrIdx])
1752 case ALC_FORMAT_CHANNELS_SOFT:
1753 schans = attrList[attrIdx + 1];
1754 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1755 if(!IsValidALCChannels(schans))
1756 return ALC_INVALID_VALUE;
1757 break;
1759 case ALC_FORMAT_TYPE_SOFT:
1760 stype = attrList[attrIdx + 1];
1761 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1762 if(!IsValidALCType(stype))
1763 return ALC_INVALID_VALUE;
1764 break;
1766 case ALC_FREQUENCY:
1767 freq = attrList[attrIdx + 1];
1768 TRACE_ATTR(ALC_FREQUENCY, freq);
1769 if(freq < MIN_OUTPUT_RATE)
1770 return ALC_INVALID_VALUE;
1771 break;
1773 case ALC_AMBISONIC_LAYOUT_SOFT:
1774 alayout = attrList[attrIdx + 1];
1775 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1776 if(!IsValidAmbiLayout(alayout))
1777 return ALC_INVALID_VALUE;
1778 break;
1780 case ALC_AMBISONIC_SCALING_SOFT:
1781 ascale = attrList[attrIdx + 1];
1782 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1783 if(!IsValidAmbiScaling(ascale))
1784 return ALC_INVALID_VALUE;
1785 break;
1787 case ALC_AMBISONIC_ORDER_SOFT:
1788 aorder = attrList[attrIdx + 1];
1789 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1790 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1791 return ALC_INVALID_VALUE;
1792 break;
1794 case ALC_MONO_SOURCES:
1795 numMono = attrList[attrIdx + 1];
1796 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1797 numMono = maxi(numMono, 0);
1798 break;
1800 case ALC_STEREO_SOURCES:
1801 numStereo = attrList[attrIdx + 1];
1802 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1803 numStereo = maxi(numStereo, 0);
1804 break;
1806 case ALC_MAX_AUXILIARY_SENDS:
1807 numSends = attrList[attrIdx + 1];
1808 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1809 numSends = clampi(numSends, 0, MAX_SENDS);
1810 break;
1812 case ALC_HRTF_SOFT:
1813 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1814 if(attrList[attrIdx + 1] == ALC_FALSE)
1815 hrtf_appreq = Hrtf_Disable;
1816 else if(attrList[attrIdx + 1] == ALC_TRUE)
1817 hrtf_appreq = Hrtf_Enable;
1818 else
1819 hrtf_appreq = Hrtf_Default;
1820 break;
1822 case ALC_HRTF_ID_SOFT:
1823 hrtf_id = attrList[attrIdx + 1];
1824 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1825 break;
1827 case ALC_OUTPUT_LIMITER_SOFT:
1828 gainLimiter = attrList[attrIdx + 1];
1829 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1830 break;
1832 default:
1833 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList[attrIdx],
1834 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1835 break;
1838 attrIdx += 2;
1840 #undef TRACE_ATTR
1842 if(!schans || !stype || !freq)
1844 WARN("Missing format for loopback device\n");
1845 return ALC_INVALID_VALUE;
1847 if(schans == ALC_BFORMAT3D_SOFT && (!alayout || !ascale || !aorder))
1849 WARN("Missing ambisonic info for loopback device\n");
1850 return ALC_INVALID_VALUE;
1853 if((device->Flags&DEVICE_RUNNING))
1854 V0(device->Backend,stop)();
1855 device->Flags &= ~DEVICE_RUNNING;
1857 UpdateClockBase(device);
1859 device->Frequency = freq;
1860 device->FmtChans = schans;
1861 device->FmtType = stype;
1862 if(schans == ALC_BFORMAT3D_SOFT)
1864 device->AmbiOrder = aorder;
1865 device->AmbiLayout = alayout;
1866 device->AmbiScale = ascale;
1869 if(numMono > INT_MAX-numStereo)
1870 numMono = INT_MAX-numStereo;
1871 numMono += numStereo;
1872 if(ConfigValueInt(NULL, NULL, "sources", &numMono))
1874 if(numMono <= 0)
1875 numMono = 256;
1877 else
1878 numMono = maxi(numMono, 256);
1879 numStereo = mini(numStereo, numMono);
1880 numMono -= numStereo;
1881 device->SourcesMax = numMono + numStereo;
1883 device->NumMonoSources = numMono;
1884 device->NumStereoSources = numStereo;
1886 if(ConfigValueInt(NULL, NULL, "sends", &new_sends))
1887 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1888 else
1889 new_sends = numSends;
1891 else if(attrList && attrList[0])
1893 ALCsizei numMono, numStereo, numSends;
1894 ALCsizei attrIdx = 0;
1895 ALCuint freq;
1897 /* If a context is already running on the device, stop playback so the
1898 * device attributes can be updated. */
1899 if((device->Flags&DEVICE_RUNNING))
1900 V0(device->Backend,stop)();
1901 device->Flags &= ~DEVICE_RUNNING;
1903 UpdateClockBase(device);
1905 freq = device->Frequency;
1906 numMono = device->NumMonoSources;
1907 numStereo = device->NumStereoSources;
1908 numSends = old_sends;
1910 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1911 while(attrList[attrIdx])
1913 switch(attrList[attrIdx])
1915 case ALC_FREQUENCY:
1916 freq = attrList[attrIdx + 1];
1917 TRACE_ATTR(ALC_FREQUENCY, freq);
1918 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1919 break;
1921 case ALC_MONO_SOURCES:
1922 numMono = attrList[attrIdx + 1];
1923 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1924 numMono = maxi(numMono, 0);
1925 break;
1927 case ALC_STEREO_SOURCES:
1928 numStereo = attrList[attrIdx + 1];
1929 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1930 numStereo = maxi(numStereo, 0);
1931 break;
1933 case ALC_MAX_AUXILIARY_SENDS:
1934 numSends = attrList[attrIdx + 1];
1935 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1936 numSends = clampi(numSends, 0, MAX_SENDS);
1937 break;
1939 case ALC_HRTF_SOFT:
1940 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1941 if(attrList[attrIdx + 1] == ALC_FALSE)
1942 hrtf_appreq = Hrtf_Disable;
1943 else if(attrList[attrIdx + 1] == ALC_TRUE)
1944 hrtf_appreq = Hrtf_Enable;
1945 else
1946 hrtf_appreq = Hrtf_Default;
1947 break;
1949 case ALC_HRTF_ID_SOFT:
1950 hrtf_id = attrList[attrIdx + 1];
1951 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1952 break;
1954 case ALC_OUTPUT_LIMITER_SOFT:
1955 gainLimiter = attrList[attrIdx + 1];
1956 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1957 break;
1959 default:
1960 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1961 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1962 break;
1965 attrIdx += 2;
1967 #undef TRACE_ATTR
1969 ConfigValueUInt(alstr_get_cstr(device->DeviceName), NULL, "frequency", &freq);
1970 freq = maxu(freq, MIN_OUTPUT_RATE);
1972 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1973 device->Frequency;
1974 /* SSE and Neon do best with the update size being a multiple of 4 */
1975 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1976 device->UpdateSize = (device->UpdateSize+3)&~3;
1978 device->Frequency = freq;
1980 if(numMono > INT_MAX-numStereo)
1981 numMono = INT_MAX-numStereo;
1982 numMono += numStereo;
1983 if(ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "sources", &numMono))
1985 if(numMono <= 0)
1986 numMono = 256;
1988 else
1989 numMono = maxi(numMono, 256);
1990 numStereo = mini(numStereo, numMono);
1991 numMono -= numStereo;
1992 device->SourcesMax = numMono + numStereo;
1994 device->NumMonoSources = numMono;
1995 device->NumStereoSources = numStereo;
1997 if(ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "sends", &new_sends))
1998 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1999 else
2000 new_sends = numSends;
2003 if((device->Flags&DEVICE_RUNNING))
2004 return ALC_NO_ERROR;
2006 al_free(device->Uhj_Encoder);
2007 device->Uhj_Encoder = NULL;
2009 al_free(device->Bs2b);
2010 device->Bs2b = NULL;
2012 al_free(device->ChannelDelay[0].Buffer);
2013 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2015 device->ChannelDelay[i].Length = 0;
2016 device->ChannelDelay[i].Buffer = NULL;
2019 al_free(device->Dry.Buffer);
2020 device->Dry.Buffer = NULL;
2021 device->Dry.NumChannels = 0;
2022 device->FOAOut.Buffer = NULL;
2023 device->FOAOut.NumChannels = 0;
2024 device->RealOut.Buffer = NULL;
2025 device->RealOut.NumChannels = 0;
2027 UpdateClockBase(device);
2029 device->DitherSeed = DITHER_RNG_SEED;
2031 /*************************************************************************
2032 * Update device format request if HRTF is requested
2034 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
2035 if(device->Type != Loopback)
2037 const char *hrtf;
2038 if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "hrtf", &hrtf))
2040 if(strcasecmp(hrtf, "true") == 0)
2041 hrtf_userreq = Hrtf_Enable;
2042 else if(strcasecmp(hrtf, "false") == 0)
2043 hrtf_userreq = Hrtf_Disable;
2044 else if(strcasecmp(hrtf, "auto") != 0)
2045 ERR("Unexpected hrtf value: %s\n", hrtf);
2048 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
2050 struct Hrtf *hrtf = NULL;
2051 if(VECTOR_SIZE(device->HrtfList) == 0)
2053 VECTOR_DEINIT(device->HrtfList);
2054 device->HrtfList = EnumerateHrtf(device->DeviceName);
2056 if(VECTOR_SIZE(device->HrtfList) > 0)
2058 if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->HrtfList))
2059 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, hrtf_id).hrtf);
2060 else
2061 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, 0).hrtf);
2064 if(hrtf)
2066 device->FmtChans = DevFmtStereo;
2067 device->Frequency = hrtf->sampleRate;
2068 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
2069 if(device->HrtfHandle)
2070 Hrtf_DecRef(device->HrtfHandle);
2071 device->HrtfHandle = hrtf;
2073 else
2075 hrtf_userreq = Hrtf_Default;
2076 hrtf_appreq = Hrtf_Disable;
2077 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2082 oldFreq = device->Frequency;
2083 oldChans = device->FmtChans;
2084 oldType = device->FmtType;
2086 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2087 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
2088 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
2089 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
2090 device->UpdateSize, device->NumUpdates
2093 if(V0(device->Backend,reset)() == ALC_FALSE)
2094 return ALC_INVALID_DEVICE;
2096 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
2098 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2099 DevFmtChannelsString(device->FmtChans));
2100 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2102 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2104 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2105 DevFmtTypeString(device->FmtType));
2106 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2108 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2110 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2111 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2114 if((device->UpdateSize&3) != 0)
2116 if((CPUCapFlags&CPU_CAP_SSE))
2117 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2118 if((CPUCapFlags&CPU_CAP_NEON))
2119 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2122 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2123 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2124 device->Frequency, device->UpdateSize, device->NumUpdates
2127 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2128 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device->Dry.NumChannels,
2129 device->FOAOut.NumChannels, device->RealOut.NumChannels);
2131 /* Allocate extra channels for any post-filter output. */
2132 size = (device->Dry.NumChannels + device->FOAOut.NumChannels +
2133 device->RealOut.NumChannels)*sizeof(device->Dry.Buffer[0]);
2135 TRACE("Allocating "SZFMT" channels, "SZFMT" bytes\n", size/sizeof(device->Dry.Buffer[0]), size);
2136 device->Dry.Buffer = al_calloc(16, size);
2137 if(!device->Dry.Buffer)
2139 ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
2140 return ALC_INVALID_DEVICE;
2143 if(device->RealOut.NumChannels != 0)
2144 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels +
2145 device->FOAOut.NumChannels;
2146 else
2148 device->RealOut.Buffer = device->Dry.Buffer;
2149 device->RealOut.NumChannels = device->Dry.NumChannels;
2152 if(device->FOAOut.NumChannels != 0)
2153 device->FOAOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2154 else
2156 device->FOAOut.Buffer = device->Dry.Buffer;
2157 device->FOAOut.NumChannels = device->Dry.NumChannels;
2160 device->NumAuxSends = new_sends;
2161 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2162 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
2163 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
2165 device->DitherDepth = 0.0f;
2166 if(GetConfigValueBool(alstr_get_cstr(device->DeviceName), NULL, "dither", 1))
2168 ALint depth = 0;
2169 ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "dither-depth", &depth);
2170 if(depth <= 0)
2172 switch(device->FmtType)
2174 case DevFmtByte:
2175 case DevFmtUByte:
2176 depth = 8;
2177 break;
2178 case DevFmtShort:
2179 case DevFmtUShort:
2180 depth = 16;
2181 break;
2182 case DevFmtInt:
2183 case DevFmtUInt:
2184 case DevFmtFloat:
2185 break;
2188 else if(depth > 24)
2189 depth = 24;
2190 device->DitherDepth = (depth > 0) ? powf(2.0f, (ALfloat)(depth-1)) : 0.0f;
2192 if(!(device->DitherDepth > 0.0f))
2193 TRACE("Dithering disabled\n");
2194 else
2195 TRACE("Dithering enabled (%g-bit, %g)\n", log2f(device->DitherDepth)+1.0f,
2196 device->DitherDepth);
2198 if(ConfigValueBool(alstr_get_cstr(device->DeviceName), NULL, "output-limiter", &val))
2199 gainLimiter = val ? ALC_TRUE : ALC_FALSE;
2200 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2201 * ALC_FALSE. We default to on, so ALC_DONT_CARE_SOFT is the same as
2202 * ALC_TRUE.
2204 if(gainLimiter != ALC_FALSE)
2206 if(!device->Limiter || device->Frequency != GetCompressorSampleRate(device->Limiter))
2208 al_free(device->Limiter);
2209 device->Limiter = CreateDeviceLimiter(device);
2212 else
2214 al_free(device->Limiter);
2215 device->Limiter = NULL;
2217 TRACE("Output limiter %s\n", device->Limiter ? "enabled" : "disabled");
2219 aluSelectPostProcess(device);
2221 /* Need to delay returning failure until replacement Send arrays have been
2222 * allocated with the appropriate size.
2224 update_failed = AL_FALSE;
2225 START_MIXER_MODE();
2226 context = ATOMIC_LOAD_SEQ(&device->ContextList);
2227 while(context)
2229 SourceSubList *sublist, *subend;
2230 struct ALvoiceProps *vprops;
2231 ALsizei pos;
2233 if(context->DefaultSlot)
2235 ALeffectslot *slot = context->DefaultSlot;
2236 ALeffectState *state = slot->Effect.State;
2238 state->OutBuffer = device->Dry.Buffer;
2239 state->OutChannels = device->Dry.NumChannels;
2240 if(V(state,deviceUpdate)(device) == AL_FALSE)
2241 update_failed = AL_TRUE;
2242 else
2243 UpdateEffectSlotProps(slot, context);
2246 WriteLock(&context->PropLock);
2247 almtx_lock(&context->EffectSlotLock);
2248 for(pos = 0;pos < (ALsizei)VECTOR_SIZE(context->EffectSlotList);pos++)
2250 ALeffectslot *slot = VECTOR_ELEM(context->EffectSlotList, pos);
2251 ALeffectState *state = slot->Effect.State;
2253 state->OutBuffer = device->Dry.Buffer;
2254 state->OutChannels = device->Dry.NumChannels;
2255 if(V(state,deviceUpdate)(device) == AL_FALSE)
2256 update_failed = AL_TRUE;
2257 else
2258 UpdateEffectSlotProps(slot, context);
2260 almtx_unlock(&context->EffectSlotLock);
2262 almtx_lock(&context->SourceLock);
2263 sublist = VECTOR_BEGIN(context->SourceList);
2264 subend = VECTOR_END(context->SourceList);
2265 for(;sublist != subend;++sublist)
2267 ALuint64 usemask = ~sublist->FreeMask;
2268 while(usemask)
2270 ALsizei idx = CTZ64(usemask);
2271 ALsource *source = sublist->Sources + idx;
2273 usemask &= ~(U64(1) << idx);
2275 if(old_sends != device->NumAuxSends)
2277 ALvoid *sends = al_calloc(16, device->NumAuxSends*sizeof(source->Send[0]));
2278 ALsizei s;
2280 memcpy(sends, source->Send,
2281 mini(device->NumAuxSends, old_sends)*sizeof(source->Send[0])
2283 for(s = device->NumAuxSends;s < old_sends;s++)
2285 if(source->Send[s].Slot)
2286 DecrementRef(&source->Send[s].Slot->ref);
2287 source->Send[s].Slot = NULL;
2289 al_free(source->Send);
2290 source->Send = sends;
2291 for(s = old_sends;s < device->NumAuxSends;s++)
2293 source->Send[s].Slot = NULL;
2294 source->Send[s].Gain = 1.0f;
2295 source->Send[s].GainHF = 1.0f;
2296 source->Send[s].HFReference = LOWPASSFREQREF;
2297 source->Send[s].GainLF = 1.0f;
2298 source->Send[s].LFReference = HIGHPASSFREQREF;
2302 ATOMIC_FLAG_CLEAR(&source->PropsClean, almemory_order_release);
2306 /* Clear any pre-existing voice property structs, in case the number of
2307 * auxiliary sends is changing. Active sources will have updates
2308 * respecified in UpdateAllSourceProps.
2310 vprops = ATOMIC_EXCHANGE_PTR(&context->FreeVoiceProps, NULL, almemory_order_acq_rel);
2311 while(vprops)
2313 struct ALvoiceProps *next = ATOMIC_LOAD(&vprops->next, almemory_order_relaxed);
2314 al_free(vprops);
2315 vprops = next;
2318 AllocateVoices(context, context->MaxVoices, old_sends);
2319 for(pos = 0;pos < context->VoiceCount;pos++)
2321 ALvoice *voice = context->Voices[pos];
2323 al_free(ATOMIC_EXCHANGE_PTR(&voice->Update, NULL, almemory_order_acq_rel));
2325 if(ATOMIC_LOAD(&voice->Source, almemory_order_acquire) == NULL)
2326 continue;
2328 if(device->AvgSpeakerDist > 0.0f)
2330 /* Reinitialize the NFC filters for new parameters. */
2331 ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
2332 (device->AvgSpeakerDist * device->Frequency);
2333 for(i = 0;i < voice->NumChannels;i++)
2334 NfcFilterCreate(&voice->Direct.Params[i].NFCtrlFilter, 0.0f, w1);
2337 almtx_unlock(&context->SourceLock);
2339 ATOMIC_FLAG_TEST_AND_SET(&context->PropsClean, almemory_order_release);
2340 UpdateContextProps(context);
2341 ATOMIC_FLAG_TEST_AND_SET(&context->Listener->PropsClean, almemory_order_release);
2342 UpdateListenerProps(context);
2343 UpdateAllSourceProps(context);
2344 WriteUnlock(&context->PropLock);
2346 context = context->next;
2348 END_MIXER_MODE();
2349 if(update_failed)
2350 return ALC_INVALID_DEVICE;
2352 if(!(device->Flags&DEVICE_PAUSED))
2354 if(V0(device->Backend,start)() == ALC_FALSE)
2355 return ALC_INVALID_DEVICE;
2356 device->Flags |= DEVICE_RUNNING;
2359 return ALC_NO_ERROR;
2363 static void InitDevice(ALCdevice *device)
2365 ALsizei i;
2367 device->Flags = 0;
2368 device->Render_Mode = NormalRender;
2369 device->AvgSpeakerDist = 0.0f;
2371 ATOMIC_INIT(&device->ContextList, NULL);
2373 device->ClockBase = 0;
2374 device->SamplesDone = 0;
2376 device->SourcesMax = 0;
2377 device->AuxiliaryEffectSlotMax = 0;
2378 device->NumAuxSends = 0;
2380 device->Dry.Buffer = NULL;
2381 device->Dry.NumChannels = 0;
2382 device->FOAOut.Buffer = NULL;
2383 device->FOAOut.NumChannels = 0;
2384 device->RealOut.Buffer = NULL;
2385 device->RealOut.NumChannels = 0;
2387 AL_STRING_INIT(device->DeviceName);
2389 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2391 device->ChannelDelay[i].Gain = 1.0f;
2392 device->ChannelDelay[i].Length = 0;
2393 device->ChannelDelay[i].Buffer = NULL;
2396 AL_STRING_INIT(device->HrtfName);
2397 VECTOR_INIT(device->HrtfList);
2398 device->HrtfHandle = NULL;
2399 device->Hrtf = NULL;
2400 device->Bs2b = NULL;
2401 device->Uhj_Encoder = NULL;
2402 device->AmbiDecoder = NULL;
2403 device->AmbiUp = NULL;
2404 device->Stablizer = NULL;
2405 device->Limiter = NULL;
2407 VECTOR_INIT(device->BufferList);
2408 almtx_init(&device->BufferLock, almtx_plain);
2410 VECTOR_INIT(device->EffectList);
2411 almtx_init(&device->EffectLock, almtx_plain);
2413 VECTOR_INIT(device->FilterList);
2414 almtx_init(&device->FilterLock, almtx_plain);
2416 almtx_init(&device->BackendLock, almtx_plain);
2417 device->Backend = NULL;
2420 /* FreeDevice
2422 * Frees the device structure, and destroys any objects the app failed to
2423 * delete. Called once there's no more references on the device.
2425 static ALCvoid FreeDevice(ALCdevice *device)
2427 ALsizei i;
2429 TRACE("%p\n", device);
2431 if(device->Backend)
2432 DELETE_OBJ(device->Backend);
2433 device->Backend = NULL;
2435 almtx_destroy(&device->BackendLock);
2437 ReleaseALBuffers(device);
2438 #define FREE_BUFFERSUBLIST(x) al_free((x)->Buffers)
2439 VECTOR_FOR_EACH(BufferSubList, device->BufferList, FREE_BUFFERSUBLIST);
2440 #undef FREE_BUFFERSUBLIST
2441 VECTOR_DEINIT(device->BufferList);
2442 almtx_destroy(&device->BufferLock);
2444 ReleaseALEffects(device);
2445 #define FREE_EFFECTSUBLIST(x) al_free((x)->Effects)
2446 VECTOR_FOR_EACH(EffectSubList, device->EffectList, FREE_EFFECTSUBLIST);
2447 #undef FREE_EFFECTSUBLIST
2448 VECTOR_DEINIT(device->EffectList);
2449 almtx_destroy(&device->EffectLock);
2451 ReleaseALFilters(device);
2452 #define FREE_FILTERSUBLIST(x) al_free((x)->Filters)
2453 VECTOR_FOR_EACH(FilterSubList, device->FilterList, FREE_FILTERSUBLIST);
2454 #undef FREE_FILTERSUBLIST
2455 VECTOR_DEINIT(device->FilterList);
2456 almtx_destroy(&device->FilterLock);
2458 AL_STRING_DEINIT(device->HrtfName);
2459 FreeHrtfList(&device->HrtfList);
2460 if(device->HrtfHandle)
2461 Hrtf_DecRef(device->HrtfHandle);
2462 device->HrtfHandle = NULL;
2463 al_free(device->Hrtf);
2464 device->Hrtf = NULL;
2466 al_free(device->Bs2b);
2467 device->Bs2b = NULL;
2469 al_free(device->Uhj_Encoder);
2470 device->Uhj_Encoder = NULL;
2472 bformatdec_free(&device->AmbiDecoder);
2473 ambiup_free(&device->AmbiUp);
2475 al_free(device->Stablizer);
2476 device->Stablizer = NULL;
2478 al_free(device->Limiter);
2479 device->Limiter = NULL;
2481 al_free(device->ChannelDelay[0].Buffer);
2482 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2484 device->ChannelDelay[i].Gain = 1.0f;
2485 device->ChannelDelay[i].Length = 0;
2486 device->ChannelDelay[i].Buffer = NULL;
2489 AL_STRING_DEINIT(device->DeviceName);
2491 al_free(device->Dry.Buffer);
2492 device->Dry.Buffer = NULL;
2493 device->Dry.NumChannels = 0;
2494 device->FOAOut.Buffer = NULL;
2495 device->FOAOut.NumChannels = 0;
2496 device->RealOut.Buffer = NULL;
2497 device->RealOut.NumChannels = 0;
2499 al_free(device);
2503 void ALCdevice_IncRef(ALCdevice *device)
2505 uint ref;
2506 ref = IncrementRef(&device->ref);
2507 TRACEREF("%p increasing refcount to %u\n", device, ref);
2510 void ALCdevice_DecRef(ALCdevice *device)
2512 uint ref;
2513 ref = DecrementRef(&device->ref);
2514 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2515 if(ref == 0) FreeDevice(device);
2518 /* VerifyDevice
2520 * Checks if the device handle is valid, and increments its ref count if so.
2522 static ALCboolean VerifyDevice(ALCdevice **device)
2524 ALCdevice *tmpDevice;
2526 LockLists();
2527 tmpDevice = ATOMIC_LOAD_SEQ(&DeviceList);
2528 while(tmpDevice)
2530 if(tmpDevice == *device)
2532 ALCdevice_IncRef(tmpDevice);
2533 UnlockLists();
2534 return ALC_TRUE;
2536 tmpDevice = tmpDevice->next;
2538 UnlockLists();
2540 *device = NULL;
2541 return ALC_FALSE;
2545 /* InitContext
2547 * Initializes context fields
2549 static ALvoid InitContext(ALCcontext *Context)
2551 ALlistener *listener = Context->Listener;
2552 struct ALeffectslotArray *auxslots;
2554 //Initialise listener
2555 listener->Gain = 1.0f;
2556 listener->Position[0] = 0.0f;
2557 listener->Position[1] = 0.0f;
2558 listener->Position[2] = 0.0f;
2559 listener->Velocity[0] = 0.0f;
2560 listener->Velocity[1] = 0.0f;
2561 listener->Velocity[2] = 0.0f;
2562 listener->Forward[0] = 0.0f;
2563 listener->Forward[1] = 0.0f;
2564 listener->Forward[2] = -1.0f;
2565 listener->Up[0] = 0.0f;
2566 listener->Up[1] = 1.0f;
2567 listener->Up[2] = 0.0f;
2568 ATOMIC_FLAG_TEST_AND_SET(&listener->PropsClean, almemory_order_relaxed);
2570 ATOMIC_INIT(&listener->Update, NULL);
2572 //Validate Context
2573 InitRef(&Context->UpdateCount, 0);
2574 ATOMIC_INIT(&Context->HoldUpdates, AL_FALSE);
2575 Context->GainBoost = 1.0f;
2576 RWLockInit(&Context->PropLock);
2577 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2578 VECTOR_INIT(Context->SourceList);
2579 Context->NumSources = 0;
2580 almtx_init(&Context->SourceLock, almtx_plain);
2581 VECTOR_INIT(Context->EffectSlotList);
2582 almtx_init(&Context->EffectSlotLock, almtx_plain);
2584 if(Context->DefaultSlot)
2586 auxslots = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, 1));
2587 auxslots->count = 1;
2588 auxslots->slot[0] = Context->DefaultSlot;
2590 else
2592 auxslots = al_calloc(DEF_ALIGN, sizeof(struct ALeffectslotArray));
2593 auxslots->count = 0;
2595 ATOMIC_INIT(&Context->ActiveAuxSlots, auxslots);
2597 //Set globals
2598 Context->DistanceModel = DefaultDistanceModel;
2599 Context->SourceDistanceModel = AL_FALSE;
2600 Context->DopplerFactor = 1.0f;
2601 Context->DopplerVelocity = 1.0f;
2602 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2603 Context->MetersPerUnit = AL_DEFAULT_METERS_PER_UNIT;
2604 ATOMIC_FLAG_TEST_AND_SET(&Context->PropsClean, almemory_order_relaxed);
2605 ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
2606 almtx_init(&Context->EventThrdLock, almtx_plain);
2607 alsem_init(&Context->EventSem, 0);
2608 Context->AsyncEvents = NULL;
2609 ATOMIC_INIT(&Context->EnabledEvts, 0);
2610 almtx_init(&Context->EventCbLock, almtx_plain);
2611 Context->EventCb = NULL;
2612 Context->EventParam = NULL;
2614 ATOMIC_INIT(&Context->Update, NULL);
2615 ATOMIC_INIT(&Context->FreeContextProps, NULL);
2616 ATOMIC_INIT(&Context->FreeListenerProps, NULL);
2617 ATOMIC_INIT(&Context->FreeVoiceProps, NULL);
2618 ATOMIC_INIT(&Context->FreeEffectslotProps, NULL);
2620 Context->ExtensionList = alExtList;
2623 listener->Params.Matrix = IdentityMatrixf;
2624 aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2625 listener->Params.Gain = listener->Gain;
2626 listener->Params.MetersPerUnit = Context->MetersPerUnit;
2627 listener->Params.DopplerFactor = Context->DopplerFactor;
2628 listener->Params.SpeedOfSound = Context->SpeedOfSound * Context->DopplerVelocity;
2629 listener->Params.ReverbSpeedOfSound = listener->Params.SpeedOfSound *
2630 listener->Params.MetersPerUnit;
2631 listener->Params.SourceDistanceModel = Context->SourceDistanceModel;
2632 listener->Params.DistanceModel = Context->DistanceModel;
2636 /* FreeContext
2638 * Cleans up the context, and destroys any remaining objects the app failed to
2639 * delete. Called once there's no more references on the context.
2641 static void FreeContext(ALCcontext *context)
2643 ALlistener *listener = context->Listener;
2644 struct ALeffectslotArray *auxslots;
2645 struct ALeffectslotProps *eprops;
2646 struct ALlistenerProps *lprops;
2647 struct ALcontextProps *cprops;
2648 struct ALvoiceProps *vprops;
2649 size_t count;
2650 ALsizei i;
2652 TRACE("%p\n", context);
2654 if((cprops=ATOMIC_LOAD(&context->Update, almemory_order_acquire)) != NULL)
2656 TRACE("Freed unapplied context update %p\n", cprops);
2657 al_free(cprops);
2660 count = 0;
2661 cprops = ATOMIC_LOAD(&context->FreeContextProps, almemory_order_acquire);
2662 while(cprops)
2664 struct ALcontextProps *next = ATOMIC_LOAD(&cprops->next, almemory_order_acquire);
2665 al_free(cprops);
2666 cprops = next;
2667 ++count;
2669 TRACE("Freed "SZFMT" context property object%s\n", count, (count==1)?"":"s");
2671 if(context->DefaultSlot)
2673 DeinitEffectSlot(context->DefaultSlot);
2674 context->DefaultSlot = NULL;
2677 auxslots = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, NULL, almemory_order_relaxed);
2678 al_free(auxslots);
2680 ReleaseALSources(context);
2681 #define FREE_SOURCESUBLIST(x) al_free((x)->Sources)
2682 VECTOR_FOR_EACH(SourceSubList, context->SourceList, FREE_SOURCESUBLIST);
2683 #undef FREE_SOURCESUBLIST
2684 VECTOR_DEINIT(context->SourceList);
2685 context->NumSources = 0;
2686 almtx_destroy(&context->SourceLock);
2688 count = 0;
2689 eprops = ATOMIC_LOAD(&context->FreeEffectslotProps, almemory_order_relaxed);
2690 while(eprops)
2692 struct ALeffectslotProps *next = ATOMIC_LOAD(&eprops->next, almemory_order_relaxed);
2693 if(eprops->State) ALeffectState_DecRef(eprops->State);
2694 al_free(eprops);
2695 eprops = next;
2696 ++count;
2698 TRACE("Freed "SZFMT" AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2700 ReleaseALAuxiliaryEffectSlots(context);
2701 #define FREE_EFFECTSLOTPTR(x) al_free(*(x))
2702 VECTOR_FOR_EACH(ALeffectslotPtr, context->EffectSlotList, FREE_EFFECTSLOTPTR);
2703 #undef FREE_EFFECTSLOTPTR
2704 VECTOR_DEINIT(context->EffectSlotList);
2705 almtx_destroy(&context->EffectSlotLock);
2707 count = 0;
2708 vprops = ATOMIC_LOAD(&context->FreeVoiceProps, almemory_order_relaxed);
2709 while(vprops)
2711 struct ALvoiceProps *next = ATOMIC_LOAD(&vprops->next, almemory_order_relaxed);
2712 al_free(vprops);
2713 vprops = next;
2714 ++count;
2716 TRACE("Freed "SZFMT" voice property object%s\n", count, (count==1)?"":"s");
2718 for(i = 0;i < context->VoiceCount;i++)
2719 DeinitVoice(context->Voices[i]);
2720 al_free(context->Voices);
2721 context->Voices = NULL;
2722 context->VoiceCount = 0;
2723 context->MaxVoices = 0;
2725 if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != NULL)
2727 TRACE("Freed unapplied listener update %p\n", lprops);
2728 al_free(lprops);
2730 count = 0;
2731 lprops = ATOMIC_LOAD(&context->FreeListenerProps, almemory_order_acquire);
2732 while(lprops)
2734 struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_acquire);
2735 al_free(lprops);
2736 lprops = next;
2737 ++count;
2739 TRACE("Freed "SZFMT" listener property object%s\n", count, (count==1)?"":"s");
2741 if(ATOMIC_EXCHANGE(&context->EnabledEvts, 0, almemory_order_acq_rel))
2743 static const AsyncEvent kill_evt = { 0 };
2744 while(ll_ringbuffer_write_space(context->AsyncEvents) == 0)
2745 althrd_yield();
2746 ll_ringbuffer_write(context->AsyncEvents, (const char*)&kill_evt, 1);
2747 alsem_post(&context->EventSem);
2748 althrd_join(context->EventThread, NULL);
2751 almtx_destroy(&context->EventCbLock);
2752 almtx_destroy(&context->EventThrdLock);
2753 alsem_destroy(&context->EventSem);
2755 ll_ringbuffer_free(context->AsyncEvents);
2756 context->AsyncEvents = NULL;
2758 ALCdevice_DecRef(context->Device);
2759 context->Device = NULL;
2761 //Invalidate context
2762 memset(context, 0, sizeof(ALCcontext));
2763 al_free(context);
2766 /* ReleaseContext
2768 * Removes the context reference from the given device and removes it from
2769 * being current on the running thread or globally. Returns true if other
2770 * contexts still exist on the device.
2772 static bool ReleaseContext(ALCcontext *context, ALCdevice *device)
2774 ALCcontext *origctx, *newhead;
2775 bool ret = true;
2777 if(altss_get(LocalContext) == context)
2779 WARN("%p released while current on thread\n", context);
2780 altss_set(LocalContext, NULL);
2781 ALCcontext_DecRef(context);
2784 origctx = context;
2785 if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext, &origctx, NULL))
2786 ALCcontext_DecRef(context);
2788 V0(device->Backend,lock)();
2789 origctx = context;
2790 newhead = context->next;
2791 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device->ContextList, &origctx, newhead))
2793 ALCcontext *volatile*list = &origctx->next;
2794 while(*list)
2796 if(*list == context)
2798 *list = (*list)->next;
2799 break;
2801 list = &(*list)->next;
2804 else
2805 ret = !!newhead;
2806 V0(device->Backend,unlock)();
2808 ALCcontext_DecRef(context);
2809 return ret;
2812 static void ALCcontext_IncRef(ALCcontext *context)
2814 uint ref = IncrementRef(&context->ref);
2815 TRACEREF("%p increasing refcount to %u\n", context, ref);
2818 void ALCcontext_DecRef(ALCcontext *context)
2820 uint ref = DecrementRef(&context->ref);
2821 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2822 if(ref == 0) FreeContext(context);
2825 static void ReleaseThreadCtx(void *ptr)
2827 ALCcontext *context = ptr;
2828 uint ref = DecrementRef(&context->ref);
2829 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2830 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2833 /* VerifyContext
2835 * Checks that the given context is valid, and increments its reference count.
2837 static ALCboolean VerifyContext(ALCcontext **context)
2839 ALCdevice *dev;
2841 LockLists();
2842 dev = ATOMIC_LOAD_SEQ(&DeviceList);
2843 while(dev)
2845 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList, almemory_order_acquire);
2846 while(ctx)
2848 if(ctx == *context)
2850 ALCcontext_IncRef(ctx);
2851 UnlockLists();
2852 return ALC_TRUE;
2854 ctx = ctx->next;
2856 dev = dev->next;
2858 UnlockLists();
2860 *context = NULL;
2861 return ALC_FALSE;
2865 /* GetContextRef
2867 * Returns the currently active context for this thread, and adds a reference
2868 * without locking it.
2870 ALCcontext *GetContextRef(void)
2872 ALCcontext *context;
2874 context = altss_get(LocalContext);
2875 if(context)
2876 ALCcontext_IncRef(context);
2877 else
2879 LockLists();
2880 context = ATOMIC_LOAD_SEQ(&GlobalContext);
2881 if(context)
2882 ALCcontext_IncRef(context);
2883 UnlockLists();
2886 return context;
2890 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
2892 ALCdevice *device = context->Device;
2893 ALsizei num_sends = device->NumAuxSends;
2894 struct ALvoiceProps *props;
2895 size_t sizeof_props;
2896 size_t sizeof_voice;
2897 ALvoice **voices;
2898 ALvoice *voice;
2899 ALsizei v = 0;
2900 size_t size;
2902 if(num_voices == context->MaxVoices && num_sends == old_sends)
2903 return;
2905 /* Allocate the voice pointers, voices, and the voices' stored source
2906 * property set (including the dynamically-sized Send[] array) in one
2907 * chunk.
2909 sizeof_voice = RoundUp(FAM_SIZE(ALvoice, Send, num_sends), 16);
2910 sizeof_props = RoundUp(FAM_SIZE(struct ALvoiceProps, Send, num_sends), 16);
2911 size = sizeof(ALvoice*) + sizeof_voice + sizeof_props;
2913 voices = al_calloc(16, RoundUp(size*num_voices, 16));
2914 /* The voice and property objects are stored interleaved since they're
2915 * paired together.
2917 voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
2918 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2920 if(context->Voices)
2922 const ALsizei v_count = mini(context->VoiceCount, num_voices);
2923 const ALsizei s_count = mini(old_sends, num_sends);
2925 for(;v < v_count;v++)
2927 ALvoice *old_voice = context->Voices[v];
2928 ALsizei i;
2930 /* Copy the old voice data and source property set to the new
2931 * storage.
2933 *voice = *old_voice;
2934 for(i = 0;i < s_count;i++)
2935 voice->Send[i] = old_voice->Send[i];
2936 *props = *(old_voice->Props);
2937 for(i = 0;i < s_count;i++)
2938 props->Send[i] = old_voice->Props->Send[i];
2940 /* Set this voice's property set pointer and voice reference. */
2941 voice->Props = props;
2942 voices[v] = voice;
2944 /* Increment pointers to the next storage space. */
2945 voice = (ALvoice*)((char*)props + sizeof_props);
2946 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2948 /* Deinit any left over voices that weren't copied over to the new
2949 * array. NOTE: If this does anything, v equals num_voices and
2950 * num_voices is less than VoiceCount, so the following loop won't do
2951 * anything.
2953 for(;v < context->VoiceCount;v++)
2954 DeinitVoice(context->Voices[v]);
2956 /* Finish setting the voices' property set pointers and references. */
2957 for(;v < num_voices;v++)
2959 ATOMIC_INIT(&voice->Update, NULL);
2961 voice->Props = props;
2962 voices[v] = voice;
2964 voice = (ALvoice*)((char*)props + sizeof_props);
2965 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2968 al_free(context->Voices);
2969 context->Voices = voices;
2970 context->MaxVoices = num_voices;
2971 context->VoiceCount = mini(context->VoiceCount, num_voices);
2975 /************************************************
2976 * Standard ALC functions
2977 ************************************************/
2979 /* alcGetError
2981 * Return last ALC generated error code for the given device
2983 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2985 ALCenum errorCode;
2987 if(VerifyDevice(&device))
2989 errorCode = ATOMIC_EXCHANGE_SEQ(&device->LastError, ALC_NO_ERROR);
2990 ALCdevice_DecRef(device);
2992 else
2993 errorCode = ATOMIC_EXCHANGE_SEQ(&LastNullDeviceError, ALC_NO_ERROR);
2995 return errorCode;
2999 /* alcSuspendContext
3001 * Suspends updates for the given context
3003 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
3005 if(!SuspendDefers)
3006 return;
3008 if(!VerifyContext(&context))
3009 alcSetError(NULL, ALC_INVALID_CONTEXT);
3010 else
3012 ALCcontext_DeferUpdates(context);
3013 ALCcontext_DecRef(context);
3017 /* alcProcessContext
3019 * Resumes processing updates for the given context
3021 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
3023 if(!SuspendDefers)
3024 return;
3026 if(!VerifyContext(&context))
3027 alcSetError(NULL, ALC_INVALID_CONTEXT);
3028 else
3030 ALCcontext_ProcessUpdates(context);
3031 ALCcontext_DecRef(context);
3036 /* alcGetString
3038 * Returns information about the device, and error strings
3040 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
3042 const ALCchar *value = NULL;
3044 switch(param)
3046 case ALC_NO_ERROR:
3047 value = alcNoError;
3048 break;
3050 case ALC_INVALID_ENUM:
3051 value = alcErrInvalidEnum;
3052 break;
3054 case ALC_INVALID_VALUE:
3055 value = alcErrInvalidValue;
3056 break;
3058 case ALC_INVALID_DEVICE:
3059 value = alcErrInvalidDevice;
3060 break;
3062 case ALC_INVALID_CONTEXT:
3063 value = alcErrInvalidContext;
3064 break;
3066 case ALC_OUT_OF_MEMORY:
3067 value = alcErrOutOfMemory;
3068 break;
3070 case ALC_DEVICE_SPECIFIER:
3071 value = alcDefaultName;
3072 break;
3074 case ALC_ALL_DEVICES_SPECIFIER:
3075 if(VerifyDevice(&Device))
3077 value = alstr_get_cstr(Device->DeviceName);
3078 ALCdevice_DecRef(Device);
3080 else
3082 ProbeAllDevicesList();
3083 value = alstr_get_cstr(alcAllDevicesList);
3085 break;
3087 case ALC_CAPTURE_DEVICE_SPECIFIER:
3088 if(VerifyDevice(&Device))
3090 value = alstr_get_cstr(Device->DeviceName);
3091 ALCdevice_DecRef(Device);
3093 else
3095 ProbeCaptureDeviceList();
3096 value = alstr_get_cstr(alcCaptureDeviceList);
3098 break;
3100 /* Default devices are always first in the list */
3101 case ALC_DEFAULT_DEVICE_SPECIFIER:
3102 value = alcDefaultName;
3103 break;
3105 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
3106 if(alstr_empty(alcAllDevicesList))
3107 ProbeAllDevicesList();
3109 VerifyDevice(&Device);
3111 free(alcDefaultAllDevicesSpecifier);
3112 alcDefaultAllDevicesSpecifier = strdup(alstr_get_cstr(alcAllDevicesList));
3113 if(!alcDefaultAllDevicesSpecifier)
3114 alcSetError(Device, ALC_OUT_OF_MEMORY);
3116 value = alcDefaultAllDevicesSpecifier;
3117 if(Device) ALCdevice_DecRef(Device);
3118 break;
3120 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
3121 if(alstr_empty(alcCaptureDeviceList))
3122 ProbeCaptureDeviceList();
3124 VerifyDevice(&Device);
3126 free(alcCaptureDefaultDeviceSpecifier);
3127 alcCaptureDefaultDeviceSpecifier = strdup(alstr_get_cstr(alcCaptureDeviceList));
3128 if(!alcCaptureDefaultDeviceSpecifier)
3129 alcSetError(Device, ALC_OUT_OF_MEMORY);
3131 value = alcCaptureDefaultDeviceSpecifier;
3132 if(Device) ALCdevice_DecRef(Device);
3133 break;
3135 case ALC_EXTENSIONS:
3136 if(!VerifyDevice(&Device))
3137 value = alcNoDeviceExtList;
3138 else
3140 value = alcExtensionList;
3141 ALCdevice_DecRef(Device);
3143 break;
3145 case ALC_HRTF_SPECIFIER_SOFT:
3146 if(!VerifyDevice(&Device))
3147 alcSetError(NULL, ALC_INVALID_DEVICE);
3148 else
3150 almtx_lock(&Device->BackendLock);
3151 value = (Device->HrtfHandle ? alstr_get_cstr(Device->HrtfName) : "");
3152 almtx_unlock(&Device->BackendLock);
3153 ALCdevice_DecRef(Device);
3155 break;
3157 default:
3158 VerifyDevice(&Device);
3159 alcSetError(Device, ALC_INVALID_ENUM);
3160 if(Device) ALCdevice_DecRef(Device);
3161 break;
3164 return value;
3168 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
3170 if(device->Type == Capture) return 9;
3171 if(device->Type != Loopback) return 29;
3172 if(device->FmtChans == DevFmtAmbi3D)
3173 return 35;
3174 return 29;
3177 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3179 ALCsizei i;
3181 if(size <= 0 || values == NULL)
3183 alcSetError(device, ALC_INVALID_VALUE);
3184 return 0;
3187 if(!device)
3189 switch(param)
3191 case ALC_MAJOR_VERSION:
3192 values[0] = alcMajorVersion;
3193 return 1;
3194 case ALC_MINOR_VERSION:
3195 values[0] = alcMinorVersion;
3196 return 1;
3198 case ALC_ATTRIBUTES_SIZE:
3199 case ALC_ALL_ATTRIBUTES:
3200 case ALC_FREQUENCY:
3201 case ALC_REFRESH:
3202 case ALC_SYNC:
3203 case ALC_MONO_SOURCES:
3204 case ALC_STEREO_SOURCES:
3205 case ALC_CAPTURE_SAMPLES:
3206 case ALC_FORMAT_CHANNELS_SOFT:
3207 case ALC_FORMAT_TYPE_SOFT:
3208 case ALC_AMBISONIC_LAYOUT_SOFT:
3209 case ALC_AMBISONIC_SCALING_SOFT:
3210 case ALC_AMBISONIC_ORDER_SOFT:
3211 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3212 alcSetError(NULL, ALC_INVALID_DEVICE);
3213 return 0;
3215 default:
3216 alcSetError(NULL, ALC_INVALID_ENUM);
3217 return 0;
3219 return 0;
3222 if(device->Type == Capture)
3224 switch(param)
3226 case ALC_ATTRIBUTES_SIZE:
3227 values[0] = NumAttrsForDevice(device);
3228 return 1;
3230 case ALC_ALL_ATTRIBUTES:
3231 if(size < NumAttrsForDevice(device))
3233 alcSetError(device, ALC_INVALID_VALUE);
3234 return 0;
3237 i = 0;
3238 almtx_lock(&device->BackendLock);
3239 values[i++] = ALC_MAJOR_VERSION;
3240 values[i++] = alcMajorVersion;
3241 values[i++] = ALC_MINOR_VERSION;
3242 values[i++] = alcMinorVersion;
3243 values[i++] = ALC_CAPTURE_SAMPLES;
3244 values[i++] = V0(device->Backend,availableSamples)();
3245 values[i++] = ALC_CONNECTED;
3246 values[i++] = ATOMIC_LOAD(&device->Connected, almemory_order_relaxed);
3247 almtx_unlock(&device->BackendLock);
3249 values[i++] = 0;
3250 return i;
3252 case ALC_MAJOR_VERSION:
3253 values[0] = alcMajorVersion;
3254 return 1;
3255 case ALC_MINOR_VERSION:
3256 values[0] = alcMinorVersion;
3257 return 1;
3259 case ALC_CAPTURE_SAMPLES:
3260 almtx_lock(&device->BackendLock);
3261 values[0] = V0(device->Backend,availableSamples)();
3262 almtx_unlock(&device->BackendLock);
3263 return 1;
3265 case ALC_CONNECTED:
3266 values[0] = ATOMIC_LOAD(&device->Connected, almemory_order_acquire);
3267 return 1;
3269 default:
3270 alcSetError(device, ALC_INVALID_ENUM);
3271 return 0;
3273 return 0;
3276 /* render device */
3277 switch(param)
3279 case ALC_ATTRIBUTES_SIZE:
3280 values[0] = NumAttrsForDevice(device);
3281 return 1;
3283 case ALC_ALL_ATTRIBUTES:
3284 if(size < NumAttrsForDevice(device))
3286 alcSetError(device, ALC_INVALID_VALUE);
3287 return 0;
3290 i = 0;
3291 almtx_lock(&device->BackendLock);
3292 values[i++] = ALC_MAJOR_VERSION;
3293 values[i++] = alcMajorVersion;
3294 values[i++] = ALC_MINOR_VERSION;
3295 values[i++] = alcMinorVersion;
3296 values[i++] = ALC_EFX_MAJOR_VERSION;
3297 values[i++] = alcEFXMajorVersion;
3298 values[i++] = ALC_EFX_MINOR_VERSION;
3299 values[i++] = alcEFXMinorVersion;
3301 values[i++] = ALC_FREQUENCY;
3302 values[i++] = device->Frequency;
3303 if(device->Type != Loopback)
3305 values[i++] = ALC_REFRESH;
3306 values[i++] = device->Frequency / device->UpdateSize;
3308 values[i++] = ALC_SYNC;
3309 values[i++] = ALC_FALSE;
3311 else
3313 if(device->FmtChans == DevFmtAmbi3D)
3315 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3316 values[i++] = device->AmbiLayout;
3318 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3319 values[i++] = device->AmbiScale;
3321 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3322 values[i++] = device->AmbiOrder;
3325 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3326 values[i++] = device->FmtChans;
3328 values[i++] = ALC_FORMAT_TYPE_SOFT;
3329 values[i++] = device->FmtType;
3332 values[i++] = ALC_MONO_SOURCES;
3333 values[i++] = device->NumMonoSources;
3335 values[i++] = ALC_STEREO_SOURCES;
3336 values[i++] = device->NumStereoSources;
3338 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3339 values[i++] = device->NumAuxSends;
3341 values[i++] = ALC_HRTF_SOFT;
3342 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3344 values[i++] = ALC_HRTF_STATUS_SOFT;
3345 values[i++] = device->HrtfStatus;
3347 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3348 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3350 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
3351 values[i++] = MAX_AMBI_ORDER;
3352 almtx_unlock(&device->BackendLock);
3354 values[i++] = 0;
3355 return i;
3357 case ALC_MAJOR_VERSION:
3358 values[0] = alcMajorVersion;
3359 return 1;
3361 case ALC_MINOR_VERSION:
3362 values[0] = alcMinorVersion;
3363 return 1;
3365 case ALC_EFX_MAJOR_VERSION:
3366 values[0] = alcEFXMajorVersion;
3367 return 1;
3369 case ALC_EFX_MINOR_VERSION:
3370 values[0] = alcEFXMinorVersion;
3371 return 1;
3373 case ALC_FREQUENCY:
3374 values[0] = device->Frequency;
3375 return 1;
3377 case ALC_REFRESH:
3378 if(device->Type == Loopback)
3380 alcSetError(device, ALC_INVALID_DEVICE);
3381 return 0;
3383 almtx_lock(&device->BackendLock);
3384 values[0] = device->Frequency / device->UpdateSize;
3385 almtx_unlock(&device->BackendLock);
3386 return 1;
3388 case ALC_SYNC:
3389 if(device->Type == Loopback)
3391 alcSetError(device, ALC_INVALID_DEVICE);
3392 return 0;
3394 values[0] = ALC_FALSE;
3395 return 1;
3397 case ALC_FORMAT_CHANNELS_SOFT:
3398 if(device->Type != Loopback)
3400 alcSetError(device, ALC_INVALID_DEVICE);
3401 return 0;
3403 values[0] = device->FmtChans;
3404 return 1;
3406 case ALC_FORMAT_TYPE_SOFT:
3407 if(device->Type != Loopback)
3409 alcSetError(device, ALC_INVALID_DEVICE);
3410 return 0;
3412 values[0] = device->FmtType;
3413 return 1;
3415 case ALC_AMBISONIC_LAYOUT_SOFT:
3416 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3418 alcSetError(device, ALC_INVALID_DEVICE);
3419 return 0;
3421 values[0] = device->AmbiLayout;
3422 return 1;
3424 case ALC_AMBISONIC_SCALING_SOFT:
3425 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3427 alcSetError(device, ALC_INVALID_DEVICE);
3428 return 0;
3430 values[0] = device->AmbiScale;
3431 return 1;
3433 case ALC_AMBISONIC_ORDER_SOFT:
3434 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3436 alcSetError(device, ALC_INVALID_DEVICE);
3437 return 0;
3439 values[0] = device->AmbiOrder;
3440 return 1;
3442 case ALC_MONO_SOURCES:
3443 values[0] = device->NumMonoSources;
3444 return 1;
3446 case ALC_STEREO_SOURCES:
3447 values[0] = device->NumStereoSources;
3448 return 1;
3450 case ALC_MAX_AUXILIARY_SENDS:
3451 values[0] = device->NumAuxSends;
3452 return 1;
3454 case ALC_CONNECTED:
3455 values[0] = ATOMIC_LOAD(&device->Connected, almemory_order_acquire);
3456 return 1;
3458 case ALC_HRTF_SOFT:
3459 values[0] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3460 return 1;
3462 case ALC_HRTF_STATUS_SOFT:
3463 values[0] = device->HrtfStatus;
3464 return 1;
3466 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3467 almtx_lock(&device->BackendLock);
3468 FreeHrtfList(&device->HrtfList);
3469 device->HrtfList = EnumerateHrtf(device->DeviceName);
3470 values[0] = (ALCint)VECTOR_SIZE(device->HrtfList);
3471 almtx_unlock(&device->BackendLock);
3472 return 1;
3474 case ALC_OUTPUT_LIMITER_SOFT:
3475 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3476 return 1;
3478 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3479 values[0] = MAX_AMBI_ORDER;
3480 return 1;
3482 default:
3483 alcSetError(device, ALC_INVALID_ENUM);
3484 return 0;
3486 return 0;
3489 /* alcGetIntegerv
3491 * Returns information about the device and the version of OpenAL
3493 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3495 VerifyDevice(&device);
3496 if(size <= 0 || values == NULL)
3497 alcSetError(device, ALC_INVALID_VALUE);
3498 else
3499 GetIntegerv(device, param, size, values);
3500 if(device) ALCdevice_DecRef(device);
3503 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3505 ALCint *ivals;
3506 ALsizei i;
3508 VerifyDevice(&device);
3509 if(size <= 0 || values == NULL)
3510 alcSetError(device, ALC_INVALID_VALUE);
3511 else if(!device || device->Type == Capture)
3513 ivals = malloc(size * sizeof(ALCint));
3514 size = GetIntegerv(device, pname, size, ivals);
3515 for(i = 0;i < size;i++)
3516 values[i] = ivals[i];
3517 free(ivals);
3519 else /* render device */
3521 ClockLatency clock;
3522 ALuint64 basecount;
3523 ALuint samplecount;
3524 ALuint refcount;
3526 switch(pname)
3528 case ALC_ATTRIBUTES_SIZE:
3529 *values = NumAttrsForDevice(device)+4;
3530 break;
3532 case ALC_ALL_ATTRIBUTES:
3533 if(size < NumAttrsForDevice(device)+4)
3534 alcSetError(device, ALC_INVALID_VALUE);
3535 else
3537 i = 0;
3538 almtx_lock(&device->BackendLock);
3539 values[i++] = ALC_FREQUENCY;
3540 values[i++] = device->Frequency;
3542 if(device->Type != Loopback)
3544 values[i++] = ALC_REFRESH;
3545 values[i++] = device->Frequency / device->UpdateSize;
3547 values[i++] = ALC_SYNC;
3548 values[i++] = ALC_FALSE;
3550 else
3552 if(device->FmtChans == DevFmtAmbi3D)
3554 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3555 values[i++] = device->AmbiLayout;
3557 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3558 values[i++] = device->AmbiScale;
3560 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3561 values[i++] = device->AmbiOrder;
3564 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3565 values[i++] = device->FmtChans;
3567 values[i++] = ALC_FORMAT_TYPE_SOFT;
3568 values[i++] = device->FmtType;
3571 values[i++] = ALC_MONO_SOURCES;
3572 values[i++] = device->NumMonoSources;
3574 values[i++] = ALC_STEREO_SOURCES;
3575 values[i++] = device->NumStereoSources;
3577 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3578 values[i++] = device->NumAuxSends;
3580 values[i++] = ALC_HRTF_SOFT;
3581 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3583 values[i++] = ALC_HRTF_STATUS_SOFT;
3584 values[i++] = device->HrtfStatus;
3586 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3587 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3589 clock = V0(device->Backend,getClockLatency)();
3590 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3591 values[i++] = clock.ClockTime;
3593 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3594 values[i++] = clock.Latency;
3595 almtx_unlock(&device->BackendLock);
3597 values[i++] = 0;
3599 break;
3601 case ALC_DEVICE_CLOCK_SOFT:
3602 almtx_lock(&device->BackendLock);
3603 do {
3604 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3605 althrd_yield();
3606 basecount = device->ClockBase;
3607 samplecount = device->SamplesDone;
3608 } while(refcount != ReadRef(&device->MixCount));
3609 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3610 almtx_unlock(&device->BackendLock);
3611 break;
3613 case ALC_DEVICE_LATENCY_SOFT:
3614 almtx_lock(&device->BackendLock);
3615 clock = V0(device->Backend,getClockLatency)();
3616 almtx_unlock(&device->BackendLock);
3617 *values = clock.Latency;
3618 break;
3620 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3621 if(size < 2)
3622 alcSetError(device, ALC_INVALID_VALUE);
3623 else
3625 almtx_lock(&device->BackendLock);
3626 clock = V0(device->Backend,getClockLatency)();
3627 almtx_unlock(&device->BackendLock);
3628 values[0] = clock.ClockTime;
3629 values[1] = clock.Latency;
3631 break;
3633 default:
3634 ivals = malloc(size * sizeof(ALCint));
3635 size = GetIntegerv(device, pname, size, ivals);
3636 for(i = 0;i < size;i++)
3637 values[i] = ivals[i];
3638 free(ivals);
3639 break;
3642 if(device)
3643 ALCdevice_DecRef(device);
3647 /* alcIsExtensionPresent
3649 * Determines if there is support for a particular extension
3651 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3653 ALCboolean bResult = ALC_FALSE;
3655 VerifyDevice(&device);
3657 if(!extName)
3658 alcSetError(device, ALC_INVALID_VALUE);
3659 else
3661 size_t len = strlen(extName);
3662 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3663 while(ptr && *ptr)
3665 if(strncasecmp(ptr, extName, len) == 0 &&
3666 (ptr[len] == '\0' || isspace(ptr[len])))
3668 bResult = ALC_TRUE;
3669 break;
3671 if((ptr=strchr(ptr, ' ')) != NULL)
3673 do {
3674 ++ptr;
3675 } while(isspace(*ptr));
3679 if(device)
3680 ALCdevice_DecRef(device);
3681 return bResult;
3685 /* alcGetProcAddress
3687 * Retrieves the function address for a particular extension function
3689 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3691 ALCvoid *ptr = NULL;
3693 if(!funcName)
3695 VerifyDevice(&device);
3696 alcSetError(device, ALC_INVALID_VALUE);
3697 if(device) ALCdevice_DecRef(device);
3699 else
3701 size_t i = 0;
3702 for(i = 0;i < COUNTOF(alcFunctions);i++)
3704 if(strcmp(alcFunctions[i].funcName, funcName) == 0)
3706 ptr = alcFunctions[i].address;
3707 break;
3712 return ptr;
3716 /* alcGetEnumValue
3718 * Get the value for a particular ALC enumeration name
3720 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3722 ALCenum val = 0;
3724 if(!enumName)
3726 VerifyDevice(&device);
3727 alcSetError(device, ALC_INVALID_VALUE);
3728 if(device) ALCdevice_DecRef(device);
3730 else
3732 size_t i = 0;
3733 for(i = 0;i < COUNTOF(alcEnumerations);i++)
3735 if(strcmp(alcEnumerations[i].enumName, enumName) == 0)
3737 val = alcEnumerations[i].value;
3738 break;
3743 return val;
3747 /* alcCreateContext
3749 * Create and attach a context to the given device.
3751 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3753 ALCcontext *ALContext;
3754 ALfloat valf;
3755 ALCenum err;
3757 /* Explicitly hold the list lock while taking the BackendLock in case the
3758 * device is asynchronously destropyed, to ensure this new context is
3759 * properly cleaned up after being made.
3761 LockLists();
3762 if(!VerifyDevice(&device) || device->Type == Capture ||
3763 !ATOMIC_LOAD(&device->Connected, almemory_order_relaxed))
3765 UnlockLists();
3766 alcSetError(device, ALC_INVALID_DEVICE);
3767 if(device) ALCdevice_DecRef(device);
3768 return NULL;
3770 almtx_lock(&device->BackendLock);
3771 UnlockLists();
3773 ATOMIC_STORE_SEQ(&device->LastError, ALC_NO_ERROR);
3775 if(device->Type == Playback && DefaultEffect.type != AL_EFFECT_NULL)
3776 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener)+sizeof(ALeffectslot));
3777 else
3778 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3779 if(!ALContext)
3781 almtx_unlock(&device->BackendLock);
3783 alcSetError(device, ALC_OUT_OF_MEMORY);
3784 ALCdevice_DecRef(device);
3785 return NULL;
3788 InitRef(&ALContext->ref, 1);
3789 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3790 ALContext->DefaultSlot = NULL;
3792 ALContext->Voices = NULL;
3793 ALContext->VoiceCount = 0;
3794 ALContext->MaxVoices = 0;
3795 ATOMIC_INIT(&ALContext->ActiveAuxSlots, NULL);
3796 ALContext->Device = device;
3798 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3800 almtx_unlock(&device->BackendLock);
3802 al_free(ALContext);
3803 ALContext = NULL;
3805 alcSetError(device, err);
3806 if(err == ALC_INVALID_DEVICE)
3808 V0(device->Backend,lock)();
3809 aluHandleDisconnect(device, "Device update failure");
3810 V0(device->Backend,unlock)();
3812 ALCdevice_DecRef(device);
3813 return NULL;
3815 AllocateVoices(ALContext, 256, device->NumAuxSends);
3817 if(DefaultEffect.type != AL_EFFECT_NULL && device->Type == Playback)
3819 ALContext->DefaultSlot = (ALeffectslot*)(ALContext->_listener_mem + sizeof(ALlistener));
3820 if(InitEffectSlot(ALContext->DefaultSlot) == AL_NO_ERROR)
3821 aluInitEffectPanning(ALContext->DefaultSlot);
3822 else
3824 ALContext->DefaultSlot = NULL;
3825 ERR("Failed to initialize the default effect slot\n");
3829 ALCdevice_IncRef(ALContext->Device);
3830 InitContext(ALContext);
3832 if(ConfigValueFloat(alstr_get_cstr(device->DeviceName), NULL, "volume-adjust", &valf))
3834 if(!isfinite(valf))
3835 ERR("volume-adjust must be finite: %f\n", valf);
3836 else
3838 ALfloat db = clampf(valf, -24.0f, 24.0f);
3839 if(db != valf)
3840 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3841 ALContext->GainBoost = powf(10.0f, db/20.0f);
3842 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3845 UpdateListenerProps(ALContext);
3848 ALCcontext *head = ATOMIC_LOAD_SEQ(&device->ContextList);
3849 do {
3850 ALContext->next = head;
3851 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device->ContextList, &head,
3852 ALContext) == 0);
3854 almtx_unlock(&device->BackendLock);
3856 if(ALContext->DefaultSlot)
3858 if(InitializeEffect(ALContext, ALContext->DefaultSlot, &DefaultEffect) == AL_NO_ERROR)
3859 UpdateEffectSlotProps(ALContext->DefaultSlot, ALContext);
3860 else
3861 ERR("Failed to initialize the default effect\n");
3864 ALCdevice_DecRef(device);
3866 TRACE("Created context %p\n", ALContext);
3867 return ALContext;
3870 /* alcDestroyContext
3872 * Remove a context from its device
3874 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3876 ALCdevice *Device;
3878 LockLists();
3879 if(!VerifyContext(&context))
3881 UnlockLists();
3882 alcSetError(NULL, ALC_INVALID_CONTEXT);
3883 return;
3886 Device = context->Device;
3887 if(Device)
3889 almtx_lock(&Device->BackendLock);
3890 if(!ReleaseContext(context, Device))
3892 V0(Device->Backend,stop)();
3893 Device->Flags &= ~DEVICE_RUNNING;
3895 almtx_unlock(&Device->BackendLock);
3897 UnlockLists();
3899 ALCcontext_DecRef(context);
3903 /* alcGetCurrentContext
3905 * Returns the currently active context on the calling thread
3907 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3909 ALCcontext *Context = altss_get(LocalContext);
3910 if(!Context) Context = ATOMIC_LOAD_SEQ(&GlobalContext);
3911 return Context;
3914 /* alcGetThreadContext
3916 * Returns the currently active thread-local context
3918 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3920 return altss_get(LocalContext);
3924 /* alcMakeContextCurrent
3926 * Makes the given context the active process-wide context, and removes the
3927 * thread-local context for the calling thread.
3929 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3931 /* context must be valid or NULL */
3932 if(context && !VerifyContext(&context))
3934 alcSetError(NULL, ALC_INVALID_CONTEXT);
3935 return ALC_FALSE;
3937 /* context's reference count is already incremented */
3938 context = ATOMIC_EXCHANGE_PTR_SEQ(&GlobalContext, context);
3939 if(context) ALCcontext_DecRef(context);
3941 if((context=altss_get(LocalContext)) != NULL)
3943 altss_set(LocalContext, NULL);
3944 ALCcontext_DecRef(context);
3947 return ALC_TRUE;
3950 /* alcSetThreadContext
3952 * Makes the given context the active context for the current thread
3954 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3956 ALCcontext *old;
3958 /* context must be valid or NULL */
3959 if(context && !VerifyContext(&context))
3961 alcSetError(NULL, ALC_INVALID_CONTEXT);
3962 return ALC_FALSE;
3964 /* context's reference count is already incremented */
3965 old = altss_get(LocalContext);
3966 altss_set(LocalContext, context);
3967 if(old) ALCcontext_DecRef(old);
3969 return ALC_TRUE;
3973 /* alcGetContextsDevice
3975 * Returns the device that a particular context is attached to
3977 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3979 ALCdevice *Device;
3981 if(!VerifyContext(&Context))
3983 alcSetError(NULL, ALC_INVALID_CONTEXT);
3984 return NULL;
3986 Device = Context->Device;
3987 ALCcontext_DecRef(Context);
3989 return Device;
3993 /* alcOpenDevice
3995 * Opens the named device.
3997 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3999 ALCbackendFactory *factory;
4000 const ALCchar *fmt;
4001 ALCdevice *device;
4002 ALCenum err;
4004 DO_INITCONFIG();
4006 if(!PlaybackBackend.name)
4008 alcSetError(NULL, ALC_INVALID_VALUE);
4009 return NULL;
4012 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
4013 #ifdef _WIN32
4014 /* Some old Windows apps hardcode these expecting OpenAL to use a
4015 * specific audio API, even when they're not enumerated. Creative's
4016 * router effectively ignores them too.
4018 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
4019 || strcasecmp(deviceName, "MMSYSTEM") == 0
4020 #endif
4022 deviceName = NULL;
4024 device = al_calloc(16, sizeof(ALCdevice));
4025 if(!device)
4027 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4028 return NULL;
4031 //Validate device
4032 InitRef(&device->ref, 1);
4033 ATOMIC_INIT(&device->Connected, ALC_TRUE);
4034 device->Type = Playback;
4035 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
4037 InitDevice(device);
4039 //Set output format
4040 device->FmtChans = DevFmtChannelsDefault;
4041 device->FmtType = DevFmtTypeDefault;
4042 device->Frequency = DEFAULT_OUTPUT_RATE;
4043 device->IsHeadphones = AL_FALSE;
4044 device->AmbiLayout = AmbiLayout_Default;
4045 device->AmbiScale = AmbiNorm_Default;
4046 device->NumUpdates = 3;
4047 device->UpdateSize = 1024;
4049 device->SourcesMax = 256;
4050 device->AuxiliaryEffectSlotMax = 64;
4051 device->NumAuxSends = DEFAULT_SENDS;
4053 if(ConfigValueStr(deviceName, NULL, "channels", &fmt))
4055 static const struct {
4056 const char name[16];
4057 enum DevFmtChannels chans;
4058 ALsizei order;
4059 } chanlist[] = {
4060 { "mono", DevFmtMono, 0 },
4061 { "stereo", DevFmtStereo, 0 },
4062 { "quad", DevFmtQuad, 0 },
4063 { "surround51", DevFmtX51, 0 },
4064 { "surround61", DevFmtX61, 0 },
4065 { "surround71", DevFmtX71, 0 },
4066 { "surround51rear", DevFmtX51Rear, 0 },
4067 { "ambi1", DevFmtAmbi3D, 1 },
4068 { "ambi2", DevFmtAmbi3D, 2 },
4069 { "ambi3", DevFmtAmbi3D, 3 },
4071 size_t i;
4073 for(i = 0;i < COUNTOF(chanlist);i++)
4075 if(strcasecmp(chanlist[i].name, fmt) == 0)
4077 device->FmtChans = chanlist[i].chans;
4078 device->AmbiOrder = chanlist[i].order;
4079 device->Flags |= DEVICE_CHANNELS_REQUEST;
4080 break;
4083 if(i == COUNTOF(chanlist))
4084 ERR("Unsupported channels: %s\n", fmt);
4086 if(ConfigValueStr(deviceName, NULL, "sample-type", &fmt))
4088 static const struct {
4089 const char name[16];
4090 enum DevFmtType type;
4091 } typelist[] = {
4092 { "int8", DevFmtByte },
4093 { "uint8", DevFmtUByte },
4094 { "int16", DevFmtShort },
4095 { "uint16", DevFmtUShort },
4096 { "int32", DevFmtInt },
4097 { "uint32", DevFmtUInt },
4098 { "float32", DevFmtFloat },
4100 size_t i;
4102 for(i = 0;i < COUNTOF(typelist);i++)
4104 if(strcasecmp(typelist[i].name, fmt) == 0)
4106 device->FmtType = typelist[i].type;
4107 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
4108 break;
4111 if(i == COUNTOF(typelist))
4112 ERR("Unsupported sample-type: %s\n", fmt);
4115 if(ConfigValueUInt(deviceName, NULL, "frequency", &device->Frequency))
4117 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4118 if(device->Frequency < MIN_OUTPUT_RATE)
4119 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
4120 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
4123 ConfigValueUInt(deviceName, NULL, "periods", &device->NumUpdates);
4124 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
4126 ConfigValueUInt(deviceName, NULL, "period_size", &device->UpdateSize);
4127 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
4128 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
4129 device->UpdateSize = (device->UpdateSize+3)&~3;
4131 ConfigValueUInt(deviceName, NULL, "sources", &device->SourcesMax);
4132 if(device->SourcesMax == 0) device->SourcesMax = 256;
4134 ConfigValueUInt(deviceName, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4135 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4137 if(ConfigValueInt(deviceName, NULL, "sends", &device->NumAuxSends))
4138 device->NumAuxSends = clampi(
4139 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4142 device->NumStereoSources = 1;
4143 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4145 factory = PlaybackBackend.getFactory();
4146 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
4147 if(!device->Backend)
4149 FreeDevice(device);
4150 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4151 return NULL;
4154 // Find a playback device to open
4155 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4157 FreeDevice(device);
4158 alcSetError(NULL, err);
4159 return NULL;
4162 if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt))
4164 if(strcasecmp(fmt, "fuma") == 0)
4166 device->AmbiLayout = AmbiLayout_FuMa;
4167 device->AmbiScale = AmbiNorm_FuMa;
4169 else if(strcasecmp(fmt, "acn+sn3d") == 0)
4171 device->AmbiLayout = AmbiLayout_ACN;
4172 device->AmbiScale = AmbiNorm_SN3D;
4174 else if(strcasecmp(fmt, "acn+n3d") == 0)
4176 device->AmbiLayout = AmbiLayout_ACN;
4177 device->AmbiScale = AmbiNorm_N3D;
4179 else
4180 ERR("Unsupported ambi-format: %s\n", fmt);
4183 device->Limiter = CreateDeviceLimiter(device);
4186 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4187 do {
4188 device->next = head;
4189 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4192 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
4193 return device;
4196 /* alcCloseDevice
4198 * Closes the given device.
4200 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
4202 ALCdevice *iter, *origdev;
4203 ALCcontext *ctx;
4205 LockLists();
4206 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4207 do {
4208 if(iter == device)
4209 break;
4210 } while((iter=iter->next) != NULL);
4211 if(!iter || iter->Type == Capture)
4213 alcSetError(iter, ALC_INVALID_DEVICE);
4214 UnlockLists();
4215 return ALC_FALSE;
4217 almtx_lock(&device->BackendLock);
4219 origdev = device;
4220 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, device->next))
4222 ALCdevice *volatile*list = &origdev->next;
4223 while(*list)
4225 if(*list == device)
4227 *list = (*list)->next;
4228 break;
4230 list = &(*list)->next;
4233 UnlockLists();
4235 ctx = ATOMIC_LOAD_SEQ(&device->ContextList);
4236 while(ctx != NULL)
4238 ALCcontext *next = ctx->next;
4239 WARN("Releasing context %p\n", ctx);
4240 ReleaseContext(ctx, device);
4241 ctx = next;
4243 if((device->Flags&DEVICE_RUNNING))
4244 V0(device->Backend,stop)();
4245 device->Flags &= ~DEVICE_RUNNING;
4246 almtx_unlock(&device->BackendLock);
4248 ALCdevice_DecRef(device);
4250 return ALC_TRUE;
4254 /************************************************
4255 * ALC capture functions
4256 ************************************************/
4257 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
4259 ALCbackendFactory *factory;
4260 ALCdevice *device = NULL;
4261 ALCenum err;
4263 DO_INITCONFIG();
4265 if(!CaptureBackend.name)
4267 alcSetError(NULL, ALC_INVALID_VALUE);
4268 return NULL;
4271 if(samples <= 0)
4273 alcSetError(NULL, ALC_INVALID_VALUE);
4274 return NULL;
4277 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
4278 deviceName = NULL;
4280 device = al_calloc(16, sizeof(ALCdevice));
4281 if(!device)
4283 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4284 return NULL;
4287 //Validate device
4288 InitRef(&device->ref, 1);
4289 ATOMIC_INIT(&device->Connected, ALC_TRUE);
4290 device->Type = Capture;
4292 InitDevice(device);
4294 device->Frequency = frequency;
4295 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4297 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
4299 FreeDevice(device);
4300 alcSetError(NULL, ALC_INVALID_ENUM);
4301 return NULL;
4303 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
4304 device->IsHeadphones = AL_FALSE;
4305 device->AmbiOrder = 0;
4306 device->AmbiLayout = AmbiLayout_Default;
4307 device->AmbiScale = AmbiNorm_Default;
4309 device->UpdateSize = samples;
4310 device->NumUpdates = 1;
4312 factory = CaptureBackend.getFactory();
4313 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
4314 if(!device->Backend)
4316 FreeDevice(device);
4317 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4318 return NULL;
4321 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4322 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
4323 device->Frequency, device->UpdateSize, device->NumUpdates
4325 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4327 FreeDevice(device);
4328 alcSetError(NULL, err);
4329 return NULL;
4333 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4334 do {
4335 device->next = head;
4336 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4339 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
4340 return device;
4343 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
4345 ALCdevice *iter, *origdev;
4347 LockLists();
4348 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4349 do {
4350 if(iter == device)
4351 break;
4352 } while((iter=iter->next) != NULL);
4353 if(!iter || iter->Type != Capture)
4355 alcSetError(iter, ALC_INVALID_DEVICE);
4356 UnlockLists();
4357 return ALC_FALSE;
4360 origdev = device;
4361 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, device->next))
4363 ALCdevice *volatile*list = &origdev->next;
4364 while(*list)
4366 if(*list == device)
4368 *list = (*list)->next;
4369 break;
4371 list = &(*list)->next;
4374 UnlockLists();
4376 ALCdevice_DecRef(device);
4378 return ALC_TRUE;
4381 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
4383 if(!VerifyDevice(&device) || device->Type != Capture)
4384 alcSetError(device, ALC_INVALID_DEVICE);
4385 else
4387 almtx_lock(&device->BackendLock);
4388 if(!ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
4389 alcSetError(device, ALC_INVALID_DEVICE);
4390 else if(!(device->Flags&DEVICE_RUNNING))
4392 if(V0(device->Backend,start)())
4393 device->Flags |= DEVICE_RUNNING;
4394 else
4396 aluHandleDisconnect(device, "Device start failure");
4397 alcSetError(device, ALC_INVALID_DEVICE);
4400 almtx_unlock(&device->BackendLock);
4403 if(device) ALCdevice_DecRef(device);
4406 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
4408 if(!VerifyDevice(&device) || device->Type != Capture)
4409 alcSetError(device, ALC_INVALID_DEVICE);
4410 else
4412 almtx_lock(&device->BackendLock);
4413 if((device->Flags&DEVICE_RUNNING))
4414 V0(device->Backend,stop)();
4415 device->Flags &= ~DEVICE_RUNNING;
4416 almtx_unlock(&device->BackendLock);
4419 if(device) ALCdevice_DecRef(device);
4422 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4424 if(!VerifyDevice(&device) || device->Type != Capture)
4425 alcSetError(device, ALC_INVALID_DEVICE);
4426 else
4428 ALCenum err = ALC_INVALID_VALUE;
4430 almtx_lock(&device->BackendLock);
4431 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
4432 err = V(device->Backend,captureSamples)(buffer, samples);
4433 almtx_unlock(&device->BackendLock);
4435 if(err != ALC_NO_ERROR)
4436 alcSetError(device, err);
4438 if(device) ALCdevice_DecRef(device);
4442 /************************************************
4443 * ALC loopback functions
4444 ************************************************/
4446 /* alcLoopbackOpenDeviceSOFT
4448 * Open a loopback device, for manual rendering.
4450 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
4452 ALCbackendFactory *factory;
4453 ALCdevice *device;
4455 DO_INITCONFIG();
4457 /* Make sure the device name, if specified, is us. */
4458 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
4460 alcSetError(NULL, ALC_INVALID_VALUE);
4461 return NULL;
4464 device = al_calloc(16, sizeof(ALCdevice));
4465 if(!device)
4467 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4468 return NULL;
4471 //Validate device
4472 InitRef(&device->ref, 1);
4473 ATOMIC_INIT(&device->Connected, ALC_TRUE);
4474 device->Type = Loopback;
4475 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
4477 InitDevice(device);
4479 device->SourcesMax = 256;
4480 device->AuxiliaryEffectSlotMax = 64;
4481 device->NumAuxSends = DEFAULT_SENDS;
4483 //Set output format
4484 device->NumUpdates = 0;
4485 device->UpdateSize = 0;
4487 device->Frequency = DEFAULT_OUTPUT_RATE;
4488 device->FmtChans = DevFmtChannelsDefault;
4489 device->FmtType = DevFmtTypeDefault;
4490 device->IsHeadphones = AL_FALSE;
4491 device->AmbiLayout = AmbiLayout_Default;
4492 device->AmbiScale = AmbiNorm_Default;
4494 ConfigValueUInt(NULL, NULL, "sources", &device->SourcesMax);
4495 if(device->SourcesMax == 0) device->SourcesMax = 256;
4497 ConfigValueUInt(NULL, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4498 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4500 if(ConfigValueInt(NULL, NULL, "sends", &device->NumAuxSends))
4501 device->NumAuxSends = clampi(
4502 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4505 device->NumStereoSources = 1;
4506 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4508 factory = ALCloopbackFactory_getFactory();
4509 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
4510 if(!device->Backend)
4512 al_free(device);
4513 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4514 return NULL;
4517 // Open the "backend"
4518 V(device->Backend,open)("Loopback");
4520 device->Limiter = CreateDeviceLimiter(device);
4523 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4524 do {
4525 device->next = head;
4526 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4529 TRACE("Created device %p\n", device);
4530 return device;
4533 /* alcIsRenderFormatSupportedSOFT
4535 * Determines if the loopback device supports the given format for rendering.
4537 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4539 ALCboolean ret = ALC_FALSE;
4541 if(!VerifyDevice(&device) || device->Type != Loopback)
4542 alcSetError(device, ALC_INVALID_DEVICE);
4543 else if(freq <= 0)
4544 alcSetError(device, ALC_INVALID_VALUE);
4545 else
4547 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4548 ret = ALC_TRUE;
4550 if(device) ALCdevice_DecRef(device);
4552 return ret;
4555 /* alcRenderSamplesSOFT
4557 * Renders some samples into a buffer, using the format last set by the
4558 * attributes given to alcCreateContext.
4560 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4562 if(!VerifyDevice(&device) || device->Type != Loopback)
4563 alcSetError(device, ALC_INVALID_DEVICE);
4564 else if(samples < 0 || (samples > 0 && buffer == NULL))
4565 alcSetError(device, ALC_INVALID_VALUE);
4566 else
4568 V0(device->Backend,lock)();
4569 aluMixData(device, buffer, samples);
4570 V0(device->Backend,unlock)();
4572 if(device) ALCdevice_DecRef(device);
4576 /************************************************
4577 * ALC DSP pause/resume functions
4578 ************************************************/
4580 /* alcDevicePauseSOFT
4582 * Pause the DSP to stop audio processing.
4584 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4586 if(!VerifyDevice(&device) || device->Type != Playback)
4587 alcSetError(device, ALC_INVALID_DEVICE);
4588 else
4590 almtx_lock(&device->BackendLock);
4591 if((device->Flags&DEVICE_RUNNING))
4592 V0(device->Backend,stop)();
4593 device->Flags &= ~DEVICE_RUNNING;
4594 device->Flags |= DEVICE_PAUSED;
4595 almtx_unlock(&device->BackendLock);
4597 if(device) ALCdevice_DecRef(device);
4600 /* alcDeviceResumeSOFT
4602 * Resume the DSP to restart audio processing.
4604 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4606 if(!VerifyDevice(&device) || device->Type != Playback)
4607 alcSetError(device, ALC_INVALID_DEVICE);
4608 else
4610 almtx_lock(&device->BackendLock);
4611 if((device->Flags&DEVICE_PAUSED))
4613 device->Flags &= ~DEVICE_PAUSED;
4614 if(ATOMIC_LOAD_SEQ(&device->ContextList) != NULL)
4616 if(V0(device->Backend,start)() != ALC_FALSE)
4617 device->Flags |= DEVICE_RUNNING;
4618 else
4620 V0(device->Backend,lock)();
4621 aluHandleDisconnect(device, "Device start failure");
4622 V0(device->Backend,unlock)();
4623 alcSetError(device, ALC_INVALID_DEVICE);
4627 almtx_unlock(&device->BackendLock);
4629 if(device) ALCdevice_DecRef(device);
4633 /************************************************
4634 * ALC HRTF functions
4635 ************************************************/
4637 /* alcGetStringiSOFT
4639 * Gets a string parameter at the given index.
4641 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4643 const ALCchar *str = NULL;
4645 if(!VerifyDevice(&device) || device->Type == Capture)
4646 alcSetError(device, ALC_INVALID_DEVICE);
4647 else switch(paramName)
4649 case ALC_HRTF_SPECIFIER_SOFT:
4650 if(index >= 0 && (size_t)index < VECTOR_SIZE(device->HrtfList))
4651 str = alstr_get_cstr(VECTOR_ELEM(device->HrtfList, index).name);
4652 else
4653 alcSetError(device, ALC_INVALID_VALUE);
4654 break;
4656 default:
4657 alcSetError(device, ALC_INVALID_ENUM);
4658 break;
4660 if(device) ALCdevice_DecRef(device);
4662 return str;
4665 /* alcResetDeviceSOFT
4667 * Resets the given device output, using the specified attribute list.
4669 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4671 ALCenum err;
4673 LockLists();
4674 if(!VerifyDevice(&device) || device->Type == Capture ||
4675 !ATOMIC_LOAD(&device->Connected, almemory_order_relaxed))
4677 UnlockLists();
4678 alcSetError(device, ALC_INVALID_DEVICE);
4679 if(device) ALCdevice_DecRef(device);
4680 return ALC_FALSE;
4682 almtx_lock(&device->BackendLock);
4683 UnlockLists();
4685 err = UpdateDeviceParams(device, attribs);
4686 almtx_unlock(&device->BackendLock);
4688 if(err != ALC_NO_ERROR)
4690 alcSetError(device, err);
4691 if(err == ALC_INVALID_DEVICE)
4693 V0(device->Backend,lock)();
4694 aluHandleDisconnect(device, "Device start failure");
4695 V0(device->Backend,unlock)();
4697 ALCdevice_DecRef(device);
4698 return ALC_FALSE;
4700 ALCdevice_DecRef(device);
4702 return ALC_TRUE;