Add a flag for persistent mapping
[openal-soft.git] / Alc / ALc.c
blobdbdc298618b08a4c068f38dbb36dd6395e98daf8
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include "version.h"
25 #include <math.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <memory.h>
29 #include <ctype.h>
30 #include <signal.h>
32 #include "alMain.h"
33 #include "alSource.h"
34 #include "alListener.h"
35 #include "alThunk.h"
36 #include "alSource.h"
37 #include "alBuffer.h"
38 #include "alAuxEffectSlot.h"
39 #include "alError.h"
40 #include "mastering.h"
41 #include "bformatdec.h"
42 #include "alu.h"
43 #include "alconfig.h"
45 #include "fpu_modes.h"
46 #include "cpu_caps.h"
47 #include "compat.h"
48 #include "threads.h"
49 #include "alstring.h"
50 #include "almalloc.h"
52 #include "backends/base.h"
55 /************************************************
56 * Backends
57 ************************************************/
58 struct BackendInfo {
59 const char *name;
60 ALCbackendFactory* (*getFactory)(void);
63 static struct BackendInfo BackendList[] = {
64 #ifdef HAVE_JACK
65 { "jack", ALCjackBackendFactory_getFactory },
66 #endif
67 #ifdef HAVE_PULSEAUDIO
68 { "pulse", ALCpulseBackendFactory_getFactory },
69 #endif
70 #ifdef HAVE_ALSA
71 { "alsa", ALCalsaBackendFactory_getFactory },
72 #endif
73 #ifdef HAVE_COREAUDIO
74 { "core", ALCcoreAudioBackendFactory_getFactory },
75 #endif
76 #ifdef HAVE_OSS
77 { "oss", ALCossBackendFactory_getFactory },
78 #endif
79 #ifdef HAVE_SOLARIS
80 { "solaris", ALCsolarisBackendFactory_getFactory },
81 #endif
82 #ifdef HAVE_SNDIO
83 { "sndio", ALCsndioBackendFactory_getFactory },
84 #endif
85 #ifdef HAVE_QSA
86 { "qsa", ALCqsaBackendFactory_getFactory },
87 #endif
88 #ifdef HAVE_MMDEVAPI
89 { "mmdevapi", ALCmmdevBackendFactory_getFactory },
90 #endif
91 #ifdef HAVE_DSOUND
92 { "dsound", ALCdsoundBackendFactory_getFactory },
93 #endif
94 #ifdef HAVE_WINMM
95 { "winmm", ALCwinmmBackendFactory_getFactory },
96 #endif
97 #ifdef HAVE_PORTAUDIO
98 { "port", ALCportBackendFactory_getFactory },
99 #endif
100 #ifdef HAVE_OPENSL
101 { "opensl", ALCopenslBackendFactory_getFactory },
102 #endif
104 { "null", ALCnullBackendFactory_getFactory },
105 #ifdef HAVE_WAVE
106 { "wave", ALCwaveBackendFactory_getFactory },
107 #endif
109 static ALsizei BackendListSize = COUNTOF(BackendList);
110 #undef EmptyFuncs
112 static struct BackendInfo PlaybackBackend;
113 static struct BackendInfo CaptureBackend;
116 /************************************************
117 * Functions, enums, and errors
118 ************************************************/
119 #define DECL(x) { #x, (ALCvoid*)(x) }
120 static const struct {
121 const ALCchar *funcName;
122 ALCvoid *address;
123 } alcFunctions[] = {
124 DECL(alcCreateContext),
125 DECL(alcMakeContextCurrent),
126 DECL(alcProcessContext),
127 DECL(alcSuspendContext),
128 DECL(alcDestroyContext),
129 DECL(alcGetCurrentContext),
130 DECL(alcGetContextsDevice),
131 DECL(alcOpenDevice),
132 DECL(alcCloseDevice),
133 DECL(alcGetError),
134 DECL(alcIsExtensionPresent),
135 DECL(alcGetProcAddress),
136 DECL(alcGetEnumValue),
137 DECL(alcGetString),
138 DECL(alcGetIntegerv),
139 DECL(alcCaptureOpenDevice),
140 DECL(alcCaptureCloseDevice),
141 DECL(alcCaptureStart),
142 DECL(alcCaptureStop),
143 DECL(alcCaptureSamples),
145 DECL(alcSetThreadContext),
146 DECL(alcGetThreadContext),
148 DECL(alcLoopbackOpenDeviceSOFT),
149 DECL(alcIsRenderFormatSupportedSOFT),
150 DECL(alcRenderSamplesSOFT),
152 DECL(alcDevicePauseSOFT),
153 DECL(alcDeviceResumeSOFT),
155 DECL(alcGetStringiSOFT),
156 DECL(alcResetDeviceSOFT),
158 DECL(alcGetInteger64vSOFT),
160 DECL(alEnable),
161 DECL(alDisable),
162 DECL(alIsEnabled),
163 DECL(alGetString),
164 DECL(alGetBooleanv),
165 DECL(alGetIntegerv),
166 DECL(alGetFloatv),
167 DECL(alGetDoublev),
168 DECL(alGetBoolean),
169 DECL(alGetInteger),
170 DECL(alGetFloat),
171 DECL(alGetDouble),
172 DECL(alGetError),
173 DECL(alIsExtensionPresent),
174 DECL(alGetProcAddress),
175 DECL(alGetEnumValue),
176 DECL(alListenerf),
177 DECL(alListener3f),
178 DECL(alListenerfv),
179 DECL(alListeneri),
180 DECL(alListener3i),
181 DECL(alListeneriv),
182 DECL(alGetListenerf),
183 DECL(alGetListener3f),
184 DECL(alGetListenerfv),
185 DECL(alGetListeneri),
186 DECL(alGetListener3i),
187 DECL(alGetListeneriv),
188 DECL(alGenSources),
189 DECL(alDeleteSources),
190 DECL(alIsSource),
191 DECL(alSourcef),
192 DECL(alSource3f),
193 DECL(alSourcefv),
194 DECL(alSourcei),
195 DECL(alSource3i),
196 DECL(alSourceiv),
197 DECL(alGetSourcef),
198 DECL(alGetSource3f),
199 DECL(alGetSourcefv),
200 DECL(alGetSourcei),
201 DECL(alGetSource3i),
202 DECL(alGetSourceiv),
203 DECL(alSourcePlayv),
204 DECL(alSourceStopv),
205 DECL(alSourceRewindv),
206 DECL(alSourcePausev),
207 DECL(alSourcePlay),
208 DECL(alSourceStop),
209 DECL(alSourceRewind),
210 DECL(alSourcePause),
211 DECL(alSourceQueueBuffers),
212 DECL(alSourceUnqueueBuffers),
213 DECL(alGenBuffers),
214 DECL(alDeleteBuffers),
215 DECL(alIsBuffer),
216 DECL(alBufferData),
217 DECL(alBufferf),
218 DECL(alBuffer3f),
219 DECL(alBufferfv),
220 DECL(alBufferi),
221 DECL(alBuffer3i),
222 DECL(alBufferiv),
223 DECL(alGetBufferf),
224 DECL(alGetBuffer3f),
225 DECL(alGetBufferfv),
226 DECL(alGetBufferi),
227 DECL(alGetBuffer3i),
228 DECL(alGetBufferiv),
229 DECL(alDopplerFactor),
230 DECL(alDopplerVelocity),
231 DECL(alSpeedOfSound),
232 DECL(alDistanceModel),
234 DECL(alGenFilters),
235 DECL(alDeleteFilters),
236 DECL(alIsFilter),
237 DECL(alFilteri),
238 DECL(alFilteriv),
239 DECL(alFilterf),
240 DECL(alFilterfv),
241 DECL(alGetFilteri),
242 DECL(alGetFilteriv),
243 DECL(alGetFilterf),
244 DECL(alGetFilterfv),
245 DECL(alGenEffects),
246 DECL(alDeleteEffects),
247 DECL(alIsEffect),
248 DECL(alEffecti),
249 DECL(alEffectiv),
250 DECL(alEffectf),
251 DECL(alEffectfv),
252 DECL(alGetEffecti),
253 DECL(alGetEffectiv),
254 DECL(alGetEffectf),
255 DECL(alGetEffectfv),
256 DECL(alGenAuxiliaryEffectSlots),
257 DECL(alDeleteAuxiliaryEffectSlots),
258 DECL(alIsAuxiliaryEffectSlot),
259 DECL(alAuxiliaryEffectSloti),
260 DECL(alAuxiliaryEffectSlotiv),
261 DECL(alAuxiliaryEffectSlotf),
262 DECL(alAuxiliaryEffectSlotfv),
263 DECL(alGetAuxiliaryEffectSloti),
264 DECL(alGetAuxiliaryEffectSlotiv),
265 DECL(alGetAuxiliaryEffectSlotf),
266 DECL(alGetAuxiliaryEffectSlotfv),
268 DECL(alDeferUpdatesSOFT),
269 DECL(alProcessUpdatesSOFT),
271 DECL(alSourcedSOFT),
272 DECL(alSource3dSOFT),
273 DECL(alSourcedvSOFT),
274 DECL(alGetSourcedSOFT),
275 DECL(alGetSource3dSOFT),
276 DECL(alGetSourcedvSOFT),
277 DECL(alSourcei64SOFT),
278 DECL(alSource3i64SOFT),
279 DECL(alSourcei64vSOFT),
280 DECL(alGetSourcei64SOFT),
281 DECL(alGetSource3i64SOFT),
282 DECL(alGetSourcei64vSOFT),
284 DECL(alGetStringiSOFT),
286 DECL(alMapBufferSOFT),
287 DECL(alUnmapBufferSOFT),
289 #undef DECL
291 #define DECL(x) { #x, (x) }
292 static const struct {
293 const ALCchar *enumName;
294 ALCenum value;
295 } alcEnumerations[] = {
296 DECL(ALC_INVALID),
297 DECL(ALC_FALSE),
298 DECL(ALC_TRUE),
300 DECL(ALC_MAJOR_VERSION),
301 DECL(ALC_MINOR_VERSION),
302 DECL(ALC_ATTRIBUTES_SIZE),
303 DECL(ALC_ALL_ATTRIBUTES),
304 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
305 DECL(ALC_DEVICE_SPECIFIER),
306 DECL(ALC_ALL_DEVICES_SPECIFIER),
307 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
308 DECL(ALC_EXTENSIONS),
309 DECL(ALC_FREQUENCY),
310 DECL(ALC_REFRESH),
311 DECL(ALC_SYNC),
312 DECL(ALC_MONO_SOURCES),
313 DECL(ALC_STEREO_SOURCES),
314 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
315 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
316 DECL(ALC_CAPTURE_SAMPLES),
317 DECL(ALC_CONNECTED),
319 DECL(ALC_EFX_MAJOR_VERSION),
320 DECL(ALC_EFX_MINOR_VERSION),
321 DECL(ALC_MAX_AUXILIARY_SENDS),
323 DECL(ALC_FORMAT_CHANNELS_SOFT),
324 DECL(ALC_FORMAT_TYPE_SOFT),
326 DECL(ALC_MONO_SOFT),
327 DECL(ALC_STEREO_SOFT),
328 DECL(ALC_QUAD_SOFT),
329 DECL(ALC_5POINT1_SOFT),
330 DECL(ALC_6POINT1_SOFT),
331 DECL(ALC_7POINT1_SOFT),
332 DECL(ALC_BFORMAT3D_SOFT),
334 DECL(ALC_BYTE_SOFT),
335 DECL(ALC_UNSIGNED_BYTE_SOFT),
336 DECL(ALC_SHORT_SOFT),
337 DECL(ALC_UNSIGNED_SHORT_SOFT),
338 DECL(ALC_INT_SOFT),
339 DECL(ALC_UNSIGNED_INT_SOFT),
340 DECL(ALC_FLOAT_SOFT),
342 DECL(ALC_HRTF_SOFT),
343 DECL(ALC_DONT_CARE_SOFT),
344 DECL(ALC_HRTF_STATUS_SOFT),
345 DECL(ALC_HRTF_DISABLED_SOFT),
346 DECL(ALC_HRTF_ENABLED_SOFT),
347 DECL(ALC_HRTF_DENIED_SOFT),
348 DECL(ALC_HRTF_REQUIRED_SOFT),
349 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
350 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
351 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
352 DECL(ALC_HRTF_SPECIFIER_SOFT),
353 DECL(ALC_HRTF_ID_SOFT),
355 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
356 DECL(ALC_AMBISONIC_SCALING_SOFT),
357 DECL(ALC_AMBISONIC_ORDER_SOFT),
358 DECL(ALC_ACN_SOFT),
359 DECL(ALC_FUMA_SOFT),
360 DECL(ALC_N3D_SOFT),
361 DECL(ALC_SN3D_SOFT),
363 DECL(ALC_OUTPUT_LIMITER_SOFT),
365 DECL(ALC_NO_ERROR),
366 DECL(ALC_INVALID_DEVICE),
367 DECL(ALC_INVALID_CONTEXT),
368 DECL(ALC_INVALID_ENUM),
369 DECL(ALC_INVALID_VALUE),
370 DECL(ALC_OUT_OF_MEMORY),
373 DECL(AL_INVALID),
374 DECL(AL_NONE),
375 DECL(AL_FALSE),
376 DECL(AL_TRUE),
378 DECL(AL_SOURCE_RELATIVE),
379 DECL(AL_CONE_INNER_ANGLE),
380 DECL(AL_CONE_OUTER_ANGLE),
381 DECL(AL_PITCH),
382 DECL(AL_POSITION),
383 DECL(AL_DIRECTION),
384 DECL(AL_VELOCITY),
385 DECL(AL_LOOPING),
386 DECL(AL_BUFFER),
387 DECL(AL_GAIN),
388 DECL(AL_MIN_GAIN),
389 DECL(AL_MAX_GAIN),
390 DECL(AL_ORIENTATION),
391 DECL(AL_REFERENCE_DISTANCE),
392 DECL(AL_ROLLOFF_FACTOR),
393 DECL(AL_CONE_OUTER_GAIN),
394 DECL(AL_MAX_DISTANCE),
395 DECL(AL_SEC_OFFSET),
396 DECL(AL_SAMPLE_OFFSET),
397 DECL(AL_BYTE_OFFSET),
398 DECL(AL_SOURCE_TYPE),
399 DECL(AL_STATIC),
400 DECL(AL_STREAMING),
401 DECL(AL_UNDETERMINED),
402 DECL(AL_METERS_PER_UNIT),
403 DECL(AL_LOOP_POINTS_SOFT),
404 DECL(AL_DIRECT_CHANNELS_SOFT),
406 DECL(AL_DIRECT_FILTER),
407 DECL(AL_AUXILIARY_SEND_FILTER),
408 DECL(AL_AIR_ABSORPTION_FACTOR),
409 DECL(AL_ROOM_ROLLOFF_FACTOR),
410 DECL(AL_CONE_OUTER_GAINHF),
411 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
412 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
413 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
415 DECL(AL_SOURCE_STATE),
416 DECL(AL_INITIAL),
417 DECL(AL_PLAYING),
418 DECL(AL_PAUSED),
419 DECL(AL_STOPPED),
421 DECL(AL_BUFFERS_QUEUED),
422 DECL(AL_BUFFERS_PROCESSED),
424 DECL(AL_FORMAT_MONO8),
425 DECL(AL_FORMAT_MONO16),
426 DECL(AL_FORMAT_MONO_FLOAT32),
427 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
428 DECL(AL_FORMAT_STEREO8),
429 DECL(AL_FORMAT_STEREO16),
430 DECL(AL_FORMAT_STEREO_FLOAT32),
431 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
432 DECL(AL_FORMAT_MONO_IMA4),
433 DECL(AL_FORMAT_STEREO_IMA4),
434 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
435 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
436 DECL(AL_FORMAT_QUAD8_LOKI),
437 DECL(AL_FORMAT_QUAD16_LOKI),
438 DECL(AL_FORMAT_QUAD8),
439 DECL(AL_FORMAT_QUAD16),
440 DECL(AL_FORMAT_QUAD32),
441 DECL(AL_FORMAT_51CHN8),
442 DECL(AL_FORMAT_51CHN16),
443 DECL(AL_FORMAT_51CHN32),
444 DECL(AL_FORMAT_61CHN8),
445 DECL(AL_FORMAT_61CHN16),
446 DECL(AL_FORMAT_61CHN32),
447 DECL(AL_FORMAT_71CHN8),
448 DECL(AL_FORMAT_71CHN16),
449 DECL(AL_FORMAT_71CHN32),
450 DECL(AL_FORMAT_REAR8),
451 DECL(AL_FORMAT_REAR16),
452 DECL(AL_FORMAT_REAR32),
453 DECL(AL_FORMAT_MONO_MULAW),
454 DECL(AL_FORMAT_MONO_MULAW_EXT),
455 DECL(AL_FORMAT_STEREO_MULAW),
456 DECL(AL_FORMAT_STEREO_MULAW_EXT),
457 DECL(AL_FORMAT_QUAD_MULAW),
458 DECL(AL_FORMAT_51CHN_MULAW),
459 DECL(AL_FORMAT_61CHN_MULAW),
460 DECL(AL_FORMAT_71CHN_MULAW),
461 DECL(AL_FORMAT_REAR_MULAW),
462 DECL(AL_FORMAT_MONO_ALAW_EXT),
463 DECL(AL_FORMAT_STEREO_ALAW_EXT),
465 DECL(AL_FORMAT_BFORMAT2D_8),
466 DECL(AL_FORMAT_BFORMAT2D_16),
467 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
468 DECL(AL_FORMAT_BFORMAT2D_MULAW),
469 DECL(AL_FORMAT_BFORMAT3D_8),
470 DECL(AL_FORMAT_BFORMAT3D_16),
471 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
472 DECL(AL_FORMAT_BFORMAT3D_MULAW),
474 DECL(AL_FREQUENCY),
475 DECL(AL_BITS),
476 DECL(AL_CHANNELS),
477 DECL(AL_SIZE),
478 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
479 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
481 DECL(AL_SOURCE_RADIUS),
483 DECL(AL_STEREO_ANGLES),
485 DECL(AL_UNUSED),
486 DECL(AL_PENDING),
487 DECL(AL_PROCESSED),
489 DECL(AL_NO_ERROR),
490 DECL(AL_INVALID_NAME),
491 DECL(AL_INVALID_ENUM),
492 DECL(AL_INVALID_VALUE),
493 DECL(AL_INVALID_OPERATION),
494 DECL(AL_OUT_OF_MEMORY),
496 DECL(AL_VENDOR),
497 DECL(AL_VERSION),
498 DECL(AL_RENDERER),
499 DECL(AL_EXTENSIONS),
501 DECL(AL_DOPPLER_FACTOR),
502 DECL(AL_DOPPLER_VELOCITY),
503 DECL(AL_DISTANCE_MODEL),
504 DECL(AL_SPEED_OF_SOUND),
505 DECL(AL_SOURCE_DISTANCE_MODEL),
506 DECL(AL_DEFERRED_UPDATES_SOFT),
507 DECL(AL_GAIN_LIMIT_SOFT),
509 DECL(AL_INVERSE_DISTANCE),
510 DECL(AL_INVERSE_DISTANCE_CLAMPED),
511 DECL(AL_LINEAR_DISTANCE),
512 DECL(AL_LINEAR_DISTANCE_CLAMPED),
513 DECL(AL_EXPONENT_DISTANCE),
514 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
516 DECL(AL_FILTER_TYPE),
517 DECL(AL_FILTER_NULL),
518 DECL(AL_FILTER_LOWPASS),
519 DECL(AL_FILTER_HIGHPASS),
520 DECL(AL_FILTER_BANDPASS),
522 DECL(AL_LOWPASS_GAIN),
523 DECL(AL_LOWPASS_GAINHF),
525 DECL(AL_HIGHPASS_GAIN),
526 DECL(AL_HIGHPASS_GAINLF),
528 DECL(AL_BANDPASS_GAIN),
529 DECL(AL_BANDPASS_GAINHF),
530 DECL(AL_BANDPASS_GAINLF),
532 DECL(AL_EFFECT_TYPE),
533 DECL(AL_EFFECT_NULL),
534 DECL(AL_EFFECT_REVERB),
535 DECL(AL_EFFECT_EAXREVERB),
536 DECL(AL_EFFECT_CHORUS),
537 DECL(AL_EFFECT_DISTORTION),
538 DECL(AL_EFFECT_ECHO),
539 DECL(AL_EFFECT_FLANGER),
540 #if 0
541 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
542 DECL(AL_EFFECT_VOCAL_MORPHER),
543 DECL(AL_EFFECT_PITCH_SHIFTER),
544 #endif
545 DECL(AL_EFFECT_RING_MODULATOR),
546 #if 0
547 DECL(AL_EFFECT_AUTOWAH),
548 #endif
549 DECL(AL_EFFECT_COMPRESSOR),
550 DECL(AL_EFFECT_EQUALIZER),
551 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
552 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
554 DECL(AL_EFFECTSLOT_EFFECT),
555 DECL(AL_EFFECTSLOT_GAIN),
556 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
557 DECL(AL_EFFECTSLOT_NULL),
559 DECL(AL_EAXREVERB_DENSITY),
560 DECL(AL_EAXREVERB_DIFFUSION),
561 DECL(AL_EAXREVERB_GAIN),
562 DECL(AL_EAXREVERB_GAINHF),
563 DECL(AL_EAXREVERB_GAINLF),
564 DECL(AL_EAXREVERB_DECAY_TIME),
565 DECL(AL_EAXREVERB_DECAY_HFRATIO),
566 DECL(AL_EAXREVERB_DECAY_LFRATIO),
567 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
568 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
569 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
570 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
571 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
572 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
573 DECL(AL_EAXREVERB_ECHO_TIME),
574 DECL(AL_EAXREVERB_ECHO_DEPTH),
575 DECL(AL_EAXREVERB_MODULATION_TIME),
576 DECL(AL_EAXREVERB_MODULATION_DEPTH),
577 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
578 DECL(AL_EAXREVERB_HFREFERENCE),
579 DECL(AL_EAXREVERB_LFREFERENCE),
580 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
581 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
583 DECL(AL_REVERB_DENSITY),
584 DECL(AL_REVERB_DIFFUSION),
585 DECL(AL_REVERB_GAIN),
586 DECL(AL_REVERB_GAINHF),
587 DECL(AL_REVERB_DECAY_TIME),
588 DECL(AL_REVERB_DECAY_HFRATIO),
589 DECL(AL_REVERB_REFLECTIONS_GAIN),
590 DECL(AL_REVERB_REFLECTIONS_DELAY),
591 DECL(AL_REVERB_LATE_REVERB_GAIN),
592 DECL(AL_REVERB_LATE_REVERB_DELAY),
593 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
594 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
595 DECL(AL_REVERB_DECAY_HFLIMIT),
597 DECL(AL_CHORUS_WAVEFORM),
598 DECL(AL_CHORUS_PHASE),
599 DECL(AL_CHORUS_RATE),
600 DECL(AL_CHORUS_DEPTH),
601 DECL(AL_CHORUS_FEEDBACK),
602 DECL(AL_CHORUS_DELAY),
604 DECL(AL_DISTORTION_EDGE),
605 DECL(AL_DISTORTION_GAIN),
606 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
607 DECL(AL_DISTORTION_EQCENTER),
608 DECL(AL_DISTORTION_EQBANDWIDTH),
610 DECL(AL_ECHO_DELAY),
611 DECL(AL_ECHO_LRDELAY),
612 DECL(AL_ECHO_DAMPING),
613 DECL(AL_ECHO_FEEDBACK),
614 DECL(AL_ECHO_SPREAD),
616 DECL(AL_FLANGER_WAVEFORM),
617 DECL(AL_FLANGER_PHASE),
618 DECL(AL_FLANGER_RATE),
619 DECL(AL_FLANGER_DEPTH),
620 DECL(AL_FLANGER_FEEDBACK),
621 DECL(AL_FLANGER_DELAY),
623 DECL(AL_RING_MODULATOR_FREQUENCY),
624 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
625 DECL(AL_RING_MODULATOR_WAVEFORM),
627 DECL(AL_COMPRESSOR_ONOFF),
629 DECL(AL_EQUALIZER_LOW_GAIN),
630 DECL(AL_EQUALIZER_LOW_CUTOFF),
631 DECL(AL_EQUALIZER_MID1_GAIN),
632 DECL(AL_EQUALIZER_MID1_CENTER),
633 DECL(AL_EQUALIZER_MID1_WIDTH),
634 DECL(AL_EQUALIZER_MID2_GAIN),
635 DECL(AL_EQUALIZER_MID2_CENTER),
636 DECL(AL_EQUALIZER_MID2_WIDTH),
637 DECL(AL_EQUALIZER_HIGH_GAIN),
638 DECL(AL_EQUALIZER_HIGH_CUTOFF),
640 DECL(AL_DEDICATED_GAIN),
642 DECL(AL_NUM_RESAMPLERS_SOFT),
643 DECL(AL_DEFAULT_RESAMPLER_SOFT),
644 DECL(AL_SOURCE_RESAMPLER_SOFT),
645 DECL(AL_RESAMPLER_NAME_SOFT),
647 DECL(AL_SOURCE_SPATIALIZE_SOFT),
648 DECL(AL_AUTO_SOFT),
650 DECL(AL_MAP_READ_BIT_SOFT),
651 DECL(AL_MAP_WRITE_BIT_SOFT),
653 #undef DECL
655 static const ALCchar alcNoError[] = "No Error";
656 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
657 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
658 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
659 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
660 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
663 /************************************************
664 * Global variables
665 ************************************************/
667 /* Enumerated device names */
668 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
670 static al_string alcAllDevicesList;
671 static al_string alcCaptureDeviceList;
673 /* Default is always the first in the list */
674 static ALCchar *alcDefaultAllDevicesSpecifier;
675 static ALCchar *alcCaptureDefaultDeviceSpecifier;
677 /* Default context extensions */
678 static const ALchar alExtList[] =
679 "AL_EXT_ALAW "
680 "AL_EXT_BFORMAT "
681 "AL_EXT_DOUBLE "
682 "AL_EXT_EXPONENT_DISTANCE "
683 "AL_EXT_FLOAT32 "
684 "AL_EXT_IMA4 "
685 "AL_EXT_LINEAR_DISTANCE "
686 "AL_EXT_MCFORMATS "
687 "AL_EXT_MULAW "
688 "AL_EXT_MULAW_BFORMAT "
689 "AL_EXT_MULAW_MCFORMATS "
690 "AL_EXT_OFFSET "
691 "AL_EXT_source_distance_model "
692 "AL_EXT_SOURCE_RADIUS "
693 "AL_EXT_STEREO_ANGLES "
694 "AL_LOKI_quadriphonic "
695 "AL_SOFT_block_alignment "
696 "AL_SOFT_deferred_updates "
697 "AL_SOFT_direct_channels "
698 "AL_SOFT_gain_clamp_ex "
699 "AL_SOFT_loop_points "
700 "AL_SOFTX_map_buffer "
701 "AL_SOFT_MSADPCM "
702 "AL_SOFT_source_latency "
703 "AL_SOFT_source_length "
704 "AL_SOFT_source_resampler "
705 "AL_SOFT_source_spatialize";
707 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
709 /* Thread-local current context */
710 static altss_t LocalContext;
711 /* Process-wide current context */
712 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
714 /* Mixing thread piority level */
715 ALint RTPrioLevel;
717 FILE *LogFile;
718 #ifdef _DEBUG
719 enum LogLevel LogLevel = LogWarning;
720 #else
721 enum LogLevel LogLevel = LogError;
722 #endif
724 /* Flag to trap ALC device errors */
725 static ALCboolean TrapALCError = ALC_FALSE;
727 /* One-time configuration init control */
728 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
730 /* Default effect that applies to sources that don't have an effect on send 0 */
731 static ALeffect DefaultEffect;
733 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
734 * updates.
736 static ALCboolean SuspendDefers = ALC_TRUE;
739 /************************************************
740 * ALC information
741 ************************************************/
742 static const ALCchar alcNoDeviceExtList[] =
743 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
744 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
745 static const ALCchar alcExtensionList[] =
746 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
747 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
748 "ALC_EXT_thread_local_context ALC_SOFT_device_clock ALC_SOFT_HRTF "
749 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
750 static const ALCint alcMajorVersion = 1;
751 static const ALCint alcMinorVersion = 1;
753 static const ALCint alcEFXMajorVersion = 1;
754 static const ALCint alcEFXMinorVersion = 0;
757 /************************************************
758 * Device lists
759 ************************************************/
760 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
762 static almtx_t ListLock;
763 static inline void LockLists(void)
765 int ret = almtx_lock(&ListLock);
766 assert(ret == althrd_success);
768 static inline void UnlockLists(void)
770 int ret = almtx_unlock(&ListLock);
771 assert(ret == althrd_success);
774 /************************************************
775 * Library initialization
776 ************************************************/
777 #if defined(_WIN32)
778 static void alc_init(void);
779 static void alc_deinit(void);
780 static void alc_deinit_safe(void);
782 #ifndef AL_LIBTYPE_STATIC
783 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
785 switch(reason)
787 case DLL_PROCESS_ATTACH:
788 /* Pin the DLL so we won't get unloaded until the process terminates */
789 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
790 (WCHAR*)hModule, &hModule);
791 alc_init();
792 break;
794 case DLL_THREAD_DETACH:
795 break;
797 case DLL_PROCESS_DETACH:
798 if(!lpReserved)
799 alc_deinit();
800 else
801 alc_deinit_safe();
802 break;
804 return TRUE;
806 #elif defined(_MSC_VER)
807 #pragma section(".CRT$XCU",read)
808 static void alc_constructor(void);
809 static void alc_destructor(void);
810 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
812 static void alc_constructor(void)
814 atexit(alc_destructor);
815 alc_init();
818 static void alc_destructor(void)
820 alc_deinit();
822 #elif defined(HAVE_GCC_DESTRUCTOR)
823 static void alc_init(void) __attribute__((constructor));
824 static void alc_deinit(void) __attribute__((destructor));
825 #else
826 #error "No static initialization available on this platform!"
827 #endif
829 #elif defined(HAVE_GCC_DESTRUCTOR)
831 static void alc_init(void) __attribute__((constructor));
832 static void alc_deinit(void) __attribute__((destructor));
834 #else
835 #error "No global initialization available on this platform!"
836 #endif
838 static void ReleaseThreadCtx(void *ptr);
839 static void alc_init(void)
841 const char *str;
842 int ret;
844 LogFile = stderr;
846 AL_STRING_INIT(alcAllDevicesList);
847 AL_STRING_INIT(alcCaptureDeviceList);
849 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
850 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
851 ConeScale *= 0.5f;
853 str = getenv("__ALSOFT_REVERSE_Z");
854 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
855 ZScale *= -1.0f;
857 str = getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
858 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
859 OverrideReverbSpeedOfSound = AL_TRUE;
861 ret = altss_create(&LocalContext, ReleaseThreadCtx);
862 assert(ret == althrd_success);
864 ret = almtx_init(&ListLock, almtx_recursive);
865 assert(ret == althrd_success);
867 ThunkInit();
870 static void alc_initconfig(void)
872 const char *devs, *str;
873 int capfilter;
874 float valf;
875 int i, n;
877 str = getenv("ALSOFT_LOGLEVEL");
878 if(str)
880 long lvl = strtol(str, NULL, 0);
881 if(lvl >= NoLog && lvl <= LogRef)
882 LogLevel = lvl;
885 str = getenv("ALSOFT_LOGFILE");
886 if(str && str[0])
888 FILE *logfile = al_fopen(str, "wt");
889 if(logfile) LogFile = logfile;
890 else ERR("Failed to open log file '%s'\n", str);
893 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION,
894 ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH);
896 char buf[1024] = "";
897 int len = 0;
899 if(BackendListSize > 0)
900 len += snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
901 for(i = 1;i < BackendListSize;i++)
902 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
903 TRACE("Supported backends: %s\n", buf);
905 ReadALConfig();
907 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
908 if(str && *str)
910 if(strcasecmp(str, "ignore") == 0)
912 SuspendDefers = ALC_FALSE;
913 TRACE("Selected context suspend behavior, \"ignore\"\n");
915 else
916 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
919 capfilter = 0;
920 #if defined(HAVE_SSE4_1)
921 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
922 #elif defined(HAVE_SSE3)
923 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
924 #elif defined(HAVE_SSE2)
925 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
926 #elif defined(HAVE_SSE)
927 capfilter |= CPU_CAP_SSE;
928 #endif
929 #ifdef HAVE_NEON
930 capfilter |= CPU_CAP_NEON;
931 #endif
932 if(ConfigValueStr(NULL, NULL, "disable-cpu-exts", &str))
934 if(strcasecmp(str, "all") == 0)
935 capfilter = 0;
936 else
938 size_t len;
939 const char *next = str;
941 do {
942 str = next;
943 while(isspace(str[0]))
944 str++;
945 next = strchr(str, ',');
947 if(!str[0] || str[0] == ',')
948 continue;
950 len = (next ? ((size_t)(next-str)) : strlen(str));
951 while(len > 0 && isspace(str[len-1]))
952 len--;
953 if(len == 3 && strncasecmp(str, "sse", len) == 0)
954 capfilter &= ~CPU_CAP_SSE;
955 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
956 capfilter &= ~CPU_CAP_SSE2;
957 else if(len == 4 && strncasecmp(str, "sse3", len) == 0)
958 capfilter &= ~CPU_CAP_SSE3;
959 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
960 capfilter &= ~CPU_CAP_SSE4_1;
961 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
962 capfilter &= ~CPU_CAP_NEON;
963 else
964 WARN("Invalid CPU extension \"%s\"\n", str);
965 } while(next++);
968 FillCPUCaps(capfilter);
970 #ifdef _WIN32
971 RTPrioLevel = 1;
972 #else
973 RTPrioLevel = 0;
974 #endif
975 ConfigValueInt(NULL, NULL, "rt-prio", &RTPrioLevel);
977 aluInit();
978 aluInitMixer();
980 str = getenv("ALSOFT_TRAP_ERROR");
981 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
983 TrapALError = AL_TRUE;
984 TrapALCError = AL_TRUE;
986 else
988 str = getenv("ALSOFT_TRAP_AL_ERROR");
989 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
990 TrapALError = AL_TRUE;
991 TrapALError = GetConfigValueBool(NULL, NULL, "trap-al-error", TrapALError);
993 str = getenv("ALSOFT_TRAP_ALC_ERROR");
994 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
995 TrapALCError = ALC_TRUE;
996 TrapALCError = GetConfigValueBool(NULL, NULL, "trap-alc-error", TrapALCError);
999 if(ConfigValueFloat(NULL, "reverb", "boost", &valf))
1000 ReverbBoost *= powf(10.0f, valf / 20.0f);
1002 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1003 ConfigValueStr(NULL, NULL, "drivers", &devs))
1005 int n;
1006 size_t len;
1007 const char *next = devs;
1008 int endlist, delitem;
1010 i = 0;
1011 do {
1012 devs = next;
1013 while(isspace(devs[0]))
1014 devs++;
1015 next = strchr(devs, ',');
1017 delitem = (devs[0] == '-');
1018 if(devs[0] == '-') devs++;
1020 if(!devs[0] || devs[0] == ',')
1022 endlist = 0;
1023 continue;
1025 endlist = 1;
1027 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1028 while(len > 0 && isspace(devs[len-1]))
1029 len--;
1030 for(n = i;n < BackendListSize;n++)
1032 if(len == strlen(BackendList[n].name) &&
1033 strncmp(BackendList[n].name, devs, len) == 0)
1035 if(delitem)
1037 for(;n+1 < BackendListSize;n++)
1038 BackendList[n] = BackendList[n+1];
1039 BackendListSize--;
1041 else
1043 struct BackendInfo Bkp = BackendList[n];
1044 for(;n > i;n--)
1045 BackendList[n] = BackendList[n-1];
1046 BackendList[n] = Bkp;
1048 i++;
1050 break;
1053 } while(next++);
1055 if(endlist)
1056 BackendListSize = i;
1059 for(i = 0;i < BackendListSize && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1061 ALCbackendFactory *factory = BackendList[i].getFactory();
1062 if(!V0(factory,init)())
1064 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1065 continue;
1068 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1069 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1071 PlaybackBackend = BackendList[i];
1072 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1074 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1076 CaptureBackend = BackendList[i];
1077 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1081 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1082 V0(factory,init)();
1085 if(!PlaybackBackend.name)
1086 WARN("No playback backend available!\n");
1087 if(!CaptureBackend.name)
1088 WARN("No capture backend available!\n");
1090 if(ConfigValueStr(NULL, NULL, "excludefx", &str))
1092 size_t len;
1093 const char *next = str;
1095 do {
1096 str = next;
1097 next = strchr(str, ',');
1099 if(!str[0] || next == str)
1100 continue;
1102 len = (next ? ((size_t)(next-str)) : strlen(str));
1103 for(n = 0;n < EFFECTLIST_SIZE;n++)
1105 if(len == strlen(EffectList[n].name) &&
1106 strncmp(EffectList[n].name, str, len) == 0)
1107 DisabledEffects[EffectList[n].type] = AL_TRUE;
1109 } while(next++);
1112 InitEffectFactoryMap();
1114 InitEffect(&DefaultEffect);
1115 str = getenv("ALSOFT_DEFAULT_REVERB");
1116 if((str && str[0]) || ConfigValueStr(NULL, NULL, "default-reverb", &str))
1117 LoadReverbPreset(str, &DefaultEffect);
1119 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1121 #ifdef __ANDROID__
1122 #include <jni.h>
1124 static JavaVM *gJavaVM;
1125 static pthread_key_t gJVMThreadKey;
1127 static void CleanupJNIEnv(void* UNUSED(ptr))
1129 JCALL0(gJavaVM,DetachCurrentThread)();
1132 void *Android_GetJNIEnv(void)
1134 if(!gJavaVM)
1136 WARN("gJavaVM is NULL!\n");
1137 return NULL;
1140 /* http://developer.android.com/guide/practices/jni.html
1142 * All threads are Linux threads, scheduled by the kernel. They're usually
1143 * started from managed code (using Thread.start), but they can also be
1144 * created elsewhere and then attached to the JavaVM. For example, a thread
1145 * started with pthread_create can be attached with the JNI
1146 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1147 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1148 * Attaching a natively-created thread causes a java.lang.Thread object to
1149 * be constructed and added to the "main" ThreadGroup, making it visible to
1150 * the debugger. Calling AttachCurrentThread on an already-attached thread
1151 * is a no-op.
1153 JNIEnv *env = pthread_getspecific(gJVMThreadKey);
1154 if(!env)
1156 int status = JCALL(gJavaVM,AttachCurrentThread)(&env, NULL);
1157 if(status < 0)
1159 ERR("Failed to attach current thread\n");
1160 return NULL;
1162 pthread_setspecific(gJVMThreadKey, env);
1164 return env;
1167 /* Automatically called by JNI. */
1168 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void* UNUSED(reserved))
1170 void *env;
1171 int err;
1173 gJavaVM = jvm;
1174 if(JCALL(gJavaVM,GetEnv)(&env, JNI_VERSION_1_4) != JNI_OK)
1176 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1177 return JNI_ERR;
1180 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1181 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1183 if((err=pthread_key_create(&gJVMThreadKey, CleanupJNIEnv)) != 0)
1184 ERR("pthread_key_create failed: %d\n", err);
1185 pthread_setspecific(gJVMThreadKey, env);
1186 return JNI_VERSION_1_4;
1188 #endif
1191 /************************************************
1192 * Library deinitialization
1193 ************************************************/
1194 static void alc_cleanup(void)
1196 ALCdevice *dev;
1198 AL_STRING_DEINIT(alcAllDevicesList);
1199 AL_STRING_DEINIT(alcCaptureDeviceList);
1201 free(alcDefaultAllDevicesSpecifier);
1202 alcDefaultAllDevicesSpecifier = NULL;
1203 free(alcCaptureDefaultDeviceSpecifier);
1204 alcCaptureDefaultDeviceSpecifier = NULL;
1206 if((dev=ATOMIC_EXCHANGE_PTR_SEQ(&DeviceList, NULL)) != NULL)
1208 ALCuint num = 0;
1209 do {
1210 num++;
1211 } while((dev=dev->next) != NULL);
1212 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1215 DeinitEffectFactoryMap();
1218 static void alc_deinit_safe(void)
1220 alc_cleanup();
1222 FreeHrtfs();
1223 FreeALConfig();
1225 ThunkExit();
1226 almtx_destroy(&ListLock);
1227 altss_delete(LocalContext);
1229 if(LogFile != stderr)
1230 fclose(LogFile);
1231 LogFile = NULL;
1234 static void alc_deinit(void)
1236 int i;
1238 alc_cleanup();
1240 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1241 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1243 for(i = 0;i < BackendListSize;i++)
1245 ALCbackendFactory *factory = BackendList[i].getFactory();
1246 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, struct BackendInfo *backendinfo, enum DevProbe type)
1262 DO_INITCONFIG();
1264 LockLists();
1265 alstr_clear(list);
1267 if(backendinfo->getFactory)
1269 ALCbackendFactory *factory = backendinfo->getFactory();
1270 V(factory,probe)(type);
1273 UnlockLists();
1275 static void ProbeAllDevicesList(void)
1276 { ProbeDevices(&alcAllDevicesList, &PlaybackBackend, ALL_DEVICE_PROBE); }
1277 static void ProbeCaptureDeviceList(void)
1278 { ProbeDevices(&alcCaptureDeviceList, &CaptureBackend, CAPTURE_DEVICE_PROBE); }
1280 static void AppendDevice(const ALCchar *name, al_string *devnames)
1282 size_t len = strlen(name);
1283 if(len > 0)
1284 alstr_append_range(devnames, name, name+len+1);
1286 void AppendAllDevicesList(const ALCchar *name)
1287 { AppendDevice(name, &alcAllDevicesList); }
1288 void AppendCaptureDeviceList(const ALCchar *name)
1289 { AppendDevice(name, &alcCaptureDeviceList); }
1292 /************************************************
1293 * Device format information
1294 ************************************************/
1295 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1297 switch(type)
1299 case DevFmtByte: return "Signed Byte";
1300 case DevFmtUByte: return "Unsigned Byte";
1301 case DevFmtShort: return "Signed Short";
1302 case DevFmtUShort: return "Unsigned Short";
1303 case DevFmtInt: return "Signed Int";
1304 case DevFmtUInt: return "Unsigned Int";
1305 case DevFmtFloat: return "Float";
1307 return "(unknown type)";
1309 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1311 switch(chans)
1313 case DevFmtMono: return "Mono";
1314 case DevFmtStereo: return "Stereo";
1315 case DevFmtQuad: return "Quadraphonic";
1316 case DevFmtX51: return "5.1 Surround";
1317 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1318 case DevFmtX61: return "6.1 Surround";
1319 case DevFmtX71: return "7.1 Surround";
1320 case DevFmtAmbi3D: return "Ambisonic 3D";
1322 return "(unknown channels)";
1325 extern inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type, ALsizei ambiorder);
1326 ALsizei BytesFromDevFmt(enum DevFmtType type)
1328 switch(type)
1330 case DevFmtByte: return sizeof(ALbyte);
1331 case DevFmtUByte: return sizeof(ALubyte);
1332 case DevFmtShort: return sizeof(ALshort);
1333 case DevFmtUShort: return sizeof(ALushort);
1334 case DevFmtInt: return sizeof(ALint);
1335 case DevFmtUInt: return sizeof(ALuint);
1336 case DevFmtFloat: return sizeof(ALfloat);
1338 return 0;
1340 ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans, ALsizei ambiorder)
1342 switch(chans)
1344 case DevFmtMono: return 1;
1345 case DevFmtStereo: return 2;
1346 case DevFmtQuad: return 4;
1347 case DevFmtX51: return 6;
1348 case DevFmtX51Rear: return 6;
1349 case DevFmtX61: return 7;
1350 case DevFmtX71: return 8;
1351 case DevFmtAmbi3D: return (ambiorder >= 3) ? 16 :
1352 (ambiorder == 2) ? 9 :
1353 (ambiorder == 1) ? 4 : 1;
1355 return 0;
1358 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1359 enum DevFmtType *type)
1361 static const struct {
1362 ALenum format;
1363 enum DevFmtChannels channels;
1364 enum DevFmtType type;
1365 } list[] = {
1366 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1367 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1368 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1370 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1371 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1372 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1374 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1375 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1376 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1378 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1379 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1380 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1382 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1383 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1384 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1386 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1387 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1388 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1390 ALuint i;
1392 for(i = 0;i < COUNTOF(list);i++)
1394 if(list[i].format == format)
1396 *chans = list[i].channels;
1397 *type = list[i].type;
1398 return AL_TRUE;
1402 return AL_FALSE;
1405 static ALCboolean IsValidALCType(ALCenum type)
1407 switch(type)
1409 case ALC_BYTE_SOFT:
1410 case ALC_UNSIGNED_BYTE_SOFT:
1411 case ALC_SHORT_SOFT:
1412 case ALC_UNSIGNED_SHORT_SOFT:
1413 case ALC_INT_SOFT:
1414 case ALC_UNSIGNED_INT_SOFT:
1415 case ALC_FLOAT_SOFT:
1416 return ALC_TRUE;
1418 return ALC_FALSE;
1421 static ALCboolean IsValidALCChannels(ALCenum channels)
1423 switch(channels)
1425 case ALC_MONO_SOFT:
1426 case ALC_STEREO_SOFT:
1427 case ALC_QUAD_SOFT:
1428 case ALC_5POINT1_SOFT:
1429 case ALC_6POINT1_SOFT:
1430 case ALC_7POINT1_SOFT:
1431 case ALC_BFORMAT3D_SOFT:
1432 return ALC_TRUE;
1434 return ALC_FALSE;
1437 static ALCboolean IsValidAmbiLayout(ALCenum layout)
1439 switch(layout)
1441 case ALC_ACN_SOFT:
1442 case ALC_FUMA_SOFT:
1443 return ALC_TRUE;
1445 return ALC_FALSE;
1448 static ALCboolean IsValidAmbiScaling(ALCenum scaling)
1450 switch(scaling)
1452 case ALC_N3D_SOFT:
1453 case ALC_SN3D_SOFT:
1454 case ALC_FUMA_SOFT:
1455 return ALC_TRUE;
1457 return ALC_FALSE;
1460 /************************************************
1461 * Miscellaneous ALC helpers
1462 ************************************************/
1464 /* SetDefaultWFXChannelOrder
1466 * Sets the default channel order used by WaveFormatEx.
1468 void SetDefaultWFXChannelOrder(ALCdevice *device)
1470 ALsizei i;
1472 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1473 device->RealOut.ChannelName[i] = InvalidChannel;
1475 switch(device->FmtChans)
1477 case DevFmtMono:
1478 device->RealOut.ChannelName[0] = FrontCenter;
1479 break;
1480 case DevFmtStereo:
1481 device->RealOut.ChannelName[0] = FrontLeft;
1482 device->RealOut.ChannelName[1] = FrontRight;
1483 break;
1484 case DevFmtQuad:
1485 device->RealOut.ChannelName[0] = FrontLeft;
1486 device->RealOut.ChannelName[1] = FrontRight;
1487 device->RealOut.ChannelName[2] = BackLeft;
1488 device->RealOut.ChannelName[3] = BackRight;
1489 break;
1490 case DevFmtX51:
1491 device->RealOut.ChannelName[0] = FrontLeft;
1492 device->RealOut.ChannelName[1] = FrontRight;
1493 device->RealOut.ChannelName[2] = FrontCenter;
1494 device->RealOut.ChannelName[3] = LFE;
1495 device->RealOut.ChannelName[4] = SideLeft;
1496 device->RealOut.ChannelName[5] = SideRight;
1497 break;
1498 case DevFmtX51Rear:
1499 device->RealOut.ChannelName[0] = FrontLeft;
1500 device->RealOut.ChannelName[1] = FrontRight;
1501 device->RealOut.ChannelName[2] = FrontCenter;
1502 device->RealOut.ChannelName[3] = LFE;
1503 device->RealOut.ChannelName[4] = BackLeft;
1504 device->RealOut.ChannelName[5] = BackRight;
1505 break;
1506 case DevFmtX61:
1507 device->RealOut.ChannelName[0] = FrontLeft;
1508 device->RealOut.ChannelName[1] = FrontRight;
1509 device->RealOut.ChannelName[2] = FrontCenter;
1510 device->RealOut.ChannelName[3] = LFE;
1511 device->RealOut.ChannelName[4] = BackCenter;
1512 device->RealOut.ChannelName[5] = SideLeft;
1513 device->RealOut.ChannelName[6] = SideRight;
1514 break;
1515 case DevFmtX71:
1516 device->RealOut.ChannelName[0] = FrontLeft;
1517 device->RealOut.ChannelName[1] = FrontRight;
1518 device->RealOut.ChannelName[2] = FrontCenter;
1519 device->RealOut.ChannelName[3] = LFE;
1520 device->RealOut.ChannelName[4] = BackLeft;
1521 device->RealOut.ChannelName[5] = BackRight;
1522 device->RealOut.ChannelName[6] = SideLeft;
1523 device->RealOut.ChannelName[7] = SideRight;
1524 break;
1525 case DevFmtAmbi3D:
1526 device->RealOut.ChannelName[0] = Aux0;
1527 if(device->AmbiOrder > 0)
1529 device->RealOut.ChannelName[1] = Aux1;
1530 device->RealOut.ChannelName[2] = Aux2;
1531 device->RealOut.ChannelName[3] = Aux3;
1533 if(device->AmbiOrder > 1)
1535 device->RealOut.ChannelName[4] = Aux4;
1536 device->RealOut.ChannelName[5] = Aux5;
1537 device->RealOut.ChannelName[6] = Aux6;
1538 device->RealOut.ChannelName[7] = Aux7;
1539 device->RealOut.ChannelName[8] = Aux8;
1541 if(device->AmbiOrder > 2)
1543 device->RealOut.ChannelName[9] = Aux9;
1544 device->RealOut.ChannelName[10] = Aux10;
1545 device->RealOut.ChannelName[11] = Aux11;
1546 device->RealOut.ChannelName[12] = Aux12;
1547 device->RealOut.ChannelName[13] = Aux13;
1548 device->RealOut.ChannelName[14] = Aux14;
1549 device->RealOut.ChannelName[15] = Aux15;
1551 break;
1555 /* SetDefaultChannelOrder
1557 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1559 void SetDefaultChannelOrder(ALCdevice *device)
1561 ALsizei i;
1563 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1564 device->RealOut.ChannelName[i] = InvalidChannel;
1566 switch(device->FmtChans)
1568 case DevFmtX51Rear:
1569 device->RealOut.ChannelName[0] = FrontLeft;
1570 device->RealOut.ChannelName[1] = FrontRight;
1571 device->RealOut.ChannelName[2] = BackLeft;
1572 device->RealOut.ChannelName[3] = BackRight;
1573 device->RealOut.ChannelName[4] = FrontCenter;
1574 device->RealOut.ChannelName[5] = LFE;
1575 return;
1576 case DevFmtX71:
1577 device->RealOut.ChannelName[0] = FrontLeft;
1578 device->RealOut.ChannelName[1] = FrontRight;
1579 device->RealOut.ChannelName[2] = BackLeft;
1580 device->RealOut.ChannelName[3] = BackRight;
1581 device->RealOut.ChannelName[4] = FrontCenter;
1582 device->RealOut.ChannelName[5] = LFE;
1583 device->RealOut.ChannelName[6] = SideLeft;
1584 device->RealOut.ChannelName[7] = SideRight;
1585 return;
1587 /* Same as WFX order */
1588 case DevFmtMono:
1589 case DevFmtStereo:
1590 case DevFmtQuad:
1591 case DevFmtX51:
1592 case DevFmtX61:
1593 case DevFmtAmbi3D:
1594 SetDefaultWFXChannelOrder(device);
1595 break;
1599 extern inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan);
1600 extern inline ALint GetChannelIdxByName(const RealMixParams *real, enum Channel chan);
1603 /* ALCcontext_DeferUpdates
1605 * Defers/suspends updates for the given context's listener and sources. This
1606 * does *NOT* stop mixing, but rather prevents certain property changes from
1607 * taking effect.
1609 void ALCcontext_DeferUpdates(ALCcontext *context)
1611 ATOMIC_STORE_SEQ(&context->DeferUpdates, AL_TRUE);
1614 /* ALCcontext_ProcessUpdates
1616 * Resumes update processing after being deferred.
1618 void ALCcontext_ProcessUpdates(ALCcontext *context)
1620 ReadLock(&context->PropLock);
1621 if(ATOMIC_EXCHANGE_SEQ(&context->DeferUpdates, AL_FALSE))
1623 /* Tell the mixer to stop applying updates, then wait for any active
1624 * updating to finish, before providing updates.
1626 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_TRUE);
1627 while((ATOMIC_LOAD(&context->UpdateCount, almemory_order_acquire)&1) != 0)
1628 althrd_yield();
1630 if(!ATOMIC_FLAG_TEST_AND_SET(&context->PropsClean, almemory_order_acq_rel))
1631 UpdateContextProps(context);
1632 if(!ATOMIC_FLAG_TEST_AND_SET(&context->Listener->PropsClean, almemory_order_acq_rel))
1633 UpdateListenerProps(context);
1634 UpdateAllEffectSlotProps(context);
1635 UpdateAllSourceProps(context);
1637 /* Now with all updates declared, let the mixer continue applying them
1638 * so they all happen at once.
1640 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_FALSE);
1642 ReadUnlock(&context->PropLock);
1646 /* alcSetError
1648 * Stores the latest ALC device error
1650 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1652 WARN("Error generated on device %p, code 0x%04x\n", device, errorCode);
1653 if(TrapALCError)
1655 #ifdef _WIN32
1656 /* DebugBreak() will cause an exception if there is no debugger */
1657 if(IsDebuggerPresent())
1658 DebugBreak();
1659 #elif defined(SIGTRAP)
1660 raise(SIGTRAP);
1661 #endif
1664 if(device)
1665 ATOMIC_STORE_SEQ(&device->LastError, errorCode);
1666 else
1667 ATOMIC_STORE_SEQ(&LastNullDeviceError, errorCode);
1671 struct Compressor *CreateDeviceLimiter(const ALCdevice *device)
1673 return CompressorInit(0.0f, 0.0f, AL_FALSE, AL_TRUE, 0.0f, 0.0f, 0.5f, 2.0f,
1674 0.0f, -3.0f, 3.0f, device->Frequency);
1677 /* UpdateClockBase
1679 * Updates the device's base clock time with however many samples have been
1680 * done. This is used so frequency changes on the device don't cause the time
1681 * to jump forward or back. Must not be called while the device is running/
1682 * mixing.
1684 static inline void UpdateClockBase(ALCdevice *device)
1686 IncrementRef(&device->MixCount);
1687 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1688 device->SamplesDone = 0;
1689 IncrementRef(&device->MixCount);
1692 /* UpdateDeviceParams
1694 * Updates device parameters according to the attribute list (caller is
1695 * responsible for holding the list lock).
1697 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1699 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1700 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1701 ALCenum gainLimiter = device->Limiter ? ALC_TRUE : ALC_FALSE;
1702 const ALsizei old_sends = device->NumAuxSends;
1703 ALsizei new_sends = device->NumAuxSends;
1704 enum DevFmtChannels oldChans;
1705 enum DevFmtType oldType;
1706 ALboolean update_failed;
1707 ALCsizei hrtf_id = -1;
1708 ALCcontext *context;
1709 ALCuint oldFreq;
1710 size_t size;
1711 ALCsizei i;
1712 int val;
1714 // Check for attributes
1715 if(device->Type == Loopback)
1717 ALCsizei numMono, numStereo, numSends;
1718 ALCenum alayout = AL_NONE;
1719 ALCenum ascale = AL_NONE;
1720 ALCenum schans = AL_NONE;
1721 ALCenum stype = AL_NONE;
1722 ALCsizei attrIdx = 0;
1723 ALCsizei aorder = 0;
1724 ALCuint freq = 0;
1726 if(!attrList)
1728 WARN("Missing attributes for loopback device\n");
1729 return ALC_INVALID_VALUE;
1732 numMono = device->NumMonoSources;
1733 numStereo = device->NumStereoSources;
1734 numSends = old_sends;
1736 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1737 while(attrList[attrIdx])
1739 switch(attrList[attrIdx])
1741 case ALC_FORMAT_CHANNELS_SOFT:
1742 schans = attrList[attrIdx + 1];
1743 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1744 if(!IsValidALCChannels(schans))
1745 return ALC_INVALID_VALUE;
1746 break;
1748 case ALC_FORMAT_TYPE_SOFT:
1749 stype = attrList[attrIdx + 1];
1750 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1751 if(!IsValidALCType(stype))
1752 return ALC_INVALID_VALUE;
1753 break;
1755 case ALC_FREQUENCY:
1756 freq = attrList[attrIdx + 1];
1757 TRACE_ATTR(ALC_FREQUENCY, freq);
1758 if(freq < MIN_OUTPUT_RATE)
1759 return ALC_INVALID_VALUE;
1760 break;
1762 case ALC_AMBISONIC_LAYOUT_SOFT:
1763 alayout = attrList[attrIdx + 1];
1764 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1765 if(!IsValidAmbiLayout(alayout))
1766 return ALC_INVALID_VALUE;
1767 break;
1769 case ALC_AMBISONIC_SCALING_SOFT:
1770 ascale = attrList[attrIdx + 1];
1771 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1772 if(!IsValidAmbiScaling(ascale))
1773 return ALC_INVALID_VALUE;
1774 break;
1776 case ALC_AMBISONIC_ORDER_SOFT:
1777 aorder = attrList[attrIdx + 1];
1778 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1779 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1780 return ALC_INVALID_VALUE;
1781 break;
1783 case ALC_MONO_SOURCES:
1784 numMono = attrList[attrIdx + 1];
1785 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1786 numMono = maxi(numMono, 0);
1787 break;
1789 case ALC_STEREO_SOURCES:
1790 numStereo = attrList[attrIdx + 1];
1791 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1792 numStereo = maxi(numStereo, 0);
1793 break;
1795 case ALC_MAX_AUXILIARY_SENDS:
1796 numSends = attrList[attrIdx + 1];
1797 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1798 numSends = clampi(numSends, 0, MAX_SENDS);
1799 break;
1801 case ALC_HRTF_SOFT:
1802 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1803 if(attrList[attrIdx + 1] == ALC_FALSE)
1804 hrtf_appreq = Hrtf_Disable;
1805 else if(attrList[attrIdx + 1] == ALC_TRUE)
1806 hrtf_appreq = Hrtf_Enable;
1807 else
1808 hrtf_appreq = Hrtf_Default;
1809 break;
1811 case ALC_HRTF_ID_SOFT:
1812 hrtf_id = attrList[attrIdx + 1];
1813 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1814 break;
1816 case ALC_OUTPUT_LIMITER_SOFT:
1817 gainLimiter = attrList[attrIdx + 1];
1818 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1819 break;
1821 default:
1822 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList[attrIdx],
1823 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1824 break;
1827 attrIdx += 2;
1829 #undef TRACE_ATTR
1831 if(!schans || !stype || !freq)
1833 WARN("Missing format for loopback device\n");
1834 return ALC_INVALID_VALUE;
1836 if(schans == ALC_BFORMAT3D_SOFT && (!alayout || !ascale || !aorder))
1838 WARN("Missing ambisonic info for loopback device\n");
1839 return ALC_INVALID_VALUE;
1842 if((device->Flags&DEVICE_RUNNING))
1843 V0(device->Backend,stop)();
1844 device->Flags &= ~DEVICE_RUNNING;
1846 UpdateClockBase(device);
1848 device->Frequency = freq;
1849 device->FmtChans = schans;
1850 device->FmtType = stype;
1851 if(schans == ALC_BFORMAT3D_SOFT)
1853 device->AmbiOrder = aorder;
1854 device->AmbiLayout = alayout;
1855 device->AmbiScale = ascale;
1858 if(numMono > INT_MAX-numStereo)
1859 numMono = INT_MAX-numStereo;
1860 numMono += numStereo;
1861 if(ConfigValueInt(NULL, NULL, "sources", &numMono))
1863 if(numMono <= 0)
1864 numMono = 256;
1866 else
1867 numMono = maxi(numMono, 256);
1868 numStereo = mini(numStereo, numMono);
1869 numMono -= numStereo;
1870 device->SourcesMax = numMono + numStereo;
1872 device->NumMonoSources = numMono;
1873 device->NumStereoSources = numStereo;
1875 if(ConfigValueInt(NULL, NULL, "sends", &new_sends))
1876 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1877 else
1878 new_sends = numSends;
1880 else if(attrList && attrList[0])
1882 ALCsizei numMono, numStereo, numSends;
1883 ALCsizei attrIdx = 0;
1884 ALCuint freq;
1886 /* If a context is already running on the device, stop playback so the
1887 * device attributes can be updated. */
1888 if((device->Flags&DEVICE_RUNNING))
1889 V0(device->Backend,stop)();
1890 device->Flags &= ~DEVICE_RUNNING;
1892 UpdateClockBase(device);
1894 freq = device->Frequency;
1895 numMono = device->NumMonoSources;
1896 numStereo = device->NumStereoSources;
1897 numSends = old_sends;
1899 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1900 while(attrList[attrIdx])
1902 switch(attrList[attrIdx])
1904 case ALC_FREQUENCY:
1905 freq = attrList[attrIdx + 1];
1906 TRACE_ATTR(ALC_FREQUENCY, freq);
1907 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1908 break;
1910 case ALC_MONO_SOURCES:
1911 numMono = attrList[attrIdx + 1];
1912 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1913 numMono = maxi(numMono, 0);
1914 break;
1916 case ALC_STEREO_SOURCES:
1917 numStereo = attrList[attrIdx + 1];
1918 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1919 numStereo = maxi(numStereo, 0);
1920 break;
1922 case ALC_MAX_AUXILIARY_SENDS:
1923 numSends = attrList[attrIdx + 1];
1924 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1925 numSends = clampi(numSends, 0, MAX_SENDS);
1926 break;
1928 case ALC_HRTF_SOFT:
1929 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1930 if(attrList[attrIdx + 1] == ALC_FALSE)
1931 hrtf_appreq = Hrtf_Disable;
1932 else if(attrList[attrIdx + 1] == ALC_TRUE)
1933 hrtf_appreq = Hrtf_Enable;
1934 else
1935 hrtf_appreq = Hrtf_Default;
1936 break;
1938 case ALC_HRTF_ID_SOFT:
1939 hrtf_id = attrList[attrIdx + 1];
1940 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1941 break;
1943 case ALC_OUTPUT_LIMITER_SOFT:
1944 gainLimiter = attrList[attrIdx + 1];
1945 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1946 break;
1948 default:
1949 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1950 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1951 break;
1954 attrIdx += 2;
1956 #undef TRACE_ATTR
1958 ConfigValueUInt(alstr_get_cstr(device->DeviceName), NULL, "frequency", &freq);
1959 freq = maxu(freq, MIN_OUTPUT_RATE);
1961 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1962 device->Frequency;
1963 /* SSE and Neon do best with the update size being a multiple of 4 */
1964 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1965 device->UpdateSize = (device->UpdateSize+3)&~3;
1967 device->Frequency = freq;
1969 if(numMono > INT_MAX-numStereo)
1970 numMono = INT_MAX-numStereo;
1971 numMono += numStereo;
1972 if(ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "sources", &numMono))
1974 if(numMono <= 0)
1975 numMono = 256;
1977 else
1978 numMono = maxi(numMono, 256);
1979 numStereo = mini(numStereo, numMono);
1980 numMono -= numStereo;
1981 device->SourcesMax = numMono + numStereo;
1983 device->NumMonoSources = numMono;
1984 device->NumStereoSources = numStereo;
1986 if(ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "sends", &new_sends))
1987 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1988 else
1989 new_sends = numSends;
1992 if((device->Flags&DEVICE_RUNNING))
1993 return ALC_NO_ERROR;
1995 al_free(device->Uhj_Encoder);
1996 device->Uhj_Encoder = NULL;
1998 al_free(device->Bs2b);
1999 device->Bs2b = NULL;
2001 al_free(device->ChannelDelay[0].Buffer);
2002 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2004 device->ChannelDelay[i].Length = 0;
2005 device->ChannelDelay[i].Buffer = NULL;
2008 al_free(device->Dry.Buffer);
2009 device->Dry.Buffer = NULL;
2010 device->Dry.NumChannels = 0;
2011 device->FOAOut.Buffer = NULL;
2012 device->FOAOut.NumChannels = 0;
2013 device->RealOut.Buffer = NULL;
2014 device->RealOut.NumChannels = 0;
2016 UpdateClockBase(device);
2018 device->DitherSeed = DITHER_RNG_SEED;
2020 /*************************************************************************
2021 * Update device format request if HRTF is requested
2023 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
2024 if(device->Type != Loopback)
2026 const char *hrtf;
2027 if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "hrtf", &hrtf))
2029 if(strcasecmp(hrtf, "true") == 0)
2030 hrtf_userreq = Hrtf_Enable;
2031 else if(strcasecmp(hrtf, "false") == 0)
2032 hrtf_userreq = Hrtf_Disable;
2033 else if(strcasecmp(hrtf, "auto") != 0)
2034 ERR("Unexpected hrtf value: %s\n", hrtf);
2037 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
2039 struct Hrtf *hrtf = NULL;
2040 if(VECTOR_SIZE(device->HrtfList) == 0)
2042 VECTOR_DEINIT(device->HrtfList);
2043 device->HrtfList = EnumerateHrtf(device->DeviceName);
2045 if(VECTOR_SIZE(device->HrtfList) > 0)
2047 if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->HrtfList))
2048 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, hrtf_id).hrtf);
2049 else
2050 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, 0).hrtf);
2053 if(hrtf)
2055 device->FmtChans = DevFmtStereo;
2056 device->Frequency = hrtf->sampleRate;
2057 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
2058 if(device->HrtfHandle)
2059 Hrtf_DecRef(device->HrtfHandle);
2060 device->HrtfHandle = hrtf;
2062 else
2064 hrtf_userreq = Hrtf_Default;
2065 hrtf_appreq = Hrtf_Disable;
2066 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2071 oldFreq = device->Frequency;
2072 oldChans = device->FmtChans;
2073 oldType = device->FmtType;
2075 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2076 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
2077 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
2078 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
2079 device->UpdateSize, device->NumUpdates
2082 if(V0(device->Backend,reset)() == ALC_FALSE)
2083 return ALC_INVALID_DEVICE;
2085 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
2087 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2088 DevFmtChannelsString(device->FmtChans));
2089 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2091 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2093 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2094 DevFmtTypeString(device->FmtType));
2095 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2097 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2099 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2100 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2103 if((device->UpdateSize&3) != 0)
2105 if((CPUCapFlags&CPU_CAP_SSE))
2106 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2107 if((CPUCapFlags&CPU_CAP_NEON))
2108 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2111 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2112 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2113 device->Frequency, device->UpdateSize, device->NumUpdates
2116 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2117 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device->Dry.NumChannels,
2118 device->FOAOut.NumChannels, device->RealOut.NumChannels);
2120 /* Allocate extra channels for any post-filter output. */
2121 size = (device->Dry.NumChannels + device->FOAOut.NumChannels +
2122 device->RealOut.NumChannels)*sizeof(device->Dry.Buffer[0]);
2124 TRACE("Allocating "SZFMT" channels, "SZFMT" bytes\n", size/sizeof(device->Dry.Buffer[0]), size);
2125 device->Dry.Buffer = al_calloc(16, size);
2126 if(!device->Dry.Buffer)
2128 ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
2129 return ALC_INVALID_DEVICE;
2132 if(device->RealOut.NumChannels != 0)
2133 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels +
2134 device->FOAOut.NumChannels;
2135 else
2137 device->RealOut.Buffer = device->Dry.Buffer;
2138 device->RealOut.NumChannels = device->Dry.NumChannels;
2141 if(device->FOAOut.NumChannels != 0)
2142 device->FOAOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2143 else
2145 device->FOAOut.Buffer = device->Dry.Buffer;
2146 device->FOAOut.NumChannels = device->Dry.NumChannels;
2149 device->NumAuxSends = new_sends;
2150 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2151 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
2152 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
2154 device->DitherDepth = 0.0f;
2155 if(GetConfigValueBool(alstr_get_cstr(device->DeviceName), NULL, "dither", 1))
2157 ALint depth = 0;
2158 ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "dither-depth", &depth);
2159 if(depth <= 0)
2161 switch(device->FmtType)
2163 case DevFmtByte:
2164 case DevFmtUByte:
2165 depth = 8;
2166 break;
2167 case DevFmtShort:
2168 case DevFmtUShort:
2169 depth = 16;
2170 break;
2171 case DevFmtInt:
2172 case DevFmtUInt:
2173 case DevFmtFloat:
2174 break;
2177 else if(depth > 24)
2178 depth = 24;
2179 device->DitherDepth = (depth > 0) ? powf(2.0f, (ALfloat)(depth-1)) : 0.0f;
2181 if(!(device->DitherDepth > 0.0f))
2182 TRACE("Dithering disabled\n");
2183 else
2184 TRACE("Dithering enabled (%g-bit, %g)\n", log2f(device->DitherDepth)+1.0f,
2185 device->DitherDepth);
2187 if(ConfigValueBool(alstr_get_cstr(device->DeviceName), NULL, "output-limiter", &val))
2188 gainLimiter = val ? ALC_TRUE : ALC_FALSE;
2189 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2190 * ALC_FALSE. We default to on, so ALC_DONT_CARE_SOFT is the same as
2191 * ALC_TRUE.
2193 if(gainLimiter != ALC_FALSE)
2195 if(!device->Limiter || device->Frequency != GetCompressorSampleRate(device->Limiter))
2197 al_free(device->Limiter);
2198 device->Limiter = CreateDeviceLimiter(device);
2201 else
2203 al_free(device->Limiter);
2204 device->Limiter = NULL;
2206 TRACE("Output limiter %s\n", device->Limiter ? "enabled" : "disabled");
2208 /* Need to delay returning failure until replacement Send arrays have been
2209 * allocated with the appropriate size.
2211 update_failed = AL_FALSE;
2212 START_MIXER_MODE();
2213 context = ATOMIC_LOAD_SEQ(&device->ContextList);
2214 while(context)
2216 struct ALvoiceProps *vprops;
2217 ALsizei pos;
2219 if(context->DefaultSlot)
2221 ALeffectslot *slot = context->DefaultSlot;
2222 ALeffectState *state = slot->Effect.State;
2224 state->OutBuffer = device->Dry.Buffer;
2225 state->OutChannels = device->Dry.NumChannels;
2226 if(V(state,deviceUpdate)(device) == AL_FALSE)
2227 update_failed = AL_TRUE;
2228 else
2229 UpdateEffectSlotProps(slot, context);
2232 WriteLock(&context->PropLock);
2233 LockUIntMapRead(&context->EffectSlotMap);
2234 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
2236 ALeffectslot *slot = context->EffectSlotMap.values[pos];
2237 ALeffectState *state = slot->Effect.State;
2239 state->OutBuffer = device->Dry.Buffer;
2240 state->OutChannels = device->Dry.NumChannels;
2241 if(V(state,deviceUpdate)(device) == AL_FALSE)
2242 update_failed = AL_TRUE;
2243 else
2244 UpdateEffectSlotProps(slot, context);
2246 UnlockUIntMapRead(&context->EffectSlotMap);
2248 LockUIntMapRead(&context->SourceMap);
2249 RelimitUIntMapNoLock(&context->SourceMap, device->SourcesMax);
2250 for(pos = 0;pos < context->SourceMap.size;pos++)
2252 ALsource *source = context->SourceMap.values[pos];
2254 if(old_sends != device->NumAuxSends)
2256 ALvoid *sends = al_calloc(16, device->NumAuxSends*sizeof(source->Send[0]));
2257 ALsizei s;
2259 memcpy(sends, source->Send,
2260 mini(device->NumAuxSends, old_sends)*sizeof(source->Send[0])
2262 for(s = device->NumAuxSends;s < old_sends;s++)
2264 if(source->Send[s].Slot)
2265 DecrementRef(&source->Send[s].Slot->ref);
2266 source->Send[s].Slot = NULL;
2268 al_free(source->Send);
2269 source->Send = sends;
2270 for(s = old_sends;s < device->NumAuxSends;s++)
2272 source->Send[s].Slot = NULL;
2273 source->Send[s].Gain = 1.0f;
2274 source->Send[s].GainHF = 1.0f;
2275 source->Send[s].HFReference = LOWPASSFREQREF;
2276 source->Send[s].GainLF = 1.0f;
2277 source->Send[s].LFReference = HIGHPASSFREQREF;
2281 ATOMIC_FLAG_CLEAR(&source->PropsClean, almemory_order_release);
2284 /* Clear any pre-existing voice property structs, in case the number of
2285 * auxiliary sends is changing. Active sources will have updates
2286 * respecified in UpdateAllSourceProps.
2288 vprops = ATOMIC_EXCHANGE_PTR(&context->FreeVoiceProps, NULL, almemory_order_acq_rel);
2289 while(vprops)
2291 struct ALvoiceProps *next = ATOMIC_LOAD(&vprops->next, almemory_order_relaxed);
2292 al_free(vprops);
2293 vprops = next;
2296 AllocateVoices(context, context->MaxVoices, old_sends);
2297 for(pos = 0;pos < context->VoiceCount;pos++)
2299 ALvoice *voice = context->Voices[pos];
2301 al_free(ATOMIC_EXCHANGE_PTR(&voice->Update, NULL, almemory_order_acq_rel));
2303 if(ATOMIC_LOAD(&voice->Source, almemory_order_acquire) == NULL)
2304 continue;
2306 if(device->AvgSpeakerDist > 0.0f)
2308 /* Reinitialize the NFC filters for new parameters. */
2309 ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
2310 (device->AvgSpeakerDist * device->Frequency);
2311 for(i = 0;i < voice->NumChannels;i++)
2313 NfcFilterCreate1(&voice->Direct.Params[i].NFCtrlFilter[0], 0.0f, w1);
2314 NfcFilterCreate2(&voice->Direct.Params[i].NFCtrlFilter[1], 0.0f, w1);
2315 NfcFilterCreate3(&voice->Direct.Params[i].NFCtrlFilter[2], 0.0f, w1);
2319 UnlockUIntMapRead(&context->SourceMap);
2321 ATOMIC_FLAG_TEST_AND_SET(&context->PropsClean, almemory_order_release);
2322 UpdateContextProps(context);
2323 ATOMIC_FLAG_TEST_AND_SET(&context->Listener->PropsClean, almemory_order_release);
2324 UpdateListenerProps(context);
2325 UpdateAllSourceProps(context);
2326 WriteUnlock(&context->PropLock);
2328 context = context->next;
2330 END_MIXER_MODE();
2331 if(update_failed)
2332 return ALC_INVALID_DEVICE;
2334 if(!(device->Flags&DEVICE_PAUSED))
2336 if(V0(device->Backend,start)() == ALC_FALSE)
2337 return ALC_INVALID_DEVICE;
2338 device->Flags |= DEVICE_RUNNING;
2341 return ALC_NO_ERROR;
2344 /* FreeDevice
2346 * Frees the device structure, and destroys any objects the app failed to
2347 * delete. Called once there's no more references on the device.
2349 static ALCvoid FreeDevice(ALCdevice *device)
2351 ALsizei i;
2353 TRACE("%p\n", device);
2355 V0(device->Backend,close)();
2356 DELETE_OBJ(device->Backend);
2357 device->Backend = NULL;
2359 almtx_destroy(&device->BackendLock);
2361 if(device->BufferMap.size > 0)
2363 WARN("(%p) Deleting %d Buffer%s\n", device, device->BufferMap.size,
2364 (device->BufferMap.size==1)?"":"s");
2365 ReleaseALBuffers(device);
2367 ResetUIntMap(&device->BufferMap);
2369 if(device->EffectMap.size > 0)
2371 WARN("(%p) Deleting %d Effect%s\n", device, device->EffectMap.size,
2372 (device->EffectMap.size==1)?"":"s");
2373 ReleaseALEffects(device);
2375 ResetUIntMap(&device->EffectMap);
2377 if(device->FilterMap.size > 0)
2379 WARN("(%p) Deleting %d Filter%s\n", device, device->FilterMap.size,
2380 (device->FilterMap.size==1)?"":"s");
2381 ReleaseALFilters(device);
2383 ResetUIntMap(&device->FilterMap);
2385 AL_STRING_DEINIT(device->HrtfName);
2386 FreeHrtfList(&device->HrtfList);
2387 if(device->HrtfHandle)
2388 Hrtf_DecRef(device->HrtfHandle);
2389 device->HrtfHandle = NULL;
2390 al_free(device->Hrtf);
2391 device->Hrtf = NULL;
2393 al_free(device->Bs2b);
2394 device->Bs2b = NULL;
2396 al_free(device->Uhj_Encoder);
2397 device->Uhj_Encoder = NULL;
2399 bformatdec_free(device->AmbiDecoder);
2400 device->AmbiDecoder = NULL;
2402 ambiup_free(device->AmbiUp);
2403 device->AmbiUp = NULL;
2405 al_free(device->Stablizer);
2406 device->Stablizer = NULL;
2408 al_free(device->Limiter);
2409 device->Limiter = NULL;
2411 al_free(device->ChannelDelay[0].Buffer);
2412 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2414 device->ChannelDelay[i].Gain = 1.0f;
2415 device->ChannelDelay[i].Length = 0;
2416 device->ChannelDelay[i].Buffer = NULL;
2419 AL_STRING_DEINIT(device->DeviceName);
2421 al_free(device->Dry.Buffer);
2422 device->Dry.Buffer = NULL;
2423 device->Dry.NumChannels = 0;
2424 device->FOAOut.Buffer = NULL;
2425 device->FOAOut.NumChannels = 0;
2426 device->RealOut.Buffer = NULL;
2427 device->RealOut.NumChannels = 0;
2429 al_free(device);
2433 void ALCdevice_IncRef(ALCdevice *device)
2435 uint ref;
2436 ref = IncrementRef(&device->ref);
2437 TRACEREF("%p increasing refcount to %u\n", device, ref);
2440 void ALCdevice_DecRef(ALCdevice *device)
2442 uint ref;
2443 ref = DecrementRef(&device->ref);
2444 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2445 if(ref == 0) FreeDevice(device);
2448 /* VerifyDevice
2450 * Checks if the device handle is valid, and increments its ref count if so.
2452 static ALCboolean VerifyDevice(ALCdevice **device)
2454 ALCdevice *tmpDevice;
2456 LockLists();
2457 tmpDevice = ATOMIC_LOAD_SEQ(&DeviceList);
2458 while(tmpDevice)
2460 if(tmpDevice == *device)
2462 ALCdevice_IncRef(tmpDevice);
2463 UnlockLists();
2464 return ALC_TRUE;
2466 tmpDevice = tmpDevice->next;
2468 UnlockLists();
2470 *device = NULL;
2471 return ALC_FALSE;
2475 /* InitContext
2477 * Initializes context fields
2479 static ALvoid InitContext(ALCcontext *Context)
2481 ALlistener *listener = Context->Listener;
2482 struct ALeffectslotArray *auxslots;
2484 //Initialise listener
2485 listener->Gain = 1.0f;
2486 listener->Position[0] = 0.0f;
2487 listener->Position[1] = 0.0f;
2488 listener->Position[2] = 0.0f;
2489 listener->Velocity[0] = 0.0f;
2490 listener->Velocity[1] = 0.0f;
2491 listener->Velocity[2] = 0.0f;
2492 listener->Forward[0] = 0.0f;
2493 listener->Forward[1] = 0.0f;
2494 listener->Forward[2] = -1.0f;
2495 listener->Up[0] = 0.0f;
2496 listener->Up[1] = 1.0f;
2497 listener->Up[2] = 0.0f;
2498 ATOMIC_FLAG_TEST_AND_SET(&listener->PropsClean, almemory_order_relaxed);
2500 ATOMIC_INIT(&listener->Update, NULL);
2502 //Validate Context
2503 InitRef(&Context->UpdateCount, 0);
2504 ATOMIC_INIT(&Context->HoldUpdates, AL_FALSE);
2505 Context->GainBoost = 1.0f;
2506 RWLockInit(&Context->PropLock);
2507 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2508 InitUIntMap(&Context->SourceMap, Context->Device->SourcesMax);
2509 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2511 if(Context->DefaultSlot)
2513 auxslots = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, 1));
2514 auxslots->count = 1;
2515 auxslots->slot[0] = Context->DefaultSlot;
2517 else
2519 auxslots = al_calloc(DEF_ALIGN, sizeof(struct ALeffectslotArray));
2520 auxslots->count = 0;
2522 ATOMIC_INIT(&Context->ActiveAuxSlots, auxslots);
2524 //Set globals
2525 Context->DistanceModel = DefaultDistanceModel;
2526 Context->SourceDistanceModel = AL_FALSE;
2527 Context->DopplerFactor = 1.0f;
2528 Context->DopplerVelocity = 1.0f;
2529 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2530 Context->MetersPerUnit = AL_DEFAULT_METERS_PER_UNIT;
2531 ATOMIC_FLAG_TEST_AND_SET(&Context->PropsClean, almemory_order_relaxed);
2532 ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
2534 ATOMIC_INIT(&Context->Update, NULL);
2535 ATOMIC_INIT(&Context->FreeContextProps, NULL);
2536 ATOMIC_INIT(&Context->FreeListenerProps, NULL);
2537 ATOMIC_INIT(&Context->FreeVoiceProps, NULL);
2538 ATOMIC_INIT(&Context->FreeEffectslotProps, NULL);
2540 Context->ExtensionList = alExtList;
2543 listener->Params.Matrix = IdentityMatrixf;
2544 aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2545 listener->Params.Gain = listener->Gain;
2546 listener->Params.MetersPerUnit = Context->MetersPerUnit;
2547 listener->Params.DopplerFactor = Context->DopplerFactor;
2548 listener->Params.SpeedOfSound = Context->SpeedOfSound * Context->DopplerVelocity;
2549 listener->Params.ReverbSpeedOfSound = listener->Params.SpeedOfSound *
2550 listener->Params.MetersPerUnit;
2551 listener->Params.SourceDistanceModel = Context->SourceDistanceModel;
2552 listener->Params.DistanceModel = Context->DistanceModel;
2556 /* FreeContext
2558 * Cleans up the context, and destroys any remaining objects the app failed to
2559 * delete. Called once there's no more references on the context.
2561 static void FreeContext(ALCcontext *context)
2563 ALlistener *listener = context->Listener;
2564 struct ALeffectslotArray *auxslots;
2565 struct ALeffectslotProps *eprops;
2566 struct ALlistenerProps *lprops;
2567 struct ALcontextProps *cprops;
2568 struct ALvoiceProps *vprops;
2569 size_t count;
2570 ALsizei i;
2572 TRACE("%p\n", context);
2574 if((cprops=ATOMIC_LOAD(&context->Update, almemory_order_acquire)) != NULL)
2576 TRACE("Freed unapplied context update %p\n", cprops);
2577 al_free(cprops);
2580 count = 0;
2581 cprops = ATOMIC_LOAD(&context->FreeContextProps, almemory_order_acquire);
2582 while(cprops)
2584 struct ALcontextProps *next = ATOMIC_LOAD(&cprops->next, almemory_order_acquire);
2585 al_free(cprops);
2586 cprops = next;
2587 ++count;
2589 TRACE("Freed "SZFMT" context property object%s\n", count, (count==1)?"":"s");
2591 if(context->DefaultSlot)
2593 DeinitEffectSlot(context->DefaultSlot);
2594 context->DefaultSlot = NULL;
2597 auxslots = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, NULL, almemory_order_relaxed);
2598 al_free(auxslots);
2600 if(context->SourceMap.size > 0)
2602 WARN("(%p) Deleting %d Source%s\n", context, context->SourceMap.size,
2603 (context->SourceMap.size==1)?"":"s");
2604 ReleaseALSources(context);
2606 ResetUIntMap(&context->SourceMap);
2608 count = 0;
2609 eprops = ATOMIC_LOAD(&context->FreeEffectslotProps, almemory_order_relaxed);
2610 while(eprops)
2612 struct ALeffectslotProps *next = ATOMIC_LOAD(&eprops->next, almemory_order_relaxed);
2613 if(eprops->State) ALeffectState_DecRef(eprops->State);
2614 al_free(eprops);
2615 eprops = next;
2616 ++count;
2618 TRACE("Freed "SZFMT" AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2619 if(context->EffectSlotMap.size > 0)
2621 WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context, context->EffectSlotMap.size,
2622 (context->EffectSlotMap.size==1)?"":"s");
2623 ReleaseALAuxiliaryEffectSlots(context);
2625 ResetUIntMap(&context->EffectSlotMap);
2627 count = 0;
2628 vprops = ATOMIC_LOAD(&context->FreeVoiceProps, almemory_order_relaxed);
2629 while(vprops)
2631 struct ALvoiceProps *next = ATOMIC_LOAD(&vprops->next, almemory_order_relaxed);
2632 al_free(vprops);
2633 vprops = next;
2634 ++count;
2636 TRACE("Freed "SZFMT" voice property object%s\n", count, (count==1)?"":"s");
2638 for(i = 0;i < context->VoiceCount;i++)
2639 DeinitVoice(context->Voices[i]);
2640 al_free(context->Voices);
2641 context->Voices = NULL;
2642 context->VoiceCount = 0;
2643 context->MaxVoices = 0;
2645 if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != NULL)
2647 TRACE("Freed unapplied listener update %p\n", lprops);
2648 al_free(lprops);
2650 count = 0;
2651 lprops = ATOMIC_LOAD(&context->FreeListenerProps, almemory_order_acquire);
2652 while(lprops)
2654 struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_acquire);
2655 al_free(lprops);
2656 lprops = next;
2657 ++count;
2659 TRACE("Freed "SZFMT" listener property object%s\n", count, (count==1)?"":"s");
2661 ALCdevice_DecRef(context->Device);
2662 context->Device = NULL;
2664 //Invalidate context
2665 memset(context, 0, sizeof(ALCcontext));
2666 al_free(context);
2669 /* ReleaseContext
2671 * Removes the context reference from the given device and removes it from
2672 * being current on the running thread or globally. Returns true if other
2673 * contexts still exist on the device.
2675 static bool ReleaseContext(ALCcontext *context, ALCdevice *device)
2677 ALCcontext *origctx, *newhead;
2678 bool ret = true;
2680 if(altss_get(LocalContext) == context)
2682 WARN("%p released while current on thread\n", context);
2683 altss_set(LocalContext, NULL);
2684 ALCcontext_DecRef(context);
2687 origctx = context;
2688 if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext, &origctx, NULL))
2689 ALCcontext_DecRef(context);
2691 V0(device->Backend,lock)();
2692 origctx = context;
2693 newhead = context->next;
2694 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device->ContextList, &origctx, newhead))
2696 ALCcontext *volatile*list = &origctx->next;
2697 while(*list)
2699 if(*list == context)
2701 *list = (*list)->next;
2702 break;
2704 list = &(*list)->next;
2707 else
2708 ret = !!newhead;
2709 V0(device->Backend,unlock)();
2711 ALCcontext_DecRef(context);
2712 return ret;
2715 static void ALCcontext_IncRef(ALCcontext *context)
2717 uint ref = IncrementRef(&context->ref);
2718 TRACEREF("%p increasing refcount to %u\n", context, ref);
2721 void ALCcontext_DecRef(ALCcontext *context)
2723 uint ref = DecrementRef(&context->ref);
2724 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2725 if(ref == 0) FreeContext(context);
2728 static void ReleaseThreadCtx(void *ptr)
2730 ALCcontext *context = ptr;
2731 uint ref = DecrementRef(&context->ref);
2732 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2733 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2736 /* VerifyContext
2738 * Checks that the given context is valid, and increments its reference count.
2740 static ALCboolean VerifyContext(ALCcontext **context)
2742 ALCdevice *dev;
2744 LockLists();
2745 dev = ATOMIC_LOAD_SEQ(&DeviceList);
2746 while(dev)
2748 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList, almemory_order_acquire);
2749 while(ctx)
2751 if(ctx == *context)
2753 ALCcontext_IncRef(ctx);
2754 UnlockLists();
2755 return ALC_TRUE;
2757 ctx = ctx->next;
2759 dev = dev->next;
2761 UnlockLists();
2763 *context = NULL;
2764 return ALC_FALSE;
2768 /* GetContextRef
2770 * Returns the currently active context for this thread, and adds a reference
2771 * without locking it.
2773 ALCcontext *GetContextRef(void)
2775 ALCcontext *context;
2777 context = altss_get(LocalContext);
2778 if(context)
2779 ALCcontext_IncRef(context);
2780 else
2782 LockLists();
2783 context = ATOMIC_LOAD_SEQ(&GlobalContext);
2784 if(context)
2785 ALCcontext_IncRef(context);
2786 UnlockLists();
2789 return context;
2793 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
2795 ALCdevice *device = context->Device;
2796 ALsizei num_sends = device->NumAuxSends;
2797 struct ALvoiceProps *props;
2798 size_t sizeof_props;
2799 size_t sizeof_voice;
2800 ALvoice **voices;
2801 ALvoice *voice;
2802 ALsizei v = 0;
2803 size_t size;
2805 if(num_voices == context->MaxVoices && num_sends == old_sends)
2806 return;
2808 /* Allocate the voice pointers, voices, and the voices' stored source
2809 * property set (including the dynamically-sized Send[] array) in one
2810 * chunk.
2812 sizeof_voice = RoundUp(FAM_SIZE(ALvoice, Send, num_sends), 16);
2813 sizeof_props = RoundUp(FAM_SIZE(struct ALvoiceProps, Send, num_sends), 16);
2814 size = sizeof(ALvoice*) + sizeof_voice + sizeof_props;
2816 voices = al_calloc(16, RoundUp(size*num_voices, 16));
2817 /* The voice and property objects are stored interleaved since they're
2818 * paired together.
2820 voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
2821 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2823 if(context->Voices)
2825 const ALsizei v_count = mini(context->VoiceCount, num_voices);
2826 const ALsizei s_count = mini(old_sends, num_sends);
2828 for(;v < v_count;v++)
2830 ALvoice *old_voice = context->Voices[v];
2831 ALsizei i;
2833 /* Copy the old voice data and source property set to the new
2834 * storage.
2836 *voice = *old_voice;
2837 for(i = 0;i < s_count;i++)
2838 voice->Send[i] = old_voice->Send[i];
2839 *props = *(old_voice->Props);
2840 for(i = 0;i < s_count;i++)
2841 props->Send[i] = old_voice->Props->Send[i];
2843 /* Set this voice's property set pointer and voice reference. */
2844 voice->Props = props;
2845 voices[v] = voice;
2847 /* Increment pointers to the next storage space. */
2848 voice = (ALvoice*)((char*)props + sizeof_props);
2849 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2851 /* Deinit any left over voices that weren't copied over to the new
2852 * array. NOTE: If this does anything, v equals num_voices and
2853 * num_voices is less than VoiceCount, so the following loop won't do
2854 * anything.
2856 for(;v < context->VoiceCount;v++)
2857 DeinitVoice(context->Voices[v]);
2859 /* Finish setting the voices' property set pointers and references. */
2860 for(;v < num_voices;v++)
2862 ATOMIC_INIT(&voice->Update, NULL);
2864 voice->Props = props;
2865 voices[v] = voice;
2867 voice = (ALvoice*)((char*)props + sizeof_props);
2868 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2871 al_free(context->Voices);
2872 context->Voices = voices;
2873 context->MaxVoices = num_voices;
2874 context->VoiceCount = mini(context->VoiceCount, num_voices);
2878 /************************************************
2879 * Standard ALC functions
2880 ************************************************/
2882 /* alcGetError
2884 * Return last ALC generated error code for the given device
2886 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2888 ALCenum errorCode;
2890 if(VerifyDevice(&device))
2892 errorCode = ATOMIC_EXCHANGE_SEQ(&device->LastError, ALC_NO_ERROR);
2893 ALCdevice_DecRef(device);
2895 else
2896 errorCode = ATOMIC_EXCHANGE_SEQ(&LastNullDeviceError, ALC_NO_ERROR);
2898 return errorCode;
2902 /* alcSuspendContext
2904 * Suspends updates for the given context
2906 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2908 if(!SuspendDefers)
2909 return;
2911 if(!VerifyContext(&context))
2912 alcSetError(NULL, ALC_INVALID_CONTEXT);
2913 else
2915 ALCcontext_DeferUpdates(context);
2916 ALCcontext_DecRef(context);
2920 /* alcProcessContext
2922 * Resumes processing updates for the given context
2924 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2926 if(!SuspendDefers)
2927 return;
2929 if(!VerifyContext(&context))
2930 alcSetError(NULL, ALC_INVALID_CONTEXT);
2931 else
2933 ALCcontext_ProcessUpdates(context);
2934 ALCcontext_DecRef(context);
2939 /* alcGetString
2941 * Returns information about the device, and error strings
2943 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2945 const ALCchar *value = NULL;
2947 switch(param)
2949 case ALC_NO_ERROR:
2950 value = alcNoError;
2951 break;
2953 case ALC_INVALID_ENUM:
2954 value = alcErrInvalidEnum;
2955 break;
2957 case ALC_INVALID_VALUE:
2958 value = alcErrInvalidValue;
2959 break;
2961 case ALC_INVALID_DEVICE:
2962 value = alcErrInvalidDevice;
2963 break;
2965 case ALC_INVALID_CONTEXT:
2966 value = alcErrInvalidContext;
2967 break;
2969 case ALC_OUT_OF_MEMORY:
2970 value = alcErrOutOfMemory;
2971 break;
2973 case ALC_DEVICE_SPECIFIER:
2974 value = alcDefaultName;
2975 break;
2977 case ALC_ALL_DEVICES_SPECIFIER:
2978 if(VerifyDevice(&Device))
2980 value = alstr_get_cstr(Device->DeviceName);
2981 ALCdevice_DecRef(Device);
2983 else
2985 ProbeAllDevicesList();
2986 value = alstr_get_cstr(alcAllDevicesList);
2988 break;
2990 case ALC_CAPTURE_DEVICE_SPECIFIER:
2991 if(VerifyDevice(&Device))
2993 value = alstr_get_cstr(Device->DeviceName);
2994 ALCdevice_DecRef(Device);
2996 else
2998 ProbeCaptureDeviceList();
2999 value = alstr_get_cstr(alcCaptureDeviceList);
3001 break;
3003 /* Default devices are always first in the list */
3004 case ALC_DEFAULT_DEVICE_SPECIFIER:
3005 value = alcDefaultName;
3006 break;
3008 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
3009 if(alstr_empty(alcAllDevicesList))
3010 ProbeAllDevicesList();
3012 VerifyDevice(&Device);
3014 free(alcDefaultAllDevicesSpecifier);
3015 alcDefaultAllDevicesSpecifier = strdup(alstr_get_cstr(alcAllDevicesList));
3016 if(!alcDefaultAllDevicesSpecifier)
3017 alcSetError(Device, ALC_OUT_OF_MEMORY);
3019 value = alcDefaultAllDevicesSpecifier;
3020 if(Device) ALCdevice_DecRef(Device);
3021 break;
3023 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
3024 if(alstr_empty(alcCaptureDeviceList))
3025 ProbeCaptureDeviceList();
3027 VerifyDevice(&Device);
3029 free(alcCaptureDefaultDeviceSpecifier);
3030 alcCaptureDefaultDeviceSpecifier = strdup(alstr_get_cstr(alcCaptureDeviceList));
3031 if(!alcCaptureDefaultDeviceSpecifier)
3032 alcSetError(Device, ALC_OUT_OF_MEMORY);
3034 value = alcCaptureDefaultDeviceSpecifier;
3035 if(Device) ALCdevice_DecRef(Device);
3036 break;
3038 case ALC_EXTENSIONS:
3039 if(!VerifyDevice(&Device))
3040 value = alcNoDeviceExtList;
3041 else
3043 value = alcExtensionList;
3044 ALCdevice_DecRef(Device);
3046 break;
3048 case ALC_HRTF_SPECIFIER_SOFT:
3049 if(!VerifyDevice(&Device))
3050 alcSetError(NULL, ALC_INVALID_DEVICE);
3051 else
3053 almtx_lock(&Device->BackendLock);
3054 value = (Device->HrtfHandle ? alstr_get_cstr(Device->HrtfName) : "");
3055 almtx_unlock(&Device->BackendLock);
3056 ALCdevice_DecRef(Device);
3058 break;
3060 default:
3061 VerifyDevice(&Device);
3062 alcSetError(Device, ALC_INVALID_ENUM);
3063 if(Device) ALCdevice_DecRef(Device);
3064 break;
3067 return value;
3071 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
3073 if(device->Type == Capture) return 9;
3074 if(device->Type != Loopback) return 29;
3075 if(device->FmtChans == DevFmtAmbi3D)
3076 return 35;
3077 return 29;
3080 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3082 ALCsizei i;
3084 if(size <= 0 || values == NULL)
3086 alcSetError(device, ALC_INVALID_VALUE);
3087 return 0;
3090 if(!device)
3092 switch(param)
3094 case ALC_MAJOR_VERSION:
3095 values[0] = alcMajorVersion;
3096 return 1;
3097 case ALC_MINOR_VERSION:
3098 values[0] = alcMinorVersion;
3099 return 1;
3101 case ALC_ATTRIBUTES_SIZE:
3102 case ALC_ALL_ATTRIBUTES:
3103 case ALC_FREQUENCY:
3104 case ALC_REFRESH:
3105 case ALC_SYNC:
3106 case ALC_MONO_SOURCES:
3107 case ALC_STEREO_SOURCES:
3108 case ALC_CAPTURE_SAMPLES:
3109 case ALC_FORMAT_CHANNELS_SOFT:
3110 case ALC_FORMAT_TYPE_SOFT:
3111 case ALC_AMBISONIC_LAYOUT_SOFT:
3112 case ALC_AMBISONIC_SCALING_SOFT:
3113 case ALC_AMBISONIC_ORDER_SOFT:
3114 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3115 alcSetError(NULL, ALC_INVALID_DEVICE);
3116 return 0;
3118 default:
3119 alcSetError(NULL, ALC_INVALID_ENUM);
3120 return 0;
3122 return 0;
3125 if(device->Type == Capture)
3127 switch(param)
3129 case ALC_ATTRIBUTES_SIZE:
3130 values[0] = NumAttrsForDevice(device);
3131 return 1;
3133 case ALC_ALL_ATTRIBUTES:
3134 if(size < NumAttrsForDevice(device))
3136 alcSetError(device, ALC_INVALID_VALUE);
3137 return 0;
3140 i = 0;
3141 almtx_lock(&device->BackendLock);
3142 values[i++] = ALC_MAJOR_VERSION;
3143 values[i++] = alcMajorVersion;
3144 values[i++] = ALC_MINOR_VERSION;
3145 values[i++] = alcMinorVersion;
3146 values[i++] = ALC_CAPTURE_SAMPLES;
3147 values[i++] = V0(device->Backend,availableSamples)();
3148 values[i++] = ALC_CONNECTED;
3149 values[i++] = device->Connected;
3150 almtx_unlock(&device->BackendLock);
3152 values[i++] = 0;
3153 return i;
3155 case ALC_MAJOR_VERSION:
3156 values[0] = alcMajorVersion;
3157 return 1;
3158 case ALC_MINOR_VERSION:
3159 values[0] = alcMinorVersion;
3160 return 1;
3162 case ALC_CAPTURE_SAMPLES:
3163 almtx_lock(&device->BackendLock);
3164 values[0] = V0(device->Backend,availableSamples)();
3165 almtx_unlock(&device->BackendLock);
3166 return 1;
3168 case ALC_CONNECTED:
3169 values[0] = device->Connected;
3170 return 1;
3172 default:
3173 alcSetError(device, ALC_INVALID_ENUM);
3174 return 0;
3176 return 0;
3179 /* render device */
3180 switch(param)
3182 case ALC_ATTRIBUTES_SIZE:
3183 values[0] = NumAttrsForDevice(device);
3184 return 1;
3186 case ALC_ALL_ATTRIBUTES:
3187 if(size < NumAttrsForDevice(device))
3189 alcSetError(device, ALC_INVALID_VALUE);
3190 return 0;
3193 i = 0;
3194 almtx_lock(&device->BackendLock);
3195 values[i++] = ALC_MAJOR_VERSION;
3196 values[i++] = alcMajorVersion;
3197 values[i++] = ALC_MINOR_VERSION;
3198 values[i++] = alcMinorVersion;
3199 values[i++] = ALC_EFX_MAJOR_VERSION;
3200 values[i++] = alcEFXMajorVersion;
3201 values[i++] = ALC_EFX_MINOR_VERSION;
3202 values[i++] = alcEFXMinorVersion;
3204 values[i++] = ALC_FREQUENCY;
3205 values[i++] = device->Frequency;
3206 if(device->Type != Loopback)
3208 values[i++] = ALC_REFRESH;
3209 values[i++] = device->Frequency / device->UpdateSize;
3211 values[i++] = ALC_SYNC;
3212 values[i++] = ALC_FALSE;
3214 else
3216 if(device->FmtChans == DevFmtAmbi3D)
3218 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3219 values[i++] = device->AmbiLayout;
3221 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3222 values[i++] = device->AmbiScale;
3224 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3225 values[i++] = device->AmbiOrder;
3228 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3229 values[i++] = device->FmtChans;
3231 values[i++] = ALC_FORMAT_TYPE_SOFT;
3232 values[i++] = device->FmtType;
3235 values[i++] = ALC_MONO_SOURCES;
3236 values[i++] = device->NumMonoSources;
3238 values[i++] = ALC_STEREO_SOURCES;
3239 values[i++] = device->NumStereoSources;
3241 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3242 values[i++] = device->NumAuxSends;
3244 values[i++] = ALC_HRTF_SOFT;
3245 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3247 values[i++] = ALC_HRTF_STATUS_SOFT;
3248 values[i++] = device->HrtfStatus;
3250 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3251 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3253 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
3254 values[i++] = MAX_AMBI_ORDER;
3255 almtx_unlock(&device->BackendLock);
3257 values[i++] = 0;
3258 return i;
3260 case ALC_MAJOR_VERSION:
3261 values[0] = alcMajorVersion;
3262 return 1;
3264 case ALC_MINOR_VERSION:
3265 values[0] = alcMinorVersion;
3266 return 1;
3268 case ALC_EFX_MAJOR_VERSION:
3269 values[0] = alcEFXMajorVersion;
3270 return 1;
3272 case ALC_EFX_MINOR_VERSION:
3273 values[0] = alcEFXMinorVersion;
3274 return 1;
3276 case ALC_FREQUENCY:
3277 values[0] = device->Frequency;
3278 return 1;
3280 case ALC_REFRESH:
3281 if(device->Type == Loopback)
3283 alcSetError(device, ALC_INVALID_DEVICE);
3284 return 0;
3286 almtx_lock(&device->BackendLock);
3287 values[0] = device->Frequency / device->UpdateSize;
3288 almtx_unlock(&device->BackendLock);
3289 return 1;
3291 case ALC_SYNC:
3292 if(device->Type == Loopback)
3294 alcSetError(device, ALC_INVALID_DEVICE);
3295 return 0;
3297 values[0] = ALC_FALSE;
3298 return 1;
3300 case ALC_FORMAT_CHANNELS_SOFT:
3301 if(device->Type != Loopback)
3303 alcSetError(device, ALC_INVALID_DEVICE);
3304 return 0;
3306 values[0] = device->FmtChans;
3307 return 1;
3309 case ALC_FORMAT_TYPE_SOFT:
3310 if(device->Type != Loopback)
3312 alcSetError(device, ALC_INVALID_DEVICE);
3313 return 0;
3315 values[0] = device->FmtType;
3316 return 1;
3318 case ALC_AMBISONIC_LAYOUT_SOFT:
3319 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3321 alcSetError(device, ALC_INVALID_DEVICE);
3322 return 0;
3324 values[0] = device->AmbiLayout;
3325 return 1;
3327 case ALC_AMBISONIC_SCALING_SOFT:
3328 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3330 alcSetError(device, ALC_INVALID_DEVICE);
3331 return 0;
3333 values[0] = device->AmbiScale;
3334 return 1;
3336 case ALC_AMBISONIC_ORDER_SOFT:
3337 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3339 alcSetError(device, ALC_INVALID_DEVICE);
3340 return 0;
3342 values[0] = device->AmbiOrder;
3343 return 1;
3345 case ALC_MONO_SOURCES:
3346 values[0] = device->NumMonoSources;
3347 return 1;
3349 case ALC_STEREO_SOURCES:
3350 values[0] = device->NumStereoSources;
3351 return 1;
3353 case ALC_MAX_AUXILIARY_SENDS:
3354 values[0] = device->NumAuxSends;
3355 return 1;
3357 case ALC_CONNECTED:
3358 values[0] = device->Connected;
3359 return 1;
3361 case ALC_HRTF_SOFT:
3362 values[0] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3363 return 1;
3365 case ALC_HRTF_STATUS_SOFT:
3366 values[0] = device->HrtfStatus;
3367 return 1;
3369 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3370 almtx_lock(&device->BackendLock);
3371 FreeHrtfList(&device->HrtfList);
3372 device->HrtfList = EnumerateHrtf(device->DeviceName);
3373 values[0] = (ALCint)VECTOR_SIZE(device->HrtfList);
3374 almtx_unlock(&device->BackendLock);
3375 return 1;
3377 case ALC_OUTPUT_LIMITER_SOFT:
3378 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3379 return 1;
3381 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3382 values[0] = MAX_AMBI_ORDER;
3383 return 1;
3385 default:
3386 alcSetError(device, ALC_INVALID_ENUM);
3387 return 0;
3389 return 0;
3392 /* alcGetIntegerv
3394 * Returns information about the device and the version of OpenAL
3396 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3398 VerifyDevice(&device);
3399 if(size <= 0 || values == NULL)
3400 alcSetError(device, ALC_INVALID_VALUE);
3401 else
3402 GetIntegerv(device, param, size, values);
3403 if(device) ALCdevice_DecRef(device);
3406 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3408 ALCint *ivals;
3409 ALsizei i;
3411 VerifyDevice(&device);
3412 if(size <= 0 || values == NULL)
3413 alcSetError(device, ALC_INVALID_VALUE);
3414 else if(!device || device->Type == Capture)
3416 ivals = malloc(size * sizeof(ALCint));
3417 size = GetIntegerv(device, pname, size, ivals);
3418 for(i = 0;i < size;i++)
3419 values[i] = ivals[i];
3420 free(ivals);
3422 else /* render device */
3424 ClockLatency clock;
3425 ALuint64 basecount;
3426 ALuint samplecount;
3427 ALuint refcount;
3429 switch(pname)
3431 case ALC_ATTRIBUTES_SIZE:
3432 *values = NumAttrsForDevice(device)+4;
3433 break;
3435 case ALC_ALL_ATTRIBUTES:
3436 if(size < NumAttrsForDevice(device)+4)
3437 alcSetError(device, ALC_INVALID_VALUE);
3438 else
3440 i = 0;
3441 almtx_lock(&device->BackendLock);
3442 values[i++] = ALC_FREQUENCY;
3443 values[i++] = device->Frequency;
3445 if(device->Type != Loopback)
3447 values[i++] = ALC_REFRESH;
3448 values[i++] = device->Frequency / device->UpdateSize;
3450 values[i++] = ALC_SYNC;
3451 values[i++] = ALC_FALSE;
3453 else
3455 if(device->FmtChans == DevFmtAmbi3D)
3457 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3458 values[i++] = device->AmbiLayout;
3460 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3461 values[i++] = device->AmbiScale;
3463 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3464 values[i++] = device->AmbiOrder;
3467 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3468 values[i++] = device->FmtChans;
3470 values[i++] = ALC_FORMAT_TYPE_SOFT;
3471 values[i++] = device->FmtType;
3474 values[i++] = ALC_MONO_SOURCES;
3475 values[i++] = device->NumMonoSources;
3477 values[i++] = ALC_STEREO_SOURCES;
3478 values[i++] = device->NumStereoSources;
3480 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3481 values[i++] = device->NumAuxSends;
3483 values[i++] = ALC_HRTF_SOFT;
3484 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3486 values[i++] = ALC_HRTF_STATUS_SOFT;
3487 values[i++] = device->HrtfStatus;
3489 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3490 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3492 clock = V0(device->Backend,getClockLatency)();
3493 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3494 values[i++] = clock.ClockTime;
3496 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3497 values[i++] = clock.Latency;
3498 almtx_unlock(&device->BackendLock);
3500 values[i++] = 0;
3502 break;
3504 case ALC_DEVICE_CLOCK_SOFT:
3505 almtx_lock(&device->BackendLock);
3506 do {
3507 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3508 althrd_yield();
3509 basecount = device->ClockBase;
3510 samplecount = device->SamplesDone;
3511 } while(refcount != ReadRef(&device->MixCount));
3512 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3513 almtx_unlock(&device->BackendLock);
3514 break;
3516 case ALC_DEVICE_LATENCY_SOFT:
3517 almtx_lock(&device->BackendLock);
3518 clock = V0(device->Backend,getClockLatency)();
3519 almtx_unlock(&device->BackendLock);
3520 *values = clock.Latency;
3521 break;
3523 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3524 if(size < 2)
3525 alcSetError(device, ALC_INVALID_VALUE);
3526 else
3528 almtx_lock(&device->BackendLock);
3529 clock = V0(device->Backend,getClockLatency)();
3530 almtx_unlock(&device->BackendLock);
3531 values[0] = clock.ClockTime;
3532 values[1] = clock.Latency;
3534 break;
3536 default:
3537 ivals = malloc(size * sizeof(ALCint));
3538 size = GetIntegerv(device, pname, size, ivals);
3539 for(i = 0;i < size;i++)
3540 values[i] = ivals[i];
3541 free(ivals);
3542 break;
3545 if(device)
3546 ALCdevice_DecRef(device);
3550 /* alcIsExtensionPresent
3552 * Determines if there is support for a particular extension
3554 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3556 ALCboolean bResult = ALC_FALSE;
3558 VerifyDevice(&device);
3560 if(!extName)
3561 alcSetError(device, ALC_INVALID_VALUE);
3562 else
3564 size_t len = strlen(extName);
3565 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3566 while(ptr && *ptr)
3568 if(strncasecmp(ptr, extName, len) == 0 &&
3569 (ptr[len] == '\0' || isspace(ptr[len])))
3571 bResult = ALC_TRUE;
3572 break;
3574 if((ptr=strchr(ptr, ' ')) != NULL)
3576 do {
3577 ++ptr;
3578 } while(isspace(*ptr));
3582 if(device)
3583 ALCdevice_DecRef(device);
3584 return bResult;
3588 /* alcGetProcAddress
3590 * Retrieves the function address for a particular extension function
3592 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3594 ALCvoid *ptr = NULL;
3596 if(!funcName)
3598 VerifyDevice(&device);
3599 alcSetError(device, ALC_INVALID_VALUE);
3600 if(device) ALCdevice_DecRef(device);
3602 else
3604 size_t i = 0;
3605 for(i = 0;i < COUNTOF(alcFunctions);i++)
3607 if(strcmp(alcFunctions[i].funcName, funcName) == 0)
3609 ptr = alcFunctions[i].address;
3610 break;
3615 return ptr;
3619 /* alcGetEnumValue
3621 * Get the value for a particular ALC enumeration name
3623 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3625 ALCenum val = 0;
3627 if(!enumName)
3629 VerifyDevice(&device);
3630 alcSetError(device, ALC_INVALID_VALUE);
3631 if(device) ALCdevice_DecRef(device);
3633 else
3635 size_t i = 0;
3636 for(i = 0;i < COUNTOF(alcEnumerations);i++)
3638 if(strcmp(alcEnumerations[i].enumName, enumName) == 0)
3640 val = alcEnumerations[i].value;
3641 break;
3646 return val;
3650 /* alcCreateContext
3652 * Create and attach a context to the given device.
3654 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3656 ALCcontext *ALContext;
3657 ALfloat valf;
3658 ALCenum err;
3660 /* Explicitly hold the list lock while taking the BackendLock in case the
3661 * device is asynchronously destropyed, to ensure this new context is
3662 * properly cleaned up after being made.
3664 LockLists();
3665 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
3667 UnlockLists();
3668 alcSetError(device, ALC_INVALID_DEVICE);
3669 if(device) ALCdevice_DecRef(device);
3670 return NULL;
3672 almtx_lock(&device->BackendLock);
3673 UnlockLists();
3675 ATOMIC_STORE_SEQ(&device->LastError, ALC_NO_ERROR);
3677 if(device->Type == Playback && DefaultEffect.type != AL_EFFECT_NULL)
3678 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener)+sizeof(ALeffectslot));
3679 else
3680 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3681 if(!ALContext)
3683 almtx_unlock(&device->BackendLock);
3685 alcSetError(device, ALC_OUT_OF_MEMORY);
3686 ALCdevice_DecRef(device);
3687 return NULL;
3690 InitRef(&ALContext->ref, 1);
3691 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3692 ALContext->DefaultSlot = NULL;
3694 ALContext->Voices = NULL;
3695 ALContext->VoiceCount = 0;
3696 ALContext->MaxVoices = 0;
3697 ATOMIC_INIT(&ALContext->ActiveAuxSlots, NULL);
3698 ALContext->Device = device;
3700 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3702 almtx_unlock(&device->BackendLock);
3704 al_free(ALContext);
3705 ALContext = NULL;
3707 alcSetError(device, err);
3708 if(err == ALC_INVALID_DEVICE)
3710 V0(device->Backend,lock)();
3711 aluHandleDisconnect(device);
3712 V0(device->Backend,unlock)();
3714 ALCdevice_DecRef(device);
3715 return NULL;
3717 AllocateVoices(ALContext, 256, device->NumAuxSends);
3719 if(DefaultEffect.type != AL_EFFECT_NULL && device->Type == Playback)
3721 ALContext->DefaultSlot = (ALeffectslot*)(ALContext->_listener_mem + sizeof(ALlistener));
3722 if(InitEffectSlot(ALContext->DefaultSlot) == AL_NO_ERROR)
3723 aluInitEffectPanning(ALContext->DefaultSlot);
3724 else
3726 ALContext->DefaultSlot = NULL;
3727 ERR("Failed to initialize the default effect slot\n");
3731 ALCdevice_IncRef(ALContext->Device);
3732 InitContext(ALContext);
3734 if(ConfigValueFloat(alstr_get_cstr(device->DeviceName), NULL, "volume-adjust", &valf))
3736 if(!isfinite(valf))
3737 ERR("volume-adjust must be finite: %f\n", valf);
3738 else
3740 ALfloat db = clampf(valf, -24.0f, 24.0f);
3741 if(db != valf)
3742 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3743 ALContext->GainBoost = powf(10.0f, db/20.0f);
3744 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3747 UpdateListenerProps(ALContext);
3750 ALCcontext *head = ATOMIC_LOAD_SEQ(&device->ContextList);
3751 do {
3752 ALContext->next = head;
3753 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device->ContextList, &head,
3754 ALContext) == 0);
3756 almtx_unlock(&device->BackendLock);
3758 if(ALContext->DefaultSlot)
3760 if(InitializeEffect(ALContext, ALContext->DefaultSlot, &DefaultEffect) == AL_NO_ERROR)
3761 UpdateEffectSlotProps(ALContext->DefaultSlot, ALContext);
3762 else
3763 ERR("Failed to initialize the default effect\n");
3766 ALCdevice_DecRef(device);
3768 TRACE("Created context %p\n", ALContext);
3769 return ALContext;
3772 /* alcDestroyContext
3774 * Remove a context from its device
3776 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3778 ALCdevice *Device;
3780 LockLists();
3781 if(!VerifyContext(&context))
3783 UnlockLists();
3784 alcSetError(NULL, ALC_INVALID_CONTEXT);
3785 return;
3788 Device = context->Device;
3789 if(Device)
3791 almtx_lock(&Device->BackendLock);
3792 if(!ReleaseContext(context, Device))
3794 V0(Device->Backend,stop)();
3795 Device->Flags &= ~DEVICE_RUNNING;
3797 almtx_unlock(&Device->BackendLock);
3799 UnlockLists();
3801 ALCcontext_DecRef(context);
3805 /* alcGetCurrentContext
3807 * Returns the currently active context on the calling thread
3809 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3811 ALCcontext *Context = altss_get(LocalContext);
3812 if(!Context) Context = ATOMIC_LOAD_SEQ(&GlobalContext);
3813 return Context;
3816 /* alcGetThreadContext
3818 * Returns the currently active thread-local context
3820 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3822 return altss_get(LocalContext);
3826 /* alcMakeContextCurrent
3828 * Makes the given context the active process-wide context, and removes the
3829 * thread-local context for the calling thread.
3831 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3833 /* context must be valid or NULL */
3834 if(context && !VerifyContext(&context))
3836 alcSetError(NULL, ALC_INVALID_CONTEXT);
3837 return ALC_FALSE;
3839 /* context's reference count is already incremented */
3840 context = ATOMIC_EXCHANGE_PTR_SEQ(&GlobalContext, context);
3841 if(context) ALCcontext_DecRef(context);
3843 if((context=altss_get(LocalContext)) != NULL)
3845 altss_set(LocalContext, NULL);
3846 ALCcontext_DecRef(context);
3849 return ALC_TRUE;
3852 /* alcSetThreadContext
3854 * Makes the given context the active context for the current thread
3856 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3858 ALCcontext *old;
3860 /* context must be valid or NULL */
3861 if(context && !VerifyContext(&context))
3863 alcSetError(NULL, ALC_INVALID_CONTEXT);
3864 return ALC_FALSE;
3866 /* context's reference count is already incremented */
3867 old = altss_get(LocalContext);
3868 altss_set(LocalContext, context);
3869 if(old) ALCcontext_DecRef(old);
3871 return ALC_TRUE;
3875 /* alcGetContextsDevice
3877 * Returns the device that a particular context is attached to
3879 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3881 ALCdevice *Device;
3883 if(!VerifyContext(&Context))
3885 alcSetError(NULL, ALC_INVALID_CONTEXT);
3886 return NULL;
3888 Device = Context->Device;
3889 ALCcontext_DecRef(Context);
3891 return Device;
3895 /* alcOpenDevice
3897 * Opens the named device.
3899 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3901 ALCbackendFactory *factory;
3902 const ALCchar *fmt;
3903 ALCdevice *device;
3904 ALCenum err;
3905 ALCsizei i;
3907 DO_INITCONFIG();
3909 if(!PlaybackBackend.name)
3911 alcSetError(NULL, ALC_INVALID_VALUE);
3912 return NULL;
3915 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
3916 #ifdef _WIN32
3917 /* Some old Windows apps hardcode these expecting OpenAL to use a
3918 * specific audio API, even when they're not enumerated. Creative's
3919 * router effectively ignores them too.
3921 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
3922 || strcasecmp(deviceName, "MMSYSTEM") == 0
3923 #endif
3925 deviceName = NULL;
3927 device = al_calloc(16, sizeof(ALCdevice));
3928 if(!device)
3930 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3931 return NULL;
3934 //Validate device
3935 InitRef(&device->ref, 1);
3936 device->Connected = ALC_TRUE;
3937 device->Type = Playback;
3938 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3940 device->Flags = 0;
3941 device->Bs2b = NULL;
3942 device->Uhj_Encoder = NULL;
3943 device->Hrtf = NULL;
3944 device->HrtfHandle = NULL;
3945 VECTOR_INIT(device->HrtfList);
3946 AL_STRING_INIT(device->HrtfName);
3947 device->Render_Mode = NormalRender;
3948 AL_STRING_INIT(device->DeviceName);
3949 device->Dry.Buffer = NULL;
3950 device->Dry.NumChannels = 0;
3951 device->FOAOut.Buffer = NULL;
3952 device->FOAOut.NumChannels = 0;
3953 device->RealOut.Buffer = NULL;
3954 device->RealOut.NumChannels = 0;
3955 device->Limiter = NULL;
3956 device->AvgSpeakerDist = 0.0f;
3958 ATOMIC_INIT(&device->ContextList, NULL);
3960 device->ClockBase = 0;
3961 device->SamplesDone = 0;
3963 device->SourcesMax = 256;
3964 device->AuxiliaryEffectSlotMax = 64;
3965 device->NumAuxSends = DEFAULT_SENDS;
3967 InitUIntMap(&device->BufferMap, INT_MAX);
3968 InitUIntMap(&device->EffectMap, INT_MAX);
3969 InitUIntMap(&device->FilterMap, INT_MAX);
3971 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
3973 device->ChannelDelay[i].Gain = 1.0f;
3974 device->ChannelDelay[i].Length = 0;
3975 device->ChannelDelay[i].Buffer = NULL;
3978 //Set output format
3979 device->FmtChans = DevFmtChannelsDefault;
3980 device->FmtType = DevFmtTypeDefault;
3981 device->Frequency = DEFAULT_OUTPUT_RATE;
3982 device->IsHeadphones = AL_FALSE;
3983 device->AmbiLayout = AmbiLayout_Default;
3984 device->AmbiScale = AmbiNorm_Default;
3985 device->NumUpdates = 3;
3986 device->UpdateSize = 1024;
3988 factory = PlaybackBackend.getFactory();
3989 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3990 if(!device->Backend)
3992 al_free(device);
3993 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3994 return NULL;
3998 if(ConfigValueStr(deviceName, NULL, "channels", &fmt))
4000 static const struct {
4001 const char name[16];
4002 enum DevFmtChannels chans;
4003 ALsizei order;
4004 } chanlist[] = {
4005 { "mono", DevFmtMono, 0 },
4006 { "stereo", DevFmtStereo, 0 },
4007 { "quad", DevFmtQuad, 0 },
4008 { "surround51", DevFmtX51, 0 },
4009 { "surround61", DevFmtX61, 0 },
4010 { "surround71", DevFmtX71, 0 },
4011 { "surround51rear", DevFmtX51Rear, 0 },
4012 { "ambi1", DevFmtAmbi3D, 1 },
4013 { "ambi2", DevFmtAmbi3D, 2 },
4014 { "ambi3", DevFmtAmbi3D, 3 },
4016 size_t i;
4018 for(i = 0;i < COUNTOF(chanlist);i++)
4020 if(strcasecmp(chanlist[i].name, fmt) == 0)
4022 device->FmtChans = chanlist[i].chans;
4023 device->AmbiOrder = chanlist[i].order;
4024 device->Flags |= DEVICE_CHANNELS_REQUEST;
4025 break;
4028 if(i == COUNTOF(chanlist))
4029 ERR("Unsupported channels: %s\n", fmt);
4031 if(ConfigValueStr(deviceName, NULL, "sample-type", &fmt))
4033 static const struct {
4034 const char name[16];
4035 enum DevFmtType type;
4036 } typelist[] = {
4037 { "int8", DevFmtByte },
4038 { "uint8", DevFmtUByte },
4039 { "int16", DevFmtShort },
4040 { "uint16", DevFmtUShort },
4041 { "int32", DevFmtInt },
4042 { "uint32", DevFmtUInt },
4043 { "float32", DevFmtFloat },
4045 size_t i;
4047 for(i = 0;i < COUNTOF(typelist);i++)
4049 if(strcasecmp(typelist[i].name, fmt) == 0)
4051 device->FmtType = typelist[i].type;
4052 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
4053 break;
4056 if(i == COUNTOF(typelist))
4057 ERR("Unsupported sample-type: %s\n", fmt);
4060 if(ConfigValueUInt(deviceName, NULL, "frequency", &device->Frequency))
4062 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4063 if(device->Frequency < MIN_OUTPUT_RATE)
4064 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
4065 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
4068 ConfigValueUInt(deviceName, NULL, "periods", &device->NumUpdates);
4069 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
4071 ConfigValueUInt(deviceName, NULL, "period_size", &device->UpdateSize);
4072 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
4073 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
4074 device->UpdateSize = (device->UpdateSize+3)&~3;
4076 ConfigValueUInt(deviceName, NULL, "sources", &device->SourcesMax);
4077 if(device->SourcesMax == 0) device->SourcesMax = 256;
4079 ConfigValueUInt(deviceName, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4080 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4082 if(ConfigValueInt(deviceName, NULL, "sends", &device->NumAuxSends))
4083 device->NumAuxSends = clampi(
4084 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4087 device->NumStereoSources = 1;
4088 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4090 // Find a playback device to open
4091 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4093 DELETE_OBJ(device->Backend);
4094 al_free(device);
4095 alcSetError(NULL, err);
4096 return NULL;
4098 almtx_init(&device->BackendLock, almtx_plain);
4100 if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt))
4102 if(strcasecmp(fmt, "fuma") == 0)
4104 device->AmbiLayout = AmbiLayout_FuMa;
4105 device->AmbiScale = AmbiNorm_FuMa;
4107 else if(strcasecmp(fmt, "acn+sn3d") == 0)
4109 device->AmbiLayout = AmbiLayout_ACN;
4110 device->AmbiScale = AmbiNorm_SN3D;
4112 else if(strcasecmp(fmt, "acn+n3d") == 0)
4114 device->AmbiLayout = AmbiLayout_ACN;
4115 device->AmbiScale = AmbiNorm_N3D;
4117 else
4118 ERR("Unsupported ambi-format: %s\n", fmt);
4121 device->Limiter = CreateDeviceLimiter(device);
4124 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4125 do {
4126 device->next = head;
4127 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4130 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
4131 return device;
4134 /* alcCloseDevice
4136 * Closes the given device.
4138 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
4140 ALCdevice *iter, *origdev;
4141 ALCcontext *ctx;
4143 LockLists();
4144 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4145 do {
4146 if(iter == device)
4147 break;
4148 } while((iter=iter->next) != NULL);
4149 if(!iter || iter->Type == Capture)
4151 alcSetError(iter, ALC_INVALID_DEVICE);
4152 UnlockLists();
4153 return ALC_FALSE;
4155 almtx_lock(&device->BackendLock);
4157 origdev = device;
4158 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, device->next))
4160 ALCdevice *volatile*list = &origdev->next;
4161 while(*list)
4163 if(*list == device)
4165 *list = (*list)->next;
4166 break;
4168 list = &(*list)->next;
4171 UnlockLists();
4173 ctx = ATOMIC_LOAD_SEQ(&device->ContextList);
4174 while(ctx != NULL)
4176 ALCcontext *next = ctx->next;
4177 WARN("Releasing context %p\n", ctx);
4178 ReleaseContext(ctx, device);
4179 ctx = next;
4181 if((device->Flags&DEVICE_RUNNING))
4182 V0(device->Backend,stop)();
4183 device->Flags &= ~DEVICE_RUNNING;
4184 almtx_unlock(&device->BackendLock);
4186 ALCdevice_DecRef(device);
4188 return ALC_TRUE;
4192 /************************************************
4193 * ALC capture functions
4194 ************************************************/
4195 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
4197 ALCbackendFactory *factory;
4198 ALCdevice *device = NULL;
4199 ALCenum err;
4200 ALCsizei i;
4202 DO_INITCONFIG();
4204 if(!CaptureBackend.name)
4206 alcSetError(NULL, ALC_INVALID_VALUE);
4207 return NULL;
4210 if(samples <= 0)
4212 alcSetError(NULL, ALC_INVALID_VALUE);
4213 return NULL;
4216 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
4217 deviceName = NULL;
4219 device = al_calloc(16, sizeof(ALCdevice));
4220 if(!device)
4222 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4223 return NULL;
4226 //Validate device
4227 InitRef(&device->ref, 1);
4228 device->Connected = ALC_TRUE;
4229 device->Type = Capture;
4231 device->Hrtf = NULL;
4232 device->HrtfHandle = NULL;
4233 VECTOR_INIT(device->HrtfList);
4234 AL_STRING_INIT(device->HrtfName);
4236 AL_STRING_INIT(device->DeviceName);
4237 device->Dry.Buffer = NULL;
4238 device->Dry.NumChannels = 0;
4239 device->FOAOut.Buffer = NULL;
4240 device->FOAOut.NumChannels = 0;
4241 device->RealOut.Buffer = NULL;
4242 device->RealOut.NumChannels = 0;
4244 InitUIntMap(&device->BufferMap, INT_MAX);
4245 InitUIntMap(&device->EffectMap, INT_MAX);
4246 InitUIntMap(&device->FilterMap, INT_MAX);
4248 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
4250 device->ChannelDelay[i].Gain = 1.0f;
4251 device->ChannelDelay[i].Length = 0;
4252 device->ChannelDelay[i].Buffer = NULL;
4255 factory = CaptureBackend.getFactory();
4256 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
4257 if(!device->Backend)
4259 al_free(device);
4260 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4261 return NULL;
4264 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4265 device->Frequency = frequency;
4267 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
4268 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
4270 al_free(device);
4271 alcSetError(NULL, ALC_INVALID_ENUM);
4272 return NULL;
4274 device->IsHeadphones = AL_FALSE;
4275 device->AmbiOrder = 0;
4276 device->AmbiLayout = AmbiLayout_Default;
4277 device->AmbiScale = AmbiNorm_Default;
4279 device->UpdateSize = samples;
4280 device->NumUpdates = 1;
4282 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4283 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
4284 device->Frequency, device->UpdateSize, device->NumUpdates
4286 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4288 al_free(device);
4289 alcSetError(NULL, err);
4290 return NULL;
4292 almtx_init(&device->BackendLock, almtx_plain);
4295 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4296 do {
4297 device->next = head;
4298 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4301 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
4302 return device;
4305 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
4307 ALCdevice *iter, *origdev;
4309 LockLists();
4310 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4311 do {
4312 if(iter == device)
4313 break;
4314 } while((iter=iter->next) != NULL);
4315 if(!iter || iter->Type != Capture)
4317 alcSetError(iter, ALC_INVALID_DEVICE);
4318 UnlockLists();
4319 return ALC_FALSE;
4322 origdev = device;
4323 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, device->next))
4325 ALCdevice *volatile*list = &origdev->next;
4326 while(*list)
4328 if(*list == device)
4330 *list = (*list)->next;
4331 break;
4333 list = &(*list)->next;
4336 UnlockLists();
4338 ALCdevice_DecRef(device);
4340 return ALC_TRUE;
4343 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
4345 if(!VerifyDevice(&device) || device->Type != Capture)
4346 alcSetError(device, ALC_INVALID_DEVICE);
4347 else
4349 almtx_lock(&device->BackendLock);
4350 if(!device->Connected)
4351 alcSetError(device, ALC_INVALID_DEVICE);
4352 else if(!(device->Flags&DEVICE_RUNNING))
4354 if(V0(device->Backend,start)())
4355 device->Flags |= DEVICE_RUNNING;
4356 else
4358 aluHandleDisconnect(device);
4359 alcSetError(device, ALC_INVALID_DEVICE);
4362 almtx_unlock(&device->BackendLock);
4365 if(device) ALCdevice_DecRef(device);
4368 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
4370 if(!VerifyDevice(&device) || device->Type != Capture)
4371 alcSetError(device, ALC_INVALID_DEVICE);
4372 else
4374 almtx_lock(&device->BackendLock);
4375 if((device->Flags&DEVICE_RUNNING))
4376 V0(device->Backend,stop)();
4377 device->Flags &= ~DEVICE_RUNNING;
4378 almtx_unlock(&device->BackendLock);
4381 if(device) ALCdevice_DecRef(device);
4384 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4386 if(!VerifyDevice(&device) || device->Type != Capture)
4387 alcSetError(device, ALC_INVALID_DEVICE);
4388 else
4390 ALCenum err = ALC_INVALID_VALUE;
4392 almtx_lock(&device->BackendLock);
4393 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
4394 err = V(device->Backend,captureSamples)(buffer, samples);
4395 almtx_unlock(&device->BackendLock);
4397 if(err != ALC_NO_ERROR)
4398 alcSetError(device, err);
4400 if(device) ALCdevice_DecRef(device);
4404 /************************************************
4405 * ALC loopback functions
4406 ************************************************/
4408 /* alcLoopbackOpenDeviceSOFT
4410 * Open a loopback device, for manual rendering.
4412 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
4414 ALCbackendFactory *factory;
4415 ALCdevice *device;
4416 ALCsizei i;
4418 DO_INITCONFIG();
4420 /* Make sure the device name, if specified, is us. */
4421 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
4423 alcSetError(NULL, ALC_INVALID_VALUE);
4424 return NULL;
4427 device = al_calloc(16, sizeof(ALCdevice));
4428 if(!device)
4430 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4431 return NULL;
4434 //Validate device
4435 InitRef(&device->ref, 1);
4436 device->Connected = ALC_TRUE;
4437 device->Type = Loopback;
4438 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
4440 device->Flags = 0;
4441 device->Hrtf = NULL;
4442 device->HrtfHandle = NULL;
4443 VECTOR_INIT(device->HrtfList);
4444 AL_STRING_INIT(device->HrtfName);
4445 device->Bs2b = NULL;
4446 device->Uhj_Encoder = NULL;
4447 device->Render_Mode = NormalRender;
4448 AL_STRING_INIT(device->DeviceName);
4449 device->Dry.Buffer = NULL;
4450 device->Dry.NumChannels = 0;
4451 device->FOAOut.Buffer = NULL;
4452 device->FOAOut.NumChannels = 0;
4453 device->RealOut.Buffer = NULL;
4454 device->RealOut.NumChannels = 0;
4455 device->Limiter = NULL;
4456 device->AvgSpeakerDist = 0.0f;
4458 ATOMIC_INIT(&device->ContextList, NULL);
4460 device->ClockBase = 0;
4461 device->SamplesDone = 0;
4463 device->SourcesMax = 256;
4464 device->AuxiliaryEffectSlotMax = 64;
4465 device->NumAuxSends = DEFAULT_SENDS;
4467 InitUIntMap(&device->BufferMap, INT_MAX);
4468 InitUIntMap(&device->EffectMap, INT_MAX);
4469 InitUIntMap(&device->FilterMap, INT_MAX);
4471 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
4473 device->ChannelDelay[i].Gain = 1.0f;
4474 device->ChannelDelay[i].Length = 0;
4475 device->ChannelDelay[i].Buffer = NULL;
4478 factory = ALCloopbackFactory_getFactory();
4479 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
4480 if(!device->Backend)
4482 al_free(device);
4483 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4484 return NULL;
4486 almtx_init(&device->BackendLock, almtx_plain);
4488 //Set output format
4489 device->NumUpdates = 0;
4490 device->UpdateSize = 0;
4492 device->Frequency = DEFAULT_OUTPUT_RATE;
4493 device->FmtChans = DevFmtChannelsDefault;
4494 device->FmtType = DevFmtTypeDefault;
4495 device->IsHeadphones = AL_FALSE;
4496 device->AmbiLayout = AmbiLayout_Default;
4497 device->AmbiScale = AmbiNorm_Default;
4499 ConfigValueUInt(NULL, NULL, "sources", &device->SourcesMax);
4500 if(device->SourcesMax == 0) device->SourcesMax = 256;
4502 ConfigValueUInt(NULL, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4503 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4505 if(ConfigValueInt(NULL, NULL, "sends", &device->NumAuxSends))
4506 device->NumAuxSends = clampi(
4507 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4510 device->NumStereoSources = 1;
4511 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4513 // Open the "backend"
4514 V(device->Backend,open)("Loopback");
4516 device->Limiter = CreateDeviceLimiter(device);
4519 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4520 do {
4521 device->next = head;
4522 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4525 TRACE("Created device %p\n", device);
4526 return device;
4529 /* alcIsRenderFormatSupportedSOFT
4531 * Determines if the loopback device supports the given format for rendering.
4533 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4535 ALCboolean ret = ALC_FALSE;
4537 if(!VerifyDevice(&device) || device->Type != Loopback)
4538 alcSetError(device, ALC_INVALID_DEVICE);
4539 else if(freq <= 0)
4540 alcSetError(device, ALC_INVALID_VALUE);
4541 else
4543 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4544 ret = ALC_TRUE;
4546 if(device) ALCdevice_DecRef(device);
4548 return ret;
4551 /* alcRenderSamplesSOFT
4553 * Renders some samples into a buffer, using the format last set by the
4554 * attributes given to alcCreateContext.
4556 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4558 if(!VerifyDevice(&device) || device->Type != Loopback)
4559 alcSetError(device, ALC_INVALID_DEVICE);
4560 else if(samples < 0 || (samples > 0 && buffer == NULL))
4561 alcSetError(device, ALC_INVALID_VALUE);
4562 else
4564 V0(device->Backend,lock)();
4565 aluMixData(device, buffer, samples);
4566 V0(device->Backend,unlock)();
4568 if(device) ALCdevice_DecRef(device);
4572 /************************************************
4573 * ALC DSP pause/resume functions
4574 ************************************************/
4576 /* alcDevicePauseSOFT
4578 * Pause the DSP to stop audio processing.
4580 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4582 if(!VerifyDevice(&device) || device->Type != Playback)
4583 alcSetError(device, ALC_INVALID_DEVICE);
4584 else
4586 almtx_lock(&device->BackendLock);
4587 if((device->Flags&DEVICE_RUNNING))
4588 V0(device->Backend,stop)();
4589 device->Flags &= ~DEVICE_RUNNING;
4590 device->Flags |= DEVICE_PAUSED;
4591 almtx_unlock(&device->BackendLock);
4593 if(device) ALCdevice_DecRef(device);
4596 /* alcDeviceResumeSOFT
4598 * Resume the DSP to restart audio processing.
4600 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4602 if(!VerifyDevice(&device) || device->Type != Playback)
4603 alcSetError(device, ALC_INVALID_DEVICE);
4604 else
4606 almtx_lock(&device->BackendLock);
4607 if((device->Flags&DEVICE_PAUSED))
4609 device->Flags &= ~DEVICE_PAUSED;
4610 if(ATOMIC_LOAD_SEQ(&device->ContextList) != NULL)
4612 if(V0(device->Backend,start)() != ALC_FALSE)
4613 device->Flags |= DEVICE_RUNNING;
4614 else
4616 alcSetError(device, ALC_INVALID_DEVICE);
4617 V0(device->Backend,lock)();
4618 aluHandleDisconnect(device);
4619 V0(device->Backend,unlock)();
4623 almtx_unlock(&device->BackendLock);
4625 if(device) ALCdevice_DecRef(device);
4629 /************************************************
4630 * ALC HRTF functions
4631 ************************************************/
4633 /* alcGetStringiSOFT
4635 * Gets a string parameter at the given index.
4637 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4639 const ALCchar *str = NULL;
4641 if(!VerifyDevice(&device) || device->Type == Capture)
4642 alcSetError(device, ALC_INVALID_DEVICE);
4643 else switch(paramName)
4645 case ALC_HRTF_SPECIFIER_SOFT:
4646 if(index >= 0 && (size_t)index < VECTOR_SIZE(device->HrtfList))
4647 str = alstr_get_cstr(VECTOR_ELEM(device->HrtfList, index).name);
4648 else
4649 alcSetError(device, ALC_INVALID_VALUE);
4650 break;
4652 default:
4653 alcSetError(device, ALC_INVALID_ENUM);
4654 break;
4656 if(device) ALCdevice_DecRef(device);
4658 return str;
4661 /* alcResetDeviceSOFT
4663 * Resets the given device output, using the specified attribute list.
4665 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4667 ALCenum err;
4669 LockLists();
4670 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
4672 UnlockLists();
4673 alcSetError(device, ALC_INVALID_DEVICE);
4674 if(device) ALCdevice_DecRef(device);
4675 return ALC_FALSE;
4677 almtx_lock(&device->BackendLock);
4678 UnlockLists();
4680 err = UpdateDeviceParams(device, attribs);
4681 almtx_unlock(&device->BackendLock);
4683 if(err != ALC_NO_ERROR)
4685 alcSetError(device, err);
4686 if(err == ALC_INVALID_DEVICE)
4688 V0(device->Backend,lock)();
4689 aluHandleDisconnect(device);
4690 V0(device->Backend,unlock)();
4692 ALCdevice_DecRef(device);
4693 return ALC_FALSE;
4695 ALCdevice_DecRef(device);
4697 return ALC_TRUE;