Avoid separate updates to sources that should apply together
[openal-soft.git] / Alc / ALc.c
blob86b8e59ef484faab08454468a745fdc613661018
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 <math.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <memory.h>
27 #include <ctype.h>
28 #include <signal.h>
30 #include "alMain.h"
31 #include "alSource.h"
32 #include "alListener.h"
33 #include "alThunk.h"
34 #include "alSource.h"
35 #include "alBuffer.h"
36 #include "alAuxEffectSlot.h"
37 #include "alError.h"
38 #include "bformatdec.h"
39 #include "alu.h"
41 #include "compat.h"
42 #include "threads.h"
43 #include "alstring.h"
44 #include "almalloc.h"
46 #include "backends/base.h"
49 /************************************************
50 * Backends
51 ************************************************/
52 struct BackendInfo {
53 const char *name;
54 ALCbackendFactory* (*getFactory)(void);
55 ALCboolean (*Init)(BackendFuncs*);
56 void (*Deinit)(void);
57 void (*Probe)(enum DevProbe);
58 BackendFuncs Funcs;
61 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
62 static struct BackendInfo BackendList[] = {
63 #ifdef HAVE_JACK
64 { "jack", ALCjackBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
65 #endif
66 #ifdef HAVE_PULSEAUDIO
67 { "pulse", ALCpulseBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
68 #endif
69 #ifdef HAVE_ALSA
70 { "alsa", ALCalsaBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
71 #endif
72 #ifdef HAVE_COREAUDIO
73 { "core", NULL, alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
74 #endif
75 #ifdef HAVE_OSS
76 { "oss", ALCossBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
77 #endif
78 #ifdef HAVE_SOLARIS
79 { "solaris", ALCsolarisBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
80 #endif
81 #ifdef HAVE_SNDIO
82 { "sndio", NULL, alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs },
83 #endif
84 #ifdef HAVE_QSA
85 { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs },
86 #endif
87 #ifdef HAVE_MMDEVAPI
88 { "mmdevapi", ALCmmdevBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
89 #endif
90 #ifdef HAVE_DSOUND
91 { "dsound", ALCdsoundBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
92 #endif
93 #ifdef HAVE_WINMM
94 { "winmm", ALCwinmmBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
95 #endif
96 #ifdef HAVE_PORTAUDIO
97 { "port", ALCportBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
98 #endif
99 #ifdef HAVE_OPENSL
100 { "opensl", NULL, alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs },
101 #endif
103 { "null", ALCnullBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
104 #ifdef HAVE_WAVE
105 { "wave", ALCwaveBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
106 #endif
108 { NULL, NULL, NULL, NULL, NULL, EmptyFuncs }
110 #undef EmptyFuncs
112 static struct BackendInfo PlaybackBackend;
113 static struct BackendInfo CaptureBackend;
116 /************************************************
117 * Functions, enums, and errors
118 ************************************************/
119 typedef struct ALCfunction {
120 const ALCchar *funcName;
121 ALCvoid *address;
122 } ALCfunction;
124 typedef struct ALCenums {
125 const ALCchar *enumName;
126 ALCenum value;
127 } ALCenums;
129 #define DECL(x) { #x, (ALCvoid*)(x) }
130 static const ALCfunction alcFunctions[] = {
131 DECL(alcCreateContext),
132 DECL(alcMakeContextCurrent),
133 DECL(alcProcessContext),
134 DECL(alcSuspendContext),
135 DECL(alcDestroyContext),
136 DECL(alcGetCurrentContext),
137 DECL(alcGetContextsDevice),
138 DECL(alcOpenDevice),
139 DECL(alcCloseDevice),
140 DECL(alcGetError),
141 DECL(alcIsExtensionPresent),
142 DECL(alcGetProcAddress),
143 DECL(alcGetEnumValue),
144 DECL(alcGetString),
145 DECL(alcGetIntegerv),
146 DECL(alcCaptureOpenDevice),
147 DECL(alcCaptureCloseDevice),
148 DECL(alcCaptureStart),
149 DECL(alcCaptureStop),
150 DECL(alcCaptureSamples),
152 DECL(alcSetThreadContext),
153 DECL(alcGetThreadContext),
155 DECL(alcLoopbackOpenDeviceSOFT),
156 DECL(alcIsRenderFormatSupportedSOFT),
157 DECL(alcRenderSamplesSOFT),
159 DECL(alcDevicePauseSOFT),
160 DECL(alcDeviceResumeSOFT),
162 DECL(alcGetStringiSOFT),
163 DECL(alcResetDeviceSOFT),
165 DECL(alcGetInteger64vSOFT),
167 DECL(alEnable),
168 DECL(alDisable),
169 DECL(alIsEnabled),
170 DECL(alGetString),
171 DECL(alGetBooleanv),
172 DECL(alGetIntegerv),
173 DECL(alGetFloatv),
174 DECL(alGetDoublev),
175 DECL(alGetBoolean),
176 DECL(alGetInteger),
177 DECL(alGetFloat),
178 DECL(alGetDouble),
179 DECL(alGetError),
180 DECL(alIsExtensionPresent),
181 DECL(alGetProcAddress),
182 DECL(alGetEnumValue),
183 DECL(alListenerf),
184 DECL(alListener3f),
185 DECL(alListenerfv),
186 DECL(alListeneri),
187 DECL(alListener3i),
188 DECL(alListeneriv),
189 DECL(alGetListenerf),
190 DECL(alGetListener3f),
191 DECL(alGetListenerfv),
192 DECL(alGetListeneri),
193 DECL(alGetListener3i),
194 DECL(alGetListeneriv),
195 DECL(alGenSources),
196 DECL(alDeleteSources),
197 DECL(alIsSource),
198 DECL(alSourcef),
199 DECL(alSource3f),
200 DECL(alSourcefv),
201 DECL(alSourcei),
202 DECL(alSource3i),
203 DECL(alSourceiv),
204 DECL(alGetSourcef),
205 DECL(alGetSource3f),
206 DECL(alGetSourcefv),
207 DECL(alGetSourcei),
208 DECL(alGetSource3i),
209 DECL(alGetSourceiv),
210 DECL(alSourcePlayv),
211 DECL(alSourceStopv),
212 DECL(alSourceRewindv),
213 DECL(alSourcePausev),
214 DECL(alSourcePlay),
215 DECL(alSourceStop),
216 DECL(alSourceRewind),
217 DECL(alSourcePause),
218 DECL(alSourceQueueBuffers),
219 DECL(alSourceUnqueueBuffers),
220 DECL(alGenBuffers),
221 DECL(alDeleteBuffers),
222 DECL(alIsBuffer),
223 DECL(alBufferData),
224 DECL(alBufferf),
225 DECL(alBuffer3f),
226 DECL(alBufferfv),
227 DECL(alBufferi),
228 DECL(alBuffer3i),
229 DECL(alBufferiv),
230 DECL(alGetBufferf),
231 DECL(alGetBuffer3f),
232 DECL(alGetBufferfv),
233 DECL(alGetBufferi),
234 DECL(alGetBuffer3i),
235 DECL(alGetBufferiv),
236 DECL(alDopplerFactor),
237 DECL(alDopplerVelocity),
238 DECL(alSpeedOfSound),
239 DECL(alDistanceModel),
241 DECL(alGenFilters),
242 DECL(alDeleteFilters),
243 DECL(alIsFilter),
244 DECL(alFilteri),
245 DECL(alFilteriv),
246 DECL(alFilterf),
247 DECL(alFilterfv),
248 DECL(alGetFilteri),
249 DECL(alGetFilteriv),
250 DECL(alGetFilterf),
251 DECL(alGetFilterfv),
252 DECL(alGenEffects),
253 DECL(alDeleteEffects),
254 DECL(alIsEffect),
255 DECL(alEffecti),
256 DECL(alEffectiv),
257 DECL(alEffectf),
258 DECL(alEffectfv),
259 DECL(alGetEffecti),
260 DECL(alGetEffectiv),
261 DECL(alGetEffectf),
262 DECL(alGetEffectfv),
263 DECL(alGenAuxiliaryEffectSlots),
264 DECL(alDeleteAuxiliaryEffectSlots),
265 DECL(alIsAuxiliaryEffectSlot),
266 DECL(alAuxiliaryEffectSloti),
267 DECL(alAuxiliaryEffectSlotiv),
268 DECL(alAuxiliaryEffectSlotf),
269 DECL(alAuxiliaryEffectSlotfv),
270 DECL(alGetAuxiliaryEffectSloti),
271 DECL(alGetAuxiliaryEffectSlotiv),
272 DECL(alGetAuxiliaryEffectSlotf),
273 DECL(alGetAuxiliaryEffectSlotfv),
275 DECL(alDeferUpdatesSOFT),
276 DECL(alProcessUpdatesSOFT),
278 DECL(alSourcedSOFT),
279 DECL(alSource3dSOFT),
280 DECL(alSourcedvSOFT),
281 DECL(alGetSourcedSOFT),
282 DECL(alGetSource3dSOFT),
283 DECL(alGetSourcedvSOFT),
284 DECL(alSourcei64SOFT),
285 DECL(alSource3i64SOFT),
286 DECL(alSourcei64vSOFT),
287 DECL(alGetSourcei64SOFT),
288 DECL(alGetSource3i64SOFT),
289 DECL(alGetSourcei64vSOFT),
291 DECL(alBufferSamplesSOFT),
292 DECL(alGetBufferSamplesSOFT),
293 DECL(alIsBufferFormatSupportedSOFT),
295 { NULL, NULL }
297 #undef DECL
299 #define DECL(x) { #x, (x) }
300 static const ALCenums enumeration[] = {
301 DECL(ALC_INVALID),
302 DECL(ALC_FALSE),
303 DECL(ALC_TRUE),
305 DECL(ALC_MAJOR_VERSION),
306 DECL(ALC_MINOR_VERSION),
307 DECL(ALC_ATTRIBUTES_SIZE),
308 DECL(ALC_ALL_ATTRIBUTES),
309 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
310 DECL(ALC_DEVICE_SPECIFIER),
311 DECL(ALC_ALL_DEVICES_SPECIFIER),
312 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
313 DECL(ALC_EXTENSIONS),
314 DECL(ALC_FREQUENCY),
315 DECL(ALC_REFRESH),
316 DECL(ALC_SYNC),
317 DECL(ALC_MONO_SOURCES),
318 DECL(ALC_STEREO_SOURCES),
319 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
320 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
321 DECL(ALC_CAPTURE_SAMPLES),
322 DECL(ALC_CONNECTED),
324 DECL(ALC_EFX_MAJOR_VERSION),
325 DECL(ALC_EFX_MINOR_VERSION),
326 DECL(ALC_MAX_AUXILIARY_SENDS),
328 DECL(ALC_FORMAT_CHANNELS_SOFT),
329 DECL(ALC_FORMAT_TYPE_SOFT),
331 DECL(ALC_MONO_SOFT),
332 DECL(ALC_STEREO_SOFT),
333 DECL(ALC_QUAD_SOFT),
334 DECL(ALC_5POINT1_SOFT),
335 DECL(ALC_6POINT1_SOFT),
336 DECL(ALC_7POINT1_SOFT),
338 DECL(ALC_BYTE_SOFT),
339 DECL(ALC_UNSIGNED_BYTE_SOFT),
340 DECL(ALC_SHORT_SOFT),
341 DECL(ALC_UNSIGNED_SHORT_SOFT),
342 DECL(ALC_INT_SOFT),
343 DECL(ALC_UNSIGNED_INT_SOFT),
344 DECL(ALC_FLOAT_SOFT),
346 DECL(ALC_HRTF_SOFT),
347 DECL(ALC_DONT_CARE_SOFT),
348 DECL(ALC_HRTF_STATUS_SOFT),
349 DECL(ALC_HRTF_DISABLED_SOFT),
350 DECL(ALC_HRTF_ENABLED_SOFT),
351 DECL(ALC_HRTF_DENIED_SOFT),
352 DECL(ALC_HRTF_REQUIRED_SOFT),
353 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
354 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
355 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
356 DECL(ALC_HRTF_SPECIFIER_SOFT),
357 DECL(ALC_HRTF_ID_SOFT),
359 DECL(ALC_NO_ERROR),
360 DECL(ALC_INVALID_DEVICE),
361 DECL(ALC_INVALID_CONTEXT),
362 DECL(ALC_INVALID_ENUM),
363 DECL(ALC_INVALID_VALUE),
364 DECL(ALC_OUT_OF_MEMORY),
367 DECL(AL_INVALID),
368 DECL(AL_NONE),
369 DECL(AL_FALSE),
370 DECL(AL_TRUE),
372 DECL(AL_SOURCE_RELATIVE),
373 DECL(AL_CONE_INNER_ANGLE),
374 DECL(AL_CONE_OUTER_ANGLE),
375 DECL(AL_PITCH),
376 DECL(AL_POSITION),
377 DECL(AL_DIRECTION),
378 DECL(AL_VELOCITY),
379 DECL(AL_LOOPING),
380 DECL(AL_BUFFER),
381 DECL(AL_GAIN),
382 DECL(AL_MIN_GAIN),
383 DECL(AL_MAX_GAIN),
384 DECL(AL_ORIENTATION),
385 DECL(AL_REFERENCE_DISTANCE),
386 DECL(AL_ROLLOFF_FACTOR),
387 DECL(AL_CONE_OUTER_GAIN),
388 DECL(AL_MAX_DISTANCE),
389 DECL(AL_SEC_OFFSET),
390 DECL(AL_SAMPLE_OFFSET),
391 DECL(AL_BYTE_OFFSET),
392 DECL(AL_SOURCE_TYPE),
393 DECL(AL_STATIC),
394 DECL(AL_STREAMING),
395 DECL(AL_UNDETERMINED),
396 DECL(AL_METERS_PER_UNIT),
397 DECL(AL_LOOP_POINTS_SOFT),
398 DECL(AL_DIRECT_CHANNELS_SOFT),
400 DECL(AL_DIRECT_FILTER),
401 DECL(AL_AUXILIARY_SEND_FILTER),
402 DECL(AL_AIR_ABSORPTION_FACTOR),
403 DECL(AL_ROOM_ROLLOFF_FACTOR),
404 DECL(AL_CONE_OUTER_GAINHF),
405 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
406 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
407 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
409 DECL(AL_SOURCE_STATE),
410 DECL(AL_INITIAL),
411 DECL(AL_PLAYING),
412 DECL(AL_PAUSED),
413 DECL(AL_STOPPED),
415 DECL(AL_BUFFERS_QUEUED),
416 DECL(AL_BUFFERS_PROCESSED),
418 DECL(AL_FORMAT_MONO8),
419 DECL(AL_FORMAT_MONO16),
420 DECL(AL_FORMAT_MONO_FLOAT32),
421 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
422 DECL(AL_FORMAT_STEREO8),
423 DECL(AL_FORMAT_STEREO16),
424 DECL(AL_FORMAT_STEREO_FLOAT32),
425 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
426 DECL(AL_FORMAT_MONO_IMA4),
427 DECL(AL_FORMAT_STEREO_IMA4),
428 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
429 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
430 DECL(AL_FORMAT_QUAD8_LOKI),
431 DECL(AL_FORMAT_QUAD16_LOKI),
432 DECL(AL_FORMAT_QUAD8),
433 DECL(AL_FORMAT_QUAD16),
434 DECL(AL_FORMAT_QUAD32),
435 DECL(AL_FORMAT_51CHN8),
436 DECL(AL_FORMAT_51CHN16),
437 DECL(AL_FORMAT_51CHN32),
438 DECL(AL_FORMAT_61CHN8),
439 DECL(AL_FORMAT_61CHN16),
440 DECL(AL_FORMAT_61CHN32),
441 DECL(AL_FORMAT_71CHN8),
442 DECL(AL_FORMAT_71CHN16),
443 DECL(AL_FORMAT_71CHN32),
444 DECL(AL_FORMAT_REAR8),
445 DECL(AL_FORMAT_REAR16),
446 DECL(AL_FORMAT_REAR32),
447 DECL(AL_FORMAT_MONO_MULAW),
448 DECL(AL_FORMAT_MONO_MULAW_EXT),
449 DECL(AL_FORMAT_STEREO_MULAW),
450 DECL(AL_FORMAT_STEREO_MULAW_EXT),
451 DECL(AL_FORMAT_QUAD_MULAW),
452 DECL(AL_FORMAT_51CHN_MULAW),
453 DECL(AL_FORMAT_61CHN_MULAW),
454 DECL(AL_FORMAT_71CHN_MULAW),
455 DECL(AL_FORMAT_REAR_MULAW),
456 DECL(AL_FORMAT_MONO_ALAW_EXT),
457 DECL(AL_FORMAT_STEREO_ALAW_EXT),
459 DECL(AL_FORMAT_BFORMAT2D_8),
460 DECL(AL_FORMAT_BFORMAT2D_16),
461 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
462 DECL(AL_FORMAT_BFORMAT2D_MULAW),
463 DECL(AL_FORMAT_BFORMAT3D_8),
464 DECL(AL_FORMAT_BFORMAT3D_16),
465 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
466 DECL(AL_FORMAT_BFORMAT3D_MULAW),
468 DECL(AL_MONO8_SOFT),
469 DECL(AL_MONO16_SOFT),
470 DECL(AL_MONO32F_SOFT),
471 DECL(AL_STEREO8_SOFT),
472 DECL(AL_STEREO16_SOFT),
473 DECL(AL_STEREO32F_SOFT),
474 DECL(AL_QUAD8_SOFT),
475 DECL(AL_QUAD16_SOFT),
476 DECL(AL_QUAD32F_SOFT),
477 DECL(AL_REAR8_SOFT),
478 DECL(AL_REAR16_SOFT),
479 DECL(AL_REAR32F_SOFT),
480 DECL(AL_5POINT1_8_SOFT),
481 DECL(AL_5POINT1_16_SOFT),
482 DECL(AL_5POINT1_32F_SOFT),
483 DECL(AL_6POINT1_8_SOFT),
484 DECL(AL_6POINT1_16_SOFT),
485 DECL(AL_6POINT1_32F_SOFT),
486 DECL(AL_7POINT1_8_SOFT),
487 DECL(AL_7POINT1_16_SOFT),
488 DECL(AL_7POINT1_32F_SOFT),
489 DECL(AL_BFORMAT2D_8_SOFT),
490 DECL(AL_BFORMAT2D_16_SOFT),
491 DECL(AL_BFORMAT2D_32F_SOFT),
492 DECL(AL_BFORMAT3D_8_SOFT),
493 DECL(AL_BFORMAT3D_16_SOFT),
494 DECL(AL_BFORMAT3D_32F_SOFT),
496 DECL(AL_MONO_SOFT),
497 DECL(AL_STEREO_SOFT),
498 DECL(AL_QUAD_SOFT),
499 DECL(AL_REAR_SOFT),
500 DECL(AL_5POINT1_SOFT),
501 DECL(AL_6POINT1_SOFT),
502 DECL(AL_7POINT1_SOFT),
503 DECL(AL_BFORMAT2D_SOFT),
504 DECL(AL_BFORMAT3D_SOFT),
506 DECL(AL_BYTE_SOFT),
507 DECL(AL_UNSIGNED_BYTE_SOFT),
508 DECL(AL_SHORT_SOFT),
509 DECL(AL_UNSIGNED_SHORT_SOFT),
510 DECL(AL_INT_SOFT),
511 DECL(AL_UNSIGNED_INT_SOFT),
512 DECL(AL_FLOAT_SOFT),
513 DECL(AL_DOUBLE_SOFT),
514 DECL(AL_BYTE3_SOFT),
515 DECL(AL_UNSIGNED_BYTE3_SOFT),
516 DECL(AL_MULAW_SOFT),
518 DECL(AL_FREQUENCY),
519 DECL(AL_BITS),
520 DECL(AL_CHANNELS),
521 DECL(AL_SIZE),
522 DECL(AL_INTERNAL_FORMAT_SOFT),
523 DECL(AL_BYTE_LENGTH_SOFT),
524 DECL(AL_SAMPLE_LENGTH_SOFT),
525 DECL(AL_SEC_LENGTH_SOFT),
526 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
527 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
529 DECL(AL_SOURCE_RADIUS),
531 DECL(AL_STEREO_ANGLES),
533 DECL(AL_UNUSED),
534 DECL(AL_PENDING),
535 DECL(AL_PROCESSED),
537 DECL(AL_NO_ERROR),
538 DECL(AL_INVALID_NAME),
539 DECL(AL_INVALID_ENUM),
540 DECL(AL_INVALID_VALUE),
541 DECL(AL_INVALID_OPERATION),
542 DECL(AL_OUT_OF_MEMORY),
544 DECL(AL_VENDOR),
545 DECL(AL_VERSION),
546 DECL(AL_RENDERER),
547 DECL(AL_EXTENSIONS),
549 DECL(AL_DOPPLER_FACTOR),
550 DECL(AL_DOPPLER_VELOCITY),
551 DECL(AL_DISTANCE_MODEL),
552 DECL(AL_SPEED_OF_SOUND),
553 DECL(AL_SOURCE_DISTANCE_MODEL),
554 DECL(AL_DEFERRED_UPDATES_SOFT),
556 DECL(AL_INVERSE_DISTANCE),
557 DECL(AL_INVERSE_DISTANCE_CLAMPED),
558 DECL(AL_LINEAR_DISTANCE),
559 DECL(AL_LINEAR_DISTANCE_CLAMPED),
560 DECL(AL_EXPONENT_DISTANCE),
561 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
563 DECL(AL_FILTER_TYPE),
564 DECL(AL_FILTER_NULL),
565 DECL(AL_FILTER_LOWPASS),
566 DECL(AL_FILTER_HIGHPASS),
567 DECL(AL_FILTER_BANDPASS),
569 DECL(AL_LOWPASS_GAIN),
570 DECL(AL_LOWPASS_GAINHF),
572 DECL(AL_HIGHPASS_GAIN),
573 DECL(AL_HIGHPASS_GAINLF),
575 DECL(AL_BANDPASS_GAIN),
576 DECL(AL_BANDPASS_GAINHF),
577 DECL(AL_BANDPASS_GAINLF),
579 DECL(AL_EFFECT_TYPE),
580 DECL(AL_EFFECT_NULL),
581 DECL(AL_EFFECT_REVERB),
582 DECL(AL_EFFECT_EAXREVERB),
583 DECL(AL_EFFECT_CHORUS),
584 DECL(AL_EFFECT_DISTORTION),
585 DECL(AL_EFFECT_ECHO),
586 DECL(AL_EFFECT_FLANGER),
587 #if 0
588 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
589 DECL(AL_EFFECT_VOCAL_MORPHER),
590 DECL(AL_EFFECT_PITCH_SHIFTER),
591 #endif
592 DECL(AL_EFFECT_RING_MODULATOR),
593 #if 0
594 DECL(AL_EFFECT_AUTOWAH),
595 #endif
596 DECL(AL_EFFECT_COMPRESSOR),
597 DECL(AL_EFFECT_EQUALIZER),
598 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
599 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
601 DECL(AL_EAXREVERB_DENSITY),
602 DECL(AL_EAXREVERB_DIFFUSION),
603 DECL(AL_EAXREVERB_GAIN),
604 DECL(AL_EAXREVERB_GAINHF),
605 DECL(AL_EAXREVERB_GAINLF),
606 DECL(AL_EAXREVERB_DECAY_TIME),
607 DECL(AL_EAXREVERB_DECAY_HFRATIO),
608 DECL(AL_EAXREVERB_DECAY_LFRATIO),
609 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
610 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
611 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
612 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
613 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
614 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
615 DECL(AL_EAXREVERB_ECHO_TIME),
616 DECL(AL_EAXREVERB_ECHO_DEPTH),
617 DECL(AL_EAXREVERB_MODULATION_TIME),
618 DECL(AL_EAXREVERB_MODULATION_DEPTH),
619 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
620 DECL(AL_EAXREVERB_HFREFERENCE),
621 DECL(AL_EAXREVERB_LFREFERENCE),
622 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
623 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
625 DECL(AL_REVERB_DENSITY),
626 DECL(AL_REVERB_DIFFUSION),
627 DECL(AL_REVERB_GAIN),
628 DECL(AL_REVERB_GAINHF),
629 DECL(AL_REVERB_DECAY_TIME),
630 DECL(AL_REVERB_DECAY_HFRATIO),
631 DECL(AL_REVERB_REFLECTIONS_GAIN),
632 DECL(AL_REVERB_REFLECTIONS_DELAY),
633 DECL(AL_REVERB_LATE_REVERB_GAIN),
634 DECL(AL_REVERB_LATE_REVERB_DELAY),
635 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
636 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
637 DECL(AL_REVERB_DECAY_HFLIMIT),
639 DECL(AL_CHORUS_WAVEFORM),
640 DECL(AL_CHORUS_PHASE),
641 DECL(AL_CHORUS_RATE),
642 DECL(AL_CHORUS_DEPTH),
643 DECL(AL_CHORUS_FEEDBACK),
644 DECL(AL_CHORUS_DELAY),
646 DECL(AL_DISTORTION_EDGE),
647 DECL(AL_DISTORTION_GAIN),
648 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
649 DECL(AL_DISTORTION_EQCENTER),
650 DECL(AL_DISTORTION_EQBANDWIDTH),
652 DECL(AL_ECHO_DELAY),
653 DECL(AL_ECHO_LRDELAY),
654 DECL(AL_ECHO_DAMPING),
655 DECL(AL_ECHO_FEEDBACK),
656 DECL(AL_ECHO_SPREAD),
658 DECL(AL_FLANGER_WAVEFORM),
659 DECL(AL_FLANGER_PHASE),
660 DECL(AL_FLANGER_RATE),
661 DECL(AL_FLANGER_DEPTH),
662 DECL(AL_FLANGER_FEEDBACK),
663 DECL(AL_FLANGER_DELAY),
665 DECL(AL_RING_MODULATOR_FREQUENCY),
666 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
667 DECL(AL_RING_MODULATOR_WAVEFORM),
669 #if 0
670 DECL(AL_AUTOWAH_ATTACK_TIME),
671 DECL(AL_AUTOWAH_PEAK_GAIN),
672 DECL(AL_AUTOWAH_RELEASE_TIME),
673 DECL(AL_AUTOWAH_RESONANCE),
674 #endif
676 DECL(AL_COMPRESSOR_ONOFF),
678 DECL(AL_EQUALIZER_LOW_GAIN),
679 DECL(AL_EQUALIZER_LOW_CUTOFF),
680 DECL(AL_EQUALIZER_MID1_GAIN),
681 DECL(AL_EQUALIZER_MID1_CENTER),
682 DECL(AL_EQUALIZER_MID1_WIDTH),
683 DECL(AL_EQUALIZER_MID2_GAIN),
684 DECL(AL_EQUALIZER_MID2_CENTER),
685 DECL(AL_EQUALIZER_MID2_WIDTH),
686 DECL(AL_EQUALIZER_HIGH_GAIN),
687 DECL(AL_EQUALIZER_HIGH_CUTOFF),
689 DECL(AL_DEDICATED_GAIN),
691 { NULL, (ALCenum)0 }
693 #undef DECL
695 static const ALCchar alcNoError[] = "No Error";
696 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
697 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
698 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
699 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
700 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
703 /************************************************
704 * Global variables
705 ************************************************/
707 /* Enumerated device names */
708 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
710 static al_string alcAllDevicesList;
711 static al_string alcCaptureDeviceList;
713 /* Default is always the first in the list */
714 static ALCchar *alcDefaultAllDevicesSpecifier;
715 static ALCchar *alcCaptureDefaultDeviceSpecifier;
717 /* Default context extensions */
718 static const ALchar alExtList[] =
719 "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
720 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS "
721 "AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
722 "AL_EXT_source_distance_model AL_EXT_SOURCE_RADIUS AL_EXT_STEREO_ANGLES "
723 "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_deferred_updates "
724 "AL_SOFT_direct_channels AL_SOFT_loop_points AL_SOFT_MSADPCM "
725 "AL_SOFT_source_latency AL_SOFT_source_length";
727 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
729 /* Thread-local current context */
730 static altss_t LocalContext;
731 /* Process-wide current context */
732 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
734 /* Mixing thread piority level */
735 ALint RTPrioLevel;
737 FILE *LogFile;
738 #ifdef _DEBUG
739 enum LogLevel LogLevel = LogWarning;
740 #else
741 enum LogLevel LogLevel = LogError;
742 #endif
744 /* Flag to trap ALC device errors */
745 static ALCboolean TrapALCError = ALC_FALSE;
747 /* One-time configuration init control */
748 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
750 /* Default effect that applies to sources that don't have an effect on send 0 */
751 static ALeffect DefaultEffect;
753 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
754 * updates.
756 static ALCboolean SuspendDefers = ALC_TRUE;
759 /************************************************
760 * ALC information
761 ************************************************/
762 static const ALCchar alcNoDeviceExtList[] =
763 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
764 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
765 static const ALCchar alcExtensionList[] =
766 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
767 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
768 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFT_HRTF "
769 "ALC_SOFT_loopback ALC_SOFT_pause_device";
770 static const ALCint alcMajorVersion = 1;
771 static const ALCint alcMinorVersion = 1;
773 static const ALCint alcEFXMajorVersion = 1;
774 static const ALCint alcEFXMinorVersion = 0;
777 /************************************************
778 * Device lists
779 ************************************************/
780 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
782 static almtx_t ListLock;
783 static inline void LockLists(void)
785 int lockret = almtx_lock(&ListLock);
786 assert(lockret == althrd_success);
788 static inline void UnlockLists(void)
790 int unlockret = almtx_unlock(&ListLock);
791 assert(unlockret == althrd_success);
794 /************************************************
795 * Library initialization
796 ************************************************/
797 #if defined(_WIN32)
798 static void alc_init(void);
799 static void alc_deinit(void);
800 static void alc_deinit_safe(void);
802 #ifndef AL_LIBTYPE_STATIC
803 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
805 switch(reason)
807 case DLL_PROCESS_ATTACH:
808 /* Pin the DLL so we won't get unloaded until the process terminates */
809 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
810 (WCHAR*)hModule, &hModule);
811 alc_init();
812 break;
814 case DLL_THREAD_DETACH:
815 break;
817 case DLL_PROCESS_DETACH:
818 if(!lpReserved)
819 alc_deinit();
820 else
821 alc_deinit_safe();
822 break;
824 return TRUE;
826 #elif defined(_MSC_VER)
827 #pragma section(".CRT$XCU",read)
828 static void alc_constructor(void);
829 static void alc_destructor(void);
830 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
832 static void alc_constructor(void)
834 atexit(alc_destructor);
835 alc_init();
838 static void alc_destructor(void)
840 alc_deinit();
842 #elif defined(HAVE_GCC_DESTRUCTOR)
843 static void alc_init(void) __attribute__((constructor));
844 static void alc_deinit(void) __attribute__((destructor));
845 #else
846 #error "No static initialization available on this platform!"
847 #endif
849 #elif defined(HAVE_GCC_DESTRUCTOR)
851 static void alc_init(void) __attribute__((constructor));
852 static void alc_deinit(void) __attribute__((destructor));
854 #else
855 #error "No global initialization available on this platform!"
856 #endif
858 static void ReleaseThreadCtx(void *ptr);
859 static void alc_init(void)
861 const char *str;
862 int ret;
864 LogFile = stderr;
866 AL_STRING_INIT(alcAllDevicesList);
867 AL_STRING_INIT(alcCaptureDeviceList);
869 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
870 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
871 ConeScale *= 0.5f;
873 str = getenv("__ALSOFT_REVERSE_Z");
874 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
875 ZScale *= -1.0f;
877 ret = altss_create(&LocalContext, ReleaseThreadCtx);
878 assert(ret == althrd_success);
880 ret = almtx_init(&ListLock, almtx_recursive);
881 assert(ret == althrd_success);
883 ThunkInit();
886 static void alc_initconfig(void)
888 const char *devs, *str;
889 ALuint 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);
910 char buf[1024] = "";
911 int len = snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
912 for(i = 1;BackendList[i].name;i++)
913 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
914 TRACE("Supported backends: %s\n", buf);
916 ReadALConfig();
918 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
919 if(str && *str)
921 if(strcasecmp(str, "ignore") == 0)
923 SuspendDefers = ALC_FALSE;
924 TRACE("Selected context suspend behavior, \"ignore\"\n");
926 else
927 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
930 capfilter = 0;
931 #if defined(HAVE_SSE4_1)
932 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
933 #elif defined(HAVE_SSE3)
934 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
935 #elif defined(HAVE_SSE2)
936 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
937 #elif defined(HAVE_SSE)
938 capfilter |= CPU_CAP_SSE;
939 #endif
940 #ifdef HAVE_NEON
941 capfilter |= CPU_CAP_NEON;
942 #endif
943 if(ConfigValueStr(NULL, NULL, "disable-cpu-exts", &str))
945 if(strcasecmp(str, "all") == 0)
946 capfilter = 0;
947 else
949 size_t len;
950 const char *next = str;
952 do {
953 str = next;
954 while(isspace(str[0]))
955 str++;
956 next = strchr(str, ',');
958 if(!str[0] || str[0] == ',')
959 continue;
961 len = (next ? ((size_t)(next-str)) : strlen(str));
962 while(len > 0 && isspace(str[len-1]))
963 len--;
964 if(len == 3 && strncasecmp(str, "sse", len) == 0)
965 capfilter &= ~CPU_CAP_SSE;
966 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
967 capfilter &= ~CPU_CAP_SSE2;
968 else if(len == 4 && strncasecmp(str, "sse3", len) == 0)
969 capfilter &= ~CPU_CAP_SSE3;
970 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
971 capfilter &= ~CPU_CAP_SSE4_1;
972 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
973 capfilter &= ~CPU_CAP_NEON;
974 else
975 WARN("Invalid CPU extension \"%s\"\n", str);
976 } while(next++);
979 FillCPUCaps(capfilter);
981 #ifdef _WIN32
982 RTPrioLevel = 1;
983 #else
984 RTPrioLevel = 0;
985 #endif
986 ConfigValueInt(NULL, NULL, "rt-prio", &RTPrioLevel);
988 aluInitMixer();
990 str = getenv("ALSOFT_TRAP_ERROR");
991 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
993 TrapALError = AL_TRUE;
994 TrapALCError = AL_TRUE;
996 else
998 str = getenv("ALSOFT_TRAP_AL_ERROR");
999 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1000 TrapALError = AL_TRUE;
1001 TrapALError = GetConfigValueBool(NULL, NULL, "trap-al-error", TrapALError);
1003 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1004 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1005 TrapALCError = ALC_TRUE;
1006 TrapALCError = GetConfigValueBool(NULL, NULL, "trap-alc-error", TrapALCError);
1009 if(ConfigValueFloat(NULL, "reverb", "boost", &valf))
1010 ReverbBoost *= powf(10.0f, valf / 20.0f);
1012 EmulateEAXReverb = GetConfigValueBool(NULL, "reverb", "emulate-eax", AL_FALSE);
1014 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1015 ConfigValueStr(NULL, NULL, "drivers", &devs))
1017 int n;
1018 size_t len;
1019 const char *next = devs;
1020 int endlist, delitem;
1022 i = 0;
1023 do {
1024 devs = next;
1025 while(isspace(devs[0]))
1026 devs++;
1027 next = strchr(devs, ',');
1029 delitem = (devs[0] == '-');
1030 if(devs[0] == '-') devs++;
1032 if(!devs[0] || devs[0] == ',')
1034 endlist = 0;
1035 continue;
1037 endlist = 1;
1039 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1040 while(len > 0 && isspace(devs[len-1]))
1041 len--;
1042 for(n = i;BackendList[n].name;n++)
1044 if(len == strlen(BackendList[n].name) &&
1045 strncmp(BackendList[n].name, devs, len) == 0)
1047 if(delitem)
1049 do {
1050 BackendList[n] = BackendList[n+1];
1051 ++n;
1052 } while(BackendList[n].name);
1054 else
1056 struct BackendInfo Bkp = BackendList[n];
1057 while(n > i)
1059 BackendList[n] = BackendList[n-1];
1060 --n;
1062 BackendList[n] = Bkp;
1064 i++;
1066 break;
1069 } while(next++);
1071 if(endlist)
1073 BackendList[i].name = NULL;
1074 BackendList[i].getFactory = NULL;
1075 BackendList[i].Init = NULL;
1076 BackendList[i].Deinit = NULL;
1077 BackendList[i].Probe = NULL;
1081 for(i = 0;(BackendList[i].Init || BackendList[i].getFactory) && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1083 if(BackendList[i].getFactory)
1085 ALCbackendFactory *factory = BackendList[i].getFactory();
1086 if(!V0(factory,init)())
1088 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1089 continue;
1092 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1093 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1095 PlaybackBackend = BackendList[i];
1096 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1098 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1100 CaptureBackend = BackendList[i];
1101 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1104 continue;
1107 if(!BackendList[i].Init(&BackendList[i].Funcs))
1109 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1110 continue;
1113 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1114 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1116 PlaybackBackend = BackendList[i];
1117 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1119 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1121 CaptureBackend = BackendList[i];
1122 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1126 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1127 V0(factory,init)();
1130 if(!PlaybackBackend.name)
1131 WARN("No playback backend available!\n");
1132 if(!CaptureBackend.name)
1133 WARN("No capture backend available!\n");
1135 if(ConfigValueStr(NULL, NULL, "excludefx", &str))
1137 size_t len;
1138 const char *next = str;
1140 do {
1141 str = next;
1142 next = strchr(str, ',');
1144 if(!str[0] || next == str)
1145 continue;
1147 len = (next ? ((size_t)(next-str)) : strlen(str));
1148 for(n = 0;EffectList[n].name;n++)
1150 if(len == strlen(EffectList[n].name) &&
1151 strncmp(EffectList[n].name, str, len) == 0)
1152 DisabledEffects[EffectList[n].type] = AL_TRUE;
1154 } while(next++);
1157 InitEffectFactoryMap();
1159 InitEffect(&DefaultEffect);
1160 str = getenv("ALSOFT_DEFAULT_REVERB");
1161 if((str && str[0]) || ConfigValueStr(NULL, NULL, "default-reverb", &str))
1162 LoadReverbPreset(str, &DefaultEffect);
1164 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1167 /************************************************
1168 * Library deinitialization
1169 ************************************************/
1170 static void alc_cleanup(void)
1172 ALCdevice *dev;
1174 AL_STRING_DEINIT(alcAllDevicesList);
1175 AL_STRING_DEINIT(alcCaptureDeviceList);
1177 free(alcDefaultAllDevicesSpecifier);
1178 alcDefaultAllDevicesSpecifier = NULL;
1179 free(alcCaptureDefaultDeviceSpecifier);
1180 alcCaptureDefaultDeviceSpecifier = NULL;
1182 if((dev=ATOMIC_EXCHANGE(ALCdevice*, &DeviceList, NULL)) != NULL)
1184 ALCuint num = 0;
1185 do {
1186 num++;
1187 } while((dev=dev->next) != NULL);
1188 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1191 DeinitEffectFactoryMap();
1194 static void alc_deinit_safe(void)
1196 alc_cleanup();
1198 FreeHrtfs();
1199 FreeALConfig();
1201 ThunkExit();
1202 almtx_destroy(&ListLock);
1203 altss_delete(LocalContext);
1205 if(LogFile != stderr)
1206 fclose(LogFile);
1207 LogFile = NULL;
1210 static void alc_deinit(void)
1212 int i;
1214 alc_cleanup();
1216 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1217 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1219 for(i = 0;BackendList[i].Deinit || BackendList[i].getFactory;i++)
1221 if(!BackendList[i].getFactory)
1222 BackendList[i].Deinit();
1223 else
1225 ALCbackendFactory *factory = BackendList[i].getFactory();
1226 V0(factory,deinit)();
1230 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1231 V0(factory,deinit)();
1234 alc_deinit_safe();
1238 /************************************************
1239 * Device enumeration
1240 ************************************************/
1241 static void ProbeDevices(al_string *list, struct BackendInfo *backendinfo, enum DevProbe type)
1243 DO_INITCONFIG();
1245 LockLists();
1246 al_string_clear(list);
1248 if(backendinfo->Probe)
1249 backendinfo->Probe(type);
1250 else if(backendinfo->getFactory)
1252 ALCbackendFactory *factory = backendinfo->getFactory();
1253 V(factory,probe)(type);
1256 UnlockLists();
1258 static void ProbeAllDevicesList(void)
1259 { ProbeDevices(&alcAllDevicesList, &PlaybackBackend, ALL_DEVICE_PROBE); }
1260 static void ProbeCaptureDeviceList(void)
1261 { ProbeDevices(&alcCaptureDeviceList, &CaptureBackend, CAPTURE_DEVICE_PROBE); }
1263 static void AppendDevice(const ALCchar *name, al_string *devnames)
1265 size_t len = strlen(name);
1266 if(len > 0)
1267 al_string_append_range(devnames, name, name+len+1);
1269 void AppendAllDevicesList(const ALCchar *name)
1270 { AppendDevice(name, &alcAllDevicesList); }
1271 void AppendCaptureDeviceList(const ALCchar *name)
1272 { AppendDevice(name, &alcCaptureDeviceList); }
1275 /************************************************
1276 * Device format information
1277 ************************************************/
1278 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1280 switch(type)
1282 case DevFmtByte: return "Signed Byte";
1283 case DevFmtUByte: return "Unsigned Byte";
1284 case DevFmtShort: return "Signed Short";
1285 case DevFmtUShort: return "Unsigned Short";
1286 case DevFmtInt: return "Signed Int";
1287 case DevFmtUInt: return "Unsigned Int";
1288 case DevFmtFloat: return "Float";
1290 return "(unknown type)";
1292 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1294 switch(chans)
1296 case DevFmtMono: return "Mono";
1297 case DevFmtStereo: return "Stereo";
1298 case DevFmtQuad: return "Quadraphonic";
1299 case DevFmtX51: return "5.1 Surround";
1300 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1301 case DevFmtX61: return "6.1 Surround";
1302 case DevFmtX71: return "7.1 Surround";
1303 case DevFmtBFormat3D: return "B-Format 3D";
1305 return "(unknown channels)";
1308 extern inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
1309 ALuint BytesFromDevFmt(enum DevFmtType type)
1311 switch(type)
1313 case DevFmtByte: return sizeof(ALbyte);
1314 case DevFmtUByte: return sizeof(ALubyte);
1315 case DevFmtShort: return sizeof(ALshort);
1316 case DevFmtUShort: return sizeof(ALushort);
1317 case DevFmtInt: return sizeof(ALint);
1318 case DevFmtUInt: return sizeof(ALuint);
1319 case DevFmtFloat: return sizeof(ALfloat);
1321 return 0;
1323 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1325 switch(chans)
1327 case DevFmtMono: return 1;
1328 case DevFmtStereo: return 2;
1329 case DevFmtQuad: return 4;
1330 case DevFmtX51: return 6;
1331 case DevFmtX51Rear: return 6;
1332 case DevFmtX61: return 7;
1333 case DevFmtX71: return 8;
1334 case DevFmtBFormat3D: return 4;
1336 return 0;
1339 DECL_CONST static ALboolean DecomposeDevFormat(ALenum format,
1340 enum DevFmtChannels *chans, enum DevFmtType *type)
1342 static const struct {
1343 ALenum format;
1344 enum DevFmtChannels channels;
1345 enum DevFmtType type;
1346 } list[] = {
1347 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1348 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1349 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1351 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1352 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1353 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1355 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1356 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1357 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1359 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1360 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1361 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1363 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1364 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1365 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1367 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1368 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1369 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1371 ALuint i;
1373 for(i = 0;i < COUNTOF(list);i++)
1375 if(list[i].format == format)
1377 *chans = list[i].channels;
1378 *type = list[i].type;
1379 return AL_TRUE;
1383 return AL_FALSE;
1386 DECL_CONST static ALCboolean IsValidALCType(ALCenum type)
1388 switch(type)
1390 case ALC_BYTE_SOFT:
1391 case ALC_UNSIGNED_BYTE_SOFT:
1392 case ALC_SHORT_SOFT:
1393 case ALC_UNSIGNED_SHORT_SOFT:
1394 case ALC_INT_SOFT:
1395 case ALC_UNSIGNED_INT_SOFT:
1396 case ALC_FLOAT_SOFT:
1397 return ALC_TRUE;
1399 return ALC_FALSE;
1402 DECL_CONST static ALCboolean IsValidALCChannels(ALCenum channels)
1404 switch(channels)
1406 case ALC_MONO_SOFT:
1407 case ALC_STEREO_SOFT:
1408 case ALC_QUAD_SOFT:
1409 case ALC_5POINT1_SOFT:
1410 case ALC_6POINT1_SOFT:
1411 case ALC_7POINT1_SOFT:
1412 return ALC_TRUE;
1414 return ALC_FALSE;
1418 /************************************************
1419 * Miscellaneous ALC helpers
1420 ************************************************/
1422 extern inline void LockContext(ALCcontext *context);
1423 extern inline void UnlockContext(ALCcontext *context);
1425 void ALCdevice_Lock(ALCdevice *device)
1427 V0(device->Backend,lock)();
1430 void ALCdevice_Unlock(ALCdevice *device)
1432 V0(device->Backend,unlock)();
1436 /* SetDefaultWFXChannelOrder
1438 * Sets the default channel order used by WaveFormatEx.
1440 void SetDefaultWFXChannelOrder(ALCdevice *device)
1442 ALuint i;
1444 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1445 device->RealOut.ChannelName[i] = InvalidChannel;
1447 switch(device->FmtChans)
1449 case DevFmtMono:
1450 device->RealOut.ChannelName[0] = FrontCenter;
1451 break;
1452 case DevFmtStereo:
1453 device->RealOut.ChannelName[0] = FrontLeft;
1454 device->RealOut.ChannelName[1] = FrontRight;
1455 break;
1456 case DevFmtQuad:
1457 device->RealOut.ChannelName[0] = FrontLeft;
1458 device->RealOut.ChannelName[1] = FrontRight;
1459 device->RealOut.ChannelName[2] = BackLeft;
1460 device->RealOut.ChannelName[3] = BackRight;
1461 break;
1462 case DevFmtX51:
1463 device->RealOut.ChannelName[0] = FrontLeft;
1464 device->RealOut.ChannelName[1] = FrontRight;
1465 device->RealOut.ChannelName[2] = FrontCenter;
1466 device->RealOut.ChannelName[3] = LFE;
1467 device->RealOut.ChannelName[4] = SideLeft;
1468 device->RealOut.ChannelName[5] = SideRight;
1469 break;
1470 case DevFmtX51Rear:
1471 device->RealOut.ChannelName[0] = FrontLeft;
1472 device->RealOut.ChannelName[1] = FrontRight;
1473 device->RealOut.ChannelName[2] = FrontCenter;
1474 device->RealOut.ChannelName[3] = LFE;
1475 device->RealOut.ChannelName[4] = BackLeft;
1476 device->RealOut.ChannelName[5] = BackRight;
1477 break;
1478 case DevFmtX61:
1479 device->RealOut.ChannelName[0] = FrontLeft;
1480 device->RealOut.ChannelName[1] = FrontRight;
1481 device->RealOut.ChannelName[2] = FrontCenter;
1482 device->RealOut.ChannelName[3] = LFE;
1483 device->RealOut.ChannelName[4] = BackCenter;
1484 device->RealOut.ChannelName[5] = SideLeft;
1485 device->RealOut.ChannelName[6] = SideRight;
1486 break;
1487 case DevFmtX71:
1488 device->RealOut.ChannelName[0] = FrontLeft;
1489 device->RealOut.ChannelName[1] = FrontRight;
1490 device->RealOut.ChannelName[2] = FrontCenter;
1491 device->RealOut.ChannelName[3] = LFE;
1492 device->RealOut.ChannelName[4] = BackLeft;
1493 device->RealOut.ChannelName[5] = BackRight;
1494 device->RealOut.ChannelName[6] = SideLeft;
1495 device->RealOut.ChannelName[7] = SideRight;
1496 break;
1497 case DevFmtBFormat3D:
1498 device->RealOut.ChannelName[0] = Aux0;
1499 device->RealOut.ChannelName[1] = Aux1;
1500 device->RealOut.ChannelName[2] = Aux2;
1501 device->RealOut.ChannelName[3] = Aux3;
1502 break;
1506 /* SetDefaultChannelOrder
1508 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1510 void SetDefaultChannelOrder(ALCdevice *device)
1512 ALuint i;
1514 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1515 device->RealOut.ChannelName[i] = InvalidChannel;
1517 switch(device->FmtChans)
1519 case DevFmtX51Rear:
1520 device->RealOut.ChannelName[0] = FrontLeft;
1521 device->RealOut.ChannelName[1] = FrontRight;
1522 device->RealOut.ChannelName[2] = BackLeft;
1523 device->RealOut.ChannelName[3] = BackRight;
1524 device->RealOut.ChannelName[4] = FrontCenter;
1525 device->RealOut.ChannelName[5] = LFE;
1526 return;
1527 case DevFmtX71:
1528 device->RealOut.ChannelName[0] = FrontLeft;
1529 device->RealOut.ChannelName[1] = FrontRight;
1530 device->RealOut.ChannelName[2] = BackLeft;
1531 device->RealOut.ChannelName[3] = BackRight;
1532 device->RealOut.ChannelName[4] = FrontCenter;
1533 device->RealOut.ChannelName[5] = LFE;
1534 device->RealOut.ChannelName[6] = SideLeft;
1535 device->RealOut.ChannelName[7] = SideRight;
1536 return;
1538 /* Same as WFX order */
1539 case DevFmtMono:
1540 case DevFmtStereo:
1541 case DevFmtQuad:
1542 case DevFmtX51:
1543 case DevFmtX61:
1544 case DevFmtBFormat3D:
1545 SetDefaultWFXChannelOrder(device);
1546 break;
1550 extern inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan);
1553 /* ALCcontext_DeferUpdates
1555 * Defers/suspends updates for the given context's listener and sources. This
1556 * does *NOT* stop mixing, but rather prevents certain property changes from
1557 * taking effect.
1559 void ALCcontext_DeferUpdates(ALCcontext *context)
1561 ATOMIC_STORE(&context->DeferUpdates, AL_TRUE);
1564 /* ALCcontext_ProcessUpdates
1566 * Resumes update processing after being deferred.
1568 void ALCcontext_ProcessUpdates(ALCcontext *context)
1570 ALCdevice *device = context->Device;
1572 ReadLock(&context->PropLock);
1573 if(ATOMIC_EXCHANGE(ALenum, &context->DeferUpdates, AL_FALSE))
1575 ALsizei pos;
1577 UpdateListenerProps(context);
1579 LockUIntMapRead(&context->SourceMap);
1580 V0(device->Backend,lock)();
1581 for(pos = 0;pos < context->SourceMap.size;pos++)
1583 ALsource *Source = context->SourceMap.array[pos].value;
1584 ALenum new_state;
1586 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
1587 Source->OffsetType != AL_NONE)
1589 WriteLock(&Source->queue_lock);
1590 ApplyOffset(Source);
1591 WriteUnlock(&Source->queue_lock);
1594 new_state = Source->new_state;
1595 Source->new_state = AL_NONE;
1596 if(new_state)
1597 SetSourceState(Source, context, new_state);
1599 V0(device->Backend,unlock)();
1600 UnlockUIntMapRead(&context->SourceMap);
1601 UpdateAllSourceProps(context);
1603 ReadUnlock(&context->PropLock);
1607 /* alcSetError
1609 * Stores the latest ALC device error
1611 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1613 if(TrapALCError)
1615 #ifdef _WIN32
1616 /* DebugBreak() will cause an exception if there is no debugger */
1617 if(IsDebuggerPresent())
1618 DebugBreak();
1619 #elif defined(SIGTRAP)
1620 raise(SIGTRAP);
1621 #endif
1624 if(device)
1625 ATOMIC_STORE(&device->LastError, errorCode);
1626 else
1627 ATOMIC_STORE(&LastNullDeviceError, errorCode);
1631 /* UpdateClockBase
1633 * Updates the device's base clock time with however many samples have been
1634 * done. This is used so frequency changes on the device don't cause the time
1635 * to jump forward or back.
1637 static inline void UpdateClockBase(ALCdevice *device)
1639 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1640 device->SamplesDone = 0;
1643 /* UpdateDeviceParams
1645 * Updates device parameters according to the attribute list (caller is
1646 * responsible for holding the list lock).
1648 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1650 ALCcontext *context;
1651 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1652 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1653 enum DevFmtChannels oldChans;
1654 enum DevFmtType oldType;
1655 ALCuint oldFreq;
1656 FPUCtl oldMode;
1657 ALCsizei hrtf_id = -1;
1658 size_t size;
1660 // Check for attributes
1661 if(device->Type == Loopback)
1663 enum {
1664 GotFreq = 1<<0,
1665 GotChans = 1<<1,
1666 GotType = 1<<2,
1667 GotAll = GotFreq|GotChans|GotType
1669 ALCuint freq, numMono, numStereo, numSends;
1670 enum DevFmtChannels schans;
1671 enum DevFmtType stype;
1672 ALCuint attrIdx = 0;
1673 ALCint gotFmt = 0;
1675 if(!attrList)
1677 WARN("Missing attributes for loopback device\n");
1678 return ALC_INVALID_VALUE;
1681 numMono = device->NumMonoSources;
1682 numStereo = device->NumStereoSources;
1683 numSends = device->NumAuxSends;
1684 schans = device->FmtChans;
1685 stype = device->FmtType;
1686 freq = device->Frequency;
1688 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1689 while(attrList[attrIdx])
1691 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1693 ALCint val = attrList[attrIdx + 1];
1694 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, val);
1695 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1696 return ALC_INVALID_VALUE;
1697 schans = val;
1698 gotFmt |= GotChans;
1701 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1703 ALCint val = attrList[attrIdx + 1];
1704 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, val);
1705 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1706 return ALC_INVALID_VALUE;
1707 stype = val;
1708 gotFmt |= GotType;
1711 if(attrList[attrIdx] == ALC_FREQUENCY)
1713 freq = attrList[attrIdx + 1];
1714 TRACE_ATTR(ALC_FREQUENCY, freq);
1715 if(freq < MIN_OUTPUT_RATE)
1716 return ALC_INVALID_VALUE;
1717 gotFmt |= GotFreq;
1720 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1722 numStereo = attrList[attrIdx + 1];
1723 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1724 if(numStereo > device->MaxNoOfSources)
1725 numStereo = device->MaxNoOfSources;
1727 numMono = device->MaxNoOfSources - numStereo;
1730 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1732 numSends = attrList[attrIdx + 1];
1733 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1736 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1738 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1739 if(attrList[attrIdx + 1] == ALC_FALSE)
1740 hrtf_appreq = Hrtf_Disable;
1741 else if(attrList[attrIdx + 1] == ALC_TRUE)
1742 hrtf_appreq = Hrtf_Enable;
1743 else
1744 hrtf_appreq = Hrtf_Default;
1747 if(attrList[attrIdx] == ALC_HRTF_ID_SOFT)
1749 hrtf_id = attrList[attrIdx + 1];
1750 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1753 attrIdx += 2;
1755 #undef TRACE_ATTR
1757 if(gotFmt != GotAll)
1759 WARN("Missing format for loopback device\n");
1760 return ALC_INVALID_VALUE;
1763 ConfigValueUInt(NULL, NULL, "sends", &numSends);
1764 numSends = minu(MAX_SENDS, numSends);
1766 if((device->Flags&DEVICE_RUNNING))
1767 V0(device->Backend,stop)();
1768 device->Flags &= ~DEVICE_RUNNING;
1770 UpdateClockBase(device);
1772 device->Frequency = freq;
1773 device->FmtChans = schans;
1774 device->FmtType = stype;
1775 device->NumMonoSources = numMono;
1776 device->NumStereoSources = numStereo;
1777 device->NumAuxSends = numSends;
1779 else if(attrList && attrList[0])
1781 ALCuint freq, numMono, numStereo, numSends;
1782 ALCuint attrIdx = 0;
1784 /* If a context is already running on the device, stop playback so the
1785 * device attributes can be updated. */
1786 if((device->Flags&DEVICE_RUNNING))
1787 V0(device->Backend,stop)();
1788 device->Flags &= ~DEVICE_RUNNING;
1790 freq = device->Frequency;
1791 numMono = device->NumMonoSources;
1792 numStereo = device->NumStereoSources;
1793 numSends = device->NumAuxSends;
1795 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1796 while(attrList[attrIdx])
1798 if(attrList[attrIdx] == ALC_FREQUENCY)
1800 freq = attrList[attrIdx + 1];
1801 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1802 TRACE_ATTR(ALC_FREQUENCY, freq);
1805 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1807 numStereo = attrList[attrIdx + 1];
1808 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1809 if(numStereo > device->MaxNoOfSources)
1810 numStereo = device->MaxNoOfSources;
1812 numMono = device->MaxNoOfSources - numStereo;
1815 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1817 numSends = attrList[attrIdx + 1];
1818 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1821 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1823 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1824 if(attrList[attrIdx + 1] == ALC_FALSE)
1825 hrtf_appreq = Hrtf_Disable;
1826 else if(attrList[attrIdx + 1] == ALC_TRUE)
1827 hrtf_appreq = Hrtf_Enable;
1828 else
1829 hrtf_appreq = Hrtf_Default;
1832 if(attrList[attrIdx] == ALC_HRTF_ID_SOFT)
1834 hrtf_id = attrList[attrIdx + 1];
1835 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1838 attrIdx += 2;
1840 #undef TRACE_ATTR
1842 ConfigValueUInt(al_string_get_cstr(device->DeviceName), NULL, "frequency", &freq);
1843 freq = maxu(freq, MIN_OUTPUT_RATE);
1845 ConfigValueUInt(al_string_get_cstr(device->DeviceName), NULL, "sends", &numSends);
1846 numSends = minu(MAX_SENDS, numSends);
1848 UpdateClockBase(device);
1850 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1851 device->Frequency;
1852 /* SSE and Neon do best with the update size being a multiple of 4 */
1853 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1854 device->UpdateSize = (device->UpdateSize+3)&~3;
1856 device->Frequency = freq;
1857 device->NumMonoSources = numMono;
1858 device->NumStereoSources = numStereo;
1859 device->NumAuxSends = numSends;
1862 if((device->Flags&DEVICE_RUNNING))
1863 return ALC_NO_ERROR;
1865 al_free(device->Uhj_Encoder);
1866 device->Uhj_Encoder = NULL;
1868 al_free(device->Bs2b);
1869 device->Bs2b = NULL;
1871 al_free(device->Dry.Buffer);
1872 device->Dry.Buffer = NULL;
1873 device->Dry.NumChannels = 0;
1874 device->VirtOut.Buffer = NULL;
1875 device->VirtOut.NumChannels = 0;
1876 device->RealOut.Buffer = NULL;
1877 device->RealOut.NumChannels = 0;
1879 UpdateClockBase(device);
1881 /*************************************************************************
1882 * Update device format request if HRTF is requested
1884 device->Hrtf_Status = ALC_HRTF_DISABLED_SOFT;
1885 if(device->Type != Loopback)
1887 const char *hrtf;
1888 if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "hrtf", &hrtf))
1890 if(strcasecmp(hrtf, "true") == 0)
1891 hrtf_userreq = Hrtf_Enable;
1892 else if(strcasecmp(hrtf, "false") == 0)
1893 hrtf_userreq = Hrtf_Disable;
1894 else if(strcasecmp(hrtf, "auto") != 0)
1895 ERR("Unexpected hrtf value: %s\n", hrtf);
1898 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
1900 if(VECTOR_SIZE(device->Hrtf_List) == 0)
1902 VECTOR_DEINIT(device->Hrtf_List);
1903 device->Hrtf_List = EnumerateHrtf(device->DeviceName);
1905 if(VECTOR_SIZE(device->Hrtf_List) > 0)
1907 device->FmtChans = DevFmtStereo;
1908 if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->Hrtf_List))
1909 device->Frequency = GetHrtfSampleRate(VECTOR_ELEM(device->Hrtf_List, hrtf_id).hrtf);
1910 else
1911 device->Frequency = GetHrtfSampleRate(VECTOR_ELEM(device->Hrtf_List, 0).hrtf);
1912 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
1914 else
1916 hrtf_userreq = Hrtf_Default;
1917 hrtf_appreq = Hrtf_Disable;
1918 device->Hrtf_Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
1922 else if(hrtf_appreq == Hrtf_Enable)
1924 size_t i = VECTOR_SIZE(device->Hrtf_List);
1925 /* Loopback device. We don't need to match to a specific HRTF entry
1926 * here. If the requested ID matches, we'll pick that later, if not,
1927 * we'll try to auto-select one anyway. Just make sure one exists
1928 * that'll work.
1930 if(device->FmtChans == DevFmtStereo)
1932 if(VECTOR_SIZE(device->Hrtf_List) == 0)
1934 VECTOR_DEINIT(device->Hrtf_List);
1935 device->Hrtf_List = EnumerateHrtf(device->DeviceName);
1937 for(i = 0;i < VECTOR_SIZE(device->Hrtf_List);i++)
1939 const struct Hrtf *hrtf = VECTOR_ELEM(device->Hrtf_List, i).hrtf;
1940 if(GetHrtfSampleRate(hrtf) == device->Frequency)
1941 break;
1944 if(i == VECTOR_SIZE(device->Hrtf_List))
1946 ERR("Requested format not HRTF compatible: %s, %uhz\n",
1947 DevFmtChannelsString(device->FmtChans), device->Frequency);
1948 hrtf_appreq = Hrtf_Disable;
1949 device->Hrtf_Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
1953 oldFreq = device->Frequency;
1954 oldChans = device->FmtChans;
1955 oldType = device->FmtType;
1957 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
1958 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
1959 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
1960 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
1961 device->UpdateSize, device->NumUpdates
1964 if(V0(device->Backend,reset)() == ALC_FALSE)
1965 return ALC_INVALID_DEVICE;
1967 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1969 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1970 DevFmtChannelsString(device->FmtChans));
1971 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1973 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1975 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1976 DevFmtTypeString(device->FmtType));
1977 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1979 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1981 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1982 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1985 if((device->UpdateSize&3) != 0)
1987 if((CPUCapFlags&CPU_CAP_SSE))
1988 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1989 if((CPUCapFlags&CPU_CAP_NEON))
1990 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1993 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
1994 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
1995 device->Frequency, device->UpdateSize, device->NumUpdates
1998 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2000 /* Allocate extra channels for any post-filter output. */
2001 size = device->Dry.NumChannels * sizeof(device->Dry.Buffer[0]);
2002 if(device->AmbiDecoder && bformatdec_getOrder(device->AmbiDecoder) >= 2)
2003 size += (ChannelsFromDevFmt(device->FmtChans)+4) * sizeof(device->Dry.Buffer[0]);
2004 else if(device->Hrtf || device->Uhj_Encoder || device->AmbiDecoder)
2005 size += ChannelsFromDevFmt(device->FmtChans) * sizeof(device->Dry.Buffer[0]);
2006 device->Dry.Buffer = al_calloc(16, size);
2007 if(!device->Dry.Buffer)
2009 ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
2010 return ALC_INVALID_DEVICE;
2013 if(device->Hrtf || device->Uhj_Encoder || device->AmbiDecoder)
2015 device->VirtOut.Buffer = device->Dry.Buffer;
2016 device->VirtOut.NumChannels = device->Dry.NumChannels;
2017 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2018 device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans);
2020 else
2022 device->VirtOut.Buffer = NULL;
2023 device->VirtOut.NumChannels = 0;
2024 device->RealOut.Buffer = device->Dry.Buffer;
2025 device->RealOut.NumChannels = device->Dry.NumChannels;
2028 if(device->AmbiDecoder && bformatdec_getOrder(device->AmbiDecoder) >= 2)
2030 /* Higher-order high quality decoding requires upsampling first-order
2031 * content, so make sure to mix it separately.
2033 device->FOAOut.Buffer = device->RealOut.Buffer + device->RealOut.NumChannels;
2034 device->FOAOut.NumChannels = 4;
2036 else
2038 device->FOAOut.Buffer = device->Dry.Buffer;
2039 device->FOAOut.NumChannels = device->Dry.NumChannels;
2042 SetMixerFPUMode(&oldMode);
2043 if(device->DefaultSlot)
2045 ALeffectslot *slot = device->DefaultSlot;
2046 ALeffectState *state = slot->Params.EffectState;
2048 state->OutBuffer = device->Dry.Buffer;
2049 state->OutChannels = device->Dry.NumChannels;
2050 if(V(state,deviceUpdate)(device) == AL_FALSE)
2052 RestoreFPUMode(&oldMode);
2053 return ALC_INVALID_DEVICE;
2055 UpdateEffectSlotProps(slot);
2058 context = ATOMIC_LOAD(&device->ContextList);
2059 while(context)
2061 ALsizei pos;
2063 ReadLock(&context->PropLock);
2064 LockUIntMapRead(&context->EffectSlotMap);
2065 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
2067 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
2068 ALeffectState *state = slot->Params.EffectState;
2070 state->OutBuffer = device->Dry.Buffer;
2071 state->OutChannels = device->Dry.NumChannels;
2072 if(V(state,deviceUpdate)(device) == AL_FALSE)
2074 UnlockUIntMapRead(&context->EffectSlotMap);
2075 ReadUnlock(&context->PropLock);
2076 RestoreFPUMode(&oldMode);
2077 return ALC_INVALID_DEVICE;
2080 UpdateEffectSlotProps(slot);
2082 UnlockUIntMapRead(&context->EffectSlotMap);
2084 LockUIntMapRead(&context->SourceMap);
2085 for(pos = 0;pos < context->SourceMap.size;pos++)
2087 ALsource *source = context->SourceMap.array[pos].value;
2088 ALuint s = device->NumAuxSends;
2089 while(s < MAX_SENDS)
2091 if(source->Send[s].Slot)
2092 DecrementRef(&source->Send[s].Slot->ref);
2093 source->Send[s].Slot = NULL;
2094 source->Send[s].Gain = 1.0f;
2095 source->Send[s].GainHF = 1.0f;
2096 source->Send[s].HFReference = LOWPASSFREQREF;
2097 source->Send[s].GainLF = 1.0f;
2098 source->Send[s].LFReference = HIGHPASSFREQREF;
2099 s++;
2102 UnlockUIntMapRead(&context->SourceMap);
2104 UpdateAllSourceProps(context);
2105 ReadUnlock(&context->PropLock);
2107 context = context->next;
2109 RestoreFPUMode(&oldMode);
2111 if(!(device->Flags&DEVICE_PAUSED))
2113 if(V0(device->Backend,start)() == ALC_FALSE)
2114 return ALC_INVALID_DEVICE;
2115 device->Flags |= DEVICE_RUNNING;
2118 return ALC_NO_ERROR;
2121 /* FreeDevice
2123 * Frees the device structure, and destroys any objects the app failed to
2124 * delete. Called once there's no more references on the device.
2126 static ALCvoid FreeDevice(ALCdevice *device)
2128 TRACE("%p\n", device);
2130 V0(device->Backend,close)();
2131 DELETE_OBJ(device->Backend);
2132 device->Backend = NULL;
2134 if(device->DefaultSlot)
2136 DeinitEffectSlot(device->DefaultSlot);
2137 device->DefaultSlot = NULL;
2140 if(device->BufferMap.size > 0)
2142 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
2143 ReleaseALBuffers(device);
2145 ResetUIntMap(&device->BufferMap);
2147 if(device->EffectMap.size > 0)
2149 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
2150 ReleaseALEffects(device);
2152 ResetUIntMap(&device->EffectMap);
2154 if(device->FilterMap.size > 0)
2156 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
2157 ReleaseALFilters(device);
2159 ResetUIntMap(&device->FilterMap);
2161 AL_STRING_DEINIT(device->Hrtf_Name);
2162 FreeHrtfList(&device->Hrtf_List);
2164 al_free(device->Bs2b);
2165 device->Bs2b = NULL;
2167 al_free(device->Uhj_Encoder);
2168 device->Uhj_Encoder = NULL;
2170 bformatdec_free(device->AmbiDecoder);
2171 device->AmbiDecoder = NULL;
2173 AL_STRING_DEINIT(device->DeviceName);
2175 al_free(device->Dry.Buffer);
2176 device->Dry.Buffer = NULL;
2177 device->Dry.NumChannels = 0;
2178 device->VirtOut.Buffer = NULL;
2179 device->VirtOut.NumChannels = 0;
2180 device->RealOut.Buffer = NULL;
2181 device->RealOut.NumChannels = 0;
2183 al_free(device);
2187 void ALCdevice_IncRef(ALCdevice *device)
2189 uint ref;
2190 ref = IncrementRef(&device->ref);
2191 TRACEREF("%p increasing refcount to %u\n", device, ref);
2194 void ALCdevice_DecRef(ALCdevice *device)
2196 uint ref;
2197 ref = DecrementRef(&device->ref);
2198 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2199 if(ref == 0) FreeDevice(device);
2202 /* VerifyDevice
2204 * Checks if the device handle is valid, and increments its ref count if so.
2206 static ALCboolean VerifyDevice(ALCdevice **device)
2208 ALCdevice *tmpDevice;
2210 LockLists();
2211 tmpDevice = ATOMIC_LOAD(&DeviceList);
2212 while(tmpDevice)
2214 if(tmpDevice == *device)
2216 ALCdevice_IncRef(tmpDevice);
2217 UnlockLists();
2218 return ALC_TRUE;
2220 tmpDevice = tmpDevice->next;
2222 UnlockLists();
2224 *device = NULL;
2225 return ALC_FALSE;
2229 /* InitContext
2231 * Initializes context fields
2233 static ALvoid InitContext(ALCcontext *Context)
2235 ALlistener *listener = Context->Listener;
2237 //Initialise listener
2238 listener->Gain = 1.0f;
2239 listener->MetersPerUnit = 1.0f;
2240 listener->Position[0] = 0.0f;
2241 listener->Position[1] = 0.0f;
2242 listener->Position[2] = 0.0f;
2243 listener->Velocity[0] = 0.0f;
2244 listener->Velocity[1] = 0.0f;
2245 listener->Velocity[2] = 0.0f;
2246 listener->Forward[0] = 0.0f;
2247 listener->Forward[1] = 0.0f;
2248 listener->Forward[2] = -1.0f;
2249 listener->Up[0] = 0.0f;
2250 listener->Up[1] = 1.0f;
2251 listener->Up[2] = 0.0f;
2253 aluMatrixdSet(&listener->Params.Matrix,
2254 1.0, 0.0, 0.0, 0.0,
2255 0.0, 1.0, 0.0, 0.0,
2256 0.0, 0.0, 1.0, 0.0,
2257 0.0, 0.0, 0.0, 1.0
2259 aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2260 listener->Params.Gain = 1.0f;
2261 listener->Params.MetersPerUnit = 1.0f;
2262 listener->Params.DopplerFactor = 1.0f;
2263 listener->Params.SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2265 ATOMIC_INIT(&listener->Update, NULL);
2266 ATOMIC_INIT(&listener->FreeList, NULL);
2268 //Validate Context
2269 InitRef(&Context->UpdateCount, 0);
2270 ATOMIC_INIT(&Context->HoldUpdates, AL_FALSE);
2271 RWLockInit(&Context->PropLock);
2272 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2273 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
2274 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2276 //Set globals
2277 Context->DistanceModel = DefaultDistanceModel;
2278 Context->SourceDistanceModel = AL_FALSE;
2279 Context->DopplerFactor = 1.0f;
2280 Context->DopplerVelocity = 1.0f;
2281 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2282 ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
2284 Context->ExtensionList = alExtList;
2288 /* FreeContext
2290 * Cleans up the context, and destroys any remaining objects the app failed to
2291 * delete. Called once there's no more references on the context.
2293 static void FreeContext(ALCcontext *context)
2295 ALlistener *listener = context->Listener;
2296 struct ALlistenerProps *lprops;
2297 size_t count;
2299 TRACE("%p\n", context);
2301 if(context->SourceMap.size > 0)
2303 WARN("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
2304 ReleaseALSources(context);
2306 ResetUIntMap(&context->SourceMap);
2308 if(context->EffectSlotMap.size > 0)
2310 WARN("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
2311 ReleaseALAuxiliaryEffectSlots(context);
2313 ResetUIntMap(&context->EffectSlotMap);
2315 al_free(context->Voices);
2316 context->Voices = NULL;
2317 context->VoiceCount = 0;
2318 context->MaxVoices = 0;
2320 VECTOR_DEINIT(context->ActiveAuxSlots);
2322 if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != NULL)
2324 TRACE("Freed unapplied listener update %p\n", lprops);
2325 al_free(lprops);
2327 count = 0;
2328 lprops = ATOMIC_LOAD(&listener->FreeList, almemory_order_consume);
2329 while(lprops)
2331 struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_consume);
2332 al_free(lprops);
2333 lprops = next;
2334 ++count;
2336 TRACE("Freed "SZFMT" listener property object%s\n", count, (count==1)?"":"s");
2338 ALCdevice_DecRef(context->Device);
2339 context->Device = NULL;
2341 //Invalidate context
2342 memset(context, 0, sizeof(ALCcontext));
2343 al_free(context);
2346 /* ReleaseContext
2348 * Removes the context reference from the given device and removes it from
2349 * being current on the running thread or globally.
2351 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
2353 ALCcontext *nextctx;
2354 ALCcontext *origctx;
2356 if(altss_get(LocalContext) == context)
2358 WARN("%p released while current on thread\n", context);
2359 altss_set(LocalContext, NULL);
2360 ALCcontext_DecRef(context);
2363 origctx = context;
2364 if(ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &GlobalContext, &origctx, NULL))
2365 ALCcontext_DecRef(context);
2367 ALCdevice_Lock(device);
2368 origctx = context;
2369 nextctx = context->next;
2370 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &device->ContextList, &origctx, nextctx))
2372 ALCcontext *list;
2373 do {
2374 list = origctx;
2375 origctx = context;
2376 } while(!COMPARE_EXCHANGE(&list->next, &origctx, nextctx));
2378 ALCdevice_Unlock(device);
2380 ALCcontext_DecRef(context);
2383 void ALCcontext_IncRef(ALCcontext *context)
2385 uint ref;
2386 ref = IncrementRef(&context->ref);
2387 TRACEREF("%p increasing refcount to %u\n", context, ref);
2390 void ALCcontext_DecRef(ALCcontext *context)
2392 uint ref;
2393 ref = DecrementRef(&context->ref);
2394 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2395 if(ref == 0) FreeContext(context);
2398 static void ReleaseThreadCtx(void *ptr)
2400 WARN("%p current for thread being destroyed\n", ptr);
2401 ALCcontext_DecRef(ptr);
2404 /* VerifyContext
2406 * Checks that the given context is valid, and increments its reference count.
2408 static ALCboolean VerifyContext(ALCcontext **context)
2410 ALCdevice *dev;
2412 LockLists();
2413 dev = ATOMIC_LOAD(&DeviceList);
2414 while(dev)
2416 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList);
2417 while(ctx)
2419 if(ctx == *context)
2421 ALCcontext_IncRef(ctx);
2422 UnlockLists();
2423 return ALC_TRUE;
2425 ctx = ctx->next;
2427 dev = dev->next;
2429 UnlockLists();
2431 *context = NULL;
2432 return ALC_FALSE;
2436 /* GetContextRef
2438 * Returns the currently active context for this thread, and adds a reference
2439 * without locking it.
2441 ALCcontext *GetContextRef(void)
2443 ALCcontext *context;
2445 context = altss_get(LocalContext);
2446 if(context)
2447 ALCcontext_IncRef(context);
2448 else
2450 LockLists();
2451 context = ATOMIC_LOAD(&GlobalContext);
2452 if(context)
2453 ALCcontext_IncRef(context);
2454 UnlockLists();
2457 return context;
2461 /************************************************
2462 * Standard ALC functions
2463 ************************************************/
2465 /* alcGetError
2467 * Return last ALC generated error code for the given device
2469 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2471 ALCenum errorCode;
2473 if(VerifyDevice(&device))
2475 errorCode = ATOMIC_EXCHANGE(ALCenum, &device->LastError, ALC_NO_ERROR);
2476 ALCdevice_DecRef(device);
2478 else
2479 errorCode = ATOMIC_EXCHANGE(ALCenum, &LastNullDeviceError, ALC_NO_ERROR);
2481 return errorCode;
2485 /* alcSuspendContext
2487 * Suspends updates for the given context
2489 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2491 if(!SuspendDefers)
2492 return;
2494 if(!VerifyContext(&context))
2495 alcSetError(NULL, ALC_INVALID_CONTEXT);
2496 else
2498 ALCcontext_DeferUpdates(context);
2499 ALCcontext_DecRef(context);
2503 /* alcProcessContext
2505 * Resumes processing updates for the given context
2507 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2509 if(!SuspendDefers)
2510 return;
2512 if(!VerifyContext(&context))
2513 alcSetError(NULL, ALC_INVALID_CONTEXT);
2514 else
2516 ALCcontext_ProcessUpdates(context);
2517 ALCcontext_DecRef(context);
2522 /* alcGetString
2524 * Returns information about the device, and error strings
2526 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2528 const ALCchar *value = NULL;
2530 switch(param)
2532 case ALC_NO_ERROR:
2533 value = alcNoError;
2534 break;
2536 case ALC_INVALID_ENUM:
2537 value = alcErrInvalidEnum;
2538 break;
2540 case ALC_INVALID_VALUE:
2541 value = alcErrInvalidValue;
2542 break;
2544 case ALC_INVALID_DEVICE:
2545 value = alcErrInvalidDevice;
2546 break;
2548 case ALC_INVALID_CONTEXT:
2549 value = alcErrInvalidContext;
2550 break;
2552 case ALC_OUT_OF_MEMORY:
2553 value = alcErrOutOfMemory;
2554 break;
2556 case ALC_DEVICE_SPECIFIER:
2557 value = alcDefaultName;
2558 break;
2560 case ALC_ALL_DEVICES_SPECIFIER:
2561 if(VerifyDevice(&Device))
2563 value = al_string_get_cstr(Device->DeviceName);
2564 ALCdevice_DecRef(Device);
2566 else
2568 ProbeAllDevicesList();
2569 value = al_string_get_cstr(alcAllDevicesList);
2571 break;
2573 case ALC_CAPTURE_DEVICE_SPECIFIER:
2574 if(VerifyDevice(&Device))
2576 value = al_string_get_cstr(Device->DeviceName);
2577 ALCdevice_DecRef(Device);
2579 else
2581 ProbeCaptureDeviceList();
2582 value = al_string_get_cstr(alcCaptureDeviceList);
2584 break;
2586 /* Default devices are always first in the list */
2587 case ALC_DEFAULT_DEVICE_SPECIFIER:
2588 value = alcDefaultName;
2589 break;
2591 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2592 if(al_string_empty(alcAllDevicesList))
2593 ProbeAllDevicesList();
2595 VerifyDevice(&Device);
2597 free(alcDefaultAllDevicesSpecifier);
2598 alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2599 if(!alcDefaultAllDevicesSpecifier)
2600 alcSetError(Device, ALC_OUT_OF_MEMORY);
2602 value = alcDefaultAllDevicesSpecifier;
2603 if(Device) ALCdevice_DecRef(Device);
2604 break;
2606 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2607 if(al_string_empty(alcCaptureDeviceList))
2608 ProbeCaptureDeviceList();
2610 VerifyDevice(&Device);
2612 free(alcCaptureDefaultDeviceSpecifier);
2613 alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcCaptureDeviceList));
2614 if(!alcCaptureDefaultDeviceSpecifier)
2615 alcSetError(Device, ALC_OUT_OF_MEMORY);
2617 value = alcCaptureDefaultDeviceSpecifier;
2618 if(Device) ALCdevice_DecRef(Device);
2619 break;
2621 case ALC_EXTENSIONS:
2622 if(!VerifyDevice(&Device))
2623 value = alcNoDeviceExtList;
2624 else
2626 value = alcExtensionList;
2627 ALCdevice_DecRef(Device);
2629 break;
2631 case ALC_HRTF_SPECIFIER_SOFT:
2632 if(!VerifyDevice(&Device))
2633 alcSetError(NULL, ALC_INVALID_DEVICE);
2634 else
2636 LockLists();
2637 value = (Device->Hrtf ? al_string_get_cstr(Device->Hrtf_Name) : "");
2638 UnlockLists();
2639 ALCdevice_DecRef(Device);
2641 break;
2643 default:
2644 VerifyDevice(&Device);
2645 alcSetError(Device, ALC_INVALID_ENUM);
2646 if(Device) ALCdevice_DecRef(Device);
2647 break;
2650 return value;
2654 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2656 ALCsizei i;
2658 if(size <= 0 || values == NULL)
2660 alcSetError(device, ALC_INVALID_VALUE);
2661 return 0;
2664 if(!device)
2666 switch(param)
2668 case ALC_MAJOR_VERSION:
2669 values[0] = alcMajorVersion;
2670 return 1;
2671 case ALC_MINOR_VERSION:
2672 values[0] = alcMinorVersion;
2673 return 1;
2675 case ALC_ATTRIBUTES_SIZE:
2676 case ALC_ALL_ATTRIBUTES:
2677 case ALC_FREQUENCY:
2678 case ALC_REFRESH:
2679 case ALC_SYNC:
2680 case ALC_MONO_SOURCES:
2681 case ALC_STEREO_SOURCES:
2682 case ALC_CAPTURE_SAMPLES:
2683 case ALC_FORMAT_CHANNELS_SOFT:
2684 case ALC_FORMAT_TYPE_SOFT:
2685 alcSetError(NULL, ALC_INVALID_DEVICE);
2686 return 0;
2688 default:
2689 alcSetError(NULL, ALC_INVALID_ENUM);
2690 return 0;
2692 return 0;
2695 if(device->Type == Capture)
2697 switch(param)
2699 case ALC_CAPTURE_SAMPLES:
2700 V0(device->Backend,lock)();
2701 values[0] = V0(device->Backend,availableSamples)();
2702 V0(device->Backend,unlock)();
2703 return 1;
2705 case ALC_CONNECTED:
2706 values[0] = device->Connected;
2707 return 1;
2709 default:
2710 alcSetError(device, ALC_INVALID_ENUM);
2711 return 0;
2713 return 0;
2716 /* render device */
2717 switch(param)
2719 case ALC_MAJOR_VERSION:
2720 values[0] = alcMajorVersion;
2721 return 1;
2723 case ALC_MINOR_VERSION:
2724 values[0] = alcMinorVersion;
2725 return 1;
2727 case ALC_EFX_MAJOR_VERSION:
2728 values[0] = alcEFXMajorVersion;
2729 return 1;
2731 case ALC_EFX_MINOR_VERSION:
2732 values[0] = alcEFXMinorVersion;
2733 return 1;
2735 case ALC_ATTRIBUTES_SIZE:
2736 values[0] = 17;
2737 return 1;
2739 case ALC_ALL_ATTRIBUTES:
2740 if(size < 17)
2742 alcSetError(device, ALC_INVALID_VALUE);
2743 return 0;
2746 i = 0;
2747 values[i++] = ALC_FREQUENCY;
2748 values[i++] = device->Frequency;
2750 if(device->Type != Loopback)
2752 values[i++] = ALC_REFRESH;
2753 values[i++] = device->Frequency / device->UpdateSize;
2755 values[i++] = ALC_SYNC;
2756 values[i++] = ALC_FALSE;
2758 else
2760 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2761 values[i++] = device->FmtChans;
2763 values[i++] = ALC_FORMAT_TYPE_SOFT;
2764 values[i++] = device->FmtType;
2767 values[i++] = ALC_MONO_SOURCES;
2768 values[i++] = device->NumMonoSources;
2770 values[i++] = ALC_STEREO_SOURCES;
2771 values[i++] = device->NumStereoSources;
2773 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2774 values[i++] = device->NumAuxSends;
2776 values[i++] = ALC_HRTF_SOFT;
2777 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2779 values[i++] = ALC_HRTF_STATUS_SOFT;
2780 values[i++] = device->Hrtf_Status;
2782 values[i++] = 0;
2783 return i;
2785 case ALC_FREQUENCY:
2786 values[0] = device->Frequency;
2787 return 1;
2789 case ALC_REFRESH:
2790 if(device->Type == Loopback)
2792 alcSetError(device, ALC_INVALID_DEVICE);
2793 return 0;
2795 values[0] = device->Frequency / device->UpdateSize;
2796 return 1;
2798 case ALC_SYNC:
2799 if(device->Type == Loopback)
2801 alcSetError(device, ALC_INVALID_DEVICE);
2802 return 0;
2804 values[0] = ALC_FALSE;
2805 return 1;
2807 case ALC_FORMAT_CHANNELS_SOFT:
2808 if(device->Type != Loopback)
2810 alcSetError(device, ALC_INVALID_DEVICE);
2811 return 0;
2813 values[0] = device->FmtChans;
2814 return 1;
2816 case ALC_FORMAT_TYPE_SOFT:
2817 if(device->Type != Loopback)
2819 alcSetError(device, ALC_INVALID_DEVICE);
2820 return 0;
2822 values[0] = device->FmtType;
2823 return 1;
2825 case ALC_MONO_SOURCES:
2826 values[0] = device->NumMonoSources;
2827 return 1;
2829 case ALC_STEREO_SOURCES:
2830 values[0] = device->NumStereoSources;
2831 return 1;
2833 case ALC_MAX_AUXILIARY_SENDS:
2834 values[0] = device->NumAuxSends;
2835 return 1;
2837 case ALC_CONNECTED:
2838 values[0] = device->Connected;
2839 return 1;
2841 case ALC_HRTF_SOFT:
2842 values[0] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2843 return 1;
2845 case ALC_HRTF_STATUS_SOFT:
2846 values[0] = device->Hrtf_Status;
2847 return 1;
2849 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
2850 FreeHrtfList(&device->Hrtf_List);
2851 device->Hrtf_List = EnumerateHrtf(device->DeviceName);
2852 values[0] = (ALCint)VECTOR_SIZE(device->Hrtf_List);
2853 return 1;
2855 default:
2856 alcSetError(device, ALC_INVALID_ENUM);
2857 return 0;
2859 return 0;
2862 /* alcGetIntegerv
2864 * Returns information about the device and the version of OpenAL
2866 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2868 VerifyDevice(&device);
2869 if(size <= 0 || values == NULL)
2870 alcSetError(device, ALC_INVALID_VALUE);
2871 else
2872 GetIntegerv(device, param, size, values);
2873 if(device) ALCdevice_DecRef(device);
2876 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
2878 ALCint *ivals;
2879 ALsizei i;
2881 VerifyDevice(&device);
2882 if(size <= 0 || values == NULL)
2883 alcSetError(device, ALC_INVALID_VALUE);
2884 else if(!device || device->Type == Capture)
2886 ivals = malloc(size * sizeof(ALCint));
2887 size = GetIntegerv(device, pname, size, ivals);
2888 for(i = 0;i < size;i++)
2889 values[i] = ivals[i];
2890 free(ivals);
2892 else /* render device */
2894 switch(pname)
2896 case ALC_ATTRIBUTES_SIZE:
2897 *values = 19;
2898 break;
2900 case ALC_ALL_ATTRIBUTES:
2901 if(size < 19)
2902 alcSetError(device, ALC_INVALID_VALUE);
2903 else
2905 int i = 0;
2907 V0(device->Backend,lock)();
2908 values[i++] = ALC_FREQUENCY;
2909 values[i++] = device->Frequency;
2911 if(device->Type != Loopback)
2913 values[i++] = ALC_REFRESH;
2914 values[i++] = device->Frequency / device->UpdateSize;
2916 values[i++] = ALC_SYNC;
2917 values[i++] = ALC_FALSE;
2919 else
2921 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2922 values[i++] = device->FmtChans;
2924 values[i++] = ALC_FORMAT_TYPE_SOFT;
2925 values[i++] = device->FmtType;
2928 values[i++] = ALC_MONO_SOURCES;
2929 values[i++] = device->NumMonoSources;
2931 values[i++] = ALC_STEREO_SOURCES;
2932 values[i++] = device->NumStereoSources;
2934 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2935 values[i++] = device->NumAuxSends;
2937 values[i++] = ALC_HRTF_SOFT;
2938 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2940 values[i++] = ALC_HRTF_STATUS_SOFT;
2941 values[i++] = device->Hrtf_Status;
2943 values[i++] = ALC_DEVICE_CLOCK_SOFT;
2944 values[i++] = device->ClockBase +
2945 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2947 values[i++] = 0;
2948 V0(device->Backend,unlock)();
2950 break;
2952 case ALC_DEVICE_CLOCK_SOFT:
2953 V0(device->Backend,lock)();
2954 *values = device->ClockBase +
2955 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2956 V0(device->Backend,unlock)();
2957 break;
2959 default:
2960 ivals = malloc(size * sizeof(ALCint));
2961 size = GetIntegerv(device, pname, size, ivals);
2962 for(i = 0;i < size;i++)
2963 values[i] = ivals[i];
2964 free(ivals);
2965 break;
2968 if(device)
2969 ALCdevice_DecRef(device);
2973 /* alcIsExtensionPresent
2975 * Determines if there is support for a particular extension
2977 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2979 ALCboolean bResult = ALC_FALSE;
2981 VerifyDevice(&device);
2983 if(!extName)
2984 alcSetError(device, ALC_INVALID_VALUE);
2985 else
2987 size_t len = strlen(extName);
2988 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2989 while(ptr && *ptr)
2991 if(strncasecmp(ptr, extName, len) == 0 &&
2992 (ptr[len] == '\0' || isspace(ptr[len])))
2994 bResult = ALC_TRUE;
2995 break;
2997 if((ptr=strchr(ptr, ' ')) != NULL)
2999 do {
3000 ++ptr;
3001 } while(isspace(*ptr));
3005 if(device)
3006 ALCdevice_DecRef(device);
3007 return bResult;
3011 /* alcGetProcAddress
3013 * Retrieves the function address for a particular extension function
3015 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3017 ALCvoid *ptr = NULL;
3019 if(!funcName)
3021 VerifyDevice(&device);
3022 alcSetError(device, ALC_INVALID_VALUE);
3023 if(device) ALCdevice_DecRef(device);
3025 else
3027 ALsizei i = 0;
3028 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
3029 i++;
3030 ptr = alcFunctions[i].address;
3033 return ptr;
3037 /* alcGetEnumValue
3039 * Get the value for a particular ALC enumeration name
3041 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3043 ALCenum val = 0;
3045 if(!enumName)
3047 VerifyDevice(&device);
3048 alcSetError(device, ALC_INVALID_VALUE);
3049 if(device) ALCdevice_DecRef(device);
3051 else
3053 ALsizei i = 0;
3054 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
3055 i++;
3056 val = enumeration[i].value;
3059 return val;
3063 /* alcCreateContext
3065 * Create and attach a context to the given device.
3067 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3069 ALCcontext *ALContext;
3070 ALCenum err;
3072 LockLists();
3073 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
3075 UnlockLists();
3076 alcSetError(device, ALC_INVALID_DEVICE);
3077 if(device) ALCdevice_DecRef(device);
3078 return NULL;
3081 ATOMIC_STORE(&device->LastError, ALC_NO_ERROR);
3083 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3084 if(ALContext)
3086 InitRef(&ALContext->ref, 1);
3087 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3089 VECTOR_INIT(ALContext->ActiveAuxSlots);
3091 ALContext->VoiceCount = 0;
3092 ALContext->MaxVoices = 256;
3093 ALContext->Voices = al_calloc(16, ALContext->MaxVoices * sizeof(ALContext->Voices[0]));
3095 if(!ALContext || !ALContext->Voices)
3097 UnlockLists();
3099 if(ALContext)
3101 al_free(ALContext->Voices);
3102 ALContext->Voices = NULL;
3104 VECTOR_DEINIT(ALContext->ActiveAuxSlots);
3106 al_free(ALContext);
3107 ALContext = NULL;
3110 alcSetError(device, ALC_OUT_OF_MEMORY);
3111 ALCdevice_DecRef(device);
3112 return NULL;
3115 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3117 UnlockLists();
3119 al_free(ALContext->Voices);
3120 ALContext->Voices = NULL;
3122 VECTOR_DEINIT(ALContext->ActiveAuxSlots);
3124 al_free(ALContext);
3125 ALContext = NULL;
3127 alcSetError(device, err);
3128 if(err == ALC_INVALID_DEVICE)
3130 V0(device->Backend,lock)();
3131 aluHandleDisconnect(device);
3132 V0(device->Backend,unlock)();
3134 ALCdevice_DecRef(device);
3135 return NULL;
3138 ALContext->Device = device;
3139 ALCdevice_IncRef(device);
3140 InitContext(ALContext);
3143 ALCcontext *head = ATOMIC_LOAD(&device->ContextList);
3144 do {
3145 ALContext->next = head;
3146 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCcontext*, &device->ContextList, &head, ALContext));
3148 UnlockLists();
3150 ALCdevice_DecRef(device);
3152 TRACE("Created context %p\n", ALContext);
3153 return ALContext;
3156 /* alcDestroyContext
3158 * Remove a context from its device
3160 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3162 ALCdevice *Device;
3164 LockLists();
3165 /* alcGetContextsDevice sets an error for invalid contexts */
3166 Device = alcGetContextsDevice(context);
3167 if(Device)
3169 ReleaseContext(context, Device);
3170 if(!ATOMIC_LOAD(&Device->ContextList))
3172 V0(Device->Backend,stop)();
3173 Device->Flags &= ~DEVICE_RUNNING;
3176 UnlockLists();
3180 /* alcGetCurrentContext
3182 * Returns the currently active context on the calling thread
3184 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3186 ALCcontext *Context = altss_get(LocalContext);
3187 if(!Context) Context = ATOMIC_LOAD(&GlobalContext);
3188 return Context;
3191 /* alcGetThreadContext
3193 * Returns the currently active thread-local context
3195 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3197 return altss_get(LocalContext);
3201 /* alcMakeContextCurrent
3203 * Makes the given context the active process-wide context, and removes the
3204 * thread-local context for the calling thread.
3206 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3208 /* context must be valid or NULL */
3209 if(context && !VerifyContext(&context))
3211 alcSetError(NULL, ALC_INVALID_CONTEXT);
3212 return ALC_FALSE;
3214 /* context's reference count is already incremented */
3215 context = ATOMIC_EXCHANGE(ALCcontext*, &GlobalContext, context);
3216 if(context) ALCcontext_DecRef(context);
3218 if((context=altss_get(LocalContext)) != NULL)
3220 altss_set(LocalContext, NULL);
3221 ALCcontext_DecRef(context);
3224 return ALC_TRUE;
3227 /* alcSetThreadContext
3229 * Makes the given context the active context for the current thread
3231 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3233 ALCcontext *old;
3235 /* context must be valid or NULL */
3236 if(context && !VerifyContext(&context))
3238 alcSetError(NULL, ALC_INVALID_CONTEXT);
3239 return ALC_FALSE;
3241 /* context's reference count is already incremented */
3242 old = altss_get(LocalContext);
3243 altss_set(LocalContext, context);
3244 if(old) ALCcontext_DecRef(old);
3246 return ALC_TRUE;
3250 /* alcGetContextsDevice
3252 * Returns the device that a particular context is attached to
3254 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3256 ALCdevice *Device;
3258 if(!VerifyContext(&Context))
3260 alcSetError(NULL, ALC_INVALID_CONTEXT);
3261 return NULL;
3263 Device = Context->Device;
3264 ALCcontext_DecRef(Context);
3266 return Device;
3270 /* alcOpenDevice
3272 * Opens the named device.
3274 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3276 const ALCchar *fmt;
3277 ALCdevice *device;
3278 ALCenum err;
3280 DO_INITCONFIG();
3282 if(!PlaybackBackend.name)
3284 alcSetError(NULL, ALC_INVALID_VALUE);
3285 return NULL;
3288 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
3289 #ifdef _WIN32
3290 /* Some old Windows apps hardcode these expecting OpenAL to use a
3291 * specific audio API, even when they're not enumerated. Creative's
3292 * router effectively ignores them too.
3294 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
3295 || strcasecmp(deviceName, "MMSYSTEM") == 0
3296 #endif
3298 deviceName = NULL;
3300 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3301 if(!device)
3303 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3304 return NULL;
3307 //Validate device
3308 InitRef(&device->ref, 1);
3309 device->Connected = ALC_TRUE;
3310 device->Type = Playback;
3311 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3313 device->Flags = 0;
3314 device->Bs2b = NULL;
3315 device->Uhj_Encoder = NULL;
3316 VECTOR_INIT(device->Hrtf_List);
3317 AL_STRING_INIT(device->Hrtf_Name);
3318 device->Render_Mode = NormalRender;
3319 AL_STRING_INIT(device->DeviceName);
3320 device->Dry.Buffer = NULL;
3321 device->Dry.NumChannels = 0;
3322 device->VirtOut.Buffer = NULL;
3323 device->VirtOut.NumChannels = 0;
3324 device->RealOut.Buffer = NULL;
3325 device->RealOut.NumChannels = 0;
3327 ATOMIC_INIT(&device->ContextList, NULL);
3329 device->ClockBase = 0;
3330 device->SamplesDone = 0;
3332 device->MaxNoOfSources = 256;
3333 device->AuxiliaryEffectSlotMax = 4;
3334 device->NumAuxSends = MAX_SENDS;
3336 InitUIntMap(&device->BufferMap, ~0);
3337 InitUIntMap(&device->EffectMap, ~0);
3338 InitUIntMap(&device->FilterMap, ~0);
3340 //Set output format
3341 device->FmtChans = DevFmtChannelsDefault;
3342 device->FmtType = DevFmtTypeDefault;
3343 device->Frequency = DEFAULT_OUTPUT_RATE;
3344 device->IsHeadphones = AL_FALSE;
3345 device->NumUpdates = 4;
3346 device->UpdateSize = 1024;
3348 if(!PlaybackBackend.getFactory)
3349 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3350 ALCbackend_Playback);
3351 else
3353 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3354 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3356 if(!device->Backend)
3358 al_free(device);
3359 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3360 return NULL;
3364 if(ConfigValueStr(deviceName, NULL, "channels", &fmt))
3366 static const struct {
3367 const char name[16];
3368 enum DevFmtChannels chans;
3369 } chanlist[] = {
3370 { "mono", DevFmtMono },
3371 { "stereo", DevFmtStereo },
3372 { "quad", DevFmtQuad },
3373 { "surround51", DevFmtX51 },
3374 { "surround61", DevFmtX61 },
3375 { "surround71", DevFmtX71 },
3376 { "surround51rear", DevFmtX51Rear },
3378 size_t i;
3380 for(i = 0;i < COUNTOF(chanlist);i++)
3382 if(strcasecmp(chanlist[i].name, fmt) == 0)
3384 device->FmtChans = chanlist[i].chans;
3385 device->Flags |= DEVICE_CHANNELS_REQUEST;
3386 break;
3389 if(i == COUNTOF(chanlist))
3390 ERR("Unsupported channels: %s\n", fmt);
3392 if(ConfigValueStr(deviceName, NULL, "sample-type", &fmt))
3394 static const struct {
3395 const char name[16];
3396 enum DevFmtType type;
3397 } typelist[] = {
3398 { "int8", DevFmtByte },
3399 { "uint8", DevFmtUByte },
3400 { "int16", DevFmtShort },
3401 { "uint16", DevFmtUShort },
3402 { "int32", DevFmtInt },
3403 { "uint32", DevFmtUInt },
3404 { "float32", DevFmtFloat },
3406 size_t i;
3408 for(i = 0;i < COUNTOF(typelist);i++)
3410 if(strcasecmp(typelist[i].name, fmt) == 0)
3412 device->FmtType = typelist[i].type;
3413 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3414 break;
3417 if(i == COUNTOF(typelist))
3418 ERR("Unsupported sample-type: %s\n", fmt);
3421 if(ConfigValueUInt(deviceName, NULL, "frequency", &device->Frequency))
3423 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3424 if(device->Frequency < MIN_OUTPUT_RATE)
3425 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3426 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3429 ConfigValueUInt(deviceName, NULL, "periods", &device->NumUpdates);
3430 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3432 ConfigValueUInt(deviceName, NULL, "period_size", &device->UpdateSize);
3433 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3434 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
3435 device->UpdateSize = (device->UpdateSize+3)&~3;
3437 ConfigValueUInt(deviceName, NULL, "sources", &device->MaxNoOfSources);
3438 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3440 ConfigValueUInt(deviceName, NULL, "slots", &device->AuxiliaryEffectSlotMax);
3441 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3443 ConfigValueUInt(deviceName, NULL, "sends", &device->NumAuxSends);
3444 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3446 device->NumStereoSources = 1;
3447 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3449 // Find a playback device to open
3450 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3452 DELETE_OBJ(device->Backend);
3453 al_free(device);
3454 alcSetError(NULL, err);
3455 return NULL;
3458 if(DefaultEffect.type != AL_EFFECT_NULL)
3460 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3461 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3463 device->DefaultSlot = NULL;
3464 ERR("Failed to initialize the default effect slot\n");
3466 else
3468 aluInitEffectPanning(device->DefaultSlot);
3469 if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3471 DeinitEffectSlot(device->DefaultSlot);
3472 device->DefaultSlot = NULL;
3473 ERR("Failed to initialize the default effect\n");
3479 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3480 do {
3481 device->next = head;
3482 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3485 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3486 return device;
3489 /* alcCloseDevice
3491 * Closes the given device.
3493 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3495 ALCdevice *list, *origdev, *nextdev;
3496 ALCcontext *ctx;
3498 LockLists();
3499 list = ATOMIC_LOAD(&DeviceList);
3500 do {
3501 if(list == device)
3502 break;
3503 } while((list=list->next) != NULL);
3504 if(!list || list->Type == Capture)
3506 alcSetError(list, ALC_INVALID_DEVICE);
3507 UnlockLists();
3508 return ALC_FALSE;
3511 origdev = device;
3512 nextdev = device->next;
3513 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &origdev, nextdev))
3515 do {
3516 list = origdev;
3517 origdev = device;
3518 } while(!COMPARE_EXCHANGE(&list->next, &origdev, nextdev));
3520 UnlockLists();
3522 ctx = ATOMIC_LOAD(&device->ContextList);
3523 while(ctx != NULL)
3525 ALCcontext *next = ctx->next;
3526 WARN("Releasing context %p\n", ctx);
3527 ReleaseContext(ctx, device);
3528 ctx = next;
3530 if((device->Flags&DEVICE_RUNNING))
3531 V0(device->Backend,stop)();
3532 device->Flags &= ~DEVICE_RUNNING;
3534 ALCdevice_DecRef(device);
3536 return ALC_TRUE;
3540 /************************************************
3541 * ALC capture functions
3542 ************************************************/
3543 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3545 ALCdevice *device = NULL;
3546 ALCenum err;
3548 DO_INITCONFIG();
3550 if(!CaptureBackend.name)
3552 alcSetError(NULL, ALC_INVALID_VALUE);
3553 return NULL;
3556 if(samples <= 0)
3558 alcSetError(NULL, ALC_INVALID_VALUE);
3559 return NULL;
3562 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3563 deviceName = NULL;
3565 device = al_calloc(16, sizeof(ALCdevice));
3566 if(!device)
3568 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3569 return NULL;
3572 //Validate device
3573 InitRef(&device->ref, 1);
3574 device->Connected = ALC_TRUE;
3575 device->Type = Capture;
3577 VECTOR_INIT(device->Hrtf_List);
3578 AL_STRING_INIT(device->Hrtf_Name);
3580 AL_STRING_INIT(device->DeviceName);
3581 device->Dry.Buffer = NULL;
3582 device->Dry.NumChannels = 0;
3583 device->VirtOut.Buffer = NULL;
3584 device->VirtOut.NumChannels = 0;
3585 device->RealOut.Buffer = NULL;
3586 device->RealOut.NumChannels = 0;
3588 InitUIntMap(&device->BufferMap, ~0);
3589 InitUIntMap(&device->EffectMap, ~0);
3590 InitUIntMap(&device->FilterMap, ~0);
3592 if(!CaptureBackend.getFactory)
3593 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
3594 ALCbackend_Capture);
3595 else
3597 ALCbackendFactory *factory = CaptureBackend.getFactory();
3598 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
3600 if(!device->Backend)
3602 al_free(device);
3603 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3604 return NULL;
3607 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3608 device->Frequency = frequency;
3610 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
3611 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
3613 al_free(device);
3614 alcSetError(NULL, ALC_INVALID_ENUM);
3615 return NULL;
3617 device->IsHeadphones = AL_FALSE;
3619 device->UpdateSize = samples;
3620 device->NumUpdates = 1;
3622 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3624 al_free(device);
3625 alcSetError(NULL, err);
3626 return NULL;
3630 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3631 do {
3632 device->next = head;
3633 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3636 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3637 return device;
3640 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3642 ALCdevice *list, *next, *nextdev;
3644 LockLists();
3645 list = ATOMIC_LOAD(&DeviceList);
3646 do {
3647 if(list == device)
3648 break;
3649 } while((list=list->next) != NULL);
3650 if(!list || list->Type != Capture)
3652 alcSetError(list, ALC_INVALID_DEVICE);
3653 UnlockLists();
3654 return ALC_FALSE;
3657 next = device;
3658 nextdev = device->next;
3659 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &next, nextdev))
3661 do {
3662 list = next;
3663 next = device;
3664 } while(!COMPARE_EXCHANGE(&list->next, &next, nextdev));
3666 UnlockLists();
3668 ALCdevice_DecRef(device);
3670 return ALC_TRUE;
3673 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3675 if(!VerifyDevice(&device) || device->Type != Capture)
3676 alcSetError(device, ALC_INVALID_DEVICE);
3677 else
3679 V0(device->Backend,lock)();
3680 if(!device->Connected)
3681 alcSetError(device, ALC_INVALID_DEVICE);
3682 else if(!(device->Flags&DEVICE_RUNNING))
3684 if(V0(device->Backend,start)())
3685 device->Flags |= DEVICE_RUNNING;
3686 else
3688 aluHandleDisconnect(device);
3689 alcSetError(device, ALC_INVALID_DEVICE);
3692 V0(device->Backend,unlock)();
3695 if(device) ALCdevice_DecRef(device);
3698 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3700 if(!VerifyDevice(&device) || device->Type != Capture)
3701 alcSetError(device, ALC_INVALID_DEVICE);
3702 else
3704 V0(device->Backend,lock)();
3705 if((device->Flags&DEVICE_RUNNING))
3706 V0(device->Backend,stop)();
3707 device->Flags &= ~DEVICE_RUNNING;
3708 V0(device->Backend,unlock)();
3711 if(device) ALCdevice_DecRef(device);
3714 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3716 if(!VerifyDevice(&device) || device->Type != Capture)
3717 alcSetError(device, ALC_INVALID_DEVICE);
3718 else
3720 ALCenum err = ALC_INVALID_VALUE;
3722 V0(device->Backend,lock)();
3723 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
3724 err = V(device->Backend,captureSamples)(buffer, samples);
3725 V0(device->Backend,unlock)();
3727 if(err != ALC_NO_ERROR)
3728 alcSetError(device, err);
3730 if(device) ALCdevice_DecRef(device);
3734 /************************************************
3735 * ALC loopback functions
3736 ************************************************/
3738 /* alcLoopbackOpenDeviceSOFT
3740 * Open a loopback device, for manual rendering.
3742 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3744 ALCbackendFactory *factory;
3745 ALCdevice *device;
3747 DO_INITCONFIG();
3749 /* Make sure the device name, if specified, is us. */
3750 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3752 alcSetError(NULL, ALC_INVALID_VALUE);
3753 return NULL;
3756 device = al_calloc(16, sizeof(ALCdevice));
3757 if(!device)
3759 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3760 return NULL;
3763 //Validate device
3764 InitRef(&device->ref, 1);
3765 device->Connected = ALC_TRUE;
3766 device->Type = Loopback;
3767 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3769 device->Flags = 0;
3770 VECTOR_INIT(device->Hrtf_List);
3771 AL_STRING_INIT(device->Hrtf_Name);
3772 device->Bs2b = NULL;
3773 device->Uhj_Encoder = NULL;
3774 device->Render_Mode = NormalRender;
3775 AL_STRING_INIT(device->DeviceName);
3776 device->Dry.Buffer = NULL;
3777 device->Dry.NumChannels = 0;
3778 device->VirtOut.Buffer = NULL;
3779 device->VirtOut.NumChannels = 0;
3780 device->RealOut.Buffer = NULL;
3781 device->RealOut.NumChannels = 0;
3783 ATOMIC_INIT(&device->ContextList, NULL);
3785 device->ClockBase = 0;
3786 device->SamplesDone = 0;
3788 device->MaxNoOfSources = 256;
3789 device->AuxiliaryEffectSlotMax = 4;
3790 device->NumAuxSends = MAX_SENDS;
3792 InitUIntMap(&device->BufferMap, ~0);
3793 InitUIntMap(&device->EffectMap, ~0);
3794 InitUIntMap(&device->FilterMap, ~0);
3796 factory = ALCloopbackFactory_getFactory();
3797 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
3798 if(!device->Backend)
3800 al_free(device);
3801 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3802 return NULL;
3805 //Set output format
3806 device->NumUpdates = 0;
3807 device->UpdateSize = 0;
3809 device->Frequency = DEFAULT_OUTPUT_RATE;
3810 device->FmtChans = DevFmtChannelsDefault;
3811 device->FmtType = DevFmtTypeDefault;
3812 device->IsHeadphones = AL_FALSE;
3814 ConfigValueUInt(NULL, NULL, "sources", &device->MaxNoOfSources);
3815 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3817 ConfigValueUInt(NULL, NULL, "slots", &device->AuxiliaryEffectSlotMax);
3818 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3820 ConfigValueUInt(NULL, NULL, "sends", &device->NumAuxSends);
3821 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3823 device->NumStereoSources = 1;
3824 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3826 // Open the "backend"
3827 V(device->Backend,open)("Loopback");
3830 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3831 do {
3832 device->next = head;
3833 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3836 TRACE("Created device %p\n", device);
3837 return device;
3840 /* alcIsRenderFormatSupportedSOFT
3842 * Determines if the loopback device supports the given format for rendering.
3844 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3846 ALCboolean ret = ALC_FALSE;
3848 if(!VerifyDevice(&device) || device->Type != Loopback)
3849 alcSetError(device, ALC_INVALID_DEVICE);
3850 else if(freq <= 0)
3851 alcSetError(device, ALC_INVALID_VALUE);
3852 else
3854 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3855 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3856 freq >= MIN_OUTPUT_RATE)
3857 ret = ALC_TRUE;
3859 if(device) ALCdevice_DecRef(device);
3861 return ret;
3864 /* alcRenderSamplesSOFT
3866 * Renders some samples into a buffer, using the format last set by the
3867 * attributes given to alcCreateContext.
3869 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3871 if(!VerifyDevice(&device) || device->Type != Loopback)
3872 alcSetError(device, ALC_INVALID_DEVICE);
3873 else if(samples < 0 || (samples > 0 && buffer == NULL))
3874 alcSetError(device, ALC_INVALID_VALUE);
3875 else
3876 aluMixData(device, buffer, samples);
3877 if(device) ALCdevice_DecRef(device);
3881 /************************************************
3882 * ALC DSP pause/resume functions
3883 ************************************************/
3885 /* alcDevicePauseSOFT
3887 * Pause the DSP to stop audio processing.
3889 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
3891 if(!VerifyDevice(&device) || device->Type != Playback)
3892 alcSetError(device, ALC_INVALID_DEVICE);
3893 else
3895 LockLists();
3896 if((device->Flags&DEVICE_RUNNING))
3897 V0(device->Backend,stop)();
3898 device->Flags &= ~DEVICE_RUNNING;
3899 device->Flags |= DEVICE_PAUSED;
3900 UnlockLists();
3902 if(device) ALCdevice_DecRef(device);
3905 /* alcDeviceResumeSOFT
3907 * Resume the DSP to restart audio processing.
3909 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
3911 if(!VerifyDevice(&device) || device->Type != Playback)
3912 alcSetError(device, ALC_INVALID_DEVICE);
3913 else
3915 LockLists();
3916 if((device->Flags&DEVICE_PAUSED))
3918 device->Flags &= ~DEVICE_PAUSED;
3919 if(ATOMIC_LOAD(&device->ContextList) != NULL)
3921 if(V0(device->Backend,start)() != ALC_FALSE)
3922 device->Flags |= DEVICE_RUNNING;
3923 else
3925 alcSetError(device, ALC_INVALID_DEVICE);
3926 V0(device->Backend,lock)();
3927 aluHandleDisconnect(device);
3928 V0(device->Backend,unlock)();
3932 UnlockLists();
3934 if(device) ALCdevice_DecRef(device);
3938 /************************************************
3939 * ALC HRTF functions
3940 ************************************************/
3942 /* alcGetStringiSOFT
3944 * Gets a string parameter at the given index.
3946 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
3948 const ALCchar *str = NULL;
3950 if(!VerifyDevice(&device) || device->Type == Capture)
3951 alcSetError(device, ALC_INVALID_DEVICE);
3952 else switch(paramName)
3954 case ALC_HRTF_SPECIFIER_SOFT:
3955 if(index >= 0 && (size_t)index < VECTOR_SIZE(device->Hrtf_List))
3956 str = al_string_get_cstr(VECTOR_ELEM(device->Hrtf_List, index).name);
3957 else
3958 alcSetError(device, ALC_INVALID_VALUE);
3959 break;
3961 default:
3962 alcSetError(device, ALC_INVALID_ENUM);
3963 break;
3965 if(device) ALCdevice_DecRef(device);
3967 return str;
3970 /* alcResetDeviceSOFT
3972 * Resets the given device output, using the specified attribute list.
3974 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
3976 ALCenum err;
3978 LockLists();
3979 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
3981 UnlockLists();
3982 alcSetError(device, ALC_INVALID_DEVICE);
3983 if(device) ALCdevice_DecRef(device);
3984 return ALC_FALSE;
3987 if((err=UpdateDeviceParams(device, attribs)) != ALC_NO_ERROR)
3989 UnlockLists();
3990 alcSetError(device, err);
3991 if(err == ALC_INVALID_DEVICE)
3993 V0(device->Backend,lock)();
3994 aluHandleDisconnect(device);
3995 V0(device->Backend,unlock)();
3997 ALCdevice_DecRef(device);
3998 return ALC_FALSE;
4000 UnlockLists();
4001 ALCdevice_DecRef(device);
4003 return ALC_TRUE;