Fix EFX_REVERB_PRESET_DRIVING_COMMENTATOR
[openal-soft.git] / Alc / ALc.c
blob6fc1d83ed92dd85e9019397777cf95e1fc29af3a
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 "alMidi.h"
39 #include "bs2b.h"
40 #include "alu.h"
42 #include "compat.h"
43 #include "threads.h"
44 #include "alstring.h"
46 #include "backends/base.h"
47 #include "midi/base.h"
50 /************************************************
51 * Backends
52 ************************************************/
53 struct BackendInfo {
54 const char *name;
55 ALCbackendFactory* (*getFactory)(void);
56 ALCboolean (*Init)(BackendFuncs*);
57 void (*Deinit)(void);
58 void (*Probe)(enum DevProbe);
59 BackendFuncs Funcs;
62 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
63 static struct BackendInfo BackendList[] = {
64 #ifdef HAVE_JACK
65 { "jack", ALCjackBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
66 #endif
67 #ifdef HAVE_PULSEAUDIO
68 { "pulse", ALCpulseBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
69 #endif
70 #ifdef HAVE_ALSA
71 { "alsa", ALCalsaBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
72 #endif
73 #ifdef HAVE_COREAUDIO
74 { "core", NULL, alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
75 #endif
76 #ifdef HAVE_OSS
77 { "oss", ALCossBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
78 #endif
79 #ifdef HAVE_SOLARIS
80 { "solaris", NULL, alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs },
81 #endif
82 #ifdef HAVE_SNDIO
83 { "sndio", NULL, alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs },
84 #endif
85 #ifdef HAVE_QSA
86 { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs },
87 #endif
88 #ifdef HAVE_MMDEVAPI
89 { "mmdevapi", ALCmmdevBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
90 #endif
91 #ifdef HAVE_DSOUND
92 { "dsound", ALCdsoundBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
93 #endif
94 #ifdef HAVE_WINMM
95 { "winmm", ALCwinmmBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
96 #endif
97 #ifdef HAVE_PORTAUDIO
98 { "port", NULL, alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
99 #endif
100 #ifdef HAVE_OPENSL
101 { "opensl", NULL, alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs },
102 #endif
104 { "null", ALCnullBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
105 #ifdef HAVE_WAVE
106 { "wave", ALCwaveBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
107 #endif
109 { NULL, NULL, NULL, NULL, NULL, EmptyFuncs }
111 #undef EmptyFuncs
113 static struct BackendInfo PlaybackBackend;
114 static struct BackendInfo CaptureBackend;
117 /************************************************
118 * Functions, enums, and errors
119 ************************************************/
120 typedef struct ALCfunction {
121 const ALCchar *funcName;
122 ALCvoid *address;
123 } ALCfunction;
125 typedef struct ALCenums {
126 const ALCchar *enumName;
127 ALCenum value;
128 } ALCenums;
130 #define DECL(x) { #x, (ALCvoid*)(x) }
131 static const ALCfunction alcFunctions[] = {
132 DECL(alcCreateContext),
133 DECL(alcMakeContextCurrent),
134 DECL(alcProcessContext),
135 DECL(alcSuspendContext),
136 DECL(alcDestroyContext),
137 DECL(alcGetCurrentContext),
138 DECL(alcGetContextsDevice),
139 DECL(alcOpenDevice),
140 DECL(alcCloseDevice),
141 DECL(alcGetError),
142 DECL(alcIsExtensionPresent),
143 DECL(alcGetProcAddress),
144 DECL(alcGetEnumValue),
145 DECL(alcGetString),
146 DECL(alcGetIntegerv),
147 DECL(alcCaptureOpenDevice),
148 DECL(alcCaptureCloseDevice),
149 DECL(alcCaptureStart),
150 DECL(alcCaptureStop),
151 DECL(alcCaptureSamples),
153 DECL(alcSetThreadContext),
154 DECL(alcGetThreadContext),
156 DECL(alcLoopbackOpenDeviceSOFT),
157 DECL(alcIsRenderFormatSupportedSOFT),
158 DECL(alcRenderSamplesSOFT),
160 DECL(alcDevicePauseSOFT),
161 DECL(alcDeviceResumeSOFT),
163 DECL(alcGetInteger64vSOFT),
165 DECL(alEnable),
166 DECL(alDisable),
167 DECL(alIsEnabled),
168 DECL(alGetString),
169 DECL(alGetBooleanv),
170 DECL(alGetIntegerv),
171 DECL(alGetFloatv),
172 DECL(alGetDoublev),
173 DECL(alGetBoolean),
174 DECL(alGetInteger),
175 DECL(alGetFloat),
176 DECL(alGetDouble),
177 DECL(alGetError),
178 DECL(alIsExtensionPresent),
179 DECL(alGetProcAddress),
180 DECL(alGetEnumValue),
181 DECL(alListenerf),
182 DECL(alListener3f),
183 DECL(alListenerfv),
184 DECL(alListeneri),
185 DECL(alListener3i),
186 DECL(alListeneriv),
187 DECL(alGetListenerf),
188 DECL(alGetListener3f),
189 DECL(alGetListenerfv),
190 DECL(alGetListeneri),
191 DECL(alGetListener3i),
192 DECL(alGetListeneriv),
193 DECL(alGenSources),
194 DECL(alDeleteSources),
195 DECL(alIsSource),
196 DECL(alSourcef),
197 DECL(alSource3f),
198 DECL(alSourcefv),
199 DECL(alSourcei),
200 DECL(alSource3i),
201 DECL(alSourceiv),
202 DECL(alGetSourcef),
203 DECL(alGetSource3f),
204 DECL(alGetSourcefv),
205 DECL(alGetSourcei),
206 DECL(alGetSource3i),
207 DECL(alGetSourceiv),
208 DECL(alSourcePlayv),
209 DECL(alSourceStopv),
210 DECL(alSourceRewindv),
211 DECL(alSourcePausev),
212 DECL(alSourcePlay),
213 DECL(alSourceStop),
214 DECL(alSourceRewind),
215 DECL(alSourcePause),
216 DECL(alSourceQueueBuffers),
217 DECL(alSourceUnqueueBuffers),
218 DECL(alGenBuffers),
219 DECL(alDeleteBuffers),
220 DECL(alIsBuffer),
221 DECL(alBufferData),
222 DECL(alBufferf),
223 DECL(alBuffer3f),
224 DECL(alBufferfv),
225 DECL(alBufferi),
226 DECL(alBuffer3i),
227 DECL(alBufferiv),
228 DECL(alGetBufferf),
229 DECL(alGetBuffer3f),
230 DECL(alGetBufferfv),
231 DECL(alGetBufferi),
232 DECL(alGetBuffer3i),
233 DECL(alGetBufferiv),
234 DECL(alDopplerFactor),
235 DECL(alDopplerVelocity),
236 DECL(alSpeedOfSound),
237 DECL(alDistanceModel),
239 DECL(alGenFilters),
240 DECL(alDeleteFilters),
241 DECL(alIsFilter),
242 DECL(alFilteri),
243 DECL(alFilteriv),
244 DECL(alFilterf),
245 DECL(alFilterfv),
246 DECL(alGetFilteri),
247 DECL(alGetFilteriv),
248 DECL(alGetFilterf),
249 DECL(alGetFilterfv),
250 DECL(alGenEffects),
251 DECL(alDeleteEffects),
252 DECL(alIsEffect),
253 DECL(alEffecti),
254 DECL(alEffectiv),
255 DECL(alEffectf),
256 DECL(alEffectfv),
257 DECL(alGetEffecti),
258 DECL(alGetEffectiv),
259 DECL(alGetEffectf),
260 DECL(alGetEffectfv),
261 DECL(alGenAuxiliaryEffectSlots),
262 DECL(alDeleteAuxiliaryEffectSlots),
263 DECL(alIsAuxiliaryEffectSlot),
264 DECL(alAuxiliaryEffectSloti),
265 DECL(alAuxiliaryEffectSlotiv),
266 DECL(alAuxiliaryEffectSlotf),
267 DECL(alAuxiliaryEffectSlotfv),
268 DECL(alGetAuxiliaryEffectSloti),
269 DECL(alGetAuxiliaryEffectSlotiv),
270 DECL(alGetAuxiliaryEffectSlotf),
271 DECL(alGetAuxiliaryEffectSlotfv),
273 DECL(alBufferSubDataSOFT),
275 DECL(alBufferSamplesSOFT),
276 DECL(alBufferSubSamplesSOFT),
277 DECL(alGetBufferSamplesSOFT),
278 DECL(alIsBufferFormatSupportedSOFT),
280 DECL(alDeferUpdatesSOFT),
281 DECL(alProcessUpdatesSOFT),
283 DECL(alSourcedSOFT),
284 DECL(alSource3dSOFT),
285 DECL(alSourcedvSOFT),
286 DECL(alGetSourcedSOFT),
287 DECL(alGetSource3dSOFT),
288 DECL(alGetSourcedvSOFT),
289 DECL(alSourcei64SOFT),
290 DECL(alSource3i64SOFT),
291 DECL(alSourcei64vSOFT),
292 DECL(alGetSourcei64SOFT),
293 DECL(alGetSource3i64SOFT),
294 DECL(alGetSourcei64vSOFT),
296 DECL(alGenSoundfontsSOFT),
297 DECL(alDeleteSoundfontsSOFT),
298 DECL(alIsSoundfontSOFT),
299 DECL(alGetSoundfontivSOFT),
300 DECL(alSoundfontPresetsSOFT),
301 DECL(alGenPresetsSOFT),
302 DECL(alDeletePresetsSOFT),
303 DECL(alIsPresetSOFT),
304 DECL(alPresetiSOFT),
305 DECL(alPresetivSOFT),
306 DECL(alGetPresetivSOFT),
307 DECL(alPresetFontsoundsSOFT),
308 DECL(alGenFontsoundsSOFT),
309 DECL(alDeleteFontsoundsSOFT),
310 DECL(alIsFontsoundSOFT),
311 DECL(alFontsoundiSOFT),
312 DECL(alFontsound2iSOFT),
313 DECL(alFontsoundivSOFT),
314 DECL(alGetFontsoundivSOFT),
315 DECL(alFontsoundModulatoriSOFT),
316 DECL(alGetFontsoundModulatorivSOFT),
317 DECL(alMidiSoundfontSOFT),
318 DECL(alMidiSoundfontvSOFT),
319 DECL(alMidiEventSOFT),
320 DECL(alMidiSysExSOFT),
321 DECL(alMidiPlaySOFT),
322 DECL(alMidiPauseSOFT),
323 DECL(alMidiStopSOFT),
324 DECL(alMidiResetSOFT),
325 DECL(alMidiGainSOFT),
326 DECL(alGetInteger64SOFT),
327 DECL(alGetInteger64vSOFT),
328 DECL(alLoadSoundfontSOFT),
330 { NULL, NULL }
332 #undef DECL
334 #define DECL(x) { #x, (x) }
335 static const ALCenums enumeration[] = {
336 DECL(ALC_INVALID),
337 DECL(ALC_FALSE),
338 DECL(ALC_TRUE),
340 DECL(ALC_MAJOR_VERSION),
341 DECL(ALC_MINOR_VERSION),
342 DECL(ALC_ATTRIBUTES_SIZE),
343 DECL(ALC_ALL_ATTRIBUTES),
344 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
345 DECL(ALC_DEVICE_SPECIFIER),
346 DECL(ALC_ALL_DEVICES_SPECIFIER),
347 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
348 DECL(ALC_EXTENSIONS),
349 DECL(ALC_FREQUENCY),
350 DECL(ALC_REFRESH),
351 DECL(ALC_SYNC),
352 DECL(ALC_MONO_SOURCES),
353 DECL(ALC_STEREO_SOURCES),
354 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
355 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
356 DECL(ALC_CAPTURE_SAMPLES),
357 DECL(ALC_CONNECTED),
359 DECL(ALC_EFX_MAJOR_VERSION),
360 DECL(ALC_EFX_MINOR_VERSION),
361 DECL(ALC_MAX_AUXILIARY_SENDS),
363 DECL(ALC_FORMAT_CHANNELS_SOFT),
364 DECL(ALC_FORMAT_TYPE_SOFT),
366 DECL(ALC_MONO_SOFT),
367 DECL(ALC_STEREO_SOFT),
368 DECL(ALC_QUAD_SOFT),
369 DECL(ALC_5POINT1_SOFT),
370 DECL(ALC_6POINT1_SOFT),
371 DECL(ALC_7POINT1_SOFT),
373 DECL(ALC_BYTE_SOFT),
374 DECL(ALC_UNSIGNED_BYTE_SOFT),
375 DECL(ALC_SHORT_SOFT),
376 DECL(ALC_UNSIGNED_SHORT_SOFT),
377 DECL(ALC_INT_SOFT),
378 DECL(ALC_UNSIGNED_INT_SOFT),
379 DECL(ALC_FLOAT_SOFT),
381 DECL(ALC_NO_ERROR),
382 DECL(ALC_INVALID_DEVICE),
383 DECL(ALC_INVALID_CONTEXT),
384 DECL(ALC_INVALID_ENUM),
385 DECL(ALC_INVALID_VALUE),
386 DECL(ALC_OUT_OF_MEMORY),
389 DECL(AL_INVALID),
390 DECL(AL_NONE),
391 DECL(AL_FALSE),
392 DECL(AL_TRUE),
394 DECL(AL_SOURCE_RELATIVE),
395 DECL(AL_CONE_INNER_ANGLE),
396 DECL(AL_CONE_OUTER_ANGLE),
397 DECL(AL_PITCH),
398 DECL(AL_POSITION),
399 DECL(AL_DIRECTION),
400 DECL(AL_VELOCITY),
401 DECL(AL_LOOPING),
402 DECL(AL_BUFFER),
403 DECL(AL_GAIN),
404 DECL(AL_MIN_GAIN),
405 DECL(AL_MAX_GAIN),
406 DECL(AL_ORIENTATION),
407 DECL(AL_REFERENCE_DISTANCE),
408 DECL(AL_ROLLOFF_FACTOR),
409 DECL(AL_CONE_OUTER_GAIN),
410 DECL(AL_MAX_DISTANCE),
411 DECL(AL_SEC_OFFSET),
412 DECL(AL_SAMPLE_OFFSET),
413 DECL(AL_SAMPLE_RW_OFFSETS_SOFT),
414 DECL(AL_BYTE_OFFSET),
415 DECL(AL_BYTE_RW_OFFSETS_SOFT),
416 DECL(AL_SOURCE_TYPE),
417 DECL(AL_STATIC),
418 DECL(AL_STREAMING),
419 DECL(AL_UNDETERMINED),
420 DECL(AL_METERS_PER_UNIT),
421 DECL(AL_DIRECT_CHANNELS_SOFT),
423 DECL(AL_DIRECT_FILTER),
424 DECL(AL_AUXILIARY_SEND_FILTER),
425 DECL(AL_AIR_ABSORPTION_FACTOR),
426 DECL(AL_ROOM_ROLLOFF_FACTOR),
427 DECL(AL_CONE_OUTER_GAINHF),
428 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
429 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
430 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
432 DECL(AL_SOURCE_STATE),
433 DECL(AL_INITIAL),
434 DECL(AL_PLAYING),
435 DECL(AL_PAUSED),
436 DECL(AL_STOPPED),
438 DECL(AL_BUFFERS_QUEUED),
439 DECL(AL_BUFFERS_PROCESSED),
441 DECL(AL_FORMAT_MONO8),
442 DECL(AL_FORMAT_MONO16),
443 DECL(AL_FORMAT_MONO_FLOAT32),
444 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
445 DECL(AL_FORMAT_STEREO8),
446 DECL(AL_FORMAT_STEREO16),
447 DECL(AL_FORMAT_STEREO_FLOAT32),
448 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
449 DECL(AL_FORMAT_MONO_IMA4),
450 DECL(AL_FORMAT_STEREO_IMA4),
451 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
452 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
453 DECL(AL_FORMAT_QUAD8_LOKI),
454 DECL(AL_FORMAT_QUAD16_LOKI),
455 DECL(AL_FORMAT_QUAD8),
456 DECL(AL_FORMAT_QUAD16),
457 DECL(AL_FORMAT_QUAD32),
458 DECL(AL_FORMAT_51CHN8),
459 DECL(AL_FORMAT_51CHN16),
460 DECL(AL_FORMAT_51CHN32),
461 DECL(AL_FORMAT_61CHN8),
462 DECL(AL_FORMAT_61CHN16),
463 DECL(AL_FORMAT_61CHN32),
464 DECL(AL_FORMAT_71CHN8),
465 DECL(AL_FORMAT_71CHN16),
466 DECL(AL_FORMAT_71CHN32),
467 DECL(AL_FORMAT_REAR8),
468 DECL(AL_FORMAT_REAR16),
469 DECL(AL_FORMAT_REAR32),
470 DECL(AL_FORMAT_MONO_MULAW),
471 DECL(AL_FORMAT_MONO_MULAW_EXT),
472 DECL(AL_FORMAT_STEREO_MULAW),
473 DECL(AL_FORMAT_STEREO_MULAW_EXT),
474 DECL(AL_FORMAT_QUAD_MULAW),
475 DECL(AL_FORMAT_51CHN_MULAW),
476 DECL(AL_FORMAT_61CHN_MULAW),
477 DECL(AL_FORMAT_71CHN_MULAW),
478 DECL(AL_FORMAT_REAR_MULAW),
479 DECL(AL_FORMAT_MONO_ALAW_EXT),
480 DECL(AL_FORMAT_STEREO_ALAW_EXT),
482 DECL(AL_MONO8_SOFT),
483 DECL(AL_MONO16_SOFT),
484 DECL(AL_MONO32F_SOFT),
485 DECL(AL_STEREO8_SOFT),
486 DECL(AL_STEREO16_SOFT),
487 DECL(AL_STEREO32F_SOFT),
488 DECL(AL_QUAD8_SOFT),
489 DECL(AL_QUAD16_SOFT),
490 DECL(AL_QUAD32F_SOFT),
491 DECL(AL_REAR8_SOFT),
492 DECL(AL_REAR16_SOFT),
493 DECL(AL_REAR32F_SOFT),
494 DECL(AL_5POINT1_8_SOFT),
495 DECL(AL_5POINT1_16_SOFT),
496 DECL(AL_5POINT1_32F_SOFT),
497 DECL(AL_6POINT1_8_SOFT),
498 DECL(AL_6POINT1_16_SOFT),
499 DECL(AL_6POINT1_32F_SOFT),
500 DECL(AL_7POINT1_8_SOFT),
501 DECL(AL_7POINT1_16_SOFT),
502 DECL(AL_7POINT1_32F_SOFT),
503 DECL(AL_FORMAT_BFORMAT2D_8),
504 DECL(AL_FORMAT_BFORMAT2D_16),
505 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
506 DECL(AL_FORMAT_BFORMAT2D_MULAW),
507 DECL(AL_FORMAT_BFORMAT3D_8),
508 DECL(AL_FORMAT_BFORMAT3D_16),
509 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
510 DECL(AL_FORMAT_BFORMAT3D_MULAW),
512 DECL(AL_MONO_SOFT),
513 DECL(AL_STEREO_SOFT),
514 DECL(AL_QUAD_SOFT),
515 DECL(AL_REAR_SOFT),
516 DECL(AL_5POINT1_SOFT),
517 DECL(AL_6POINT1_SOFT),
518 DECL(AL_7POINT1_SOFT),
520 DECL(AL_BYTE_SOFT),
521 DECL(AL_UNSIGNED_BYTE_SOFT),
522 DECL(AL_SHORT_SOFT),
523 DECL(AL_UNSIGNED_SHORT_SOFT),
524 DECL(AL_INT_SOFT),
525 DECL(AL_UNSIGNED_INT_SOFT),
526 DECL(AL_FLOAT_SOFT),
527 DECL(AL_DOUBLE_SOFT),
528 DECL(AL_BYTE3_SOFT),
529 DECL(AL_UNSIGNED_BYTE3_SOFT),
531 DECL(AL_FREQUENCY),
532 DECL(AL_BITS),
533 DECL(AL_CHANNELS),
534 DECL(AL_SIZE),
535 DECL(AL_INTERNAL_FORMAT_SOFT),
536 DECL(AL_BYTE_LENGTH_SOFT),
537 DECL(AL_SAMPLE_LENGTH_SOFT),
538 DECL(AL_SEC_LENGTH_SOFT),
539 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
540 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
542 DECL(AL_UNUSED),
543 DECL(AL_PENDING),
544 DECL(AL_PROCESSED),
546 DECL(AL_NO_ERROR),
547 DECL(AL_INVALID_NAME),
548 DECL(AL_INVALID_ENUM),
549 DECL(AL_INVALID_VALUE),
550 DECL(AL_INVALID_OPERATION),
551 DECL(AL_OUT_OF_MEMORY),
553 DECL(AL_VENDOR),
554 DECL(AL_VERSION),
555 DECL(AL_RENDERER),
556 DECL(AL_EXTENSIONS),
558 DECL(AL_DOPPLER_FACTOR),
559 DECL(AL_DOPPLER_VELOCITY),
560 DECL(AL_DISTANCE_MODEL),
561 DECL(AL_SPEED_OF_SOUND),
562 DECL(AL_SOURCE_DISTANCE_MODEL),
563 DECL(AL_DEFERRED_UPDATES_SOFT),
565 DECL(AL_INVERSE_DISTANCE),
566 DECL(AL_INVERSE_DISTANCE_CLAMPED),
567 DECL(AL_LINEAR_DISTANCE),
568 DECL(AL_LINEAR_DISTANCE_CLAMPED),
569 DECL(AL_EXPONENT_DISTANCE),
570 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
572 DECL(AL_FILTER_TYPE),
573 DECL(AL_FILTER_NULL),
574 DECL(AL_FILTER_LOWPASS),
575 DECL(AL_FILTER_HIGHPASS),
576 DECL(AL_FILTER_BANDPASS),
578 DECL(AL_LOWPASS_GAIN),
579 DECL(AL_LOWPASS_GAINHF),
581 DECL(AL_HIGHPASS_GAIN),
582 DECL(AL_HIGHPASS_GAINLF),
584 DECL(AL_BANDPASS_GAIN),
585 DECL(AL_BANDPASS_GAINHF),
586 DECL(AL_BANDPASS_GAINLF),
588 DECL(AL_EFFECT_TYPE),
589 DECL(AL_EFFECT_NULL),
590 DECL(AL_EFFECT_REVERB),
591 DECL(AL_EFFECT_EAXREVERB),
592 DECL(AL_EFFECT_CHORUS),
593 DECL(AL_EFFECT_DISTORTION),
594 DECL(AL_EFFECT_ECHO),
595 DECL(AL_EFFECT_FLANGER),
596 #if 0
597 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
598 DECL(AL_EFFECT_VOCAL_MORPHER),
599 DECL(AL_EFFECT_PITCH_SHIFTER),
600 #endif
601 DECL(AL_EFFECT_RING_MODULATOR),
602 #if 0
603 DECL(AL_EFFECT_AUTOWAH),
604 #endif
605 DECL(AL_EFFECT_COMPRESSOR),
606 DECL(AL_EFFECT_EQUALIZER),
607 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
608 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
610 DECL(AL_EAXREVERB_DENSITY),
611 DECL(AL_EAXREVERB_DIFFUSION),
612 DECL(AL_EAXREVERB_GAIN),
613 DECL(AL_EAXREVERB_GAINHF),
614 DECL(AL_EAXREVERB_GAINLF),
615 DECL(AL_EAXREVERB_DECAY_TIME),
616 DECL(AL_EAXREVERB_DECAY_HFRATIO),
617 DECL(AL_EAXREVERB_DECAY_LFRATIO),
618 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
619 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
620 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
621 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
622 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
623 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
624 DECL(AL_EAXREVERB_ECHO_TIME),
625 DECL(AL_EAXREVERB_ECHO_DEPTH),
626 DECL(AL_EAXREVERB_MODULATION_TIME),
627 DECL(AL_EAXREVERB_MODULATION_DEPTH),
628 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
629 DECL(AL_EAXREVERB_HFREFERENCE),
630 DECL(AL_EAXREVERB_LFREFERENCE),
631 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
632 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
634 DECL(AL_REVERB_DENSITY),
635 DECL(AL_REVERB_DIFFUSION),
636 DECL(AL_REVERB_GAIN),
637 DECL(AL_REVERB_GAINHF),
638 DECL(AL_REVERB_DECAY_TIME),
639 DECL(AL_REVERB_DECAY_HFRATIO),
640 DECL(AL_REVERB_REFLECTIONS_GAIN),
641 DECL(AL_REVERB_REFLECTIONS_DELAY),
642 DECL(AL_REVERB_LATE_REVERB_GAIN),
643 DECL(AL_REVERB_LATE_REVERB_DELAY),
644 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
645 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
646 DECL(AL_REVERB_DECAY_HFLIMIT),
648 DECL(AL_CHORUS_WAVEFORM),
649 DECL(AL_CHORUS_PHASE),
650 DECL(AL_CHORUS_RATE),
651 DECL(AL_CHORUS_DEPTH),
652 DECL(AL_CHORUS_FEEDBACK),
653 DECL(AL_CHORUS_DELAY),
655 DECL(AL_DISTORTION_EDGE),
656 DECL(AL_DISTORTION_GAIN),
657 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
658 DECL(AL_DISTORTION_EQCENTER),
659 DECL(AL_DISTORTION_EQBANDWIDTH),
661 DECL(AL_ECHO_DELAY),
662 DECL(AL_ECHO_LRDELAY),
663 DECL(AL_ECHO_DAMPING),
664 DECL(AL_ECHO_FEEDBACK),
665 DECL(AL_ECHO_SPREAD),
667 DECL(AL_FLANGER_WAVEFORM),
668 DECL(AL_FLANGER_PHASE),
669 DECL(AL_FLANGER_RATE),
670 DECL(AL_FLANGER_DEPTH),
671 DECL(AL_FLANGER_FEEDBACK),
672 DECL(AL_FLANGER_DELAY),
674 DECL(AL_RING_MODULATOR_FREQUENCY),
675 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
676 DECL(AL_RING_MODULATOR_WAVEFORM),
678 #if 0
679 DECL(AL_AUTOWAH_ATTACK_TIME),
680 DECL(AL_AUTOWAH_PEAK_GAIN),
681 DECL(AL_AUTOWAH_RELEASE_TIME),
682 DECL(AL_AUTOWAH_RESONANCE),
683 #endif
685 DECL(AL_COMPRESSOR_ONOFF),
687 DECL(AL_EQUALIZER_LOW_GAIN),
688 DECL(AL_EQUALIZER_LOW_CUTOFF),
689 DECL(AL_EQUALIZER_MID1_GAIN),
690 DECL(AL_EQUALIZER_MID1_CENTER),
691 DECL(AL_EQUALIZER_MID1_WIDTH),
692 DECL(AL_EQUALIZER_MID2_GAIN),
693 DECL(AL_EQUALIZER_MID2_CENTER),
694 DECL(AL_EQUALIZER_MID2_WIDTH),
695 DECL(AL_EQUALIZER_HIGH_GAIN),
696 DECL(AL_EQUALIZER_HIGH_CUTOFF),
698 DECL(AL_DEDICATED_GAIN),
700 { NULL, (ALCenum)0 }
702 #undef DECL
704 static const ALCchar alcNoError[] = "No Error";
705 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
706 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
707 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
708 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
709 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
712 /************************************************
713 * Global variables
714 ************************************************/
716 /* Enumerated device names */
717 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
719 static al_string alcAllDevicesList;
720 static al_string alcCaptureDeviceList;
722 /* Default is always the first in the list */
723 static ALCchar *alcDefaultAllDevicesSpecifier;
724 static ALCchar *alcCaptureDefaultDeviceSpecifier;
726 /* Default context extensions */
727 static const ALchar alExtList[] =
728 "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
729 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS "
730 "AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
731 "AL_EXT_source_distance_model AL_LOKI_quadriphonic AL_SOFT_block_alignment "
732 "AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data AL_SOFT_deferred_updates "
733 "AL_SOFT_direct_channels AL_SOFT_loop_points AL_SOFT_MSADPCM "
734 "AL_SOFT_source_latency AL_SOFT_source_length";
736 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
738 /* Thread-local current context */
739 static altss_t LocalContext;
740 /* Process-wide current context */
741 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
743 /* Mixing thread piority level */
744 ALint RTPrioLevel;
746 FILE *LogFile;
747 #ifdef _DEBUG
748 enum LogLevel LogLevel = LogWarning;
749 #else
750 enum LogLevel LogLevel = LogError;
751 #endif
753 /* Flag to trap ALC device errors */
754 static ALCboolean TrapALCError = ALC_FALSE;
756 /* One-time configuration init control */
757 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
759 /* Default effect that applies to sources that don't have an effect on send 0 */
760 static ALeffect DefaultEffect;
762 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
763 * updates.
765 static ALCboolean SuspendDefers = ALC_TRUE;
768 /************************************************
769 * ALC information
770 ************************************************/
771 static const ALCchar alcNoDeviceExtList[] =
772 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
773 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
774 static const ALCchar alcExtensionList[] =
775 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
776 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
777 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFTX_HRTF "
778 "ALC_SOFT_loopback ALC_SOFTX_midi_interface ALC_SOFT_pause_device";
779 static const ALCint alcMajorVersion = 1;
780 static const ALCint alcMinorVersion = 1;
782 static const ALCint alcEFXMajorVersion = 1;
783 static const ALCint alcEFXMinorVersion = 0;
786 /************************************************
787 * Device lists
788 ************************************************/
789 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
791 static almtx_t ListLock;
792 static inline void LockLists(void)
794 int lockret = almtx_lock(&ListLock);
795 assert(lockret == althrd_success);
797 static inline void UnlockLists(void)
799 int unlockret = almtx_unlock(&ListLock);
800 assert(unlockret == althrd_success);
803 /************************************************
804 * Library initialization
805 ************************************************/
806 #if defined(_WIN32)
807 static void alc_init(void);
808 static void alc_deinit(void);
809 static void alc_deinit_safe(void);
811 #ifndef AL_LIBTYPE_STATIC
812 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
814 switch(reason)
816 case DLL_PROCESS_ATTACH:
817 /* Pin the DLL so we won't get unloaded until the process terminates */
818 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
819 (WCHAR*)hModule, &hModule);
820 alc_init();
821 break;
823 case DLL_THREAD_DETACH:
824 break;
826 case DLL_PROCESS_DETACH:
827 if(!lpReserved)
828 alc_deinit();
829 else
830 alc_deinit_safe();
831 break;
833 return TRUE;
835 #elif defined(_MSC_VER)
836 #pragma section(".CRT$XCU",read)
837 static void alc_constructor(void);
838 static void alc_destructor(void);
839 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
841 static void alc_constructor(void)
843 atexit(alc_destructor);
844 alc_init();
847 static void alc_destructor(void)
849 alc_deinit();
851 #elif defined(HAVE_GCC_DESTRUCTOR)
852 static void alc_init(void) __attribute__((constructor));
853 static void alc_deinit(void) __attribute__((destructor));
854 #else
855 #error "No static initialization available on this platform!"
856 #endif
858 #elif defined(HAVE_GCC_DESTRUCTOR)
860 static void alc_init(void) __attribute__((constructor));
861 static void alc_deinit(void) __attribute__((destructor));
863 #else
864 #error "No global initialization available on this platform!"
865 #endif
867 static void ReleaseThreadCtx(void *ptr);
868 static void alc_init(void)
870 const char *str;
871 int ret;
873 LogFile = stderr;
875 AL_STRING_INIT(alcAllDevicesList);
876 AL_STRING_INIT(alcCaptureDeviceList);
878 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
879 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
880 ConeScale *= 0.5f;
882 str = getenv("__ALSOFT_REVERSE_Z");
883 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
884 ZScale *= -1.0f;
886 ret = altss_create(&LocalContext, ReleaseThreadCtx);
887 assert(ret == althrd_success);
889 ret = almtx_init(&ListLock, almtx_recursive);
890 assert(ret == althrd_success);
892 ThunkInit();
895 static void alc_initconfig(void)
897 const char *devs, *str;
898 ALuint capfilter;
899 float valf;
900 int i, n;
902 str = getenv("ALSOFT_LOGLEVEL");
903 if(str)
905 long lvl = strtol(str, NULL, 0);
906 if(lvl >= NoLog && lvl <= LogRef)
907 LogLevel = lvl;
910 str = getenv("ALSOFT_LOGFILE");
911 if(str && str[0])
913 FILE *logfile = al_fopen(str, "wt");
914 if(logfile) LogFile = logfile;
915 else ERR("Failed to open log file '%s'\n", str);
919 char buf[1024] = "";
920 int len = snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
921 for(i = 1;BackendList[i].name;i++)
922 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
923 TRACE("Supported backends: %s\n", buf);
925 ReadALConfig();
927 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
928 if(str && *str)
930 if(strcasecmp(str, "ignore") == 0)
932 SuspendDefers = ALC_FALSE;
933 TRACE("Selected context suspend behavior, \"ignore\"\n");
935 else
936 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
939 capfilter = 0;
940 #if defined(HAVE_SSE4_1)
941 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE4_1;
942 #elif defined(HAVE_SSE2)
943 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
944 #elif defined(HAVE_SSE)
945 capfilter |= CPU_CAP_SSE;
946 #endif
947 #ifdef HAVE_NEON
948 capfilter |= CPU_CAP_NEON;
949 #endif
950 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
952 if(strcasecmp(str, "all") == 0)
953 capfilter = 0;
954 else
956 size_t len;
957 const char *next = str;
959 do {
960 str = next;
961 while(isspace(str[0]))
962 str++;
963 next = strchr(str, ',');
965 if(!str[0] || str[0] == ',')
966 continue;
968 len = (next ? ((size_t)(next-str)) : strlen(str));
969 while(len > 0 && isspace(str[len-1]))
970 len--;
971 if(len == 3 && strncasecmp(str, "sse", len) == 0)
972 capfilter &= ~CPU_CAP_SSE;
973 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
974 capfilter &= ~CPU_CAP_SSE2;
975 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
976 capfilter &= ~CPU_CAP_SSE4_1;
977 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
978 capfilter &= ~CPU_CAP_NEON;
979 else
980 WARN("Invalid CPU extension \"%s\"\n", str);
981 } while(next++);
984 FillCPUCaps(capfilter);
986 #ifdef _WIN32
987 RTPrioLevel = 1;
988 #else
989 RTPrioLevel = 0;
990 #endif
991 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
993 if(ConfigValueStr(NULL, "resampler", &str))
995 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
996 DefaultResampler = PointResampler;
997 else if(strcasecmp(str, "linear") == 0)
998 DefaultResampler = LinearResampler;
999 else if(strcasecmp(str, "cubic") == 0)
1000 DefaultResampler = CubicResampler;
1001 else
1003 char *end;
1005 n = strtol(str, &end, 0);
1006 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
1007 DefaultResampler = n;
1008 else
1009 WARN("Invalid resampler: %s\n", str);
1012 aluInitResamplers();
1014 str = getenv("ALSOFT_TRAP_ERROR");
1015 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1017 TrapALError = AL_TRUE;
1018 TrapALCError = AL_TRUE;
1020 else
1022 str = getenv("ALSOFT_TRAP_AL_ERROR");
1023 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1024 TrapALError = AL_TRUE;
1025 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
1027 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1028 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1029 TrapALCError = ALC_TRUE;
1030 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
1033 if(ConfigValueFloat("reverb", "boost", &valf))
1034 ReverbBoost *= powf(10.0f, valf / 20.0f);
1036 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
1038 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1039 ConfigValueStr(NULL, "drivers", &devs))
1041 int n;
1042 size_t len;
1043 const char *next = devs;
1044 int endlist, delitem;
1046 i = 0;
1047 do {
1048 devs = next;
1049 while(isspace(devs[0]))
1050 devs++;
1051 next = strchr(devs, ',');
1053 delitem = (devs[0] == '-');
1054 if(devs[0] == '-') devs++;
1056 if(!devs[0] || devs[0] == ',')
1058 endlist = 0;
1059 continue;
1061 endlist = 1;
1063 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1064 while(len > 0 && isspace(devs[len-1]))
1065 len--;
1066 for(n = i;BackendList[n].name;n++)
1068 if(len == strlen(BackendList[n].name) &&
1069 strncmp(BackendList[n].name, devs, len) == 0)
1071 if(delitem)
1073 do {
1074 BackendList[n] = BackendList[n+1];
1075 ++n;
1076 } while(BackendList[n].name);
1078 else
1080 struct BackendInfo Bkp = BackendList[n];
1081 while(n > i)
1083 BackendList[n] = BackendList[n-1];
1084 --n;
1086 BackendList[n] = Bkp;
1088 i++;
1090 break;
1093 } while(next++);
1095 if(endlist)
1097 BackendList[i].name = NULL;
1098 BackendList[i].getFactory = NULL;
1099 BackendList[i].Init = NULL;
1100 BackendList[i].Deinit = NULL;
1101 BackendList[i].Probe = NULL;
1105 for(i = 0;(BackendList[i].Init || BackendList[i].getFactory) && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1107 if(BackendList[i].getFactory)
1109 ALCbackendFactory *factory = BackendList[i].getFactory();
1110 if(!V0(factory,init)())
1112 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1113 continue;
1116 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1117 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1119 PlaybackBackend = BackendList[i];
1120 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1122 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1124 CaptureBackend = BackendList[i];
1125 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1128 continue;
1131 if(!BackendList[i].Init(&BackendList[i].Funcs))
1133 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1134 continue;
1137 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1138 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1140 PlaybackBackend = BackendList[i];
1141 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1143 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1145 CaptureBackend = BackendList[i];
1146 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1150 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1151 V0(factory,init)();
1154 if(ConfigValueStr(NULL, "excludefx", &str))
1156 size_t len;
1157 const char *next = str;
1159 do {
1160 str = next;
1161 next = strchr(str, ',');
1163 if(!str[0] || next == str)
1164 continue;
1166 len = (next ? ((size_t)(next-str)) : strlen(str));
1167 for(n = 0;EffectList[n].name;n++)
1169 if(len == strlen(EffectList[n].name) &&
1170 strncmp(EffectList[n].name, str, len) == 0)
1171 DisabledEffects[EffectList[n].type] = AL_TRUE;
1173 } while(next++);
1176 InitEffectFactoryMap();
1178 InitEffect(&DefaultEffect);
1179 str = getenv("ALSOFT_DEFAULT_REVERB");
1180 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
1181 LoadReverbPreset(str, &DefaultEffect);
1183 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1186 /************************************************
1187 * Library deinitialization
1188 ************************************************/
1189 static void alc_cleanup(void)
1191 ALCdevice *dev;
1193 AL_STRING_DEINIT(alcAllDevicesList);
1194 AL_STRING_DEINIT(alcCaptureDeviceList);
1196 free(alcDefaultAllDevicesSpecifier);
1197 alcDefaultAllDevicesSpecifier = NULL;
1198 free(alcCaptureDefaultDeviceSpecifier);
1199 alcCaptureDefaultDeviceSpecifier = NULL;
1201 if((dev=ATOMIC_EXCHANGE(ALCdevice*, &DeviceList, NULL)) != NULL)
1203 ALCuint num = 0;
1204 do {
1205 num++;
1206 } while((dev=dev->next) != NULL);
1207 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1210 DeinitEffectFactoryMap();
1213 static void alc_deinit_safe(void)
1215 alc_cleanup();
1217 FreeHrtfs();
1218 FreeALConfig();
1220 ThunkExit();
1221 almtx_destroy(&ListLock);
1222 altss_delete(LocalContext);
1224 if(LogFile != stderr)
1225 fclose(LogFile);
1226 LogFile = NULL;
1229 static void alc_deinit(void)
1231 int i;
1233 alc_cleanup();
1235 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1236 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1238 for(i = 0;BackendList[i].Deinit || BackendList[i].getFactory;i++)
1240 if(!BackendList[i].getFactory)
1241 BackendList[i].Deinit();
1242 else
1244 ALCbackendFactory *factory = BackendList[i].getFactory();
1245 V0(factory,deinit)();
1249 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1250 V0(factory,deinit)();
1253 alc_deinit_safe();
1257 /************************************************
1258 * Device enumeration
1259 ************************************************/
1260 static void ProbeDevices(al_string *list, enum DevProbe type)
1262 DO_INITCONFIG();
1264 LockLists();
1265 al_string_clear(list);
1267 if(type == ALL_DEVICE_PROBE && (PlaybackBackend.Probe || PlaybackBackend.getFactory))
1269 if(!PlaybackBackend.getFactory)
1270 PlaybackBackend.Probe(type);
1271 else
1273 ALCbackendFactory *factory = PlaybackBackend.getFactory();
1274 V(factory,probe)(type);
1277 else if(type == CAPTURE_DEVICE_PROBE && (CaptureBackend.Probe || CaptureBackend.getFactory))
1279 if(!CaptureBackend.getFactory)
1280 CaptureBackend.Probe(type);
1281 else
1283 ALCbackendFactory *factory = CaptureBackend.getFactory();
1284 V(factory,probe)(type);
1287 UnlockLists();
1289 static void ProbeAllDevicesList(void)
1290 { ProbeDevices(&alcAllDevicesList, ALL_DEVICE_PROBE); }
1291 static void ProbeCaptureDeviceList(void)
1292 { ProbeDevices(&alcCaptureDeviceList, CAPTURE_DEVICE_PROBE); }
1294 static void AppendDevice(const ALCchar *name, al_string *devnames)
1296 size_t len = strlen(name);
1297 if(len > 0)
1298 al_string_append_range(devnames, name, name+len+1);
1300 void AppendAllDevicesList(const ALCchar *name)
1301 { AppendDevice(name, &alcAllDevicesList); }
1302 void AppendCaptureDeviceList(const ALCchar *name)
1303 { AppendDevice(name, &alcCaptureDeviceList); }
1306 /************************************************
1307 * Device format information
1308 ************************************************/
1309 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1311 switch(type)
1313 case DevFmtByte: return "Signed Byte";
1314 case DevFmtUByte: return "Unsigned Byte";
1315 case DevFmtShort: return "Signed Short";
1316 case DevFmtUShort: return "Unsigned Short";
1317 case DevFmtInt: return "Signed Int";
1318 case DevFmtUInt: return "Unsigned Int";
1319 case DevFmtFloat: return "Float";
1321 return "(unknown type)";
1323 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1325 switch(chans)
1327 case DevFmtMono: return "Mono";
1328 case DevFmtStereo: return "Stereo";
1329 case DevFmtQuad: return "Quadraphonic";
1330 case DevFmtX51: return "5.1 Surround";
1331 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1332 case DevFmtX61: return "6.1 Surround";
1333 case DevFmtX71: return "7.1 Surround";
1334 case DevFmtBFormat3D: return "B-Format 3D";
1336 return "(unknown channels)";
1339 extern inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
1340 ALuint BytesFromDevFmt(enum DevFmtType type)
1342 switch(type)
1344 case DevFmtByte: return sizeof(ALbyte);
1345 case DevFmtUByte: return sizeof(ALubyte);
1346 case DevFmtShort: return sizeof(ALshort);
1347 case DevFmtUShort: return sizeof(ALushort);
1348 case DevFmtInt: return sizeof(ALint);
1349 case DevFmtUInt: return sizeof(ALuint);
1350 case DevFmtFloat: return sizeof(ALfloat);
1352 return 0;
1354 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1356 switch(chans)
1358 case DevFmtMono: return 1;
1359 case DevFmtStereo: return 2;
1360 case DevFmtQuad: return 4;
1361 case DevFmtX51: return 6;
1362 case DevFmtX51Rear: return 6;
1363 case DevFmtX61: return 7;
1364 case DevFmtX71: return 8;
1365 case DevFmtBFormat3D: return 4;
1367 return 0;
1370 DECL_CONST static ALboolean DecomposeDevFormat(ALenum format,
1371 enum DevFmtChannels *chans, enum DevFmtType *type)
1373 static const struct {
1374 ALenum format;
1375 enum DevFmtChannels channels;
1376 enum DevFmtType type;
1377 } list[] = {
1378 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1379 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1380 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1382 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1383 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1384 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1386 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1387 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1388 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1390 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1391 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1392 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1394 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1395 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1396 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1398 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1399 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1400 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1402 ALuint i;
1404 for(i = 0;i < COUNTOF(list);i++)
1406 if(list[i].format == format)
1408 *chans = list[i].channels;
1409 *type = list[i].type;
1410 return AL_TRUE;
1414 return AL_FALSE;
1417 DECL_CONST static ALCboolean IsValidALCType(ALCenum type)
1419 switch(type)
1421 case ALC_BYTE_SOFT:
1422 case ALC_UNSIGNED_BYTE_SOFT:
1423 case ALC_SHORT_SOFT:
1424 case ALC_UNSIGNED_SHORT_SOFT:
1425 case ALC_INT_SOFT:
1426 case ALC_UNSIGNED_INT_SOFT:
1427 case ALC_FLOAT_SOFT:
1428 return ALC_TRUE;
1430 return ALC_FALSE;
1433 DECL_CONST static ALCboolean IsValidALCChannels(ALCenum channels)
1435 switch(channels)
1437 case ALC_MONO_SOFT:
1438 case ALC_STEREO_SOFT:
1439 case ALC_QUAD_SOFT:
1440 case ALC_5POINT1_SOFT:
1441 case ALC_6POINT1_SOFT:
1442 case ALC_7POINT1_SOFT:
1443 return ALC_TRUE;
1445 return ALC_FALSE;
1449 /************************************************
1450 * Miscellaneous ALC helpers
1451 ************************************************/
1452 extern inline void LockContext(ALCcontext *context);
1453 extern inline void UnlockContext(ALCcontext *context);
1455 ALint64 ALCdevice_GetLatency(ALCdevice *device)
1457 return V0(device->Backend,getLatency)();
1460 void ALCdevice_Lock(ALCdevice *device)
1462 V0(device->Backend,lock)();
1465 void ALCdevice_Unlock(ALCdevice *device)
1467 V0(device->Backend,unlock)();
1471 /* SetDefaultWFXChannelOrder
1473 * Sets the default channel order used by WaveFormatEx.
1475 void SetDefaultWFXChannelOrder(ALCdevice *device)
1477 ALuint i;
1479 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1480 device->ChannelName[i] = InvalidChannel;
1482 switch(device->FmtChans)
1484 case DevFmtMono:
1485 device->ChannelName[0] = FrontCenter;
1486 break;
1487 case DevFmtStereo:
1488 device->ChannelName[0] = FrontLeft;
1489 device->ChannelName[1] = FrontRight;
1490 break;
1491 case DevFmtQuad:
1492 device->ChannelName[0] = FrontLeft;
1493 device->ChannelName[1] = FrontRight;
1494 device->ChannelName[2] = BackLeft;
1495 device->ChannelName[3] = BackRight;
1496 break;
1497 case DevFmtX51:
1498 device->ChannelName[0] = FrontLeft;
1499 device->ChannelName[1] = FrontRight;
1500 device->ChannelName[2] = FrontCenter;
1501 device->ChannelName[3] = LFE;
1502 device->ChannelName[4] = SideLeft;
1503 device->ChannelName[5] = SideRight;
1504 break;
1505 case DevFmtX51Rear:
1506 device->ChannelName[0] = FrontLeft;
1507 device->ChannelName[1] = FrontRight;
1508 device->ChannelName[2] = FrontCenter;
1509 device->ChannelName[3] = LFE;
1510 device->ChannelName[4] = BackLeft;
1511 device->ChannelName[5] = BackRight;
1512 break;
1513 case DevFmtX61:
1514 device->ChannelName[0] = FrontLeft;
1515 device->ChannelName[1] = FrontRight;
1516 device->ChannelName[2] = FrontCenter;
1517 device->ChannelName[3] = LFE;
1518 device->ChannelName[4] = BackCenter;
1519 device->ChannelName[5] = SideLeft;
1520 device->ChannelName[6] = SideRight;
1521 break;
1522 case DevFmtX71:
1523 device->ChannelName[0] = FrontLeft;
1524 device->ChannelName[1] = FrontRight;
1525 device->ChannelName[2] = FrontCenter;
1526 device->ChannelName[3] = LFE;
1527 device->ChannelName[4] = BackLeft;
1528 device->ChannelName[5] = BackRight;
1529 device->ChannelName[6] = SideLeft;
1530 device->ChannelName[7] = SideRight;
1531 break;
1532 case DevFmtBFormat3D:
1533 device->ChannelName[0] = Aux0;
1534 device->ChannelName[1] = Aux1;
1535 device->ChannelName[2] = Aux2;
1536 device->ChannelName[3] = Aux3;
1537 break;
1541 /* SetDefaultChannelOrder
1543 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1545 void SetDefaultChannelOrder(ALCdevice *device)
1547 ALuint i;
1549 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1550 device->ChannelName[i] = InvalidChannel;
1552 switch(device->FmtChans)
1554 case DevFmtX51Rear:
1555 device->ChannelName[0] = FrontLeft;
1556 device->ChannelName[1] = FrontRight;
1557 device->ChannelName[2] = BackLeft;
1558 device->ChannelName[3] = BackRight;
1559 device->ChannelName[4] = FrontCenter;
1560 device->ChannelName[5] = LFE;
1561 return;
1562 case DevFmtX71:
1563 device->ChannelName[0] = FrontLeft;
1564 device->ChannelName[1] = FrontRight;
1565 device->ChannelName[2] = BackLeft;
1566 device->ChannelName[3] = BackRight;
1567 device->ChannelName[4] = FrontCenter;
1568 device->ChannelName[5] = LFE;
1569 device->ChannelName[6] = SideLeft;
1570 device->ChannelName[7] = SideRight;
1571 return;
1573 /* Same as WFX order */
1574 case DevFmtMono:
1575 case DevFmtStereo:
1576 case DevFmtQuad:
1577 case DevFmtX51:
1578 case DevFmtX61:
1579 case DevFmtBFormat3D:
1580 SetDefaultWFXChannelOrder(device);
1581 break;
1585 extern inline ALint GetChannelIdxByName(const ALCdevice *device, enum Channel chan);
1588 /* ALCcontext_DeferUpdates
1590 * Defers/suspends updates for the given context's listener and sources. This
1591 * does *NOT* stop mixing, but rather prevents certain property changes from
1592 * taking effect.
1594 void ALCcontext_DeferUpdates(ALCcontext *context)
1596 ALCdevice *device = context->Device;
1597 FPUCtl oldMode;
1599 SetMixerFPUMode(&oldMode);
1601 V0(device->Backend,lock)();
1602 if(!context->DeferUpdates)
1604 ALboolean UpdateSources;
1605 ALvoice *voice, *voice_end;
1606 ALeffectslot **slot, **slot_end;
1608 context->DeferUpdates = AL_TRUE;
1610 /* Make sure all pending updates are performed */
1611 UpdateSources = ATOMIC_EXCHANGE(ALenum, &context->UpdateSources, AL_FALSE);
1613 voice = context->Voices;
1614 voice_end = voice + context->VoiceCount;
1615 while(voice != voice_end)
1617 ALsource *source = voice->Source;
1618 if(!source) goto next;
1620 if(source->state != AL_PLAYING && source->state != AL_PAUSED)
1622 voice->Source = NULL;
1623 goto next;
1626 if(ATOMIC_EXCHANGE(ALenum, &source->NeedsUpdate, AL_FALSE) || UpdateSources)
1627 voice->Update(voice, source, context);
1628 next:
1629 voice++;
1632 slot = VECTOR_ITER_BEGIN(context->ActiveAuxSlots);
1633 slot_end = VECTOR_ITER_END(context->ActiveAuxSlots);
1634 while(slot != slot_end)
1636 if(ATOMIC_EXCHANGE(ALenum, &(*slot)->NeedsUpdate, AL_FALSE))
1637 V((*slot)->EffectState,update)(context->Device, *slot);
1638 slot++;
1641 V0(device->Backend,unlock)();
1643 RestoreFPUMode(&oldMode);
1646 /* ALCcontext_ProcessUpdates
1648 * Resumes update processing after being deferred.
1650 void ALCcontext_ProcessUpdates(ALCcontext *context)
1652 ALCdevice *device = context->Device;
1654 V0(device->Backend,lock)();
1655 if(context->DeferUpdates)
1657 ALsizei pos;
1659 context->DeferUpdates = AL_FALSE;
1661 LockUIntMapRead(&context->SourceMap);
1662 for(pos = 0;pos < context->SourceMap.size;pos++)
1664 ALsource *Source = context->SourceMap.array[pos].value;
1665 ALenum new_state;
1667 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
1668 Source->Offset >= 0.0)
1670 ReadLock(&Source->queue_lock);
1671 ApplyOffset(Source);
1672 ReadUnlock(&Source->queue_lock);
1675 new_state = Source->new_state;
1676 Source->new_state = AL_NONE;
1677 if(new_state)
1678 SetSourceState(Source, context, new_state);
1680 UnlockUIntMapRead(&context->SourceMap);
1682 V0(device->Backend,unlock)();
1686 /* alcSetError
1688 * Stores the latest ALC device error
1690 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1692 if(TrapALCError)
1694 #ifdef _WIN32
1695 /* DebugBreak() will cause an exception if there is no debugger */
1696 if(IsDebuggerPresent())
1697 DebugBreak();
1698 #elif defined(SIGTRAP)
1699 raise(SIGTRAP);
1700 #endif
1703 if(device)
1704 ATOMIC_STORE(&device->LastError, errorCode);
1705 else
1706 ATOMIC_STORE(&LastNullDeviceError, errorCode);
1710 /* UpdateClockBase
1712 * Updates the device's base clock time with however many samples have been
1713 * done. This is used so frequency changes on the device don't cause the time
1714 * to jump forward or back.
1716 static inline void UpdateClockBase(ALCdevice *device)
1718 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1719 device->SamplesDone = 0;
1722 /* UpdateDeviceParams
1724 * Updates device parameters according to the attribute list (caller is
1725 * responsible for holding the list lock).
1727 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1729 ALCcontext *context;
1730 enum DevFmtChannels oldChans;
1731 enum DevFmtType oldType;
1732 ALCuint oldFreq;
1733 FPUCtl oldMode;
1734 size_t size;
1736 // Check for attributes
1737 if(device->Type == Loopback)
1739 enum {
1740 GotFreq = 1<<0,
1741 GotChans = 1<<1,
1742 GotType = 1<<2,
1743 GotAll = GotFreq|GotChans|GotType
1745 ALCuint freq, numMono, numStereo, numSends, flags;
1746 enum DevFmtChannels schans;
1747 enum DevFmtType stype;
1748 ALCuint attrIdx = 0;
1749 ALCint gotFmt = 0;
1751 if(!attrList)
1753 WARN("Missing attributes for loopback device\n");
1754 return ALC_INVALID_VALUE;
1757 numMono = device->NumMonoSources;
1758 numStereo = device->NumStereoSources;
1759 numSends = device->NumAuxSends;
1760 schans = device->FmtChans;
1761 stype = device->FmtType;
1762 freq = device->Frequency;
1763 flags = device->Flags;
1765 while(attrList[attrIdx])
1767 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1769 ALCint val = attrList[attrIdx + 1];
1770 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1771 return ALC_INVALID_VALUE;
1772 schans = val;
1773 gotFmt |= GotChans;
1776 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1778 ALCint val = attrList[attrIdx + 1];
1779 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1780 return ALC_INVALID_VALUE;
1781 stype = val;
1782 gotFmt |= GotType;
1785 if(attrList[attrIdx] == ALC_FREQUENCY)
1787 freq = attrList[attrIdx + 1];
1788 if(freq < MIN_OUTPUT_RATE)
1789 return ALC_INVALID_VALUE;
1790 gotFmt |= GotFreq;
1793 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1795 numStereo = attrList[attrIdx + 1];
1796 if(numStereo > device->MaxNoOfSources)
1797 numStereo = device->MaxNoOfSources;
1799 numMono = device->MaxNoOfSources - numStereo;
1802 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1803 numSends = attrList[attrIdx + 1];
1805 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1807 if(attrList[attrIdx + 1] != ALC_FALSE)
1808 flags |= DEVICE_HRTF_REQUEST;
1809 else
1810 flags &= ~DEVICE_HRTF_REQUEST;
1813 attrIdx += 2;
1816 if(gotFmt != GotAll)
1818 WARN("Missing format for loopback device\n");
1819 return ALC_INVALID_VALUE;
1822 ConfigValueUInt(NULL, "sends", &numSends);
1823 numSends = minu(MAX_SENDS, numSends);
1825 if((device->Flags&DEVICE_RUNNING))
1826 V0(device->Backend,stop)();
1827 device->Flags = (flags & ~DEVICE_RUNNING);
1829 UpdateClockBase(device);
1831 device->Frequency = freq;
1832 device->FmtChans = schans;
1833 device->FmtType = stype;
1834 device->NumMonoSources = numMono;
1835 device->NumStereoSources = numStereo;
1836 device->NumAuxSends = numSends;
1838 else if(attrList && attrList[0])
1840 ALCuint freq, numMono, numStereo, numSends;
1841 ALCuint attrIdx = 0;
1843 /* If a context is already running on the device, stop playback so the
1844 * device attributes can be updated. */
1845 if((device->Flags&DEVICE_RUNNING))
1846 V0(device->Backend,stop)();
1847 device->Flags &= ~DEVICE_RUNNING;
1849 freq = device->Frequency;
1850 numMono = device->NumMonoSources;
1851 numStereo = device->NumStereoSources;
1852 numSends = device->NumAuxSends;
1854 while(attrList[attrIdx])
1856 if(attrList[attrIdx] == ALC_FREQUENCY)
1858 freq = attrList[attrIdx + 1];
1859 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1862 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1864 numStereo = attrList[attrIdx + 1];
1865 if(numStereo > device->MaxNoOfSources)
1866 numStereo = device->MaxNoOfSources;
1868 numMono = device->MaxNoOfSources - numStereo;
1871 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1872 numSends = attrList[attrIdx + 1];
1874 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1876 if(attrList[attrIdx + 1] != ALC_FALSE)
1877 device->Flags |= DEVICE_HRTF_REQUEST;
1878 else
1879 device->Flags &= ~DEVICE_HRTF_REQUEST;
1882 attrIdx += 2;
1885 ConfigValueUInt(NULL, "frequency", &freq);
1886 freq = maxu(freq, MIN_OUTPUT_RATE);
1888 ConfigValueUInt(NULL, "sends", &numSends);
1889 numSends = minu(MAX_SENDS, numSends);
1891 UpdateClockBase(device);
1893 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1894 device->Frequency;
1895 /* SSE and Neon do best with the update size being a multiple of 4 */
1896 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1897 device->UpdateSize = (device->UpdateSize+3)&~3;
1899 device->Frequency = freq;
1900 device->NumMonoSources = numMono;
1901 device->NumStereoSources = numStereo;
1902 device->NumAuxSends = numSends;
1905 if((device->Flags&DEVICE_RUNNING))
1906 return ALC_NO_ERROR;
1908 al_free(device->DryBuffer);
1909 device->DryBuffer = NULL;
1911 UpdateClockBase(device);
1913 if(device->Type != Loopback && ((device->Flags&DEVICE_HRTF_REQUEST) || GetConfigValueBool(NULL, "hrtf", 0)))
1915 if(!FindHrtfFormat(&device->FmtChans, &device->Frequency))
1916 device->Flags &= ~DEVICE_HRTF_REQUEST;
1917 else
1918 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST |
1919 DEVICE_HRTF_REQUEST;
1921 if(device->Type == Loopback && (device->Flags&DEVICE_HRTF_REQUEST))
1923 enum DevFmtChannels chans = device->FmtChans;
1924 ALCuint freq = device->Frequency;
1925 if(!FindHrtfFormat(&chans, &freq) || chans != device->FmtChans || freq != device->Frequency)
1927 ERR("Requested format not HRTF compatible: %s, %uhz\n",
1928 DevFmtChannelsString(device->FmtChans), device->Frequency);
1929 device->Flags &= ~DEVICE_HRTF_REQUEST;
1933 oldFreq = device->Frequency;
1934 oldChans = device->FmtChans;
1935 oldType = device->FmtType;
1937 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
1938 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
1939 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
1940 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
1941 device->UpdateSize, device->NumUpdates
1944 if(V0(device->Backend,reset)() == ALC_FALSE)
1945 return ALC_INVALID_DEVICE;
1947 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1949 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1950 DevFmtChannelsString(device->FmtChans));
1951 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1953 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1955 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1956 DevFmtTypeString(device->FmtType));
1957 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1959 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1961 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1962 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1965 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
1966 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
1967 device->Frequency, device->UpdateSize, device->NumUpdates
1970 if((device->UpdateSize&3) != 0)
1972 if((CPUCapFlags&CPU_CAP_SSE))
1973 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1974 if((CPUCapFlags&CPU_CAP_NEON))
1975 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1978 device->Hrtf = NULL;
1979 device->Hrtf_Mode = DisabledHrtf;
1980 if(device->FmtChans != DevFmtStereo)
1982 free(device->Bs2b);
1983 device->Bs2b = NULL;
1985 else
1987 bool headphones = device->IsHeadphones;
1988 enum HrtfMode hrtf_mode = FullHrtf;
1989 const char *mode;
1990 int bs2blevel;
1991 int usehrtf;
1993 if(device->Type != Loopback)
1995 if(ConfigValueStr(NULL, "stereo-mode", &mode))
1997 if(strcasecmp(mode, "headphones") == 0)
1998 headphones = true;
1999 else if(strcasecmp(mode, "speakers") == 0)
2000 headphones = false;
2001 else if(strcasecmp(mode, "auto") != 0)
2002 ERR("Unexpected stereo-mode: %s\n", mode);
2005 if(ConfigValueStr(NULL, "hrtf-mode", &mode))
2007 if(strcasecmp(mode, "full") == 0)
2008 hrtf_mode = FullHrtf;
2009 else if(strcasecmp(mode, "basic") == 0)
2010 hrtf_mode = BasicHrtf;
2011 else
2012 ERR("Unexpected hrtf-mode: %s\n", mode);
2017 if(device->Type == Loopback || !ConfigValueBool(NULL, "hrtf", &usehrtf))
2018 usehrtf = ((device->Flags&DEVICE_HRTF_REQUEST) || headphones);
2020 if(usehrtf)
2021 device->Hrtf = GetHrtf(device->FmtChans, device->Frequency);
2022 if(device->Hrtf)
2024 device->Hrtf_Mode = hrtf_mode;
2025 TRACE("HRTF enabled\n");
2026 free(device->Bs2b);
2027 device->Bs2b = NULL;
2029 else
2031 device->Flags &= ~DEVICE_HRTF_REQUEST;
2032 TRACE("HRTF disabled\n");
2034 bs2blevel = (headphones ? 5 : 0);
2035 if(device->Type != Loopback)
2036 ConfigValueInt(NULL, "cf_level", &bs2blevel);
2037 if(bs2blevel > 0 && bs2blevel <= 6)
2039 if(!device->Bs2b)
2041 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
2042 bs2b_clear(device->Bs2b);
2044 bs2b_set_srate(device->Bs2b, device->Frequency);
2045 bs2b_set_level(device->Bs2b, bs2blevel);
2046 TRACE("BS2B enabled\n");
2048 else
2050 free(device->Bs2b);
2051 device->Bs2b = NULL;
2052 TRACE("BS2B disabled\n");
2057 aluInitPanning(device);
2059 /* With HRTF enabled, virtual channels are allocated for B-Format and
2060 * effects renfering. Two extra channels are allocated for the actual HRTF-
2061 * filtered output.
2063 size = sizeof(device->DryBuffer[0]) * (device->NumChannels + (device->Hrtf ? 2 : 0));
2064 device->DryBuffer = al_calloc(16, size);
2065 if(!device->DryBuffer)
2067 ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
2068 return ALC_INVALID_DEVICE;
2071 V(device->Synth,update)(device);
2073 SetMixerFPUMode(&oldMode);
2074 V0(device->Backend,lock)();
2075 context = ATOMIC_LOAD(&device->ContextList);
2076 while(context)
2078 ALsizei pos;
2080 ATOMIC_STORE(&context->UpdateSources, AL_FALSE);
2081 LockUIntMapRead(&context->EffectSlotMap);
2082 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
2084 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
2086 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
2088 UnlockUIntMapRead(&context->EffectSlotMap);
2089 V0(device->Backend,unlock)();
2090 RestoreFPUMode(&oldMode);
2091 return ALC_INVALID_DEVICE;
2093 ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE);
2094 V(slot->EffectState,update)(device, slot);
2096 UnlockUIntMapRead(&context->EffectSlotMap);
2098 LockUIntMapRead(&context->SourceMap);
2099 for(pos = 0;pos < context->SourceMap.size;pos++)
2101 ALsource *source = context->SourceMap.array[pos].value;
2102 ALuint s = device->NumAuxSends;
2103 while(s < MAX_SENDS)
2105 if(source->Send[s].Slot)
2106 DecrementRef(&source->Send[s].Slot->ref);
2107 source->Send[s].Slot = NULL;
2108 source->Send[s].Gain = 1.0f;
2109 source->Send[s].GainHF = 1.0f;
2110 s++;
2112 ATOMIC_STORE(&source->NeedsUpdate, AL_TRUE);
2114 UnlockUIntMapRead(&context->SourceMap);
2116 for(pos = 0;pos < context->VoiceCount;pos++)
2118 ALvoice *voice = &context->Voices[pos];
2119 ALsource *source = voice->Source;
2120 ALuint s = device->NumAuxSends;
2122 while(s < MAX_SENDS)
2124 voice->Send[s].Moving = AL_FALSE;
2125 voice->Send[s].Counter = 0;
2126 s++;
2129 if(source)
2131 ATOMIC_STORE(&source->NeedsUpdate, AL_FALSE);
2132 voice->Update(voice, source, context);
2136 context = context->next;
2138 if(device->DefaultSlot)
2140 ALeffectslot *slot = device->DefaultSlot;
2142 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
2144 V0(device->Backend,unlock)();
2145 RestoreFPUMode(&oldMode);
2146 return ALC_INVALID_DEVICE;
2148 ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE);
2149 V(slot->EffectState,update)(device, slot);
2151 V0(device->Backend,unlock)();
2152 RestoreFPUMode(&oldMode);
2154 if(!(device->Flags&DEVICE_PAUSED))
2156 if(V0(device->Backend,start)() == ALC_FALSE)
2157 return ALC_INVALID_DEVICE;
2158 device->Flags |= DEVICE_RUNNING;
2161 return ALC_NO_ERROR;
2164 /* FreeDevice
2166 * Frees the device structure, and destroys any objects the app failed to
2167 * delete. Called once there's no more references on the device.
2169 static ALCvoid FreeDevice(ALCdevice *device)
2171 TRACE("%p\n", device);
2173 V0(device->Backend,close)();
2174 DELETE_OBJ(device->Backend);
2175 device->Backend = NULL;
2177 DELETE_OBJ(device->Synth);
2178 device->Synth = NULL;
2180 if(device->DefaultSlot)
2182 ALeffectState *state = device->DefaultSlot->EffectState;
2183 device->DefaultSlot = NULL;
2184 DELETE_OBJ(state);
2187 if(device->DefaultSfont)
2188 ALsoundfont_deleteSoundfont(device->DefaultSfont, device);
2189 device->DefaultSfont = NULL;
2191 if(device->BufferMap.size > 0)
2193 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
2194 ReleaseALBuffers(device);
2196 ResetUIntMap(&device->BufferMap);
2198 if(device->EffectMap.size > 0)
2200 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
2201 ReleaseALEffects(device);
2203 ResetUIntMap(&device->EffectMap);
2205 if(device->FilterMap.size > 0)
2207 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
2208 ReleaseALFilters(device);
2210 ResetUIntMap(&device->FilterMap);
2212 if(device->SfontMap.size > 0)
2214 WARN("(%p) Deleting %d Soundfont(s)\n", device, device->SfontMap.size);
2215 ReleaseALSoundfonts(device);
2217 ResetUIntMap(&device->SfontMap);
2219 if(device->PresetMap.size > 0)
2221 WARN("(%p) Deleting %d Preset(s)\n", device, device->PresetMap.size);
2222 ReleaseALPresets(device);
2224 ResetUIntMap(&device->PresetMap);
2226 if(device->FontsoundMap.size > 0)
2228 WARN("(%p) Deleting %d Fontsound(s)\n", device, device->FontsoundMap.size);
2229 ReleaseALFontsounds(device);
2231 ResetUIntMap(&device->FontsoundMap);
2233 free(device->Bs2b);
2234 device->Bs2b = NULL;
2236 AL_STRING_DEINIT(device->DeviceName);
2238 al_free(device->DryBuffer);
2239 device->DryBuffer = NULL;
2241 al_free(device);
2245 void ALCdevice_IncRef(ALCdevice *device)
2247 uint ref;
2248 ref = IncrementRef(&device->ref);
2249 TRACEREF("%p increasing refcount to %u\n", device, ref);
2252 void ALCdevice_DecRef(ALCdevice *device)
2254 uint ref;
2255 ref = DecrementRef(&device->ref);
2256 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2257 if(ref == 0) FreeDevice(device);
2260 /* VerifyDevice
2262 * Checks if the device handle is valid, and increments its ref count if so.
2264 static ALCdevice *VerifyDevice(ALCdevice *device)
2266 ALCdevice *tmpDevice;
2268 if(!device)
2269 return NULL;
2271 LockLists();
2272 tmpDevice = ATOMIC_LOAD(&DeviceList);
2273 while(tmpDevice && tmpDevice != device)
2274 tmpDevice = tmpDevice->next;
2276 if(tmpDevice)
2277 ALCdevice_IncRef(tmpDevice);
2278 UnlockLists();
2279 return tmpDevice;
2283 /* InitContext
2285 * Initializes context fields
2287 static ALvoid InitContext(ALCcontext *Context)
2289 //Initialise listener
2290 Context->Listener->Gain = 1.0f;
2291 Context->Listener->MetersPerUnit = 1.0f;
2292 aluVectorSet(&Context->Listener->Position, 0.0f, 0.0f, 0.0f, 1.0f);
2293 aluVectorSet(&Context->Listener->Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2294 Context->Listener->Forward[0] = 0.0f;
2295 Context->Listener->Forward[1] = 0.0f;
2296 Context->Listener->Forward[2] = -1.0f;
2297 Context->Listener->Up[0] = 0.0f;
2298 Context->Listener->Up[1] = 1.0f;
2299 Context->Listener->Up[2] = 0.0f;
2300 aluMatrixSet(&Context->Listener->Params.Matrix,
2301 1.0f, 0.0f, 0.0f, 0.0f,
2302 0.0f, 1.0f, 0.0f, 0.0f,
2303 0.0f, 0.0f, 1.0f, 0.0f,
2304 0.0f, 0.0f, 0.0f, 1.0f
2306 aluVectorSet(&Context->Listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2308 //Validate Context
2309 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2310 ATOMIC_INIT(&Context->UpdateSources, AL_FALSE);
2311 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
2312 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2314 //Set globals
2315 Context->DistanceModel = DefaultDistanceModel;
2316 Context->SourceDistanceModel = AL_FALSE;
2317 Context->DopplerFactor = 1.0f;
2318 Context->DopplerVelocity = 1.0f;
2319 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2320 Context->DeferUpdates = AL_FALSE;
2322 Context->ExtensionList = alExtList;
2326 /* FreeContext
2328 * Cleans up the context, and destroys any remaining objects the app failed to
2329 * delete. Called once there's no more references on the context.
2331 static void FreeContext(ALCcontext *context)
2333 TRACE("%p\n", context);
2335 if(context->SourceMap.size > 0)
2337 WARN("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
2338 ReleaseALSources(context);
2340 ResetUIntMap(&context->SourceMap);
2342 if(context->EffectSlotMap.size > 0)
2344 WARN("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
2345 ReleaseALAuxiliaryEffectSlots(context);
2347 ResetUIntMap(&context->EffectSlotMap);
2349 al_free(context->Voices);
2350 context->Voices = NULL;
2351 context->VoiceCount = 0;
2352 context->MaxVoices = 0;
2354 VECTOR_DEINIT(context->ActiveAuxSlots);
2356 ALCdevice_DecRef(context->Device);
2357 context->Device = NULL;
2359 //Invalidate context
2360 memset(context, 0, sizeof(ALCcontext));
2361 al_free(context);
2364 /* ReleaseContext
2366 * Removes the context reference from the given device and removes it from
2367 * being current on the running thread or globally.
2369 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
2371 ALCcontext *nextctx;
2372 ALCcontext *origctx;
2374 if(altss_get(LocalContext) == context)
2376 WARN("%p released while current on thread\n", context);
2377 altss_set(LocalContext, NULL);
2378 ALCcontext_DecRef(context);
2381 origctx = context;
2382 if(ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &GlobalContext, &origctx, NULL))
2383 ALCcontext_DecRef(context);
2385 ALCdevice_Lock(device);
2386 origctx = context;
2387 nextctx = context->next;
2388 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &device->ContextList, &origctx, nextctx))
2390 ALCcontext *list;
2391 do {
2392 list = origctx;
2393 origctx = context;
2394 } while(!COMPARE_EXCHANGE(&list->next, &origctx, nextctx));
2396 ALCdevice_Unlock(device);
2398 ALCcontext_DecRef(context);
2401 void ALCcontext_IncRef(ALCcontext *context)
2403 uint ref;
2404 ref = IncrementRef(&context->ref);
2405 TRACEREF("%p increasing refcount to %u\n", context, ref);
2408 void ALCcontext_DecRef(ALCcontext *context)
2410 uint ref;
2411 ref = DecrementRef(&context->ref);
2412 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2413 if(ref == 0) FreeContext(context);
2416 static void ReleaseThreadCtx(void *ptr)
2418 WARN("%p current for thread being destroyed\n", ptr);
2419 ALCcontext_DecRef(ptr);
2422 /* VerifyContext
2424 * Checks that the given context is valid, and increments its reference count.
2426 static ALCcontext *VerifyContext(ALCcontext *context)
2428 ALCdevice *dev;
2430 LockLists();
2431 dev = ATOMIC_LOAD(&DeviceList);
2432 while(dev)
2434 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList);
2435 while(ctx)
2437 if(ctx == context)
2439 ALCcontext_IncRef(ctx);
2440 UnlockLists();
2441 return ctx;
2443 ctx = ctx->next;
2445 dev = dev->next;
2447 UnlockLists();
2449 return NULL;
2453 /* GetContextRef
2455 * Returns the currently active context for this thread, and adds a reference
2456 * without locking it.
2458 ALCcontext *GetContextRef(void)
2460 ALCcontext *context;
2462 context = altss_get(LocalContext);
2463 if(context)
2464 ALCcontext_IncRef(context);
2465 else
2467 LockLists();
2468 context = ATOMIC_LOAD(&GlobalContext);
2469 if(context)
2470 ALCcontext_IncRef(context);
2471 UnlockLists();
2474 return context;
2478 /************************************************
2479 * Standard ALC functions
2480 ************************************************/
2482 /* alcGetError
2484 * Return last ALC generated error code for the given device
2486 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2488 ALCenum errorCode;
2490 if(VerifyDevice(device))
2492 errorCode = ATOMIC_EXCHANGE(ALCenum, &device->LastError, ALC_NO_ERROR);
2493 ALCdevice_DecRef(device);
2495 else
2496 errorCode = ATOMIC_EXCHANGE(ALCenum, &LastNullDeviceError, ALC_NO_ERROR);
2498 return errorCode;
2502 /* alcSuspendContext
2504 * Suspends updates for the given context
2506 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2508 if(!SuspendDefers)
2509 return;
2511 context = VerifyContext(context);
2512 if(!context)
2513 alcSetError(NULL, ALC_INVALID_CONTEXT);
2514 else
2516 ALCcontext_DeferUpdates(context);
2517 ALCcontext_DecRef(context);
2521 /* alcProcessContext
2523 * Resumes processing updates for the given context
2525 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2527 if(!SuspendDefers)
2528 return;
2530 context = VerifyContext(context);
2531 if(!context)
2532 alcSetError(NULL, ALC_INVALID_CONTEXT);
2533 else
2535 ALCcontext_ProcessUpdates(context);
2536 ALCcontext_DecRef(context);
2541 /* alcGetString
2543 * Returns information about the device, and error strings
2545 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2547 const ALCchar *value = NULL;
2549 switch(param)
2551 case ALC_NO_ERROR:
2552 value = alcNoError;
2553 break;
2555 case ALC_INVALID_ENUM:
2556 value = alcErrInvalidEnum;
2557 break;
2559 case ALC_INVALID_VALUE:
2560 value = alcErrInvalidValue;
2561 break;
2563 case ALC_INVALID_DEVICE:
2564 value = alcErrInvalidDevice;
2565 break;
2567 case ALC_INVALID_CONTEXT:
2568 value = alcErrInvalidContext;
2569 break;
2571 case ALC_OUT_OF_MEMORY:
2572 value = alcErrOutOfMemory;
2573 break;
2575 case ALC_DEVICE_SPECIFIER:
2576 value = alcDefaultName;
2577 break;
2579 case ALC_ALL_DEVICES_SPECIFIER:
2580 if(VerifyDevice(Device))
2582 value = al_string_get_cstr(Device->DeviceName);
2583 ALCdevice_DecRef(Device);
2585 else
2587 ProbeAllDevicesList();
2588 value = al_string_get_cstr(alcAllDevicesList);
2590 break;
2592 case ALC_CAPTURE_DEVICE_SPECIFIER:
2593 if(VerifyDevice(Device))
2595 value = al_string_get_cstr(Device->DeviceName);
2596 ALCdevice_DecRef(Device);
2598 else
2600 ProbeCaptureDeviceList();
2601 value = al_string_get_cstr(alcCaptureDeviceList);
2603 break;
2605 /* Default devices are always first in the list */
2606 case ALC_DEFAULT_DEVICE_SPECIFIER:
2607 value = alcDefaultName;
2608 break;
2610 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2611 if(al_string_empty(alcAllDevicesList))
2612 ProbeAllDevicesList();
2614 Device = VerifyDevice(Device);
2616 free(alcDefaultAllDevicesSpecifier);
2617 alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2618 if(!alcDefaultAllDevicesSpecifier)
2619 alcSetError(Device, ALC_OUT_OF_MEMORY);
2621 value = alcDefaultAllDevicesSpecifier;
2622 if(Device) ALCdevice_DecRef(Device);
2623 break;
2625 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2626 if(al_string_empty(alcCaptureDeviceList))
2627 ProbeCaptureDeviceList();
2629 Device = VerifyDevice(Device);
2631 free(alcCaptureDefaultDeviceSpecifier);
2632 alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcCaptureDeviceList));
2633 if(!alcCaptureDefaultDeviceSpecifier)
2634 alcSetError(Device, ALC_OUT_OF_MEMORY);
2636 value = alcCaptureDefaultDeviceSpecifier;
2637 if(Device) ALCdevice_DecRef(Device);
2638 break;
2640 case ALC_EXTENSIONS:
2641 if(!VerifyDevice(Device))
2642 value = alcNoDeviceExtList;
2643 else
2645 value = alcExtensionList;
2646 ALCdevice_DecRef(Device);
2648 break;
2650 default:
2651 Device = VerifyDevice(Device);
2652 alcSetError(Device, ALC_INVALID_ENUM);
2653 if(Device) ALCdevice_DecRef(Device);
2654 break;
2657 return value;
2661 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2663 ALCsizei i;
2665 if(size <= 0 || values == NULL)
2667 alcSetError(device, ALC_INVALID_VALUE);
2668 return 0;
2671 if(!device)
2673 switch(param)
2675 case ALC_MAJOR_VERSION:
2676 values[0] = alcMajorVersion;
2677 return 1;
2678 case ALC_MINOR_VERSION:
2679 values[0] = alcMinorVersion;
2680 return 1;
2682 case ALC_ATTRIBUTES_SIZE:
2683 case ALC_ALL_ATTRIBUTES:
2684 case ALC_FREQUENCY:
2685 case ALC_REFRESH:
2686 case ALC_SYNC:
2687 case ALC_MONO_SOURCES:
2688 case ALC_STEREO_SOURCES:
2689 case ALC_CAPTURE_SAMPLES:
2690 case ALC_FORMAT_CHANNELS_SOFT:
2691 case ALC_FORMAT_TYPE_SOFT:
2692 alcSetError(NULL, ALC_INVALID_DEVICE);
2693 return 0;
2695 default:
2696 alcSetError(NULL, ALC_INVALID_ENUM);
2697 return 0;
2699 return 0;
2702 if(device->Type == Capture)
2704 switch(param)
2706 case ALC_CAPTURE_SAMPLES:
2707 V0(device->Backend,lock)();
2708 values[0] = V0(device->Backend,availableSamples)();
2709 V0(device->Backend,unlock)();
2710 return 1;
2712 case ALC_CONNECTED:
2713 values[0] = device->Connected;
2714 return 1;
2716 default:
2717 alcSetError(device, ALC_INVALID_ENUM);
2718 return 0;
2720 return 0;
2723 /* render device */
2724 switch(param)
2726 case ALC_MAJOR_VERSION:
2727 values[0] = alcMajorVersion;
2728 return 1;
2730 case ALC_MINOR_VERSION:
2731 values[0] = alcMinorVersion;
2732 return 1;
2734 case ALC_EFX_MAJOR_VERSION:
2735 values[0] = alcEFXMajorVersion;
2736 return 1;
2738 case ALC_EFX_MINOR_VERSION:
2739 values[0] = alcEFXMinorVersion;
2740 return 1;
2742 case ALC_ATTRIBUTES_SIZE:
2743 values[0] = 15;
2744 return 1;
2746 case ALC_ALL_ATTRIBUTES:
2747 if(size < 15)
2749 alcSetError(device, ALC_INVALID_VALUE);
2750 return 0;
2753 i = 0;
2754 values[i++] = ALC_FREQUENCY;
2755 values[i++] = device->Frequency;
2757 if(device->Type != Loopback)
2759 values[i++] = ALC_REFRESH;
2760 values[i++] = device->Frequency / device->UpdateSize;
2762 values[i++] = ALC_SYNC;
2763 values[i++] = ALC_FALSE;
2765 else
2767 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2768 values[i++] = device->FmtChans;
2770 values[i++] = ALC_FORMAT_TYPE_SOFT;
2771 values[i++] = device->FmtType;
2774 values[i++] = ALC_MONO_SOURCES;
2775 values[i++] = device->NumMonoSources;
2777 values[i++] = ALC_STEREO_SOURCES;
2778 values[i++] = device->NumStereoSources;
2780 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2781 values[i++] = device->NumAuxSends;
2783 values[i++] = ALC_HRTF_SOFT;
2784 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2786 values[i++] = 0;
2787 return i;
2789 case ALC_FREQUENCY:
2790 values[0] = device->Frequency;
2791 return 1;
2793 case ALC_REFRESH:
2794 if(device->Type == Loopback)
2796 alcSetError(device, ALC_INVALID_DEVICE);
2797 return 0;
2799 values[0] = device->Frequency / device->UpdateSize;
2800 return 1;
2802 case ALC_SYNC:
2803 if(device->Type == Loopback)
2805 alcSetError(device, ALC_INVALID_DEVICE);
2806 return 0;
2808 values[0] = ALC_FALSE;
2809 return 1;
2811 case ALC_FORMAT_CHANNELS_SOFT:
2812 if(device->Type != Loopback)
2814 alcSetError(device, ALC_INVALID_DEVICE);
2815 return 0;
2817 values[0] = device->FmtChans;
2818 return 1;
2820 case ALC_FORMAT_TYPE_SOFT:
2821 if(device->Type != Loopback)
2823 alcSetError(device, ALC_INVALID_DEVICE);
2824 return 0;
2826 values[0] = device->FmtType;
2827 return 1;
2829 case ALC_MONO_SOURCES:
2830 values[0] = device->NumMonoSources;
2831 return 1;
2833 case ALC_STEREO_SOURCES:
2834 values[0] = device->NumStereoSources;
2835 return 1;
2837 case ALC_MAX_AUXILIARY_SENDS:
2838 values[0] = device->NumAuxSends;
2839 return 1;
2841 case ALC_CONNECTED:
2842 values[0] = device->Connected;
2843 return 1;
2845 case ALC_HRTF_SOFT:
2846 values[0] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2847 return 1;
2849 default:
2850 alcSetError(device, ALC_INVALID_ENUM);
2851 return 0;
2853 return 0;
2856 /* alcGetIntegerv
2858 * Returns information about the device and the version of OpenAL
2860 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2862 device = VerifyDevice(device);
2863 if(size <= 0 || values == NULL)
2864 alcSetError(device, ALC_INVALID_VALUE);
2865 else
2866 GetIntegerv(device, param, size, values);
2867 if(device) ALCdevice_DecRef(device);
2870 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
2872 ALCint *ivals;
2873 ALsizei i;
2875 device = VerifyDevice(device);
2876 if(size <= 0 || values == NULL)
2877 alcSetError(device, ALC_INVALID_VALUE);
2878 else if(!device || device->Type == Capture)
2880 ivals = malloc(size * sizeof(ALCint));
2881 size = GetIntegerv(device, pname, size, ivals);
2882 for(i = 0;i < size;i++)
2883 values[i] = ivals[i];
2884 free(ivals);
2886 else /* render device */
2888 switch(pname)
2890 case ALC_ATTRIBUTES_SIZE:
2891 *values = 17;
2892 break;
2894 case ALC_ALL_ATTRIBUTES:
2895 if(size < 17)
2896 alcSetError(device, ALC_INVALID_VALUE);
2897 else
2899 int i = 0;
2901 V0(device->Backend,lock)();
2902 values[i++] = ALC_FREQUENCY;
2903 values[i++] = device->Frequency;
2905 if(device->Type != Loopback)
2907 values[i++] = ALC_REFRESH;
2908 values[i++] = device->Frequency / device->UpdateSize;
2910 values[i++] = ALC_SYNC;
2911 values[i++] = ALC_FALSE;
2913 else
2915 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2916 values[i++] = device->FmtChans;
2918 values[i++] = ALC_FORMAT_TYPE_SOFT;
2919 values[i++] = device->FmtType;
2922 values[i++] = ALC_MONO_SOURCES;
2923 values[i++] = device->NumMonoSources;
2925 values[i++] = ALC_STEREO_SOURCES;
2926 values[i++] = device->NumStereoSources;
2928 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2929 values[i++] = device->NumAuxSends;
2931 values[i++] = ALC_HRTF_SOFT;
2932 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2934 values[i++] = ALC_DEVICE_CLOCK_SOFT;
2935 values[i++] = device->ClockBase +
2936 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2938 values[i++] = 0;
2939 V0(device->Backend,unlock)();
2941 break;
2943 case ALC_DEVICE_CLOCK_SOFT:
2944 V0(device->Backend,lock)();
2945 *values = device->ClockBase +
2946 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2947 V0(device->Backend,unlock)();
2948 break;
2950 default:
2951 ivals = malloc(size * sizeof(ALCint));
2952 size = GetIntegerv(device, pname, size, ivals);
2953 for(i = 0;i < size;i++)
2954 values[i] = ivals[i];
2955 free(ivals);
2956 break;
2959 if(device)
2960 ALCdevice_DecRef(device);
2964 /* alcIsExtensionPresent
2966 * Determines if there is support for a particular extension
2968 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2970 ALCboolean bResult = ALC_FALSE;
2972 device = VerifyDevice(device);
2974 if(!extName)
2975 alcSetError(device, ALC_INVALID_VALUE);
2976 else
2978 size_t len = strlen(extName);
2979 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2980 while(ptr && *ptr)
2982 if(strncasecmp(ptr, extName, len) == 0 &&
2983 (ptr[len] == '\0' || isspace(ptr[len])))
2985 bResult = ALC_TRUE;
2986 break;
2988 if((ptr=strchr(ptr, ' ')) != NULL)
2990 do {
2991 ++ptr;
2992 } while(isspace(*ptr));
2996 if(device)
2997 ALCdevice_DecRef(device);
2998 return bResult;
3002 /* alcGetProcAddress
3004 * Retrieves the function address for a particular extension function
3006 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3008 ALCvoid *ptr = NULL;
3010 if(!funcName)
3012 device = VerifyDevice(device);
3013 alcSetError(device, ALC_INVALID_VALUE);
3014 if(device) ALCdevice_DecRef(device);
3016 else
3018 ALsizei i = 0;
3019 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
3020 i++;
3021 ptr = alcFunctions[i].address;
3024 return ptr;
3028 /* alcGetEnumValue
3030 * Get the value for a particular ALC enumeration name
3032 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3034 ALCenum val = 0;
3036 if(!enumName)
3038 device = VerifyDevice(device);
3039 alcSetError(device, ALC_INVALID_VALUE);
3040 if(device) ALCdevice_DecRef(device);
3042 else
3044 ALsizei i = 0;
3045 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
3046 i++;
3047 val = enumeration[i].value;
3050 return val;
3054 /* alcCreateContext
3056 * Create and attach a context to the given device.
3058 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3060 ALCcontext *ALContext;
3061 ALCenum err;
3063 LockLists();
3064 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
3066 UnlockLists();
3067 alcSetError(device, ALC_INVALID_DEVICE);
3068 if(device) ALCdevice_DecRef(device);
3069 return NULL;
3072 ATOMIC_STORE(&device->LastError, ALC_NO_ERROR);
3074 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3076 UnlockLists();
3077 alcSetError(device, err);
3078 if(err == ALC_INVALID_DEVICE)
3080 V0(device->Backend,lock)();
3081 aluHandleDisconnect(device);
3082 V0(device->Backend,unlock)();
3084 ALCdevice_DecRef(device);
3085 return NULL;
3088 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3089 if(ALContext)
3091 InitRef(&ALContext->ref, 1);
3092 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3094 VECTOR_INIT(ALContext->ActiveAuxSlots);
3096 ALContext->VoiceCount = 0;
3097 ALContext->MaxVoices = 256;
3098 ALContext->Voices = al_calloc(16, ALContext->MaxVoices * sizeof(ALContext->Voices[0]));
3100 if(!ALContext || !ALContext->Voices)
3102 if(!ATOMIC_LOAD(&device->ContextList))
3104 V0(device->Backend,stop)();
3105 device->Flags &= ~DEVICE_RUNNING;
3107 UnlockLists();
3109 if(ALContext)
3111 al_free(ALContext->Voices);
3112 ALContext->Voices = NULL;
3114 VECTOR_DEINIT(ALContext->ActiveAuxSlots);
3116 al_free(ALContext);
3117 ALContext = NULL;
3120 alcSetError(device, ALC_OUT_OF_MEMORY);
3121 ALCdevice_DecRef(device);
3122 return NULL;
3125 ALContext->Device = device;
3126 ALCdevice_IncRef(device);
3127 InitContext(ALContext);
3130 ALCcontext *head = ATOMIC_LOAD(&device->ContextList);
3131 do {
3132 ALContext->next = head;
3133 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCcontext*, &device->ContextList, &head, ALContext));
3135 UnlockLists();
3137 ALCdevice_DecRef(device);
3139 TRACE("Created context %p\n", ALContext);
3140 return ALContext;
3143 /* alcDestroyContext
3145 * Remove a context from its device
3147 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3149 ALCdevice *Device;
3151 LockLists();
3152 /* alcGetContextsDevice sets an error for invalid contexts */
3153 Device = alcGetContextsDevice(context);
3154 if(Device)
3156 ReleaseContext(context, Device);
3157 if(!ATOMIC_LOAD(&Device->ContextList))
3159 V0(Device->Backend,stop)();
3160 Device->Flags &= ~DEVICE_RUNNING;
3163 UnlockLists();
3167 /* alcGetCurrentContext
3169 * Returns the currently active context on the calling thread
3171 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3173 ALCcontext *Context = altss_get(LocalContext);
3174 if(!Context) Context = ATOMIC_LOAD(&GlobalContext);
3175 return Context;
3178 /* alcGetThreadContext
3180 * Returns the currently active thread-local context
3182 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3184 return altss_get(LocalContext);
3188 /* alcMakeContextCurrent
3190 * Makes the given context the active process-wide context, and removes the
3191 * thread-local context for the calling thread.
3193 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3195 /* context must be valid or NULL */
3196 if(context && !(context=VerifyContext(context)))
3198 alcSetError(NULL, ALC_INVALID_CONTEXT);
3199 return ALC_FALSE;
3201 /* context's reference count is already incremented */
3202 context = ATOMIC_EXCHANGE(ALCcontext*, &GlobalContext, context);
3203 if(context) ALCcontext_DecRef(context);
3205 if((context=altss_get(LocalContext)) != NULL)
3207 altss_set(LocalContext, NULL);
3208 ALCcontext_DecRef(context);
3211 return ALC_TRUE;
3214 /* alcSetThreadContext
3216 * Makes the given context the active context for the current thread
3218 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3220 ALCcontext *old;
3222 /* context must be valid or NULL */
3223 if(context && !(context=VerifyContext(context)))
3225 alcSetError(NULL, ALC_INVALID_CONTEXT);
3226 return ALC_FALSE;
3228 /* context's reference count is already incremented */
3229 old = altss_get(LocalContext);
3230 altss_set(LocalContext, context);
3231 if(old) ALCcontext_DecRef(old);
3233 return ALC_TRUE;
3237 /* alcGetContextsDevice
3239 * Returns the device that a particular context is attached to
3241 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3243 ALCdevice *Device;
3245 if(!(Context=VerifyContext(Context)))
3247 alcSetError(NULL, ALC_INVALID_CONTEXT);
3248 return NULL;
3250 Device = Context->Device;
3251 ALCcontext_DecRef(Context);
3253 return Device;
3257 /* alcOpenDevice
3259 * Opens the named device.
3261 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3263 const ALCchar *fmt;
3264 ALCdevice *device;
3265 ALCenum err;
3267 DO_INITCONFIG();
3269 if(!PlaybackBackend.name)
3271 alcSetError(NULL, ALC_INVALID_VALUE);
3272 return NULL;
3275 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3276 deviceName = NULL;
3278 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3279 if(!device)
3281 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3282 return NULL;
3285 //Validate device
3286 InitRef(&device->ref, 1);
3287 device->Connected = ALC_TRUE;
3288 device->Type = Playback;
3289 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3291 device->Flags = 0;
3292 device->Bs2b = NULL;
3293 device->Hrtf_Mode = DisabledHrtf;
3294 AL_STRING_INIT(device->DeviceName);
3295 device->DryBuffer = NULL;
3297 ATOMIC_INIT(&device->ContextList, NULL);
3299 device->ClockBase = 0;
3300 device->SamplesDone = 0;
3302 device->MaxNoOfSources = 256;
3303 device->AuxiliaryEffectSlotMax = 4;
3304 device->NumAuxSends = MAX_SENDS;
3306 InitUIntMap(&device->BufferMap, ~0);
3307 InitUIntMap(&device->EffectMap, ~0);
3308 InitUIntMap(&device->FilterMap, ~0);
3309 InitUIntMap(&device->SfontMap, ~0);
3310 InitUIntMap(&device->PresetMap, ~0);
3311 InitUIntMap(&device->FontsoundMap, ~0);
3313 //Set output format
3314 device->FmtChans = DevFmtChannelsDefault;
3315 device->FmtType = DevFmtTypeDefault;
3316 device->Frequency = DEFAULT_OUTPUT_RATE;
3317 device->IsHeadphones = AL_FALSE;
3318 device->NumUpdates = 4;
3319 device->UpdateSize = 1024;
3321 if(!PlaybackBackend.getFactory)
3322 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3323 ALCbackend_Playback);
3324 else
3326 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3327 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3329 if(!device->Backend)
3331 al_free(device);
3332 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3333 return NULL;
3337 if(ConfigValueStr(NULL, "channels", &fmt))
3339 static const struct {
3340 const char name[16];
3341 enum DevFmtChannels chans;
3342 } chanlist[] = {
3343 { "mono", DevFmtMono },
3344 { "stereo", DevFmtStereo },
3345 { "quad", DevFmtQuad },
3346 { "surround51", DevFmtX51 },
3347 { "surround61", DevFmtX61 },
3348 { "surround71", DevFmtX71 },
3349 { "surround51rear", DevFmtX51Rear },
3351 size_t i;
3353 for(i = 0;i < COUNTOF(chanlist);i++)
3355 if(strcasecmp(chanlist[i].name, fmt) == 0)
3357 device->FmtChans = chanlist[i].chans;
3358 device->Flags |= DEVICE_CHANNELS_REQUEST;
3359 break;
3362 if(i == COUNTOF(chanlist))
3363 ERR("Unsupported channels: %s\n", fmt);
3365 if(ConfigValueStr(NULL, "sample-type", &fmt))
3367 static const struct {
3368 const char name[16];
3369 enum DevFmtType type;
3370 } typelist[] = {
3371 { "int8", DevFmtByte },
3372 { "uint8", DevFmtUByte },
3373 { "int16", DevFmtShort },
3374 { "uint16", DevFmtUShort },
3375 { "int32", DevFmtInt },
3376 { "uint32", DevFmtUInt },
3377 { "float32", DevFmtFloat },
3379 size_t i;
3381 for(i = 0;i < COUNTOF(typelist);i++)
3383 if(strcasecmp(typelist[i].name, fmt) == 0)
3385 device->FmtType = typelist[i].type;
3386 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3387 break;
3390 if(i == COUNTOF(typelist))
3391 ERR("Unsupported sample-type: %s\n", fmt);
3394 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
3396 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3397 if(device->Frequency < MIN_OUTPUT_RATE)
3398 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3399 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3402 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
3403 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3405 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
3406 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3407 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
3408 device->UpdateSize = (device->UpdateSize+3)&~3;
3410 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3411 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3413 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3414 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3416 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3417 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3419 device->NumStereoSources = 1;
3420 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3422 device->Synth = SynthCreate(device);
3423 if(!device->Synth)
3425 DELETE_OBJ(device->Backend);
3426 al_free(device);
3427 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3428 return NULL;
3431 // Find a playback device to open
3432 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3434 DELETE_OBJ(device->Synth);
3435 DELETE_OBJ(device->Backend);
3436 al_free(device);
3437 alcSetError(NULL, err);
3438 return NULL;
3441 if(DefaultEffect.type != AL_EFFECT_NULL)
3443 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3444 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3446 device->DefaultSlot = NULL;
3447 ERR("Failed to initialize the default effect slot\n");
3449 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3451 ALeffectState *state = device->DefaultSlot->EffectState;
3452 device->DefaultSlot = NULL;
3453 DELETE_OBJ(state);
3454 ERR("Failed to initialize the default effect\n");
3459 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3460 do {
3461 device->next = head;
3462 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3465 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3466 return device;
3469 /* alcCloseDevice
3471 * Closes the given device.
3473 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3475 ALCdevice *list, *origdev, *nextdev;
3476 ALCcontext *ctx;
3478 LockLists();
3479 list = ATOMIC_LOAD(&DeviceList);
3480 do {
3481 if(list == device)
3482 break;
3483 } while((list=list->next) != NULL);
3484 if(!list || list->Type == Capture)
3486 alcSetError(list, ALC_INVALID_DEVICE);
3487 UnlockLists();
3488 return ALC_FALSE;
3491 origdev = device;
3492 nextdev = device->next;
3493 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &origdev, nextdev))
3495 do {
3496 list = origdev;
3497 origdev = device;
3498 } while(!COMPARE_EXCHANGE(&list->next, &origdev, nextdev));
3500 UnlockLists();
3502 ctx = ATOMIC_LOAD(&device->ContextList);
3503 while(ctx != NULL)
3505 ALCcontext *next = ctx->next;
3506 WARN("Releasing context %p\n", ctx);
3507 ReleaseContext(ctx, device);
3508 ctx = next;
3510 if((device->Flags&DEVICE_RUNNING))
3511 V0(device->Backend,stop)();
3512 device->Flags &= ~DEVICE_RUNNING;
3514 ALCdevice_DecRef(device);
3516 return ALC_TRUE;
3520 /************************************************
3521 * ALC capture functions
3522 ************************************************/
3523 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3525 ALCdevice *device = NULL;
3526 ALCenum err;
3528 DO_INITCONFIG();
3530 if(!CaptureBackend.name)
3532 alcSetError(NULL, ALC_INVALID_VALUE);
3533 return NULL;
3536 if(samples <= 0)
3538 alcSetError(NULL, ALC_INVALID_VALUE);
3539 return NULL;
3542 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3543 deviceName = NULL;
3545 device = al_calloc(16, sizeof(ALCdevice));
3546 if(!device)
3548 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3549 return NULL;
3552 //Validate device
3553 InitRef(&device->ref, 1);
3554 device->Connected = ALC_TRUE;
3555 device->Type = Capture;
3557 AL_STRING_INIT(device->DeviceName);
3558 device->DryBuffer = NULL;
3560 InitUIntMap(&device->BufferMap, ~0);
3561 InitUIntMap(&device->EffectMap, ~0);
3562 InitUIntMap(&device->FilterMap, ~0);
3563 InitUIntMap(&device->SfontMap, ~0);
3564 InitUIntMap(&device->PresetMap, ~0);
3565 InitUIntMap(&device->FontsoundMap, ~0);
3567 if(!CaptureBackend.getFactory)
3568 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
3569 ALCbackend_Capture);
3570 else
3572 ALCbackendFactory *factory = CaptureBackend.getFactory();
3573 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
3575 if(!device->Backend)
3577 al_free(device);
3578 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3579 return NULL;
3582 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3583 device->Frequency = frequency;
3585 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
3586 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
3588 al_free(device);
3589 alcSetError(NULL, ALC_INVALID_ENUM);
3590 return NULL;
3592 device->IsHeadphones = AL_FALSE;
3594 device->UpdateSize = samples;
3595 device->NumUpdates = 1;
3597 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3599 al_free(device);
3600 alcSetError(NULL, err);
3601 return NULL;
3605 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3606 do {
3607 device->next = head;
3608 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3611 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3612 return device;
3615 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3617 ALCdevice *list, *next, *nextdev;
3619 LockLists();
3620 list = ATOMIC_LOAD(&DeviceList);
3621 do {
3622 if(list == device)
3623 break;
3624 } while((list=list->next) != NULL);
3625 if(!list || list->Type != Capture)
3627 alcSetError(list, ALC_INVALID_DEVICE);
3628 UnlockLists();
3629 return ALC_FALSE;
3632 next = device;
3633 nextdev = device->next;
3634 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &next, nextdev))
3636 do {
3637 list = next;
3638 next = device;
3639 } while(!COMPARE_EXCHANGE(&list->next, &next, nextdev));
3641 UnlockLists();
3643 ALCdevice_DecRef(device);
3645 return ALC_TRUE;
3648 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3650 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3651 alcSetError(device, ALC_INVALID_DEVICE);
3652 else
3654 V0(device->Backend,lock)();
3655 if(!device->Connected)
3656 alcSetError(device, ALC_INVALID_DEVICE);
3657 else if(!(device->Flags&DEVICE_RUNNING))
3659 if(V0(device->Backend,start)())
3660 device->Flags |= DEVICE_RUNNING;
3661 else
3663 aluHandleDisconnect(device);
3664 alcSetError(device, ALC_INVALID_DEVICE);
3667 V0(device->Backend,unlock)();
3670 if(device) ALCdevice_DecRef(device);
3673 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3675 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3676 alcSetError(device, ALC_INVALID_DEVICE);
3677 else
3679 V0(device->Backend,lock)();
3680 if((device->Flags&DEVICE_RUNNING))
3681 V0(device->Backend,stop)();
3682 device->Flags &= ~DEVICE_RUNNING;
3683 V0(device->Backend,unlock)();
3686 if(device) ALCdevice_DecRef(device);
3689 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3691 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3692 alcSetError(device, ALC_INVALID_DEVICE);
3693 else
3695 ALCenum err = ALC_INVALID_VALUE;
3697 V0(device->Backend,lock)();
3698 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
3699 err = V(device->Backend,captureSamples)(buffer, samples);
3700 V0(device->Backend,unlock)();
3702 if(err != ALC_NO_ERROR)
3703 alcSetError(device, err);
3705 if(device) ALCdevice_DecRef(device);
3709 /************************************************
3710 * ALC loopback functions
3711 ************************************************/
3713 /* alcLoopbackOpenDeviceSOFT
3715 * Open a loopback device, for manual rendering.
3717 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3719 ALCbackendFactory *factory;
3720 ALCdevice *device;
3722 DO_INITCONFIG();
3724 /* Make sure the device name, if specified, is us. */
3725 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3727 alcSetError(NULL, ALC_INVALID_VALUE);
3728 return NULL;
3731 device = al_calloc(16, sizeof(ALCdevice));
3732 if(!device)
3734 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3735 return NULL;
3738 //Validate device
3739 InitRef(&device->ref, 1);
3740 device->Connected = ALC_TRUE;
3741 device->Type = Loopback;
3742 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3744 device->Flags = 0;
3745 device->Bs2b = NULL;
3746 device->Hrtf_Mode = DisabledHrtf;
3747 AL_STRING_INIT(device->DeviceName);
3748 device->DryBuffer = NULL;
3750 ATOMIC_INIT(&device->ContextList, NULL);
3752 device->ClockBase = 0;
3753 device->SamplesDone = 0;
3755 device->MaxNoOfSources = 256;
3756 device->AuxiliaryEffectSlotMax = 4;
3757 device->NumAuxSends = MAX_SENDS;
3759 InitUIntMap(&device->BufferMap, ~0);
3760 InitUIntMap(&device->EffectMap, ~0);
3761 InitUIntMap(&device->FilterMap, ~0);
3762 InitUIntMap(&device->SfontMap, ~0);
3763 InitUIntMap(&device->PresetMap, ~0);
3764 InitUIntMap(&device->FontsoundMap, ~0);
3766 factory = ALCloopbackFactory_getFactory();
3767 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
3768 if(!device->Backend)
3770 al_free(device);
3771 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3772 return NULL;
3775 //Set output format
3776 device->NumUpdates = 0;
3777 device->UpdateSize = 0;
3779 device->Frequency = DEFAULT_OUTPUT_RATE;
3780 device->FmtChans = DevFmtChannelsDefault;
3781 device->FmtType = DevFmtTypeDefault;
3782 device->IsHeadphones = AL_FALSE;
3784 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3785 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3787 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3788 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3790 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3791 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3793 device->NumStereoSources = 1;
3794 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3796 device->Synth = SynthCreate(device);
3797 if(!device->Synth)
3799 DELETE_OBJ(device->Backend);
3800 al_free(device);
3801 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3802 return NULL;
3805 // Open the "backend"
3806 V(device->Backend,open)("Loopback");
3809 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3810 do {
3811 device->next = head;
3812 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3815 TRACE("Created device %p\n", device);
3816 return device;
3819 /* alcIsRenderFormatSupportedSOFT
3821 * Determines if the loopback device supports the given format for rendering.
3823 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3825 ALCboolean ret = ALC_FALSE;
3827 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3828 alcSetError(device, ALC_INVALID_DEVICE);
3829 else if(freq <= 0)
3830 alcSetError(device, ALC_INVALID_VALUE);
3831 else
3833 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3834 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3835 freq >= MIN_OUTPUT_RATE)
3836 ret = ALC_TRUE;
3838 if(device) ALCdevice_DecRef(device);
3840 return ret;
3843 /* alcRenderSamplesSOFT
3845 * Renders some samples into a buffer, using the format last set by the
3846 * attributes given to alcCreateContext.
3848 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3850 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3851 alcSetError(device, ALC_INVALID_DEVICE);
3852 else if(samples < 0 || (samples > 0 && buffer == NULL))
3853 alcSetError(device, ALC_INVALID_VALUE);
3854 else
3855 aluMixData(device, buffer, samples);
3856 if(device) ALCdevice_DecRef(device);
3860 /************************************************
3861 * ALC DSP pause/resume functions
3862 ************************************************/
3864 /* alcDevicePauseSOFT
3866 * Pause the DSP to stop audio processing.
3868 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
3870 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3871 alcSetError(device, ALC_INVALID_DEVICE);
3872 else
3874 LockLists();
3875 if((device->Flags&DEVICE_RUNNING))
3876 V0(device->Backend,stop)();
3877 device->Flags &= ~DEVICE_RUNNING;
3878 device->Flags |= DEVICE_PAUSED;
3879 UnlockLists();
3881 if(device) ALCdevice_DecRef(device);
3884 /* alcDeviceResumeSOFT
3886 * Resume the DSP to restart audio processing.
3888 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
3890 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3891 alcSetError(device, ALC_INVALID_DEVICE);
3892 else
3894 LockLists();
3895 if((device->Flags&DEVICE_PAUSED))
3897 device->Flags &= ~DEVICE_PAUSED;
3898 if(ATOMIC_LOAD(&device->ContextList) != NULL)
3900 if(V0(device->Backend,start)() != ALC_FALSE)
3901 device->Flags |= DEVICE_RUNNING;
3902 else
3904 alcSetError(device, ALC_INVALID_DEVICE);
3905 V0(device->Backend,lock)();
3906 aluHandleDisconnect(device);
3907 V0(device->Backend,unlock)();
3911 UnlockLists();
3913 if(device) ALCdevice_DecRef(device);