Add an SSE-enhanced HRTF mixer using intrinsics
[openal-soft.git] / Alc / ALc.c
blob14a74a923ced7e8dce99c1e097e0fe45ddb6ecf7
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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, 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 "AL/al.h"
33 #include "AL/alc.h"
34 #include "alThunk.h"
35 #include "alSource.h"
36 #include "alBuffer.h"
37 #include "alAuxEffectSlot.h"
38 #include "alError.h"
39 #include "bs2b.h"
40 #include "alu.h"
43 /************************************************
44 * Backends
45 ************************************************/
46 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
47 static struct BackendInfo BackendList[] = {
48 #ifdef HAVE_PULSEAUDIO
49 { "pulse", alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs },
50 #endif
51 #ifdef HAVE_ALSA
52 { "alsa", alc_alsa_init, alc_alsa_deinit, alc_alsa_probe, EmptyFuncs },
53 #endif
54 #ifdef HAVE_COREAUDIO
55 { "core", alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
56 #endif
57 #ifdef HAVE_OSS
58 { "oss", alc_oss_init, alc_oss_deinit, alc_oss_probe, EmptyFuncs },
59 #endif
60 #ifdef HAVE_SOLARIS
61 { "solaris", alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs },
62 #endif
63 #ifdef HAVE_SNDIO
64 { "sndio", alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs },
65 #endif
66 #ifdef HAVE_MMDEVAPI
67 { "mmdevapi", alcMMDevApiInit, alcMMDevApiDeinit, alcMMDevApiProbe, EmptyFuncs },
68 #endif
69 #ifdef HAVE_DSOUND
70 { "dsound", alcDSoundInit, alcDSoundDeinit, alcDSoundProbe, EmptyFuncs },
71 #endif
72 #ifdef HAVE_WINMM
73 { "winmm", alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs },
74 #endif
75 #ifdef HAVE_PORTAUDIO
76 { "port", alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
77 #endif
78 #ifdef HAVE_OPENSL
79 { "opensl", alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs },
80 #endif
82 { "null", alc_null_init, alc_null_deinit, alc_null_probe, EmptyFuncs },
83 #ifdef HAVE_WAVE
84 { "wave", alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs },
85 #endif
87 { NULL, NULL, NULL, NULL, EmptyFuncs }
89 static struct BackendInfo BackendLoopback = {
90 "loopback", alc_loopback_init, alc_loopback_deinit, alc_loopback_probe, EmptyFuncs
92 #undef EmptyFuncs
94 static struct BackendInfo PlaybackBackend;
95 static struct BackendInfo CaptureBackend;
97 /************************************************
98 * Functions, enums, and errors
99 ************************************************/
100 typedef struct ALCfunction {
101 const ALCchar *funcName;
102 ALCvoid *address;
103 } ALCfunction;
105 typedef struct ALCenums {
106 const ALCchar *enumName;
107 ALCenum value;
108 } ALCenums;
110 #define DECL(x) { #x, (ALCvoid*)(x) }
111 static const ALCfunction alcFunctions[] = {
112 DECL(alcCreateContext),
113 DECL(alcMakeContextCurrent),
114 DECL(alcProcessContext),
115 DECL(alcSuspendContext),
116 DECL(alcDestroyContext),
117 DECL(alcGetCurrentContext),
118 DECL(alcGetContextsDevice),
119 DECL(alcOpenDevice),
120 DECL(alcCloseDevice),
121 DECL(alcGetError),
122 DECL(alcIsExtensionPresent),
123 DECL(alcGetProcAddress),
124 DECL(alcGetEnumValue),
125 DECL(alcGetString),
126 DECL(alcGetIntegerv),
127 DECL(alcCaptureOpenDevice),
128 DECL(alcCaptureCloseDevice),
129 DECL(alcCaptureStart),
130 DECL(alcCaptureStop),
131 DECL(alcCaptureSamples),
133 DECL(alcSetThreadContext),
134 DECL(alcGetThreadContext),
136 DECL(alcLoopbackOpenDeviceSOFT),
137 DECL(alcIsRenderFormatSupportedSOFT),
138 DECL(alcRenderSamplesSOFT),
140 DECL(alEnable),
141 DECL(alDisable),
142 DECL(alIsEnabled),
143 DECL(alGetString),
144 DECL(alGetBooleanv),
145 DECL(alGetIntegerv),
146 DECL(alGetFloatv),
147 DECL(alGetDoublev),
148 DECL(alGetBoolean),
149 DECL(alGetInteger),
150 DECL(alGetFloat),
151 DECL(alGetDouble),
152 DECL(alGetError),
153 DECL(alIsExtensionPresent),
154 DECL(alGetProcAddress),
155 DECL(alGetEnumValue),
156 DECL(alListenerf),
157 DECL(alListener3f),
158 DECL(alListenerfv),
159 DECL(alListeneri),
160 DECL(alListener3i),
161 DECL(alListeneriv),
162 DECL(alGetListenerf),
163 DECL(alGetListener3f),
164 DECL(alGetListenerfv),
165 DECL(alGetListeneri),
166 DECL(alGetListener3i),
167 DECL(alGetListeneriv),
168 DECL(alGenSources),
169 DECL(alDeleteSources),
170 DECL(alIsSource),
171 DECL(alSourcef),
172 DECL(alSource3f),
173 DECL(alSourcefv),
174 DECL(alSourcei),
175 DECL(alSource3i),
176 DECL(alSourceiv),
177 DECL(alGetSourcef),
178 DECL(alGetSource3f),
179 DECL(alGetSourcefv),
180 DECL(alGetSourcei),
181 DECL(alGetSource3i),
182 DECL(alGetSourceiv),
183 DECL(alSourcePlayv),
184 DECL(alSourceStopv),
185 DECL(alSourceRewindv),
186 DECL(alSourcePausev),
187 DECL(alSourcePlay),
188 DECL(alSourceStop),
189 DECL(alSourceRewind),
190 DECL(alSourcePause),
191 DECL(alSourceQueueBuffers),
192 DECL(alSourceUnqueueBuffers),
193 DECL(alGenBuffers),
194 DECL(alDeleteBuffers),
195 DECL(alIsBuffer),
196 DECL(alBufferData),
197 DECL(alBufferf),
198 DECL(alBuffer3f),
199 DECL(alBufferfv),
200 DECL(alBufferi),
201 DECL(alBuffer3i),
202 DECL(alBufferiv),
203 DECL(alGetBufferf),
204 DECL(alGetBuffer3f),
205 DECL(alGetBufferfv),
206 DECL(alGetBufferi),
207 DECL(alGetBuffer3i),
208 DECL(alGetBufferiv),
209 DECL(alDopplerFactor),
210 DECL(alDopplerVelocity),
211 DECL(alSpeedOfSound),
212 DECL(alDistanceModel),
214 DECL(alGenFilters),
215 DECL(alDeleteFilters),
216 DECL(alIsFilter),
217 DECL(alFilteri),
218 DECL(alFilteriv),
219 DECL(alFilterf),
220 DECL(alFilterfv),
221 DECL(alGetFilteri),
222 DECL(alGetFilteriv),
223 DECL(alGetFilterf),
224 DECL(alGetFilterfv),
225 DECL(alGenEffects),
226 DECL(alDeleteEffects),
227 DECL(alIsEffect),
228 DECL(alEffecti),
229 DECL(alEffectiv),
230 DECL(alEffectf),
231 DECL(alEffectfv),
232 DECL(alGetEffecti),
233 DECL(alGetEffectiv),
234 DECL(alGetEffectf),
235 DECL(alGetEffectfv),
236 DECL(alGenAuxiliaryEffectSlots),
237 DECL(alDeleteAuxiliaryEffectSlots),
238 DECL(alIsAuxiliaryEffectSlot),
239 DECL(alAuxiliaryEffectSloti),
240 DECL(alAuxiliaryEffectSlotiv),
241 DECL(alAuxiliaryEffectSlotf),
242 DECL(alAuxiliaryEffectSlotfv),
243 DECL(alGetAuxiliaryEffectSloti),
244 DECL(alGetAuxiliaryEffectSlotiv),
245 DECL(alGetAuxiliaryEffectSlotf),
246 DECL(alGetAuxiliaryEffectSlotfv),
248 DECL(alBufferSubDataSOFT),
250 DECL(alBufferSamplesSOFT),
251 DECL(alBufferSubSamplesSOFT),
252 DECL(alGetBufferSamplesSOFT),
253 DECL(alIsBufferFormatSupportedSOFT),
255 DECL(alDeferUpdatesSOFT),
256 DECL(alProcessUpdatesSOFT),
258 { NULL, NULL }
260 #undef DECL
262 #define DECL(x) { #x, (x) }
263 static const ALCenums enumeration[] = {
264 DECL(ALC_INVALID),
265 DECL(ALC_FALSE),
266 DECL(ALC_TRUE),
268 DECL(ALC_MAJOR_VERSION),
269 DECL(ALC_MINOR_VERSION),
270 DECL(ALC_ATTRIBUTES_SIZE),
271 DECL(ALC_ALL_ATTRIBUTES),
272 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
273 DECL(ALC_DEVICE_SPECIFIER),
274 DECL(ALC_ALL_DEVICES_SPECIFIER),
275 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
276 DECL(ALC_EXTENSIONS),
277 DECL(ALC_FREQUENCY),
278 DECL(ALC_REFRESH),
279 DECL(ALC_SYNC),
280 DECL(ALC_MONO_SOURCES),
281 DECL(ALC_STEREO_SOURCES),
282 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
283 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
284 DECL(ALC_CAPTURE_SAMPLES),
285 DECL(ALC_CONNECTED),
287 DECL(ALC_EFX_MAJOR_VERSION),
288 DECL(ALC_EFX_MINOR_VERSION),
289 DECL(ALC_MAX_AUXILIARY_SENDS),
291 DECL(ALC_FORMAT_CHANNELS_SOFT),
292 DECL(ALC_FORMAT_TYPE_SOFT),
294 DECL(ALC_MONO_SOFT),
295 DECL(ALC_STEREO_SOFT),
296 DECL(ALC_QUAD_SOFT),
297 DECL(ALC_5POINT1_SOFT),
298 DECL(ALC_6POINT1_SOFT),
299 DECL(ALC_7POINT1_SOFT),
301 DECL(ALC_BYTE_SOFT),
302 DECL(ALC_UNSIGNED_BYTE_SOFT),
303 DECL(ALC_SHORT_SOFT),
304 DECL(ALC_UNSIGNED_SHORT_SOFT),
305 DECL(ALC_INT_SOFT),
306 DECL(ALC_UNSIGNED_INT_SOFT),
307 DECL(ALC_FLOAT_SOFT),
309 DECL(ALC_NO_ERROR),
310 DECL(ALC_INVALID_DEVICE),
311 DECL(ALC_INVALID_CONTEXT),
312 DECL(ALC_INVALID_ENUM),
313 DECL(ALC_INVALID_VALUE),
314 DECL(ALC_OUT_OF_MEMORY),
317 DECL(AL_INVALID),
318 DECL(AL_NONE),
319 DECL(AL_FALSE),
320 DECL(AL_TRUE),
322 DECL(AL_SOURCE_RELATIVE),
323 DECL(AL_CONE_INNER_ANGLE),
324 DECL(AL_CONE_OUTER_ANGLE),
325 DECL(AL_PITCH),
326 DECL(AL_POSITION),
327 DECL(AL_DIRECTION),
328 DECL(AL_VELOCITY),
329 DECL(AL_LOOPING),
330 DECL(AL_BUFFER),
331 DECL(AL_GAIN),
332 DECL(AL_MIN_GAIN),
333 DECL(AL_MAX_GAIN),
334 DECL(AL_ORIENTATION),
335 DECL(AL_REFERENCE_DISTANCE),
336 DECL(AL_ROLLOFF_FACTOR),
337 DECL(AL_CONE_OUTER_GAIN),
338 DECL(AL_MAX_DISTANCE),
339 DECL(AL_SEC_OFFSET),
340 DECL(AL_SAMPLE_OFFSET),
341 DECL(AL_SAMPLE_RW_OFFSETS_SOFT),
342 DECL(AL_BYTE_OFFSET),
343 DECL(AL_BYTE_RW_OFFSETS_SOFT),
344 DECL(AL_SOURCE_TYPE),
345 DECL(AL_STATIC),
346 DECL(AL_STREAMING),
347 DECL(AL_UNDETERMINED),
348 DECL(AL_METERS_PER_UNIT),
349 DECL(AL_DIRECT_CHANNELS_SOFT),
351 DECL(AL_DIRECT_FILTER),
352 DECL(AL_AUXILIARY_SEND_FILTER),
353 DECL(AL_AIR_ABSORPTION_FACTOR),
354 DECL(AL_ROOM_ROLLOFF_FACTOR),
355 DECL(AL_CONE_OUTER_GAINHF),
356 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
357 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
358 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
360 DECL(AL_SOURCE_STATE),
361 DECL(AL_INITIAL),
362 DECL(AL_PLAYING),
363 DECL(AL_PAUSED),
364 DECL(AL_STOPPED),
366 DECL(AL_BUFFERS_QUEUED),
367 DECL(AL_BUFFERS_PROCESSED),
369 DECL(AL_FORMAT_MONO8),
370 DECL(AL_FORMAT_MONO16),
371 DECL(AL_FORMAT_MONO_FLOAT32),
372 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
373 DECL(AL_FORMAT_STEREO8),
374 DECL(AL_FORMAT_STEREO16),
375 DECL(AL_FORMAT_STEREO_FLOAT32),
376 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
377 DECL(AL_FORMAT_MONO_IMA4),
378 DECL(AL_FORMAT_STEREO_IMA4),
379 DECL(AL_FORMAT_QUAD8_LOKI),
380 DECL(AL_FORMAT_QUAD16_LOKI),
381 DECL(AL_FORMAT_QUAD8),
382 DECL(AL_FORMAT_QUAD16),
383 DECL(AL_FORMAT_QUAD32),
384 DECL(AL_FORMAT_51CHN8),
385 DECL(AL_FORMAT_51CHN16),
386 DECL(AL_FORMAT_51CHN32),
387 DECL(AL_FORMAT_61CHN8),
388 DECL(AL_FORMAT_61CHN16),
389 DECL(AL_FORMAT_61CHN32),
390 DECL(AL_FORMAT_71CHN8),
391 DECL(AL_FORMAT_71CHN16),
392 DECL(AL_FORMAT_71CHN32),
393 DECL(AL_FORMAT_REAR8),
394 DECL(AL_FORMAT_REAR16),
395 DECL(AL_FORMAT_REAR32),
396 DECL(AL_FORMAT_MONO_MULAW),
397 DECL(AL_FORMAT_MONO_MULAW_EXT),
398 DECL(AL_FORMAT_STEREO_MULAW),
399 DECL(AL_FORMAT_STEREO_MULAW_EXT),
400 DECL(AL_FORMAT_QUAD_MULAW),
401 DECL(AL_FORMAT_51CHN_MULAW),
402 DECL(AL_FORMAT_61CHN_MULAW),
403 DECL(AL_FORMAT_71CHN_MULAW),
404 DECL(AL_FORMAT_REAR_MULAW),
405 DECL(AL_FORMAT_MONO_ALAW_EXT),
406 DECL(AL_FORMAT_STEREO_ALAW_EXT),
408 DECL(AL_MONO8_SOFT),
409 DECL(AL_MONO16_SOFT),
410 DECL(AL_MONO32F_SOFT),
411 DECL(AL_STEREO8_SOFT),
412 DECL(AL_STEREO16_SOFT),
413 DECL(AL_STEREO32F_SOFT),
414 DECL(AL_QUAD8_SOFT),
415 DECL(AL_QUAD16_SOFT),
416 DECL(AL_QUAD32F_SOFT),
417 DECL(AL_REAR8_SOFT),
418 DECL(AL_REAR16_SOFT),
419 DECL(AL_REAR32F_SOFT),
420 DECL(AL_5POINT1_8_SOFT),
421 DECL(AL_5POINT1_16_SOFT),
422 DECL(AL_5POINT1_32F_SOFT),
423 DECL(AL_6POINT1_8_SOFT),
424 DECL(AL_6POINT1_16_SOFT),
425 DECL(AL_6POINT1_32F_SOFT),
426 DECL(AL_7POINT1_8_SOFT),
427 DECL(AL_7POINT1_16_SOFT),
428 DECL(AL_7POINT1_32F_SOFT),
430 DECL(AL_MONO_SOFT),
431 DECL(AL_STEREO_SOFT),
432 DECL(AL_QUAD_SOFT),
433 DECL(AL_REAR_SOFT),
434 DECL(AL_5POINT1_SOFT),
435 DECL(AL_6POINT1_SOFT),
436 DECL(AL_7POINT1_SOFT),
438 DECL(AL_BYTE_SOFT),
439 DECL(AL_UNSIGNED_BYTE_SOFT),
440 DECL(AL_SHORT_SOFT),
441 DECL(AL_UNSIGNED_SHORT_SOFT),
442 DECL(AL_INT_SOFT),
443 DECL(AL_UNSIGNED_INT_SOFT),
444 DECL(AL_FLOAT_SOFT),
445 DECL(AL_DOUBLE_SOFT),
446 DECL(AL_BYTE3_SOFT),
447 DECL(AL_UNSIGNED_BYTE3_SOFT),
449 DECL(AL_FREQUENCY),
450 DECL(AL_BITS),
451 DECL(AL_CHANNELS),
452 DECL(AL_SIZE),
453 DECL(AL_INTERNAL_FORMAT_SOFT),
454 DECL(AL_BYTE_LENGTH_SOFT),
455 DECL(AL_SAMPLE_LENGTH_SOFT),
456 DECL(AL_SEC_LENGTH_SOFT),
458 DECL(AL_UNUSED),
459 DECL(AL_PENDING),
460 DECL(AL_PROCESSED),
462 DECL(AL_NO_ERROR),
463 DECL(AL_INVALID_NAME),
464 DECL(AL_INVALID_ENUM),
465 DECL(AL_INVALID_VALUE),
466 DECL(AL_INVALID_OPERATION),
467 DECL(AL_OUT_OF_MEMORY),
469 DECL(AL_VENDOR),
470 DECL(AL_VERSION),
471 DECL(AL_RENDERER),
472 DECL(AL_EXTENSIONS),
474 DECL(AL_DOPPLER_FACTOR),
475 DECL(AL_DOPPLER_VELOCITY),
476 DECL(AL_DISTANCE_MODEL),
477 DECL(AL_SPEED_OF_SOUND),
478 DECL(AL_SOURCE_DISTANCE_MODEL),
479 DECL(AL_DEFERRED_UPDATES_SOFT),
481 DECL(AL_INVERSE_DISTANCE),
482 DECL(AL_INVERSE_DISTANCE_CLAMPED),
483 DECL(AL_LINEAR_DISTANCE),
484 DECL(AL_LINEAR_DISTANCE_CLAMPED),
485 DECL(AL_EXPONENT_DISTANCE),
486 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
488 DECL(AL_FILTER_TYPE),
489 DECL(AL_FILTER_NULL),
490 DECL(AL_FILTER_LOWPASS),
491 #if 0
492 DECL(AL_FILTER_HIGHPASS),
493 DECL(AL_FILTER_BANDPASS),
494 #endif
496 DECL(AL_LOWPASS_GAIN),
497 DECL(AL_LOWPASS_GAINHF),
499 DECL(AL_EFFECT_TYPE),
500 DECL(AL_EFFECT_NULL),
501 DECL(AL_EFFECT_REVERB),
502 DECL(AL_EFFECT_EAXREVERB),
503 #if 0
504 DECL(AL_EFFECT_CHORUS),
505 DECL(AL_EFFECT_DISTORTION),
506 #endif
507 DECL(AL_EFFECT_ECHO),
508 #if 0
509 DECL(AL_EFFECT_FLANGER),
510 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
511 DECL(AL_EFFECT_VOCAL_MORPHER),
512 DECL(AL_EFFECT_PITCH_SHIFTER),
513 #endif
514 DECL(AL_EFFECT_RING_MODULATOR),
515 #if 0
516 DECL(AL_EFFECT_AUTOWAH),
517 DECL(AL_EFFECT_COMPRESSOR),
518 DECL(AL_EFFECT_EQUALIZER),
519 #endif
520 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
521 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
523 DECL(AL_EAXREVERB_DENSITY),
524 DECL(AL_EAXREVERB_DIFFUSION),
525 DECL(AL_EAXREVERB_GAIN),
526 DECL(AL_EAXREVERB_GAINHF),
527 DECL(AL_EAXREVERB_GAINLF),
528 DECL(AL_EAXREVERB_DECAY_TIME),
529 DECL(AL_EAXREVERB_DECAY_HFRATIO),
530 DECL(AL_EAXREVERB_DECAY_LFRATIO),
531 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
532 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
533 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
534 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
535 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
536 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
537 DECL(AL_EAXREVERB_ECHO_TIME),
538 DECL(AL_EAXREVERB_ECHO_DEPTH),
539 DECL(AL_EAXREVERB_MODULATION_TIME),
540 DECL(AL_EAXREVERB_MODULATION_DEPTH),
541 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
542 DECL(AL_EAXREVERB_HFREFERENCE),
543 DECL(AL_EAXREVERB_LFREFERENCE),
544 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
545 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
547 DECL(AL_REVERB_DENSITY),
548 DECL(AL_REVERB_DIFFUSION),
549 DECL(AL_REVERB_GAIN),
550 DECL(AL_REVERB_GAINHF),
551 DECL(AL_REVERB_DECAY_TIME),
552 DECL(AL_REVERB_DECAY_HFRATIO),
553 DECL(AL_REVERB_REFLECTIONS_GAIN),
554 DECL(AL_REVERB_REFLECTIONS_DELAY),
555 DECL(AL_REVERB_LATE_REVERB_GAIN),
556 DECL(AL_REVERB_LATE_REVERB_DELAY),
557 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
558 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
559 DECL(AL_REVERB_DECAY_HFLIMIT),
561 DECL(AL_ECHO_DELAY),
562 DECL(AL_ECHO_LRDELAY),
563 DECL(AL_ECHO_DAMPING),
564 DECL(AL_ECHO_FEEDBACK),
565 DECL(AL_ECHO_SPREAD),
567 DECL(AL_RING_MODULATOR_FREQUENCY),
568 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
569 DECL(AL_RING_MODULATOR_WAVEFORM),
571 DECL(AL_DEDICATED_GAIN),
573 { NULL, (ALCenum)0 }
575 #undef DECL
577 static const ALCchar alcNoError[] = "No Error";
578 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
579 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
580 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
581 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
582 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
585 /************************************************
586 * Global variables
587 ************************************************/
589 /* Enumerated device names */
590 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
591 static ALCchar *alcAllDevicesList;
592 static ALCchar *alcCaptureDeviceList;
593 /* Sizes only include the first ending null character, not the second */
594 static size_t alcAllDevicesListSize;
595 static size_t alcCaptureDeviceListSize;
597 /* Default is always the first in the list */
598 static ALCchar *alcDefaultAllDevicesSpecifier;
599 static ALCchar *alcCaptureDefaultDeviceSpecifier;
601 /* Default context extensions */
602 static const ALchar alExtList[] =
603 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
604 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
605 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
606 "AL_LOKI_quadriphonic AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data "
607 "AL_SOFTX_deferred_updates AL_SOFT_direct_channels AL_SOFT_loop_points";
609 static volatile ALCenum LastNullDeviceError = ALC_NO_ERROR;
611 /* Thread-local current context */
612 static pthread_key_t LocalContext;
613 /* Process-wide current context */
614 static ALCcontext *volatile GlobalContext = NULL;
616 /* Mixing thread piority level */
617 ALint RTPrioLevel;
619 FILE *LogFile;
620 #ifdef _DEBUG
621 enum LogLevel LogLevel = LogWarning;
622 #else
623 enum LogLevel LogLevel = LogError;
624 #endif
626 /* Flag to trap ALC device errors */
627 static ALCboolean TrapALCError = ALC_FALSE;
629 /* One-time configuration init control */
630 static pthread_once_t alc_config_once = PTHREAD_ONCE_INIT;
632 /* Default effect that applies to sources that don't have an effect on send 0 */
633 static ALeffect DefaultEffect;
636 /************************************************
637 * ALC information
638 ************************************************/
639 static const ALCchar alcNoDeviceExtList[] =
640 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
641 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
642 static const ALCchar alcExtensionList[] =
643 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
644 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
645 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
646 static const ALCint alcMajorVersion = 1;
647 static const ALCint alcMinorVersion = 1;
649 static const ALCint alcEFXMajorVersion = 1;
650 static const ALCint alcEFXMinorVersion = 0;
653 /************************************************
654 * Device lists
655 ************************************************/
656 static ALCdevice *volatile DeviceList = NULL;
658 static CRITICAL_SECTION ListLock;
660 static void LockLists(void)
662 EnterCriticalSection(&ListLock);
664 static void UnlockLists(void)
666 LeaveCriticalSection(&ListLock);
669 /************************************************
670 * Library initialization
671 ************************************************/
672 #if defined(_WIN32)
673 static void alc_init(void);
674 static void alc_deinit(void);
675 static void alc_deinit_safe(void);
677 UIntMap TlsDestructor;
679 #ifndef AL_LIBTYPE_STATIC
680 BOOL APIENTRY DllMain(HINSTANCE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
682 ALsizei i;
684 // Perform actions based on the reason for calling.
685 switch(ul_reason_for_call)
687 case DLL_PROCESS_ATTACH:
688 /* Pin the DLL so we won't get unloaded until the process terminates */
689 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
690 (WCHAR*)hModule, &hModule);
691 InitUIntMap(&TlsDestructor, ~0);
692 alc_init();
693 break;
695 case DLL_THREAD_DETACH:
696 LockUIntMapRead(&TlsDestructor);
697 for(i = 0;i < TlsDestructor.size;i++)
699 void *ptr = pthread_getspecific(TlsDestructor.array[i].key);
700 void (*callback)(void*) = (void(*)(void*))TlsDestructor.array[i].value;
701 if(ptr && callback)
702 callback(ptr);
704 UnlockUIntMapRead(&TlsDestructor);
705 break;
707 case DLL_PROCESS_DETACH:
708 if(!lpReserved)
709 alc_deinit();
710 else
711 alc_deinit_safe();
712 ResetUIntMap(&TlsDestructor);
713 break;
715 return TRUE;
717 #elif defined(_MSC_VER)
718 #pragma section(".CRT$XCU",read)
719 static void alc_constructor(void);
720 static void alc_destructor(void);
721 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
723 static void alc_constructor(void)
725 atexit(alc_destructor);
726 alc_init();
729 static void alc_destructor(void)
731 alc_deinit();
733 #elif defined(HAVE_GCC_DESTRUCTOR)
734 static void alc_init(void) __attribute__((constructor));
735 static void alc_deinit(void) __attribute__((destructor));
736 #else
737 #error "No static initialization available on this platform!"
738 #endif
740 #elif defined(HAVE_GCC_DESTRUCTOR)
742 static void alc_init(void) __attribute__((constructor));
743 static void alc_deinit(void) __attribute__((destructor));
745 #else
746 #error "No global initialization available on this platform!"
747 #endif
749 static void ReleaseThreadCtx(void *ptr);
750 static void alc_init(void)
752 const char *str;
754 LogFile = stderr;
756 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
757 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
758 ConeScale *= 0.5f;
760 str = getenv("__ALSOFT_REVERSE_Z");
761 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
762 ZScale *= -1.0f;
764 pthread_key_create(&LocalContext, ReleaseThreadCtx);
765 InitializeCriticalSection(&ListLock);
766 ThunkInit();
769 static void alc_initconfig(void)
771 const char *devs, *str;
772 ALuint capfilter;
773 float valf;
774 int i, n;
776 str = getenv("ALSOFT_LOGLEVEL");
777 if(str)
779 long lvl = strtol(str, NULL, 0);
780 if(lvl >= NoLog && lvl <= LogRef)
781 LogLevel = lvl;
784 str = getenv("ALSOFT_LOGFILE");
785 if(str && str[0])
787 FILE *logfile = fopen(str, "wat");
788 if(logfile) LogFile = logfile;
789 else ERR("Failed to open log file '%s'\n", str);
792 ReadALConfig();
794 capfilter = CPU_CAP_ALL;
795 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
797 if(strcasecmp(str, "all") == 0)
798 capfilter = 0;
799 else
801 size_t len;
802 const char *next = str;
804 i = 0;
805 do {
806 str = next;
807 next = strchr(str, ',');
809 while(isspace(str[0]))
810 str++;
811 if(!str[0] || str[0] == ',')
812 continue;
814 len = (next ? ((size_t)(next-str)) : strlen(str));
815 if(strncasecmp(str, "sse", len) == 0)
816 capfilter &= ~CPU_CAP_SSE;
817 else if(strncasecmp(str, "neon", len) == 0)
818 capfilter &= ~CPU_CAP_NEON;
819 else
820 WARN("Invalid CPU extension \"%s\"\n", str);
821 } while(next++);
824 FillCPUCaps(capfilter);
826 InitHrtf();
828 #ifdef _WIN32
829 RTPrioLevel = 1;
830 #else
831 RTPrioLevel = 0;
832 #endif
833 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
835 if(ConfigValueStr(NULL, "resampler", &str))
837 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
838 DefaultResampler = PointResampler;
839 else if(strcasecmp(str, "linear") == 0)
840 DefaultResampler = LinearResampler;
841 else if(strcasecmp(str, "cubic") == 0)
842 DefaultResampler = CubicResampler;
843 else
845 char *end;
847 n = strtol(str, &end, 0);
848 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
849 DefaultResampler = n;
850 else
851 WARN("Invalid resampler: %s\n", str);
855 str = getenv("ALSOFT_TRAP_ERROR");
856 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
858 TrapALError = AL_TRUE;
859 TrapALCError = AL_TRUE;
861 else
863 str = getenv("ALSOFT_TRAP_AL_ERROR");
864 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
865 TrapALError = AL_TRUE;
866 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
868 str = getenv("ALSOFT_TRAP_ALC_ERROR");
869 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
870 TrapALCError = ALC_TRUE;
871 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
874 if(ConfigValueFloat("reverb", "boost", &valf))
875 ReverbBoost *= powf(10.0f, valf / 20.0f);
877 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
879 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
880 ConfigValueStr(NULL, "drivers", &devs))
882 int n;
883 size_t len;
884 const char *next = devs;
885 int endlist, delitem;
887 i = 0;
888 do {
889 devs = next;
890 next = strchr(devs, ',');
892 delitem = (devs[0] == '-');
893 if(devs[0] == '-') devs++;
895 if(!devs[0] || devs[0] == ',')
897 endlist = 0;
898 continue;
900 endlist = 1;
902 len = (next ? ((size_t)(next-devs)) : strlen(devs));
903 for(n = i;BackendList[n].Init;n++)
905 if(len == strlen(BackendList[n].name) &&
906 strncmp(BackendList[n].name, devs, len) == 0)
908 if(delitem)
910 do {
911 BackendList[n] = BackendList[n+1];
912 ++n;
913 } while(BackendList[n].Init);
915 else
917 struct BackendInfo Bkp = BackendList[n];
918 while(n > i)
920 BackendList[n] = BackendList[n-1];
921 --n;
923 BackendList[n] = Bkp;
925 i++;
927 break;
930 } while(next++);
932 if(endlist)
934 BackendList[i].name = NULL;
935 BackendList[i].Init = NULL;
936 BackendList[i].Deinit = NULL;
937 BackendList[i].Probe = NULL;
941 for(i = 0;BackendList[i].Init && (!PlaybackBackend.name || !CaptureBackend.name);i++)
943 if(!BackendList[i].Init(&BackendList[i].Funcs))
945 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
946 continue;
949 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
950 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
952 PlaybackBackend = BackendList[i];
953 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
955 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
957 CaptureBackend = BackendList[i];
958 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
961 BackendLoopback.Init(&BackendLoopback.Funcs);
963 if(ConfigValueStr(NULL, "excludefx", &str))
965 size_t len;
966 const char *next = str;
968 do {
969 str = next;
970 next = strchr(str, ',');
972 if(!str[0] || next == str)
973 continue;
975 len = (next ? ((size_t)(next-str)) : strlen(str));
976 for(n = 0;EffectList[n].name;n++)
978 if(len == strlen(EffectList[n].name) &&
979 strncmp(EffectList[n].name, str, len) == 0)
980 DisabledEffects[EffectList[n].type] = AL_TRUE;
982 } while(next++);
985 InitEffect(&DefaultEffect);
986 str = getenv("ALSOFT_DEFAULT_REVERB");
987 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
988 LoadReverbPreset(str, &DefaultEffect);
990 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
993 /************************************************
994 * Library deinitialization
995 ************************************************/
996 static void alc_cleanup(void)
998 ALCdevice *dev;
1000 free(alcAllDevicesList); alcAllDevicesList = NULL;
1001 alcAllDevicesListSize = 0;
1002 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
1003 alcCaptureDeviceListSize = 0;
1005 free(alcDefaultAllDevicesSpecifier);
1006 alcDefaultAllDevicesSpecifier = NULL;
1007 free(alcCaptureDefaultDeviceSpecifier);
1008 alcCaptureDefaultDeviceSpecifier = NULL;
1010 if((dev=ExchangePtr((XchgPtr*)&DeviceList, NULL)) != NULL)
1012 ALCuint num = 0;
1013 do {
1014 num++;
1015 } while((dev=dev->next) != NULL);
1016 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1020 static void alc_deinit_safe(void)
1022 alc_cleanup();
1024 FreeHrtf();
1025 FreeALConfig();
1027 ThunkExit();
1028 DeleteCriticalSection(&ListLock);
1029 pthread_key_delete(LocalContext);
1031 if(LogFile != stderr)
1032 fclose(LogFile);
1033 LogFile = NULL;
1036 static void alc_deinit(void)
1038 int i;
1040 alc_cleanup();
1042 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1043 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1045 for(i = 0;BackendList[i].Deinit;i++)
1046 BackendList[i].Deinit();
1047 BackendLoopback.Deinit();
1049 alc_deinit_safe();
1053 /************************************************
1054 * Device enumeration
1055 ************************************************/
1056 static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type)
1058 DO_INITCONFIG();
1060 LockLists();
1061 free(*list);
1062 *list = NULL;
1063 *listsize = 0;
1065 if(type == ALL_DEVICE_PROBE && PlaybackBackend.Probe)
1066 PlaybackBackend.Probe(type);
1067 else if(type == CAPTURE_DEVICE_PROBE && CaptureBackend.Probe)
1068 CaptureBackend.Probe(type);
1069 UnlockLists();
1072 static void ProbeAllDevicesList(void)
1073 { ProbeList(&alcAllDevicesList, &alcAllDevicesListSize, ALL_DEVICE_PROBE); }
1074 static void ProbeCaptureDeviceList(void)
1075 { ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); }
1078 static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize)
1080 size_t len = strlen(name);
1081 void *temp;
1083 if(len == 0)
1084 return;
1086 temp = realloc(*List, (*ListSize) + len + 2);
1087 if(!temp)
1089 ERR("Realloc failed to add %s!\n", name);
1090 return;
1092 *List = temp;
1094 memcpy((*List)+(*ListSize), name, len+1);
1095 *ListSize += len+1;
1096 (*List)[*ListSize] = 0;
1099 #define DECL_APPEND_LIST_FUNC(type) \
1100 void Append##type##List(const ALCchar *name) \
1101 { AppendList(name, &alc##type##List, &alc##type##ListSize); }
1103 DECL_APPEND_LIST_FUNC(AllDevices)
1104 DECL_APPEND_LIST_FUNC(CaptureDevice)
1106 #undef DECL_APPEND_LIST_FUNC
1109 /************************************************
1110 * Device format information
1111 ************************************************/
1112 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1114 switch(type)
1116 case DevFmtByte: return "Signed Byte";
1117 case DevFmtUByte: return "Unsigned Byte";
1118 case DevFmtShort: return "Signed Short";
1119 case DevFmtUShort: return "Unsigned Short";
1120 case DevFmtInt: return "Signed Int";
1121 case DevFmtUInt: return "Unsigned Int";
1122 case DevFmtFloat: return "Float";
1124 return "(unknown type)";
1126 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1128 switch(chans)
1130 case DevFmtMono: return "Mono";
1131 case DevFmtStereo: return "Stereo";
1132 case DevFmtQuad: return "Quadraphonic";
1133 case DevFmtX51: return "5.1 Surround";
1134 case DevFmtX51Side: return "5.1 Side";
1135 case DevFmtX61: return "6.1 Surround";
1136 case DevFmtX71: return "7.1 Surround";
1138 return "(unknown channels)";
1141 ALuint BytesFromDevFmt(enum DevFmtType type)
1143 switch(type)
1145 case DevFmtByte: return sizeof(ALbyte);
1146 case DevFmtUByte: return sizeof(ALubyte);
1147 case DevFmtShort: return sizeof(ALshort);
1148 case DevFmtUShort: return sizeof(ALushort);
1149 case DevFmtInt: return sizeof(ALint);
1150 case DevFmtUInt: return sizeof(ALuint);
1151 case DevFmtFloat: return sizeof(ALfloat);
1153 return 0;
1155 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1157 switch(chans)
1159 case DevFmtMono: return 1;
1160 case DevFmtStereo: return 2;
1161 case DevFmtQuad: return 4;
1162 case DevFmtX51: return 6;
1163 case DevFmtX51Side: return 6;
1164 case DevFmtX61: return 7;
1165 case DevFmtX71: return 8;
1167 return 0;
1170 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1171 enum DevFmtType *type)
1173 static const struct {
1174 ALenum format;
1175 enum DevFmtChannels channels;
1176 enum DevFmtType type;
1177 } list[] = {
1178 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1179 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1180 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1182 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1183 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1184 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1186 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1187 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1188 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1190 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1191 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1192 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1194 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1195 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1196 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1198 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1199 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1200 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1202 ALuint i;
1204 for(i = 0;i < COUNTOF(list);i++)
1206 if(list[i].format == format)
1208 *chans = list[i].channels;
1209 *type = list[i].type;
1210 return AL_TRUE;
1214 return AL_FALSE;
1217 static ALCboolean IsValidALCType(ALCenum type)
1219 switch(type)
1221 case ALC_BYTE_SOFT:
1222 case ALC_UNSIGNED_BYTE_SOFT:
1223 case ALC_SHORT_SOFT:
1224 case ALC_UNSIGNED_SHORT_SOFT:
1225 case ALC_INT_SOFT:
1226 case ALC_UNSIGNED_INT_SOFT:
1227 case ALC_FLOAT_SOFT:
1228 return ALC_TRUE;
1230 return ALC_FALSE;
1233 static ALCboolean IsValidALCChannels(ALCenum channels)
1235 switch(channels)
1237 case ALC_MONO_SOFT:
1238 case ALC_STEREO_SOFT:
1239 case ALC_QUAD_SOFT:
1240 case ALC_5POINT1_SOFT:
1241 case ALC_6POINT1_SOFT:
1242 case ALC_7POINT1_SOFT:
1243 return ALC_TRUE;
1245 return ALC_FALSE;
1249 /************************************************
1250 * Miscellaneous ALC helpers
1251 ************************************************/
1253 /* SetDefaultWFXChannelOrder
1255 * Sets the default channel order used by WaveFormatEx.
1257 void SetDefaultWFXChannelOrder(ALCdevice *device)
1259 switch(device->FmtChans)
1261 case DevFmtMono: device->DevChannels[0] = FrontCenter; break;
1263 case DevFmtStereo: device->DevChannels[0] = FrontLeft;
1264 device->DevChannels[1] = FrontRight; break;
1266 case DevFmtQuad: device->DevChannels[0] = FrontLeft;
1267 device->DevChannels[1] = FrontRight;
1268 device->DevChannels[2] = BackLeft;
1269 device->DevChannels[3] = BackRight; break;
1271 case DevFmtX51: device->DevChannels[0] = FrontLeft;
1272 device->DevChannels[1] = FrontRight;
1273 device->DevChannels[2] = FrontCenter;
1274 device->DevChannels[3] = LFE;
1275 device->DevChannels[4] = BackLeft;
1276 device->DevChannels[5] = BackRight; break;
1278 case DevFmtX51Side: device->DevChannels[0] = FrontLeft;
1279 device->DevChannels[1] = FrontRight;
1280 device->DevChannels[2] = FrontCenter;
1281 device->DevChannels[3] = LFE;
1282 device->DevChannels[4] = SideLeft;
1283 device->DevChannels[5] = SideRight; break;
1285 case DevFmtX61: device->DevChannels[0] = FrontLeft;
1286 device->DevChannels[1] = FrontRight;
1287 device->DevChannels[2] = FrontCenter;
1288 device->DevChannels[3] = LFE;
1289 device->DevChannels[4] = BackCenter;
1290 device->DevChannels[5] = SideLeft;
1291 device->DevChannels[6] = SideRight; break;
1293 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1294 device->DevChannels[1] = FrontRight;
1295 device->DevChannels[2] = FrontCenter;
1296 device->DevChannels[3] = LFE;
1297 device->DevChannels[4] = BackLeft;
1298 device->DevChannels[5] = BackRight;
1299 device->DevChannels[6] = SideLeft;
1300 device->DevChannels[7] = SideRight; break;
1304 /* SetDefaultChannelOrder
1306 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1308 void SetDefaultChannelOrder(ALCdevice *device)
1310 switch(device->FmtChans)
1312 case DevFmtX51: device->DevChannels[0] = FrontLeft;
1313 device->DevChannels[1] = FrontRight;
1314 device->DevChannels[2] = BackLeft;
1315 device->DevChannels[3] = BackRight;
1316 device->DevChannels[4] = FrontCenter;
1317 device->DevChannels[5] = LFE;
1318 return;
1320 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1321 device->DevChannels[1] = FrontRight;
1322 device->DevChannels[2] = BackLeft;
1323 device->DevChannels[3] = BackRight;
1324 device->DevChannels[4] = FrontCenter;
1325 device->DevChannels[5] = LFE;
1326 device->DevChannels[6] = SideLeft;
1327 device->DevChannels[7] = SideRight;
1328 return;
1330 /* Same as WFX order */
1331 case DevFmtMono:
1332 case DevFmtStereo:
1333 case DevFmtQuad:
1334 case DevFmtX51Side:
1335 case DevFmtX61:
1336 break;
1338 SetDefaultWFXChannelOrder(device);
1342 /* alcSetError
1344 * Stores the latest ALC device error
1346 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1348 if(TrapALCError)
1350 #ifdef _WIN32
1351 /* DebugBreak() will cause an exception if there is no debugger */
1352 if(IsDebuggerPresent())
1353 DebugBreak();
1354 #elif defined(SIGTRAP)
1355 raise(SIGTRAP);
1356 #endif
1359 if(device)
1360 device->LastError = errorCode;
1361 else
1362 LastNullDeviceError = errorCode;
1366 /* UpdateDeviceParams
1368 * Updates device parameters according to the attribute list (caller is
1369 * responsible for holding the list lock).
1371 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1373 ALCcontext *context;
1374 enum DevFmtChannels oldChans;
1375 enum DevFmtType oldType;
1376 ALCuint oldFreq;
1377 int oldMode;
1378 ALuint i;
1380 // Check for attributes
1381 if(device->Type == Loopback)
1383 enum {
1384 GotFreq = 1<<0,
1385 GotChans = 1<<1,
1386 GotType = 1<<2,
1387 GotAll = GotFreq|GotChans|GotType
1389 ALCuint freq, numMono, numStereo, numSends;
1390 enum DevFmtChannels schans;
1391 enum DevFmtType stype;
1392 ALCuint attrIdx = 0;
1393 ALCint gotFmt = 0;
1395 if(!attrList)
1397 WARN("Missing attributes for loopback device\n");
1398 return ALC_INVALID_VALUE;
1401 numMono = device->NumMonoSources;
1402 numStereo = device->NumStereoSources;
1403 numSends = device->NumAuxSends;
1404 schans = device->FmtChans;
1405 stype = device->FmtType;
1406 freq = device->Frequency;
1408 while(attrList[attrIdx])
1410 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1412 ALCint val = attrList[attrIdx + 1];
1413 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1414 return ALC_INVALID_VALUE;
1415 schans = val;
1416 gotFmt |= GotChans;
1419 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1421 ALCint val = attrList[attrIdx + 1];
1422 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1423 return ALC_INVALID_VALUE;
1424 stype = val;
1425 gotFmt |= GotType;
1428 if(attrList[attrIdx] == ALC_FREQUENCY)
1430 freq = attrList[attrIdx + 1];
1431 if(freq < MIN_OUTPUT_RATE)
1432 return ALC_INVALID_VALUE;
1433 gotFmt |= GotFreq;
1436 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1438 numStereo = attrList[attrIdx + 1];
1439 if(numStereo > device->MaxNoOfSources)
1440 numStereo = device->MaxNoOfSources;
1442 numMono = device->MaxNoOfSources - numStereo;
1445 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1446 numSends = attrList[attrIdx + 1];
1448 attrIdx += 2;
1451 if(gotFmt != GotAll)
1453 WARN("Missing format for loopback device\n");
1454 return ALC_INVALID_VALUE;
1457 ConfigValueUInt(NULL, "sends", &numSends);
1458 numSends = minu(MAX_SENDS, numSends);
1460 if((device->Flags&DEVICE_RUNNING))
1461 ALCdevice_StopPlayback(device);
1462 device->Flags &= ~DEVICE_RUNNING;
1464 device->Frequency = freq;
1465 device->FmtChans = schans;
1466 device->FmtType = stype;
1467 device->NumMonoSources = numMono;
1468 device->NumStereoSources = numStereo;
1469 device->NumAuxSends = numSends;
1471 else if(attrList && attrList[0])
1473 ALCuint freq, numMono, numStereo, numSends;
1474 ALCuint attrIdx = 0;
1476 /* If a context is already running on the device, stop playback so the
1477 * device attributes can be updated. */
1478 if((device->Flags&DEVICE_RUNNING))
1479 ALCdevice_StopPlayback(device);
1480 device->Flags &= ~DEVICE_RUNNING;
1482 freq = device->Frequency;
1483 numMono = device->NumMonoSources;
1484 numStereo = device->NumStereoSources;
1485 numSends = device->NumAuxSends;
1487 while(attrList[attrIdx])
1489 if(attrList[attrIdx] == ALC_FREQUENCY)
1491 freq = attrList[attrIdx + 1];
1492 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1495 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1497 numStereo = attrList[attrIdx + 1];
1498 if(numStereo > device->MaxNoOfSources)
1499 numStereo = device->MaxNoOfSources;
1501 numMono = device->MaxNoOfSources - numStereo;
1504 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1505 numSends = attrList[attrIdx + 1];
1507 attrIdx += 2;
1510 ConfigValueUInt(NULL, "frequency", &freq);
1511 freq = maxu(freq, MIN_OUTPUT_RATE);
1513 ConfigValueUInt(NULL, "sends", &numSends);
1514 numSends = minu(MAX_SENDS, numSends);
1516 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1517 device->Frequency;
1519 device->Frequency = freq;
1520 device->NumMonoSources = numMono;
1521 device->NumStereoSources = numStereo;
1522 device->NumAuxSends = numSends;
1525 if((device->Flags&DEVICE_RUNNING))
1526 return ALC_NO_ERROR;
1528 oldFreq = device->Frequency;
1529 oldChans = device->FmtChans;
1530 oldType = device->FmtType;
1532 TRACE("Format pre-setup: %s%s, %s%s, %uhz%s, %u update size x%d\n",
1533 DevFmtChannelsString(device->FmtChans),
1534 (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"",
1535 DevFmtTypeString(device->FmtType),
1536 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?" (requested)":"",
1537 device->Frequency,
1538 (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",
1539 device->UpdateSize, device->NumUpdates);
1541 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
1542 return ALC_INVALID_DEVICE;
1544 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1546 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1547 DevFmtChannelsString(device->FmtChans));
1548 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1550 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1552 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1553 DevFmtTypeString(device->FmtType));
1554 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1556 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1558 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1559 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1562 TRACE("Format post-setup: %s, %s, %uhz, %u update size x%d\n",
1563 DevFmtChannelsString(device->FmtChans),
1564 DevFmtTypeString(device->FmtType), device->Frequency,
1565 device->UpdateSize, device->NumUpdates);
1567 aluInitPanning(device);
1569 for(i = 0;i < MaxChannels;i++)
1571 device->ClickRemoval[i] = 0.0f;
1572 device->PendingClicks[i] = 0.0f;
1575 device->Hrtf = NULL;
1576 if(device->Type != Loopback && GetConfigValueBool(NULL, "hrtf", AL_FALSE))
1577 device->Hrtf = GetHrtf(device);
1578 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1580 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1582 if(!device->Bs2b)
1584 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1585 bs2b_clear(device->Bs2b);
1587 bs2b_set_srate(device->Bs2b, device->Frequency);
1588 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1589 TRACE("BS2B level %d\n", device->Bs2bLevel);
1591 else
1593 free(device->Bs2b);
1594 device->Bs2b = NULL;
1595 TRACE("BS2B disabled\n");
1598 device->Flags &= ~DEVICE_WIDE_STEREO;
1599 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1600 device->Flags |= DEVICE_WIDE_STEREO;
1602 oldMode = SetMixerFPUMode();
1603 LockDevice(device);
1604 context = device->ContextList;
1605 while(context)
1607 ALsizei pos;
1609 context->UpdateSources = AL_FALSE;
1610 LockUIntMapRead(&context->EffectSlotMap);
1611 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1613 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1615 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1617 UnlockUIntMapRead(&context->EffectSlotMap);
1618 UnlockDevice(device);
1619 RestoreFPUMode(oldMode);
1620 return ALC_INVALID_DEVICE;
1622 slot->NeedsUpdate = AL_FALSE;
1623 ALeffectState_Update(slot->EffectState, device, slot);
1625 UnlockUIntMapRead(&context->EffectSlotMap);
1627 LockUIntMapRead(&context->SourceMap);
1628 for(pos = 0;pos < context->SourceMap.size;pos++)
1630 ALsource *source = context->SourceMap.array[pos].value;
1631 ALuint s = device->NumAuxSends;
1632 while(s < MAX_SENDS)
1634 if(source->Send[s].Slot)
1635 DecrementRef(&source->Send[s].Slot->ref);
1636 source->Send[s].Slot = NULL;
1637 source->Send[s].Gain = 1.0f;
1638 source->Send[s].GainHF = 1.0f;
1639 s++;
1641 source->NeedsUpdate = AL_FALSE;
1642 ALsource_Update(source, context);
1644 UnlockUIntMapRead(&context->SourceMap);
1646 context = context->next;
1648 if(device->DefaultSlot)
1650 ALeffectslot *slot = device->DefaultSlot;
1652 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1654 UnlockDevice(device);
1655 RestoreFPUMode(oldMode);
1656 return ALC_INVALID_DEVICE;
1658 slot->NeedsUpdate = AL_FALSE;
1659 ALeffectState_Update(slot->EffectState, device, slot);
1661 UnlockDevice(device);
1662 RestoreFPUMode(oldMode);
1664 if(ALCdevice_StartPlayback(device) == ALC_FALSE)
1665 return ALC_INVALID_DEVICE;
1666 device->Flags |= DEVICE_RUNNING;
1668 return ALC_NO_ERROR;
1671 /* FreeDevice
1673 * Frees the device structure, and destroys any objects the app failed to
1674 * delete. Called once there's no more references on the device.
1676 static ALCvoid FreeDevice(ALCdevice *device)
1678 TRACE("%p\n", device);
1680 if(device->DefaultSlot)
1682 ALeffectState_Destroy(device->DefaultSlot->EffectState);
1683 device->DefaultSlot->EffectState = NULL;
1686 if(device->BufferMap.size > 0)
1688 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
1689 ReleaseALBuffers(device);
1691 ResetUIntMap(&device->BufferMap);
1693 if(device->EffectMap.size > 0)
1695 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
1696 ReleaseALEffects(device);
1698 ResetUIntMap(&device->EffectMap);
1700 if(device->FilterMap.size > 0)
1702 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
1703 ReleaseALFilters(device);
1705 ResetUIntMap(&device->FilterMap);
1707 free(device->Bs2b);
1708 device->Bs2b = NULL;
1710 free(device->DeviceName);
1711 device->DeviceName = NULL;
1713 DeleteCriticalSection(&device->Mutex);
1715 free(device);
1719 void ALCdevice_IncRef(ALCdevice *device)
1721 RefCount ref;
1722 ref = IncrementRef(&device->ref);
1723 TRACEREF("%p increasing refcount to %u\n", device, ref);
1726 void ALCdevice_DecRef(ALCdevice *device)
1728 RefCount ref;
1729 ref = DecrementRef(&device->ref);
1730 TRACEREF("%p decreasing refcount to %u\n", device, ref);
1731 if(ref == 0) FreeDevice(device);
1734 /* VerifyDevice
1736 * Checks if the device handle is valid, and increments its ref count if so.
1738 static ALCdevice *VerifyDevice(ALCdevice *device)
1740 ALCdevice *tmpDevice;
1742 if(!device)
1743 return NULL;
1745 LockLists();
1746 tmpDevice = DeviceList;
1747 while(tmpDevice && tmpDevice != device)
1748 tmpDevice = tmpDevice->next;
1750 if(tmpDevice)
1751 ALCdevice_IncRef(tmpDevice);
1752 UnlockLists();
1753 return tmpDevice;
1757 /* InitContext
1759 * Initializes context fields
1761 static ALvoid InitContext(ALCcontext *Context)
1763 ALint i, j;
1765 //Initialise listener
1766 Context->Listener.Gain = 1.0f;
1767 Context->Listener.MetersPerUnit = 1.0f;
1768 Context->Listener.Position[0] = 0.0f;
1769 Context->Listener.Position[1] = 0.0f;
1770 Context->Listener.Position[2] = 0.0f;
1771 Context->Listener.Velocity[0] = 0.0f;
1772 Context->Listener.Velocity[1] = 0.0f;
1773 Context->Listener.Velocity[2] = 0.0f;
1774 Context->Listener.Forward[0] = 0.0f;
1775 Context->Listener.Forward[1] = 0.0f;
1776 Context->Listener.Forward[2] = -1.0f;
1777 Context->Listener.Up[0] = 0.0f;
1778 Context->Listener.Up[1] = 1.0f;
1779 Context->Listener.Up[2] = 0.0f;
1780 for(i = 0;i < 4;i++)
1782 for(j = 0;j < 4;j++)
1783 Context->Listener.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
1786 //Validate Context
1787 Context->LastError = AL_NO_ERROR;
1788 Context->UpdateSources = AL_FALSE;
1789 Context->ActiveSourceCount = 0;
1790 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
1791 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
1793 //Set globals
1794 Context->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
1795 Context->SourceDistanceModel = AL_FALSE;
1796 Context->DopplerFactor = 1.0f;
1797 Context->DopplerVelocity = 1.0f;
1798 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
1799 Context->DeferUpdates = AL_FALSE;
1801 Context->ExtensionList = alExtList;
1805 /* FreeContext
1807 * Cleans up the context, and destroys any remaining objects the app failed to
1808 * delete. Called once there's no more references on the context.
1810 static ALCvoid FreeContext(ALCcontext *context)
1812 TRACE("%p\n", context);
1814 if(context->SourceMap.size > 0)
1816 ERR("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
1817 ReleaseALSources(context);
1819 ResetUIntMap(&context->SourceMap);
1821 if(context->EffectSlotMap.size > 0)
1823 ERR("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
1824 ReleaseALAuxiliaryEffectSlots(context);
1826 ResetUIntMap(&context->EffectSlotMap);
1828 context->ActiveSourceCount = 0;
1829 free(context->ActiveSources);
1830 context->ActiveSources = NULL;
1831 context->MaxActiveSources = 0;
1833 context->ActiveEffectSlotCount = 0;
1834 free(context->ActiveEffectSlots);
1835 context->ActiveEffectSlots = NULL;
1836 context->MaxActiveEffectSlots = 0;
1838 ALCdevice_DecRef(context->Device);
1839 context->Device = NULL;
1841 //Invalidate context
1842 memset(context, 0, sizeof(ALCcontext));
1843 free(context);
1846 /* ReleaseContext
1848 * Removes the context reference from the given device and removes it from
1849 * being current on the running thread or globally.
1851 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
1853 ALCcontext *volatile*tmp_ctx;
1855 if(pthread_getspecific(LocalContext) == context)
1857 WARN("%p released while current on thread\n", context);
1858 pthread_setspecific(LocalContext, NULL);
1859 ALCcontext_DecRef(context);
1862 if(CompExchangePtr((XchgPtr*)&GlobalContext, context, NULL))
1863 ALCcontext_DecRef(context);
1865 LockDevice(device);
1866 tmp_ctx = &device->ContextList;
1867 while(*tmp_ctx)
1869 if(CompExchangePtr((XchgPtr*)tmp_ctx, context, context->next))
1870 break;
1871 tmp_ctx = &(*tmp_ctx)->next;
1873 UnlockDevice(device);
1875 ALCcontext_DecRef(context);
1878 void ALCcontext_IncRef(ALCcontext *context)
1880 RefCount ref;
1881 ref = IncrementRef(&context->ref);
1882 TRACEREF("%p increasing refcount to %u\n", context, ref);
1885 void ALCcontext_DecRef(ALCcontext *context)
1887 RefCount ref;
1888 ref = DecrementRef(&context->ref);
1889 TRACEREF("%p decreasing refcount to %u\n", context, ref);
1890 if(ref == 0) FreeContext(context);
1893 static void ReleaseThreadCtx(void *ptr)
1895 WARN("%p current for thread being destroyed\n", ptr);
1896 ALCcontext_DecRef(ptr);
1899 /* VerifyContext
1901 * Checks that the given context is valid, and increments its reference count.
1903 static ALCcontext *VerifyContext(ALCcontext *context)
1905 ALCdevice *dev;
1907 LockLists();
1908 dev = DeviceList;
1909 while(dev)
1911 ALCcontext *tmp_ctx = dev->ContextList;
1912 while(tmp_ctx)
1914 if(tmp_ctx == context)
1916 ALCcontext_IncRef(tmp_ctx);
1917 UnlockLists();
1918 return tmp_ctx;
1920 tmp_ctx = tmp_ctx->next;
1922 dev = dev->next;
1924 UnlockLists();
1926 return NULL;
1930 /* GetContextRef
1932 * Returns the currently active context for this thread, and adds a reference
1933 * without locking it.
1935 ALCcontext *GetContextRef(void)
1937 ALCcontext *context;
1939 context = pthread_getspecific(LocalContext);
1940 if(context)
1941 ALCcontext_IncRef(context);
1942 else
1944 LockLists();
1945 context = GlobalContext;
1946 if(context)
1947 ALCcontext_IncRef(context);
1948 UnlockLists();
1951 return context;
1955 /************************************************
1956 * Standard ALC functions
1957 ************************************************/
1959 /* alcGetError
1961 * Return last ALC generated error code for the given device
1963 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
1965 ALCenum errorCode;
1967 if(VerifyDevice(device))
1969 errorCode = ExchangeInt(&device->LastError, ALC_NO_ERROR);
1970 ALCdevice_DecRef(device);
1972 else
1973 errorCode = ExchangeInt(&LastNullDeviceError, ALC_NO_ERROR);
1975 return errorCode;
1979 /* alcSuspendContext
1981 * Not functional
1983 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *Context)
1985 (void)Context;
1988 /* alcProcessContext
1990 * Not functional
1992 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *Context)
1994 (void)Context;
1998 /* alcGetString
2000 * Returns information about the device, and error strings
2002 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2004 const ALCchar *value = NULL;
2006 switch(param)
2008 case ALC_NO_ERROR:
2009 value = alcNoError;
2010 break;
2012 case ALC_INVALID_ENUM:
2013 value = alcErrInvalidEnum;
2014 break;
2016 case ALC_INVALID_VALUE:
2017 value = alcErrInvalidValue;
2018 break;
2020 case ALC_INVALID_DEVICE:
2021 value = alcErrInvalidDevice;
2022 break;
2024 case ALC_INVALID_CONTEXT:
2025 value = alcErrInvalidContext;
2026 break;
2028 case ALC_OUT_OF_MEMORY:
2029 value = alcErrOutOfMemory;
2030 break;
2032 case ALC_DEVICE_SPECIFIER:
2033 value = alcDefaultName;
2034 break;
2036 case ALC_ALL_DEVICES_SPECIFIER:
2037 if(VerifyDevice(Device))
2039 value = Device->DeviceName;
2040 ALCdevice_DecRef(Device);
2042 else
2044 ProbeAllDevicesList();
2045 value = alcAllDevicesList;
2047 break;
2049 case ALC_CAPTURE_DEVICE_SPECIFIER:
2050 if(VerifyDevice(Device))
2052 value = Device->DeviceName;
2053 ALCdevice_DecRef(Device);
2055 else
2057 ProbeCaptureDeviceList();
2058 value = alcCaptureDeviceList;
2060 break;
2062 /* Default devices are always first in the list */
2063 case ALC_DEFAULT_DEVICE_SPECIFIER:
2064 value = alcDefaultName;
2065 break;
2067 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2068 if(!alcAllDevicesList)
2069 ProbeAllDevicesList();
2071 Device = VerifyDevice(Device);
2073 free(alcDefaultAllDevicesSpecifier);
2074 alcDefaultAllDevicesSpecifier = strdup(alcAllDevicesList ?
2075 alcAllDevicesList : "");
2076 if(!alcDefaultAllDevicesSpecifier)
2077 alcSetError(Device, ALC_OUT_OF_MEMORY);
2079 value = alcDefaultAllDevicesSpecifier;
2080 if(Device) ALCdevice_DecRef(Device);
2081 break;
2083 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2084 if(!alcCaptureDeviceList)
2085 ProbeCaptureDeviceList();
2087 Device = VerifyDevice(Device);
2089 free(alcCaptureDefaultDeviceSpecifier);
2090 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
2091 alcCaptureDeviceList : "");
2092 if(!alcCaptureDefaultDeviceSpecifier)
2093 alcSetError(Device, ALC_OUT_OF_MEMORY);
2095 value = alcCaptureDefaultDeviceSpecifier;
2096 if(Device) ALCdevice_DecRef(Device);
2097 break;
2099 case ALC_EXTENSIONS:
2100 if(!VerifyDevice(Device))
2101 value = alcNoDeviceExtList;
2102 else
2104 value = alcExtensionList;
2105 ALCdevice_DecRef(Device);
2107 break;
2109 default:
2110 Device = VerifyDevice(Device);
2111 alcSetError(Device, ALC_INVALID_ENUM);
2112 if(Device) ALCdevice_DecRef(Device);
2113 break;
2116 return value;
2120 /* alcGetIntegerv
2122 * Returns information about the device and the version of OpenAL
2124 ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
2126 device = VerifyDevice(device);
2128 if(size == 0 || data == NULL)
2130 alcSetError(device, ALC_INVALID_VALUE);
2131 if(device) ALCdevice_DecRef(device);
2132 return;
2135 if(!device)
2137 switch(param)
2139 case ALC_MAJOR_VERSION:
2140 *data = alcMajorVersion;
2141 break;
2142 case ALC_MINOR_VERSION:
2143 *data = alcMinorVersion;
2144 break;
2146 case ALC_ATTRIBUTES_SIZE:
2147 case ALC_ALL_ATTRIBUTES:
2148 case ALC_FREQUENCY:
2149 case ALC_REFRESH:
2150 case ALC_SYNC:
2151 case ALC_MONO_SOURCES:
2152 case ALC_STEREO_SOURCES:
2153 case ALC_CAPTURE_SAMPLES:
2154 case ALC_FORMAT_CHANNELS_SOFT:
2155 case ALC_FORMAT_TYPE_SOFT:
2156 alcSetError(NULL, ALC_INVALID_DEVICE);
2157 break;
2159 default:
2160 alcSetError(NULL, ALC_INVALID_ENUM);
2161 break;
2164 else if(device->Type == Capture)
2166 switch(param)
2168 case ALC_CAPTURE_SAMPLES:
2169 LockLists();
2170 /* Re-validate the device since it may have been closed */
2171 ALCdevice_DecRef(device);
2172 if((device=VerifyDevice(device)) != NULL)
2173 *data = ALCdevice_AvailableSamples(device);
2174 else
2175 alcSetError(NULL, ALC_INVALID_DEVICE);
2176 UnlockLists();
2177 break;
2179 case ALC_CONNECTED:
2180 *data = device->Connected;
2181 break;
2183 default:
2184 alcSetError(device, ALC_INVALID_ENUM);
2185 break;
2188 else /* render device */
2190 switch(param)
2192 case ALC_MAJOR_VERSION:
2193 *data = alcMajorVersion;
2194 break;
2196 case ALC_MINOR_VERSION:
2197 *data = alcMinorVersion;
2198 break;
2200 case ALC_EFX_MAJOR_VERSION:
2201 *data = alcEFXMajorVersion;
2202 break;
2204 case ALC_EFX_MINOR_VERSION:
2205 *data = alcEFXMinorVersion;
2206 break;
2208 case ALC_ATTRIBUTES_SIZE:
2209 *data = 13;
2210 break;
2212 case ALC_ALL_ATTRIBUTES:
2213 if(size < 13)
2214 alcSetError(device, ALC_INVALID_VALUE);
2215 else
2217 int i = 0;
2219 data[i++] = ALC_FREQUENCY;
2220 data[i++] = device->Frequency;
2222 if(device->Type != Loopback)
2224 data[i++] = ALC_REFRESH;
2225 data[i++] = device->Frequency / device->UpdateSize;
2227 data[i++] = ALC_SYNC;
2228 data[i++] = ALC_FALSE;
2230 else
2232 data[i++] = ALC_FORMAT_CHANNELS_SOFT;
2233 data[i++] = device->FmtChans;
2235 data[i++] = ALC_FORMAT_TYPE_SOFT;
2236 data[i++] = device->FmtType;
2239 data[i++] = ALC_MONO_SOURCES;
2240 data[i++] = device->NumMonoSources;
2242 data[i++] = ALC_STEREO_SOURCES;
2243 data[i++] = device->NumStereoSources;
2245 data[i++] = ALC_MAX_AUXILIARY_SENDS;
2246 data[i++] = device->NumAuxSends;
2248 data[i++] = 0;
2250 break;
2252 case ALC_FREQUENCY:
2253 *data = device->Frequency;
2254 break;
2256 case ALC_REFRESH:
2257 if(device->Type == Loopback)
2258 alcSetError(device, ALC_INVALID_DEVICE);
2259 else
2260 *data = device->Frequency / device->UpdateSize;
2261 break;
2263 case ALC_SYNC:
2264 if(device->Type == Loopback)
2265 alcSetError(device, ALC_INVALID_DEVICE);
2266 else
2267 *data = ALC_FALSE;
2268 break;
2270 case ALC_FORMAT_CHANNELS_SOFT:
2271 if(device->Type != Loopback)
2272 alcSetError(device, ALC_INVALID_DEVICE);
2273 else
2274 *data = device->FmtChans;
2275 break;
2277 case ALC_FORMAT_TYPE_SOFT:
2278 if(device->Type != Loopback)
2279 alcSetError(device, ALC_INVALID_DEVICE);
2280 else
2281 *data = device->FmtType;
2282 break;
2284 case ALC_MONO_SOURCES:
2285 *data = device->NumMonoSources;
2286 break;
2288 case ALC_STEREO_SOURCES:
2289 *data = device->NumStereoSources;
2290 break;
2292 case ALC_MAX_AUXILIARY_SENDS:
2293 *data = device->NumAuxSends;
2294 break;
2296 case ALC_CONNECTED:
2297 *data = device->Connected;
2298 break;
2300 default:
2301 alcSetError(device, ALC_INVALID_ENUM);
2302 break;
2305 if(device)
2306 ALCdevice_DecRef(device);
2310 /* alcIsExtensionPresent
2312 * Determines if there is support for a particular extension
2314 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2316 ALCboolean bResult = ALC_FALSE;
2318 device = VerifyDevice(device);
2320 if(!extName)
2321 alcSetError(device, ALC_INVALID_VALUE);
2322 else
2324 size_t len = strlen(extName);
2325 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2326 while(ptr && *ptr)
2328 if(strncasecmp(ptr, extName, len) == 0 &&
2329 (ptr[len] == '\0' || isspace(ptr[len])))
2331 bResult = ALC_TRUE;
2332 break;
2334 if((ptr=strchr(ptr, ' ')) != NULL)
2336 do {
2337 ++ptr;
2338 } while(isspace(*ptr));
2342 if(device)
2343 ALCdevice_DecRef(device);
2344 return bResult;
2348 /* alcGetProcAddress
2350 * Retrieves the function address for a particular extension function
2352 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2354 ALCvoid *ptr = NULL;
2356 if(!funcName)
2358 device = VerifyDevice(device);
2359 alcSetError(device, ALC_INVALID_VALUE);
2360 if(device) ALCdevice_DecRef(device);
2362 else
2364 ALsizei i = 0;
2365 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2366 i++;
2367 ptr = alcFunctions[i].address;
2370 return ptr;
2374 /* alcGetEnumValue
2376 * Get the value for a particular ALC enumeration name
2378 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2380 ALCenum val = 0;
2382 if(!enumName)
2384 device = VerifyDevice(device);
2385 alcSetError(device, ALC_INVALID_VALUE);
2386 if(device) ALCdevice_DecRef(device);
2388 else
2390 ALsizei i = 0;
2391 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2392 i++;
2393 val = enumeration[i].value;
2396 return val;
2400 /* alcCreateContext
2402 * Create and attach a context to the given device.
2404 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2406 ALCcontext *ALContext;
2407 ALCenum err;
2409 LockLists();
2410 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2412 UnlockLists();
2413 alcSetError(device, ALC_INVALID_DEVICE);
2414 if(device) ALCdevice_DecRef(device);
2415 return NULL;
2418 device->LastError = ALC_NO_ERROR;
2420 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2422 UnlockLists();
2423 alcSetError(device, err);
2424 if(err == ALC_INVALID_DEVICE)
2425 aluHandleDisconnect(device);
2426 ALCdevice_DecRef(device);
2427 return NULL;
2430 ALContext = calloc(1, sizeof(ALCcontext));
2431 if(ALContext)
2433 ALContext->ref = 1;
2435 ALContext->MaxActiveSources = 256;
2436 ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) *
2437 ALContext->MaxActiveSources);
2439 if(!ALContext || !ALContext->ActiveSources)
2441 if(!device->ContextList)
2443 ALCdevice_StopPlayback(device);
2444 device->Flags &= ~DEVICE_RUNNING;
2446 UnlockLists();
2448 free(ALContext);
2449 ALContext = NULL;
2451 alcSetError(device, ALC_OUT_OF_MEMORY);
2452 ALCdevice_DecRef(device);
2453 return NULL;
2456 ALContext->Device = device;
2457 ALCdevice_IncRef(device);
2458 InitContext(ALContext);
2460 do {
2461 ALContext->next = device->ContextList;
2462 } while(!CompExchangePtr((XchgPtr*)&device->ContextList, ALContext->next, ALContext));
2463 UnlockLists();
2465 ALCdevice_DecRef(device);
2467 TRACE("Created context %p\n", ALContext);
2468 return ALContext;
2471 /* alcDestroyContext
2473 * Remove a context from its device
2475 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
2477 ALCdevice *Device;
2479 LockLists();
2480 /* alcGetContextsDevice sets an error for invalid contexts */
2481 Device = alcGetContextsDevice(context);
2482 if(Device)
2484 ReleaseContext(context, Device);
2485 if(!Device->ContextList)
2487 ALCdevice_StopPlayback(Device);
2488 Device->Flags &= ~DEVICE_RUNNING;
2491 UnlockLists();
2495 /* alcGetCurrentContext
2497 * Returns the currently active context on the calling thread
2499 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
2501 ALCcontext *Context;
2503 Context = pthread_getspecific(LocalContext);
2504 if(!Context) Context = GlobalContext;
2506 return Context;
2509 /* alcGetThreadContext
2511 * Returns the currently active thread-local context
2513 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2515 ALCcontext *Context;
2516 Context = pthread_getspecific(LocalContext);
2517 return Context;
2521 /* alcMakeContextCurrent
2523 * Makes the given context the active process-wide context, and removes the
2524 * thread-local context for the calling thread.
2526 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2528 /* context must be valid or NULL */
2529 if(context && !(context=VerifyContext(context)))
2531 alcSetError(NULL, ALC_INVALID_CONTEXT);
2532 return ALC_FALSE;
2534 /* context's reference count is already incremented */
2535 context = ExchangePtr((XchgPtr*)&GlobalContext, context);
2536 if(context) ALCcontext_DecRef(context);
2538 if((context=pthread_getspecific(LocalContext)) != NULL)
2540 pthread_setspecific(LocalContext, NULL);
2541 ALCcontext_DecRef(context);
2544 return ALC_TRUE;
2547 /* alcSetThreadContext
2549 * Makes the given context the active context for the current thread
2551 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
2553 ALCcontext *old;
2555 /* context must be valid or NULL */
2556 if(context && !(context=VerifyContext(context)))
2558 alcSetError(NULL, ALC_INVALID_CONTEXT);
2559 return ALC_FALSE;
2561 /* context's reference count is already incremented */
2562 old = pthread_getspecific(LocalContext);
2563 pthread_setspecific(LocalContext, context);
2564 if(old) ALCcontext_DecRef(old);
2566 return ALC_TRUE;
2570 /* alcGetContextsDevice
2572 * Returns the device that a particular context is attached to
2574 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
2576 ALCdevice *Device;
2578 if(!(Context=VerifyContext(Context)))
2580 alcSetError(NULL, ALC_INVALID_CONTEXT);
2581 return NULL;
2583 Device = Context->Device;
2584 ALCcontext_DecRef(Context);
2586 return Device;
2590 /* alcOpenDevice
2592 * Opens the named device.
2594 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
2596 const ALCchar *fmt;
2597 ALCdevice *device;
2598 ALCenum err;
2600 DO_INITCONFIG();
2602 if(!PlaybackBackend.name)
2604 alcSetError(NULL, ALC_INVALID_VALUE);
2605 return NULL;
2608 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2609 deviceName = NULL;
2611 device = calloc(1, sizeof(ALCdevice)+sizeof(ALeffectslot));
2612 if(!device)
2614 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2615 return NULL;
2618 //Validate device
2619 device->Funcs = &PlaybackBackend.Funcs;
2620 device->ref = 1;
2621 device->Connected = ALC_TRUE;
2622 device->Type = Playback;
2623 InitializeCriticalSection(&device->Mutex);
2624 device->LastError = ALC_NO_ERROR;
2626 device->Flags = 0;
2627 device->Bs2b = NULL;
2628 device->Bs2bLevel = 0;
2629 device->DeviceName = NULL;
2631 device->ContextList = NULL;
2633 device->MaxNoOfSources = 256;
2634 device->AuxiliaryEffectSlotMax = 4;
2635 device->NumAuxSends = MAX_SENDS;
2637 InitUIntMap(&device->BufferMap, ~0);
2638 InitUIntMap(&device->EffectMap, ~0);
2639 InitUIntMap(&device->FilterMap, ~0);
2641 //Set output format
2642 device->FmtChans = DevFmtChannelsDefault;
2643 device->FmtType = DevFmtTypeDefault;
2644 device->Frequency = DEFAULT_OUTPUT_RATE;
2645 device->NumUpdates = 4;
2646 device->UpdateSize = 1024;
2648 if(ConfigValueStr(NULL, "channels", &fmt))
2650 static const struct {
2651 const char name[16];
2652 enum DevFmtChannels chans;
2653 } chanlist[] = {
2654 { "mono", DevFmtMono },
2655 { "stereo", DevFmtStereo },
2656 { "quad", DevFmtQuad },
2657 { "surround51", DevFmtX51 },
2658 { "surround61", DevFmtX61 },
2659 { "surround71", DevFmtX71 },
2661 size_t i;
2663 for(i = 0;i < COUNTOF(chanlist);i++)
2665 if(strcasecmp(chanlist[i].name, fmt) == 0)
2667 device->FmtChans = chanlist[i].chans;
2668 device->Flags |= DEVICE_CHANNELS_REQUEST;
2669 break;
2672 if(i == COUNTOF(chanlist))
2673 ERR("Unsupported channels: %s\n", fmt);
2675 if(ConfigValueStr(NULL, "sample-type", &fmt))
2677 static const struct {
2678 const char name[16];
2679 enum DevFmtType type;
2680 } typelist[] = {
2681 { "int8", DevFmtByte },
2682 { "uint8", DevFmtUByte },
2683 { "int16", DevFmtShort },
2684 { "uint16", DevFmtUShort },
2685 { "int32", DevFmtInt },
2686 { "uint32", DevFmtUInt },
2687 { "float32", DevFmtFloat },
2689 size_t i;
2691 for(i = 0;i < COUNTOF(typelist);i++)
2693 if(strcasecmp(typelist[i].name, fmt) == 0)
2695 device->FmtType = typelist[i].type;
2696 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
2697 break;
2700 if(i == COUNTOF(typelist))
2701 ERR("Unsupported sample-type: %s\n", fmt);
2703 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
2704 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
2705 ConfigValueStr(NULL, "format", &fmt))
2707 static const struct {
2708 const char name[32];
2709 enum DevFmtChannels channels;
2710 enum DevFmtType type;
2711 } formats[] = {
2712 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
2713 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
2714 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
2715 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
2716 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
2717 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
2719 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
2720 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
2721 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
2722 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
2723 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
2724 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
2726 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
2727 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
2728 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
2729 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
2730 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
2731 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
2733 size_t i;
2735 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
2736 for(i = 0;i < COUNTOF(formats);i++)
2738 if(strcasecmp(fmt, formats[i].name) == 0)
2740 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
2741 device->FmtChans = formats[i].channels;
2742 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2743 device->FmtType = formats[i].type;
2744 device->Flags |= DEVICE_FORMAT_REQUEST;
2745 break;
2748 if(i == COUNTOF(formats))
2749 ERR("Unsupported format: %s\n", fmt);
2751 #undef DEVICE_FORMAT_REQUEST
2753 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
2755 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2756 if(device->Frequency < MIN_OUTPUT_RATE)
2757 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
2758 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
2761 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
2762 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
2764 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
2765 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
2767 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
2768 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
2770 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
2771 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
2773 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
2774 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
2776 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
2778 device->NumStereoSources = 1;
2779 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
2781 // Find a playback device to open
2782 LockLists();
2783 if((err=ALCdevice_OpenPlayback(device, deviceName)) != ALC_NO_ERROR)
2785 UnlockLists();
2786 DeleteCriticalSection(&device->Mutex);
2787 free(device);
2788 alcSetError(NULL, err);
2789 return NULL;
2791 UnlockLists();
2793 if(DefaultEffect.type != AL_EFFECT_NULL)
2795 device->DefaultSlot = (ALeffectslot*)(device+1);
2796 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
2798 device->DefaultSlot = NULL;
2799 ERR("Failed to initialize the default effect slot\n");
2801 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
2803 ALeffectState_Destroy(device->DefaultSlot->EffectState);
2804 device->DefaultSlot = NULL;
2805 ERR("Failed to initialize the default effect\n");
2809 do {
2810 device->next = DeviceList;
2811 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2813 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName);
2814 return device;
2817 /* alcCloseDevice
2819 * Closes the given device.
2821 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device)
2823 ALCdevice *volatile*list;
2824 ALCcontext *ctx;
2826 LockLists();
2827 list = &DeviceList;
2828 while(*list && *list != Device)
2829 list = &(*list)->next;
2831 if(!*list || (*list)->Type == Capture)
2833 alcSetError(*list, ALC_INVALID_DEVICE);
2834 UnlockLists();
2835 return ALC_FALSE;
2838 *list = (*list)->next;
2839 UnlockLists();
2841 while((ctx=Device->ContextList) != NULL)
2843 WARN("Releasing context %p\n", ctx);
2844 ReleaseContext(ctx, Device);
2846 if((Device->Flags&DEVICE_RUNNING))
2847 ALCdevice_StopPlayback(Device);
2848 Device->Flags &= ~DEVICE_RUNNING;
2850 ALCdevice_ClosePlayback(Device);
2852 ALCdevice_DecRef(Device);
2854 return ALC_TRUE;
2858 /************************************************
2859 * ALC capture functions
2860 ************************************************/
2861 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
2863 ALCdevice *device = NULL;
2864 ALCenum err;
2866 DO_INITCONFIG();
2868 if(!CaptureBackend.name)
2870 alcSetError(NULL, ALC_INVALID_VALUE);
2871 return NULL;
2874 if(samples <= 0)
2876 alcSetError(NULL, ALC_INVALID_VALUE);
2877 return NULL;
2880 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2881 deviceName = NULL;
2883 device = calloc(1, sizeof(ALCdevice));
2884 if(!device)
2886 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2887 return NULL;
2890 //Validate device
2891 device->Funcs = &CaptureBackend.Funcs;
2892 device->ref = 1;
2893 device->Connected = ALC_TRUE;
2894 device->Type = Capture;
2895 InitializeCriticalSection(&device->Mutex);
2897 InitUIntMap(&device->BufferMap, ~0);
2898 InitUIntMap(&device->EffectMap, ~0);
2899 InitUIntMap(&device->FilterMap, ~0);
2901 device->DeviceName = NULL;
2903 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2904 device->Frequency = frequency;
2906 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
2907 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
2909 DeleteCriticalSection(&device->Mutex);
2910 free(device);
2911 alcSetError(NULL, ALC_INVALID_ENUM);
2912 return NULL;
2915 device->UpdateSize = samples;
2916 device->NumUpdates = 1;
2918 LockLists();
2919 if((err=ALCdevice_OpenCapture(device, deviceName)) != ALC_NO_ERROR)
2921 UnlockLists();
2922 DeleteCriticalSection(&device->Mutex);
2923 free(device);
2924 alcSetError(NULL, err);
2925 return NULL;
2927 UnlockLists();
2929 do {
2930 device->next = DeviceList;
2931 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2933 TRACE("Created device %p\n", device);
2934 return device;
2937 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *Device)
2939 ALCdevice *volatile*list;
2941 LockLists();
2942 list = &DeviceList;
2943 while(*list && *list != Device)
2944 list = &(*list)->next;
2946 if(!*list || (*list)->Type != Capture)
2948 alcSetError(*list, ALC_INVALID_DEVICE);
2949 UnlockLists();
2950 return ALC_FALSE;
2953 *list = (*list)->next;
2954 UnlockLists();
2956 ALCdevice_CloseCapture(Device);
2958 ALCdevice_DecRef(Device);
2960 return ALC_TRUE;
2963 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
2965 LockLists();
2966 if(!(device=VerifyDevice(device)) || device->Type != Capture)
2968 UnlockLists();
2969 alcSetError(device, ALC_INVALID_DEVICE);
2970 if(device) ALCdevice_DecRef(device);
2971 return;
2973 if(device->Connected)
2975 if(!(device->Flags&DEVICE_RUNNING))
2976 ALCdevice_StartCapture(device);
2977 device->Flags |= DEVICE_RUNNING;
2979 UnlockLists();
2981 ALCdevice_DecRef(device);
2984 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
2986 LockLists();
2987 if(!(device=VerifyDevice(device)) || device->Type != Capture)
2989 UnlockLists();
2990 alcSetError(device, ALC_INVALID_DEVICE);
2991 if(device) ALCdevice_DecRef(device);
2992 return;
2994 if((device->Flags&DEVICE_RUNNING))
2995 ALCdevice_StopCapture(device);
2996 device->Flags &= ~DEVICE_RUNNING;
2997 UnlockLists();
2999 ALCdevice_DecRef(device);
3002 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3004 ALCenum err = ALC_INVALID_DEVICE;
3005 LockLists();
3006 if((device=VerifyDevice(device)) != NULL && device->Type == Capture)
3008 err = ALC_INVALID_VALUE;
3009 if(samples >= 0 && ALCdevice_AvailableSamples(device) >= (ALCuint)samples)
3010 err = ALCdevice_CaptureSamples(device, buffer, samples);
3012 UnlockLists();
3013 if(err != ALC_NO_ERROR)
3014 alcSetError(device, err);
3015 if(device) ALCdevice_DecRef(device);
3019 /************************************************
3020 * ALC loopback functions
3021 ************************************************/
3023 /* alcLoopbackOpenDeviceSOFT
3025 * Open a loopback device, for manual rendering.
3027 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3029 ALCdevice *device;
3031 DO_INITCONFIG();
3033 /* Make sure the device name, if specified, is us. */
3034 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3036 alcSetError(NULL, ALC_INVALID_VALUE);
3037 return NULL;
3040 device = calloc(1, sizeof(ALCdevice));
3041 if(!device)
3043 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3044 return NULL;
3047 //Validate device
3048 device->Funcs = &BackendLoopback.Funcs;
3049 device->ref = 1;
3050 device->Connected = ALC_TRUE;
3051 device->Type = Loopback;
3052 InitializeCriticalSection(&device->Mutex);
3053 device->LastError = ALC_NO_ERROR;
3055 device->Flags = 0;
3056 device->Bs2b = NULL;
3057 device->Bs2bLevel = 0;
3058 device->DeviceName = NULL;
3060 device->ContextList = NULL;
3062 device->MaxNoOfSources = 256;
3063 device->AuxiliaryEffectSlotMax = 4;
3064 device->NumAuxSends = MAX_SENDS;
3066 InitUIntMap(&device->BufferMap, ~0);
3067 InitUIntMap(&device->EffectMap, ~0);
3068 InitUIntMap(&device->FilterMap, ~0);
3070 //Set output format
3071 device->NumUpdates = 0;
3072 device->UpdateSize = 0;
3074 device->Frequency = DEFAULT_OUTPUT_RATE;
3075 device->FmtChans = DevFmtChannelsDefault;
3076 device->FmtType = DevFmtTypeDefault;
3078 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3079 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3081 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3082 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3084 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3085 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3087 device->NumStereoSources = 1;
3088 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3090 // Open the "backend"
3091 ALCdevice_OpenPlayback(device, "Loopback");
3092 do {
3093 device->next = DeviceList;
3094 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
3096 TRACE("Created device %p\n", device);
3097 return device;
3100 /* alcIsRenderFormatSupportedSOFT
3102 * Determines if the loopback device supports the given format for rendering.
3104 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3106 ALCboolean ret = ALC_FALSE;
3108 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3109 alcSetError(device, ALC_INVALID_DEVICE);
3110 else if(freq <= 0)
3111 alcSetError(device, ALC_INVALID_VALUE);
3112 else
3114 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3115 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3116 freq >= MIN_OUTPUT_RATE)
3117 ret = ALC_TRUE;
3119 if(device) ALCdevice_DecRef(device);
3121 return ret;
3124 /* alcRenderSamplesSOFT
3126 * Renders some samples into a buffer, using the format last set by the
3127 * attributes given to alcCreateContext.
3129 ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3131 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3132 alcSetError(device, ALC_INVALID_DEVICE);
3133 else if(samples < 0 || (samples > 0 && buffer == NULL))
3134 alcSetError(device, ALC_INVALID_VALUE);
3135 else
3136 aluMixData(device, buffer, samples);
3137 if(device) ALCdevice_DecRef(device);