Replace a couple ALuint with ALsizei
[openal-soft.git] / Alc / ALc.c
blobe34cd75a3a9150d170ce875098c488f9ab1a696b
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 "bformatdec.h"
41 #include "alu.h"
43 #include "compat.h"
44 #include "threads.h"
45 #include "alstring.h"
46 #include "almalloc.h"
48 #include "backends/base.h"
51 /************************************************
52 * Backends
53 ************************************************/
54 struct BackendInfo {
55 const char *name;
56 ALCbackendFactory* (*getFactory)(void);
57 ALCboolean (*Init)(BackendFuncs*);
58 void (*Deinit)(void);
59 void (*Probe)(enum DevProbe);
60 BackendFuncs Funcs;
63 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
64 static struct BackendInfo BackendList[] = {
65 #ifdef HAVE_JACK
66 { "jack", ALCjackBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
67 #endif
68 #ifdef HAVE_PULSEAUDIO
69 { "pulse", ALCpulseBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
70 #endif
71 #ifdef HAVE_ALSA
72 { "alsa", ALCalsaBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
73 #endif
74 #ifdef HAVE_COREAUDIO
75 { "core", NULL, alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
76 #endif
77 #ifdef HAVE_OSS
78 { "oss", ALCossBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
79 #endif
80 #ifdef HAVE_SOLARIS
81 { "solaris", ALCsolarisBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
82 #endif
83 #ifdef HAVE_SNDIO
84 { "sndio", ALCsndioBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
85 #endif
86 #ifdef HAVE_QSA
87 { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs },
88 #endif
89 #ifdef HAVE_MMDEVAPI
90 { "mmdevapi", ALCmmdevBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
91 #endif
92 #ifdef HAVE_DSOUND
93 { "dsound", ALCdsoundBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
94 #endif
95 #ifdef HAVE_WINMM
96 { "winmm", ALCwinmmBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
97 #endif
98 #ifdef HAVE_PORTAUDIO
99 { "port", ALCportBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
100 #endif
101 #ifdef HAVE_OPENSL
102 { "opensl", ALCopenslBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
103 #endif
105 { "null", ALCnullBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
106 #ifdef HAVE_WAVE
107 { "wave", ALCwaveBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
108 #endif
110 static ALsizei BackendListSize = COUNTOF(BackendList);
111 #undef EmptyFuncs
113 static struct BackendInfo PlaybackBackend;
114 static struct BackendInfo CaptureBackend;
117 /************************************************
118 * Functions, enums, and errors
119 ************************************************/
120 #define DECL(x) { #x, (ALCvoid*)(x) }
121 static const struct {
122 const ALCchar *funcName;
123 ALCvoid *address;
124 } alcFunctions[] = {
125 DECL(alcCreateContext),
126 DECL(alcMakeContextCurrent),
127 DECL(alcProcessContext),
128 DECL(alcSuspendContext),
129 DECL(alcDestroyContext),
130 DECL(alcGetCurrentContext),
131 DECL(alcGetContextsDevice),
132 DECL(alcOpenDevice),
133 DECL(alcCloseDevice),
134 DECL(alcGetError),
135 DECL(alcIsExtensionPresent),
136 DECL(alcGetProcAddress),
137 DECL(alcGetEnumValue),
138 DECL(alcGetString),
139 DECL(alcGetIntegerv),
140 DECL(alcCaptureOpenDevice),
141 DECL(alcCaptureCloseDevice),
142 DECL(alcCaptureStart),
143 DECL(alcCaptureStop),
144 DECL(alcCaptureSamples),
146 DECL(alcSetThreadContext),
147 DECL(alcGetThreadContext),
149 DECL(alcLoopbackOpenDeviceSOFT),
150 DECL(alcIsRenderFormatSupportedSOFT),
151 DECL(alcRenderSamplesSOFT),
153 DECL(alcIsAmbisonicFormatSupportedSOFT),
155 DECL(alcDevicePauseSOFT),
156 DECL(alcDeviceResumeSOFT),
158 DECL(alcGetStringiSOFT),
159 DECL(alcResetDeviceSOFT),
161 DECL(alcGetInteger64vSOFT),
163 DECL(alEnable),
164 DECL(alDisable),
165 DECL(alIsEnabled),
166 DECL(alGetString),
167 DECL(alGetBooleanv),
168 DECL(alGetIntegerv),
169 DECL(alGetFloatv),
170 DECL(alGetDoublev),
171 DECL(alGetBoolean),
172 DECL(alGetInteger),
173 DECL(alGetFloat),
174 DECL(alGetDouble),
175 DECL(alGetError),
176 DECL(alIsExtensionPresent),
177 DECL(alGetProcAddress),
178 DECL(alGetEnumValue),
179 DECL(alListenerf),
180 DECL(alListener3f),
181 DECL(alListenerfv),
182 DECL(alListeneri),
183 DECL(alListener3i),
184 DECL(alListeneriv),
185 DECL(alGetListenerf),
186 DECL(alGetListener3f),
187 DECL(alGetListenerfv),
188 DECL(alGetListeneri),
189 DECL(alGetListener3i),
190 DECL(alGetListeneriv),
191 DECL(alGenSources),
192 DECL(alDeleteSources),
193 DECL(alIsSource),
194 DECL(alSourcef),
195 DECL(alSource3f),
196 DECL(alSourcefv),
197 DECL(alSourcei),
198 DECL(alSource3i),
199 DECL(alSourceiv),
200 DECL(alGetSourcef),
201 DECL(alGetSource3f),
202 DECL(alGetSourcefv),
203 DECL(alGetSourcei),
204 DECL(alGetSource3i),
205 DECL(alGetSourceiv),
206 DECL(alSourcePlayv),
207 DECL(alSourceStopv),
208 DECL(alSourceRewindv),
209 DECL(alSourcePausev),
210 DECL(alSourcePlay),
211 DECL(alSourceStop),
212 DECL(alSourceRewind),
213 DECL(alSourcePause),
214 DECL(alSourceQueueBuffers),
215 DECL(alSourceUnqueueBuffers),
216 DECL(alGenBuffers),
217 DECL(alDeleteBuffers),
218 DECL(alIsBuffer),
219 DECL(alBufferData),
220 DECL(alBufferf),
221 DECL(alBuffer3f),
222 DECL(alBufferfv),
223 DECL(alBufferi),
224 DECL(alBuffer3i),
225 DECL(alBufferiv),
226 DECL(alGetBufferf),
227 DECL(alGetBuffer3f),
228 DECL(alGetBufferfv),
229 DECL(alGetBufferi),
230 DECL(alGetBuffer3i),
231 DECL(alGetBufferiv),
232 DECL(alDopplerFactor),
233 DECL(alDopplerVelocity),
234 DECL(alSpeedOfSound),
235 DECL(alDistanceModel),
237 DECL(alGenFilters),
238 DECL(alDeleteFilters),
239 DECL(alIsFilter),
240 DECL(alFilteri),
241 DECL(alFilteriv),
242 DECL(alFilterf),
243 DECL(alFilterfv),
244 DECL(alGetFilteri),
245 DECL(alGetFilteriv),
246 DECL(alGetFilterf),
247 DECL(alGetFilterfv),
248 DECL(alGenEffects),
249 DECL(alDeleteEffects),
250 DECL(alIsEffect),
251 DECL(alEffecti),
252 DECL(alEffectiv),
253 DECL(alEffectf),
254 DECL(alEffectfv),
255 DECL(alGetEffecti),
256 DECL(alGetEffectiv),
257 DECL(alGetEffectf),
258 DECL(alGetEffectfv),
259 DECL(alGenAuxiliaryEffectSlots),
260 DECL(alDeleteAuxiliaryEffectSlots),
261 DECL(alIsAuxiliaryEffectSlot),
262 DECL(alAuxiliaryEffectSloti),
263 DECL(alAuxiliaryEffectSlotiv),
264 DECL(alAuxiliaryEffectSlotf),
265 DECL(alAuxiliaryEffectSlotfv),
266 DECL(alGetAuxiliaryEffectSloti),
267 DECL(alGetAuxiliaryEffectSlotiv),
268 DECL(alGetAuxiliaryEffectSlotf),
269 DECL(alGetAuxiliaryEffectSlotfv),
271 DECL(alDeferUpdatesSOFT),
272 DECL(alProcessUpdatesSOFT),
274 DECL(alSourcedSOFT),
275 DECL(alSource3dSOFT),
276 DECL(alSourcedvSOFT),
277 DECL(alGetSourcedSOFT),
278 DECL(alGetSource3dSOFT),
279 DECL(alGetSourcedvSOFT),
280 DECL(alSourcei64SOFT),
281 DECL(alSource3i64SOFT),
282 DECL(alSourcei64vSOFT),
283 DECL(alGetSourcei64SOFT),
284 DECL(alGetSource3i64SOFT),
285 DECL(alGetSourcei64vSOFT),
287 DECL(alBufferSamplesSOFT),
288 DECL(alGetBufferSamplesSOFT),
289 DECL(alIsBufferFormatSupportedSOFT),
291 #undef DECL
293 #define DECL(x) { #x, (x) }
294 static const struct {
295 const ALCchar *enumName;
296 ALCenum value;
297 } alcEnumerations[] = {
298 DECL(ALC_INVALID),
299 DECL(ALC_FALSE),
300 DECL(ALC_TRUE),
302 DECL(ALC_MAJOR_VERSION),
303 DECL(ALC_MINOR_VERSION),
304 DECL(ALC_ATTRIBUTES_SIZE),
305 DECL(ALC_ALL_ATTRIBUTES),
306 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
307 DECL(ALC_DEVICE_SPECIFIER),
308 DECL(ALC_ALL_DEVICES_SPECIFIER),
309 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
310 DECL(ALC_EXTENSIONS),
311 DECL(ALC_FREQUENCY),
312 DECL(ALC_REFRESH),
313 DECL(ALC_SYNC),
314 DECL(ALC_MONO_SOURCES),
315 DECL(ALC_STEREO_SOURCES),
316 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
317 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
318 DECL(ALC_CAPTURE_SAMPLES),
319 DECL(ALC_CONNECTED),
321 DECL(ALC_EFX_MAJOR_VERSION),
322 DECL(ALC_EFX_MINOR_VERSION),
323 DECL(ALC_MAX_AUXILIARY_SENDS),
325 DECL(ALC_FORMAT_CHANNELS_SOFT),
326 DECL(ALC_FORMAT_TYPE_SOFT),
328 DECL(ALC_MONO_SOFT),
329 DECL(ALC_STEREO_SOFT),
330 DECL(ALC_QUAD_SOFT),
331 DECL(ALC_5POINT1_SOFT),
332 DECL(ALC_6POINT1_SOFT),
333 DECL(ALC_7POINT1_SOFT),
334 DECL(ALC_BFORMAT3D_SOFT),
336 DECL(ALC_BYTE_SOFT),
337 DECL(ALC_UNSIGNED_BYTE_SOFT),
338 DECL(ALC_SHORT_SOFT),
339 DECL(ALC_UNSIGNED_SHORT_SOFT),
340 DECL(ALC_INT_SOFT),
341 DECL(ALC_UNSIGNED_INT_SOFT),
342 DECL(ALC_FLOAT_SOFT),
344 DECL(ALC_HRTF_SOFT),
345 DECL(ALC_DONT_CARE_SOFT),
346 DECL(ALC_HRTF_STATUS_SOFT),
347 DECL(ALC_HRTF_DISABLED_SOFT),
348 DECL(ALC_HRTF_ENABLED_SOFT),
349 DECL(ALC_HRTF_DENIED_SOFT),
350 DECL(ALC_HRTF_REQUIRED_SOFT),
351 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
352 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
353 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
354 DECL(ALC_HRTF_SPECIFIER_SOFT),
355 DECL(ALC_HRTF_ID_SOFT),
357 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
358 DECL(ALC_AMBISONIC_SCALING_SOFT),
359 DECL(ALC_AMBISONIC_ORDER_SOFT),
360 DECL(ALC_ACN_SOFT),
361 DECL(ALC_FUMA_SOFT),
362 DECL(ALC_N3D_SOFT),
363 DECL(ALC_SN3D_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_MONO8_SOFT),
475 DECL(AL_MONO16_SOFT),
476 DECL(AL_MONO32F_SOFT),
477 DECL(AL_STEREO8_SOFT),
478 DECL(AL_STEREO16_SOFT),
479 DECL(AL_STEREO32F_SOFT),
480 DECL(AL_QUAD8_SOFT),
481 DECL(AL_QUAD16_SOFT),
482 DECL(AL_QUAD32F_SOFT),
483 DECL(AL_REAR8_SOFT),
484 DECL(AL_REAR16_SOFT),
485 DECL(AL_REAR32F_SOFT),
486 DECL(AL_5POINT1_8_SOFT),
487 DECL(AL_5POINT1_16_SOFT),
488 DECL(AL_5POINT1_32F_SOFT),
489 DECL(AL_6POINT1_8_SOFT),
490 DECL(AL_6POINT1_16_SOFT),
491 DECL(AL_6POINT1_32F_SOFT),
492 DECL(AL_7POINT1_8_SOFT),
493 DECL(AL_7POINT1_16_SOFT),
494 DECL(AL_7POINT1_32F_SOFT),
495 DECL(AL_BFORMAT2D_8_SOFT),
496 DECL(AL_BFORMAT2D_16_SOFT),
497 DECL(AL_BFORMAT2D_32F_SOFT),
498 DECL(AL_BFORMAT3D_8_SOFT),
499 DECL(AL_BFORMAT3D_16_SOFT),
500 DECL(AL_BFORMAT3D_32F_SOFT),
502 DECL(AL_MONO_SOFT),
503 DECL(AL_STEREO_SOFT),
504 DECL(AL_QUAD_SOFT),
505 DECL(AL_REAR_SOFT),
506 DECL(AL_5POINT1_SOFT),
507 DECL(AL_6POINT1_SOFT),
508 DECL(AL_7POINT1_SOFT),
509 DECL(AL_BFORMAT2D_SOFT),
510 DECL(AL_BFORMAT3D_SOFT),
512 DECL(AL_BYTE_SOFT),
513 DECL(AL_UNSIGNED_BYTE_SOFT),
514 DECL(AL_SHORT_SOFT),
515 DECL(AL_UNSIGNED_SHORT_SOFT),
516 DECL(AL_INT_SOFT),
517 DECL(AL_UNSIGNED_INT_SOFT),
518 DECL(AL_FLOAT_SOFT),
519 DECL(AL_DOUBLE_SOFT),
520 DECL(AL_BYTE3_SOFT),
521 DECL(AL_UNSIGNED_BYTE3_SOFT),
522 DECL(AL_MULAW_SOFT),
524 DECL(AL_FREQUENCY),
525 DECL(AL_BITS),
526 DECL(AL_CHANNELS),
527 DECL(AL_SIZE),
528 DECL(AL_INTERNAL_FORMAT_SOFT),
529 DECL(AL_BYTE_LENGTH_SOFT),
530 DECL(AL_SAMPLE_LENGTH_SOFT),
531 DECL(AL_SEC_LENGTH_SOFT),
532 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
533 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
535 DECL(AL_SOURCE_RADIUS),
537 DECL(AL_STEREO_ANGLES),
539 DECL(AL_UNUSED),
540 DECL(AL_PENDING),
541 DECL(AL_PROCESSED),
543 DECL(AL_NO_ERROR),
544 DECL(AL_INVALID_NAME),
545 DECL(AL_INVALID_ENUM),
546 DECL(AL_INVALID_VALUE),
547 DECL(AL_INVALID_OPERATION),
548 DECL(AL_OUT_OF_MEMORY),
550 DECL(AL_VENDOR),
551 DECL(AL_VERSION),
552 DECL(AL_RENDERER),
553 DECL(AL_EXTENSIONS),
555 DECL(AL_DOPPLER_FACTOR),
556 DECL(AL_DOPPLER_VELOCITY),
557 DECL(AL_DISTANCE_MODEL),
558 DECL(AL_SPEED_OF_SOUND),
559 DECL(AL_SOURCE_DISTANCE_MODEL),
560 DECL(AL_DEFERRED_UPDATES_SOFT),
561 DECL(AL_GAIN_LIMIT_SOFT),
563 DECL(AL_INVERSE_DISTANCE),
564 DECL(AL_INVERSE_DISTANCE_CLAMPED),
565 DECL(AL_LINEAR_DISTANCE),
566 DECL(AL_LINEAR_DISTANCE_CLAMPED),
567 DECL(AL_EXPONENT_DISTANCE),
568 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
570 DECL(AL_FILTER_TYPE),
571 DECL(AL_FILTER_NULL),
572 DECL(AL_FILTER_LOWPASS),
573 DECL(AL_FILTER_HIGHPASS),
574 DECL(AL_FILTER_BANDPASS),
576 DECL(AL_LOWPASS_GAIN),
577 DECL(AL_LOWPASS_GAINHF),
579 DECL(AL_HIGHPASS_GAIN),
580 DECL(AL_HIGHPASS_GAINLF),
582 DECL(AL_BANDPASS_GAIN),
583 DECL(AL_BANDPASS_GAINHF),
584 DECL(AL_BANDPASS_GAINLF),
586 DECL(AL_EFFECT_TYPE),
587 DECL(AL_EFFECT_NULL),
588 DECL(AL_EFFECT_REVERB),
589 DECL(AL_EFFECT_EAXREVERB),
590 DECL(AL_EFFECT_CHORUS),
591 DECL(AL_EFFECT_DISTORTION),
592 DECL(AL_EFFECT_ECHO),
593 DECL(AL_EFFECT_FLANGER),
594 #if 0
595 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
596 DECL(AL_EFFECT_VOCAL_MORPHER),
597 DECL(AL_EFFECT_PITCH_SHIFTER),
598 #endif
599 DECL(AL_EFFECT_RING_MODULATOR),
600 #if 0
601 DECL(AL_EFFECT_AUTOWAH),
602 #endif
603 DECL(AL_EFFECT_COMPRESSOR),
604 DECL(AL_EFFECT_EQUALIZER),
605 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
606 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
608 DECL(AL_EFFECTSLOT_EFFECT),
609 DECL(AL_EFFECTSLOT_GAIN),
610 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
611 DECL(AL_EFFECTSLOT_NULL),
613 DECL(AL_EAXREVERB_DENSITY),
614 DECL(AL_EAXREVERB_DIFFUSION),
615 DECL(AL_EAXREVERB_GAIN),
616 DECL(AL_EAXREVERB_GAINHF),
617 DECL(AL_EAXREVERB_GAINLF),
618 DECL(AL_EAXREVERB_DECAY_TIME),
619 DECL(AL_EAXREVERB_DECAY_HFRATIO),
620 DECL(AL_EAXREVERB_DECAY_LFRATIO),
621 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
622 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
623 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
624 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
625 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
626 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
627 DECL(AL_EAXREVERB_ECHO_TIME),
628 DECL(AL_EAXREVERB_ECHO_DEPTH),
629 DECL(AL_EAXREVERB_MODULATION_TIME),
630 DECL(AL_EAXREVERB_MODULATION_DEPTH),
631 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
632 DECL(AL_EAXREVERB_HFREFERENCE),
633 DECL(AL_EAXREVERB_LFREFERENCE),
634 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
635 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
637 DECL(AL_REVERB_DENSITY),
638 DECL(AL_REVERB_DIFFUSION),
639 DECL(AL_REVERB_GAIN),
640 DECL(AL_REVERB_GAINHF),
641 DECL(AL_REVERB_DECAY_TIME),
642 DECL(AL_REVERB_DECAY_HFRATIO),
643 DECL(AL_REVERB_REFLECTIONS_GAIN),
644 DECL(AL_REVERB_REFLECTIONS_DELAY),
645 DECL(AL_REVERB_LATE_REVERB_GAIN),
646 DECL(AL_REVERB_LATE_REVERB_DELAY),
647 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
648 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
649 DECL(AL_REVERB_DECAY_HFLIMIT),
651 DECL(AL_CHORUS_WAVEFORM),
652 DECL(AL_CHORUS_PHASE),
653 DECL(AL_CHORUS_RATE),
654 DECL(AL_CHORUS_DEPTH),
655 DECL(AL_CHORUS_FEEDBACK),
656 DECL(AL_CHORUS_DELAY),
658 DECL(AL_DISTORTION_EDGE),
659 DECL(AL_DISTORTION_GAIN),
660 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
661 DECL(AL_DISTORTION_EQCENTER),
662 DECL(AL_DISTORTION_EQBANDWIDTH),
664 DECL(AL_ECHO_DELAY),
665 DECL(AL_ECHO_LRDELAY),
666 DECL(AL_ECHO_DAMPING),
667 DECL(AL_ECHO_FEEDBACK),
668 DECL(AL_ECHO_SPREAD),
670 DECL(AL_FLANGER_WAVEFORM),
671 DECL(AL_FLANGER_PHASE),
672 DECL(AL_FLANGER_RATE),
673 DECL(AL_FLANGER_DEPTH),
674 DECL(AL_FLANGER_FEEDBACK),
675 DECL(AL_FLANGER_DELAY),
677 DECL(AL_RING_MODULATOR_FREQUENCY),
678 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
679 DECL(AL_RING_MODULATOR_WAVEFORM),
681 DECL(AL_COMPRESSOR_ONOFF),
683 DECL(AL_EQUALIZER_LOW_GAIN),
684 DECL(AL_EQUALIZER_LOW_CUTOFF),
685 DECL(AL_EQUALIZER_MID1_GAIN),
686 DECL(AL_EQUALIZER_MID1_CENTER),
687 DECL(AL_EQUALIZER_MID1_WIDTH),
688 DECL(AL_EQUALIZER_MID2_GAIN),
689 DECL(AL_EQUALIZER_MID2_CENTER),
690 DECL(AL_EQUALIZER_MID2_WIDTH),
691 DECL(AL_EQUALIZER_HIGH_GAIN),
692 DECL(AL_EQUALIZER_HIGH_CUTOFF),
694 DECL(AL_DEDICATED_GAIN),
696 #undef DECL
698 static const ALCchar alcNoError[] = "No Error";
699 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
700 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
701 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
702 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
703 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
706 /************************************************
707 * Global variables
708 ************************************************/
710 /* Enumerated device names */
711 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
713 static al_string alcAllDevicesList;
714 static al_string alcCaptureDeviceList;
716 /* Default is always the first in the list */
717 static ALCchar *alcDefaultAllDevicesSpecifier;
718 static ALCchar *alcCaptureDefaultDeviceSpecifier;
720 /* Default context extensions */
721 static const ALchar alExtList[] =
722 "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
723 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS "
724 "AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
725 "AL_EXT_source_distance_model AL_EXT_SOURCE_RADIUS AL_EXT_STEREO_ANGLES "
726 "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_deferred_updates "
727 "AL_SOFT_direct_channels AL_SOFT_gain_clamp_ex AL_SOFT_loop_points "
728 "AL_SOFT_MSADPCM AL_SOFT_source_latency AL_SOFT_source_length";
730 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
732 /* Thread-local current context */
733 static altss_t LocalContext;
734 /* Process-wide current context */
735 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
737 /* Mixing thread piority level */
738 ALint RTPrioLevel;
740 FILE *LogFile;
741 #ifdef _DEBUG
742 enum LogLevel LogLevel = LogWarning;
743 #else
744 enum LogLevel LogLevel = LogError;
745 #endif
747 /* Flag to trap ALC device errors */
748 static ALCboolean TrapALCError = ALC_FALSE;
750 /* One-time configuration init control */
751 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
753 /* Default effect that applies to sources that don't have an effect on send 0 */
754 static ALeffect DefaultEffect;
756 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
757 * updates.
759 static ALCboolean SuspendDefers = ALC_TRUE;
762 /************************************************
763 * ALC information
764 ************************************************/
765 static const ALCchar alcNoDeviceExtList[] =
766 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
767 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
768 static const ALCchar alcExtensionList[] =
769 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
770 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
771 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFT_HRTF "
772 "ALC_SOFT_loopback ALC_SOFT_pause_device";
773 static const ALCint alcMajorVersion = 1;
774 static const ALCint alcMinorVersion = 1;
776 static const ALCint alcEFXMajorVersion = 1;
777 static const ALCint alcEFXMinorVersion = 0;
780 /************************************************
781 * Device lists
782 ************************************************/
783 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
785 static almtx_t ListLock;
786 static inline void LockLists(void)
788 int ret = almtx_lock(&ListLock);
789 assert(ret == althrd_success);
791 static inline void UnlockLists(void)
793 int ret = almtx_unlock(&ListLock);
794 assert(ret == althrd_success);
797 /************************************************
798 * Library initialization
799 ************************************************/
800 #if defined(_WIN32)
801 static void alc_init(void);
802 static void alc_deinit(void);
803 static void alc_deinit_safe(void);
805 #ifndef AL_LIBTYPE_STATIC
806 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
808 switch(reason)
810 case DLL_PROCESS_ATTACH:
811 /* Pin the DLL so we won't get unloaded until the process terminates */
812 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
813 (WCHAR*)hModule, &hModule);
814 alc_init();
815 break;
817 case DLL_THREAD_DETACH:
818 break;
820 case DLL_PROCESS_DETACH:
821 if(!lpReserved)
822 alc_deinit();
823 else
824 alc_deinit_safe();
825 break;
827 return TRUE;
829 #elif defined(_MSC_VER)
830 #pragma section(".CRT$XCU",read)
831 static void alc_constructor(void);
832 static void alc_destructor(void);
833 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
835 static void alc_constructor(void)
837 atexit(alc_destructor);
838 alc_init();
841 static void alc_destructor(void)
843 alc_deinit();
845 #elif defined(HAVE_GCC_DESTRUCTOR)
846 static void alc_init(void) __attribute__((constructor));
847 static void alc_deinit(void) __attribute__((destructor));
848 #else
849 #error "No static initialization available on this platform!"
850 #endif
852 #elif defined(HAVE_GCC_DESTRUCTOR)
854 static void alc_init(void) __attribute__((constructor));
855 static void alc_deinit(void) __attribute__((destructor));
857 #else
858 #error "No global initialization available on this platform!"
859 #endif
861 static void ReleaseThreadCtx(void *ptr);
862 static void alc_init(void)
864 const char *str;
865 int ret;
867 LogFile = stderr;
869 AL_STRING_INIT(alcAllDevicesList);
870 AL_STRING_INIT(alcCaptureDeviceList);
872 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
873 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
874 ConeScale *= 0.5f;
876 str = getenv("__ALSOFT_REVERSE_Z");
877 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
878 ZScale *= -1.0f;
880 ret = altss_create(&LocalContext, ReleaseThreadCtx);
881 assert(ret == althrd_success);
883 ret = almtx_init(&ListLock, almtx_recursive);
884 assert(ret == althrd_success);
886 ThunkInit();
889 static void alc_initconfig(void)
891 const char *devs, *str;
892 ALuint capfilter;
893 float valf;
894 int i, n;
896 str = getenv("ALSOFT_LOGLEVEL");
897 if(str)
899 long lvl = strtol(str, NULL, 0);
900 if(lvl >= NoLog && lvl <= LogRef)
901 LogLevel = lvl;
904 str = getenv("ALSOFT_LOGFILE");
905 if(str && str[0])
907 FILE *logfile = al_fopen(str, "wt");
908 if(logfile) LogFile = logfile;
909 else ERR("Failed to open log file '%s'\n", str);
912 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION,
913 ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH);
915 char buf[1024] = "";
916 int len = 0;
918 if(BackendListSize > 0)
919 len += snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
920 for(i = 1;i < BackendListSize;i++)
921 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
922 TRACE("Supported backends: %s\n", buf);
924 ReadALConfig();
926 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
927 if(str && *str)
929 if(strcasecmp(str, "ignore") == 0)
931 SuspendDefers = ALC_FALSE;
932 TRACE("Selected context suspend behavior, \"ignore\"\n");
934 else
935 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
938 capfilter = 0;
939 #if defined(HAVE_SSE4_1)
940 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
941 #elif defined(HAVE_SSE3)
942 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
943 #elif defined(HAVE_SSE2)
944 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
945 #elif defined(HAVE_SSE)
946 capfilter |= CPU_CAP_SSE;
947 #endif
948 #ifdef HAVE_NEON
949 capfilter |= CPU_CAP_NEON;
950 #endif
951 if(ConfigValueStr(NULL, NULL, "disable-cpu-exts", &str))
953 if(strcasecmp(str, "all") == 0)
954 capfilter = 0;
955 else
957 size_t len;
958 const char *next = str;
960 do {
961 str = next;
962 while(isspace(str[0]))
963 str++;
964 next = strchr(str, ',');
966 if(!str[0] || str[0] == ',')
967 continue;
969 len = (next ? ((size_t)(next-str)) : strlen(str));
970 while(len > 0 && isspace(str[len-1]))
971 len--;
972 if(len == 3 && strncasecmp(str, "sse", len) == 0)
973 capfilter &= ~CPU_CAP_SSE;
974 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
975 capfilter &= ~CPU_CAP_SSE2;
976 else if(len == 4 && strncasecmp(str, "sse3", len) == 0)
977 capfilter &= ~CPU_CAP_SSE3;
978 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
979 capfilter &= ~CPU_CAP_SSE4_1;
980 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
981 capfilter &= ~CPU_CAP_NEON;
982 else
983 WARN("Invalid CPU extension \"%s\"\n", str);
984 } while(next++);
987 FillCPUCaps(capfilter);
989 #ifdef _WIN32
990 RTPrioLevel = 1;
991 #else
992 RTPrioLevel = 0;
993 #endif
994 ConfigValueInt(NULL, NULL, "rt-prio", &RTPrioLevel);
996 aluInitMixer();
998 str = getenv("ALSOFT_TRAP_ERROR");
999 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1001 TrapALError = AL_TRUE;
1002 TrapALCError = AL_TRUE;
1004 else
1006 str = getenv("ALSOFT_TRAP_AL_ERROR");
1007 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1008 TrapALError = AL_TRUE;
1009 TrapALError = GetConfigValueBool(NULL, NULL, "trap-al-error", TrapALError);
1011 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1012 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1013 TrapALCError = ALC_TRUE;
1014 TrapALCError = GetConfigValueBool(NULL, NULL, "trap-alc-error", TrapALCError);
1017 if(ConfigValueFloat(NULL, "reverb", "boost", &valf))
1018 ReverbBoost *= powf(10.0f, valf / 20.0f);
1020 EmulateEAXReverb = GetConfigValueBool(NULL, "reverb", "emulate-eax", AL_FALSE);
1022 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1023 ConfigValueStr(NULL, NULL, "drivers", &devs))
1025 int n;
1026 size_t len;
1027 const char *next = devs;
1028 int endlist, delitem;
1030 i = 0;
1031 do {
1032 devs = next;
1033 while(isspace(devs[0]))
1034 devs++;
1035 next = strchr(devs, ',');
1037 delitem = (devs[0] == '-');
1038 if(devs[0] == '-') devs++;
1040 if(!devs[0] || devs[0] == ',')
1042 endlist = 0;
1043 continue;
1045 endlist = 1;
1047 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1048 while(len > 0 && isspace(devs[len-1]))
1049 len--;
1050 for(n = i;n < BackendListSize;n++)
1052 if(len == strlen(BackendList[n].name) &&
1053 strncmp(BackendList[n].name, devs, len) == 0)
1055 if(delitem)
1057 for(;n+1 < BackendListSize;n++)
1058 BackendList[n] = BackendList[n+1];
1059 BackendListSize--;
1061 else
1063 struct BackendInfo Bkp = BackendList[n];
1064 for(;n > i;n--)
1065 BackendList[n] = BackendList[n-1];
1066 BackendList[n] = Bkp;
1068 i++;
1070 break;
1073 } while(next++);
1075 if(endlist)
1076 BackendListSize = i;
1079 for(i = 0;i < BackendListSize && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1081 if(BackendList[i].getFactory)
1083 ALCbackendFactory *factory = BackendList[i].getFactory();
1084 if(!V0(factory,init)())
1086 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1087 continue;
1090 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1091 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1093 PlaybackBackend = BackendList[i];
1094 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1096 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1098 CaptureBackend = BackendList[i];
1099 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1102 continue;
1105 if(!BackendList[i].Init(&BackendList[i].Funcs))
1107 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1108 continue;
1111 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1112 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1114 PlaybackBackend = BackendList[i];
1115 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1117 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1119 CaptureBackend = BackendList[i];
1120 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1124 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1125 V0(factory,init)();
1128 if(!PlaybackBackend.name)
1129 WARN("No playback backend available!\n");
1130 if(!CaptureBackend.name)
1131 WARN("No capture backend available!\n");
1133 if(ConfigValueStr(NULL, NULL, "excludefx", &str))
1135 size_t len;
1136 const char *next = str;
1138 do {
1139 str = next;
1140 next = strchr(str, ',');
1142 if(!str[0] || next == str)
1143 continue;
1145 len = (next ? ((size_t)(next-str)) : strlen(str));
1146 for(n = 0;EffectList[n].name;n++)
1148 if(len == strlen(EffectList[n].name) &&
1149 strncmp(EffectList[n].name, str, len) == 0)
1150 DisabledEffects[EffectList[n].type] = AL_TRUE;
1152 } while(next++);
1155 InitEffectFactoryMap();
1157 InitEffect(&DefaultEffect);
1158 str = getenv("ALSOFT_DEFAULT_REVERB");
1159 if((str && str[0]) || ConfigValueStr(NULL, NULL, "default-reverb", &str))
1160 LoadReverbPreset(str, &DefaultEffect);
1162 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1164 #ifdef __ANDROID__
1165 #include <jni.h>
1167 static JavaVM *gJavaVM;
1168 static pthread_key_t gJVMThreadKey;
1170 static void CleanupJNIEnv(void* UNUSED(ptr))
1172 JCALL0(gJavaVM,DetachCurrentThread)();
1175 void *Android_GetJNIEnv(void)
1177 if(!gJavaVM)
1179 WARN("gJavaVM is NULL!\n");
1180 return NULL;
1183 /* http://developer.android.com/guide/practices/jni.html
1185 * All threads are Linux threads, scheduled by the kernel. They're usually
1186 * started from managed code (using Thread.start), but they can also be
1187 * created elsewhere and then attached to the JavaVM. For example, a thread
1188 * started with pthread_create can be attached with the JNI
1189 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1190 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1191 * Attaching a natively-created thread causes a java.lang.Thread object to
1192 * be constructed and added to the "main" ThreadGroup, making it visible to
1193 * the debugger. Calling AttachCurrentThread on an already-attached thread
1194 * is a no-op.
1196 JNIEnv *env = pthread_getspecific(gJVMThreadKey);
1197 if(!env)
1199 int status = JCALL(gJavaVM,AttachCurrentThread)(&env, NULL);
1200 if(status < 0)
1202 ERR("Failed to attach current thread\n");
1203 return NULL;
1205 pthread_setspecific(gJVMThreadKey, env);
1207 return env;
1210 /* Automatically called by JNI. */
1211 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void* UNUSED(reserved))
1213 void *env;
1214 int err;
1216 gJavaVM = jvm;
1217 if(JCALL(gJavaVM,GetEnv)(&env, JNI_VERSION_1_4) != JNI_OK)
1219 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1220 return JNI_ERR;
1223 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1224 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1226 if((err=pthread_key_create(&gJVMThreadKey, CleanupJNIEnv)) != 0)
1227 ERR("pthread_key_create failed: %d\n", err);
1228 pthread_setspecific(gJVMThreadKey, env);
1229 return JNI_VERSION_1_4;
1232 #endif
1235 /************************************************
1236 * Library deinitialization
1237 ************************************************/
1238 static void alc_cleanup(void)
1240 ALCdevice *dev;
1242 AL_STRING_DEINIT(alcAllDevicesList);
1243 AL_STRING_DEINIT(alcCaptureDeviceList);
1245 free(alcDefaultAllDevicesSpecifier);
1246 alcDefaultAllDevicesSpecifier = NULL;
1247 free(alcCaptureDefaultDeviceSpecifier);
1248 alcCaptureDefaultDeviceSpecifier = NULL;
1250 if((dev=ATOMIC_EXCHANGE_SEQ(ALCdevice*, &DeviceList, NULL)) != NULL)
1252 ALCuint num = 0;
1253 do {
1254 num++;
1255 } while((dev=dev->next) != NULL);
1256 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1259 DeinitEffectFactoryMap();
1262 static void alc_deinit_safe(void)
1264 alc_cleanup();
1266 FreeHrtfs();
1267 FreeALConfig();
1269 ThunkExit();
1270 almtx_destroy(&ListLock);
1271 altss_delete(LocalContext);
1273 if(LogFile != stderr)
1274 fclose(LogFile);
1275 LogFile = NULL;
1278 static void alc_deinit(void)
1280 int i;
1282 alc_cleanup();
1284 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1285 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1287 for(i = 0;i < BackendListSize;i++)
1289 if(!BackendList[i].getFactory)
1290 BackendList[i].Deinit();
1291 else
1293 ALCbackendFactory *factory = BackendList[i].getFactory();
1294 V0(factory,deinit)();
1298 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1299 V0(factory,deinit)();
1302 alc_deinit_safe();
1306 /************************************************
1307 * Device enumeration
1308 ************************************************/
1309 static void ProbeDevices(al_string *list, struct BackendInfo *backendinfo, enum DevProbe type)
1311 DO_INITCONFIG();
1313 LockLists();
1314 al_string_clear(list);
1316 if(backendinfo->Probe)
1317 backendinfo->Probe(type);
1318 else if(backendinfo->getFactory)
1320 ALCbackendFactory *factory = backendinfo->getFactory();
1321 V(factory,probe)(type);
1324 UnlockLists();
1326 static void ProbeAllDevicesList(void)
1327 { ProbeDevices(&alcAllDevicesList, &PlaybackBackend, ALL_DEVICE_PROBE); }
1328 static void ProbeCaptureDeviceList(void)
1329 { ProbeDevices(&alcCaptureDeviceList, &CaptureBackend, CAPTURE_DEVICE_PROBE); }
1331 static void AppendDevice(const ALCchar *name, al_string *devnames)
1333 size_t len = strlen(name);
1334 if(len > 0)
1335 al_string_append_range(devnames, name, name+len+1);
1337 void AppendAllDevicesList(const ALCchar *name)
1338 { AppendDevice(name, &alcAllDevicesList); }
1339 void AppendCaptureDeviceList(const ALCchar *name)
1340 { AppendDevice(name, &alcCaptureDeviceList); }
1343 /************************************************
1344 * Device format information
1345 ************************************************/
1346 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1348 switch(type)
1350 case DevFmtByte: return "Signed Byte";
1351 case DevFmtUByte: return "Unsigned Byte";
1352 case DevFmtShort: return "Signed Short";
1353 case DevFmtUShort: return "Unsigned Short";
1354 case DevFmtInt: return "Signed Int";
1355 case DevFmtUInt: return "Unsigned Int";
1356 case DevFmtFloat: return "Float";
1358 return "(unknown type)";
1360 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1362 switch(chans)
1364 case DevFmtMono: return "Mono";
1365 case DevFmtStereo: return "Stereo";
1366 case DevFmtQuad: return "Quadraphonic";
1367 case DevFmtX51: return "5.1 Surround";
1368 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1369 case DevFmtX61: return "6.1 Surround";
1370 case DevFmtX71: return "7.1 Surround";
1371 case DevFmtAmbi1: return "Ambisonic (1st Order)";
1372 case DevFmtAmbi2: return "Ambisonic (2nd Order)";
1373 case DevFmtAmbi3: return "Ambisonic (3rd Order)";
1375 return "(unknown channels)";
1378 extern inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
1379 ALsizei BytesFromDevFmt(enum DevFmtType type)
1381 switch(type)
1383 case DevFmtByte: return sizeof(ALbyte);
1384 case DevFmtUByte: return sizeof(ALubyte);
1385 case DevFmtShort: return sizeof(ALshort);
1386 case DevFmtUShort: return sizeof(ALushort);
1387 case DevFmtInt: return sizeof(ALint);
1388 case DevFmtUInt: return sizeof(ALuint);
1389 case DevFmtFloat: return sizeof(ALfloat);
1391 return 0;
1393 ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans)
1395 switch(chans)
1397 case DevFmtMono: return 1;
1398 case DevFmtStereo: return 2;
1399 case DevFmtQuad: return 4;
1400 case DevFmtX51: return 6;
1401 case DevFmtX51Rear: return 6;
1402 case DevFmtX61: return 7;
1403 case DevFmtX71: return 8;
1404 case DevFmtAmbi1: return 4;
1405 case DevFmtAmbi2: return 9;
1406 case DevFmtAmbi3: return 16;
1408 return 0;
1411 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1412 enum DevFmtType *type)
1414 static const struct {
1415 ALenum format;
1416 enum DevFmtChannels channels;
1417 enum DevFmtType type;
1418 } list[] = {
1419 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1420 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1421 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1423 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1424 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1425 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1427 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1428 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1429 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1431 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1432 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1433 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1435 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1436 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1437 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1439 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1440 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1441 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1443 ALuint i;
1445 for(i = 0;i < COUNTOF(list);i++)
1447 if(list[i].format == format)
1449 *chans = list[i].channels;
1450 *type = list[i].type;
1451 return AL_TRUE;
1455 return AL_FALSE;
1458 static ALCboolean IsValidALCType(ALCenum type)
1460 switch(type)
1462 case ALC_BYTE_SOFT:
1463 case ALC_UNSIGNED_BYTE_SOFT:
1464 case ALC_SHORT_SOFT:
1465 case ALC_UNSIGNED_SHORT_SOFT:
1466 case ALC_INT_SOFT:
1467 case ALC_UNSIGNED_INT_SOFT:
1468 case ALC_FLOAT_SOFT:
1469 return ALC_TRUE;
1471 return ALC_FALSE;
1474 static ALCboolean IsValidALCChannels(ALCenum channels)
1476 switch(channels)
1478 case ALC_MONO_SOFT:
1479 case ALC_STEREO_SOFT:
1480 case ALC_QUAD_SOFT:
1481 case ALC_5POINT1_SOFT:
1482 case ALC_6POINT1_SOFT:
1483 case ALC_7POINT1_SOFT:
1484 case ALC_BFORMAT3D_SOFT:
1485 return ALC_TRUE;
1487 return ALC_FALSE;
1490 static ALCboolean IsValidAmbiLayout(ALCenum layout)
1492 switch(layout)
1494 case ALC_ACN_SOFT:
1495 case ALC_FUMA_SOFT:
1496 return ALC_TRUE;
1498 return ALC_FALSE;
1501 static ALCboolean IsValidAmbiScaling(ALCenum scaling)
1503 switch(scaling)
1505 case ALC_N3D_SOFT:
1506 case ALC_SN3D_SOFT:
1507 case ALC_FUMA_SOFT:
1508 return ALC_TRUE;
1510 return ALC_FALSE;
1513 /************************************************
1514 * Miscellaneous ALC helpers
1515 ************************************************/
1517 void ALCdevice_Lock(ALCdevice *device)
1519 V0(device->Backend,lock)();
1522 void ALCdevice_Unlock(ALCdevice *device)
1524 V0(device->Backend,unlock)();
1528 /* SetDefaultWFXChannelOrder
1530 * Sets the default channel order used by WaveFormatEx.
1532 void SetDefaultWFXChannelOrder(ALCdevice *device)
1534 ALsizei i;
1536 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1537 device->RealOut.ChannelName[i] = InvalidChannel;
1539 switch(device->FmtChans)
1541 case DevFmtMono:
1542 device->RealOut.ChannelName[0] = FrontCenter;
1543 break;
1544 case DevFmtStereo:
1545 device->RealOut.ChannelName[0] = FrontLeft;
1546 device->RealOut.ChannelName[1] = FrontRight;
1547 break;
1548 case DevFmtQuad:
1549 device->RealOut.ChannelName[0] = FrontLeft;
1550 device->RealOut.ChannelName[1] = FrontRight;
1551 device->RealOut.ChannelName[2] = BackLeft;
1552 device->RealOut.ChannelName[3] = BackRight;
1553 break;
1554 case DevFmtX51:
1555 device->RealOut.ChannelName[0] = FrontLeft;
1556 device->RealOut.ChannelName[1] = FrontRight;
1557 device->RealOut.ChannelName[2] = FrontCenter;
1558 device->RealOut.ChannelName[3] = LFE;
1559 device->RealOut.ChannelName[4] = SideLeft;
1560 device->RealOut.ChannelName[5] = SideRight;
1561 break;
1562 case DevFmtX51Rear:
1563 device->RealOut.ChannelName[0] = FrontLeft;
1564 device->RealOut.ChannelName[1] = FrontRight;
1565 device->RealOut.ChannelName[2] = FrontCenter;
1566 device->RealOut.ChannelName[3] = LFE;
1567 device->RealOut.ChannelName[4] = BackLeft;
1568 device->RealOut.ChannelName[5] = BackRight;
1569 break;
1570 case DevFmtX61:
1571 device->RealOut.ChannelName[0] = FrontLeft;
1572 device->RealOut.ChannelName[1] = FrontRight;
1573 device->RealOut.ChannelName[2] = FrontCenter;
1574 device->RealOut.ChannelName[3] = LFE;
1575 device->RealOut.ChannelName[4] = BackCenter;
1576 device->RealOut.ChannelName[5] = SideLeft;
1577 device->RealOut.ChannelName[6] = SideRight;
1578 break;
1579 case DevFmtX71:
1580 device->RealOut.ChannelName[0] = FrontLeft;
1581 device->RealOut.ChannelName[1] = FrontRight;
1582 device->RealOut.ChannelName[2] = FrontCenter;
1583 device->RealOut.ChannelName[3] = LFE;
1584 device->RealOut.ChannelName[4] = BackLeft;
1585 device->RealOut.ChannelName[5] = BackRight;
1586 device->RealOut.ChannelName[6] = SideLeft;
1587 device->RealOut.ChannelName[7] = SideRight;
1588 break;
1589 case DevFmtAmbi1:
1590 device->RealOut.ChannelName[0] = Aux0;
1591 device->RealOut.ChannelName[1] = Aux1;
1592 device->RealOut.ChannelName[2] = Aux2;
1593 device->RealOut.ChannelName[3] = Aux3;
1594 break;
1595 case DevFmtAmbi2:
1596 device->RealOut.ChannelName[0] = Aux0;
1597 device->RealOut.ChannelName[1] = Aux1;
1598 device->RealOut.ChannelName[2] = Aux2;
1599 device->RealOut.ChannelName[3] = Aux3;
1600 device->RealOut.ChannelName[4] = Aux4;
1601 device->RealOut.ChannelName[5] = Aux5;
1602 device->RealOut.ChannelName[6] = Aux6;
1603 device->RealOut.ChannelName[7] = Aux7;
1604 device->RealOut.ChannelName[8] = Aux8;
1605 break;
1606 case DevFmtAmbi3:
1607 device->RealOut.ChannelName[0] = Aux0;
1608 device->RealOut.ChannelName[1] = Aux1;
1609 device->RealOut.ChannelName[2] = Aux2;
1610 device->RealOut.ChannelName[3] = Aux3;
1611 device->RealOut.ChannelName[4] = Aux4;
1612 device->RealOut.ChannelName[5] = Aux5;
1613 device->RealOut.ChannelName[6] = Aux6;
1614 device->RealOut.ChannelName[7] = Aux7;
1615 device->RealOut.ChannelName[8] = Aux8;
1616 device->RealOut.ChannelName[9] = Aux9;
1617 device->RealOut.ChannelName[10] = Aux10;
1618 device->RealOut.ChannelName[11] = Aux11;
1619 device->RealOut.ChannelName[12] = Aux12;
1620 device->RealOut.ChannelName[13] = Aux13;
1621 device->RealOut.ChannelName[14] = Aux14;
1622 device->RealOut.ChannelName[15] = Aux15;
1623 break;
1627 /* SetDefaultChannelOrder
1629 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1631 void SetDefaultChannelOrder(ALCdevice *device)
1633 ALsizei i;
1635 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1636 device->RealOut.ChannelName[i] = InvalidChannel;
1638 switch(device->FmtChans)
1640 case DevFmtX51Rear:
1641 device->RealOut.ChannelName[0] = FrontLeft;
1642 device->RealOut.ChannelName[1] = FrontRight;
1643 device->RealOut.ChannelName[2] = BackLeft;
1644 device->RealOut.ChannelName[3] = BackRight;
1645 device->RealOut.ChannelName[4] = FrontCenter;
1646 device->RealOut.ChannelName[5] = LFE;
1647 return;
1648 case DevFmtX71:
1649 device->RealOut.ChannelName[0] = FrontLeft;
1650 device->RealOut.ChannelName[1] = FrontRight;
1651 device->RealOut.ChannelName[2] = BackLeft;
1652 device->RealOut.ChannelName[3] = BackRight;
1653 device->RealOut.ChannelName[4] = FrontCenter;
1654 device->RealOut.ChannelName[5] = LFE;
1655 device->RealOut.ChannelName[6] = SideLeft;
1656 device->RealOut.ChannelName[7] = SideRight;
1657 return;
1659 /* Same as WFX order */
1660 case DevFmtMono:
1661 case DevFmtStereo:
1662 case DevFmtQuad:
1663 case DevFmtX51:
1664 case DevFmtX61:
1665 case DevFmtAmbi1:
1666 case DevFmtAmbi2:
1667 case DevFmtAmbi3:
1668 SetDefaultWFXChannelOrder(device);
1669 break;
1673 extern inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan);
1676 /* ALCcontext_DeferUpdates
1678 * Defers/suspends updates for the given context's listener and sources. This
1679 * does *NOT* stop mixing, but rather prevents certain property changes from
1680 * taking effect.
1682 void ALCcontext_DeferUpdates(ALCcontext *context, ALenum type)
1684 ATOMIC_STORE_SEQ(&context->DeferUpdates, type);
1687 /* ALCcontext_ProcessUpdates
1689 * Resumes update processing after being deferred.
1691 void ALCcontext_ProcessUpdates(ALCcontext *context)
1693 ALCdevice *device = context->Device;
1695 ReadLock(&context->PropLock);
1696 if(ATOMIC_EXCHANGE_SEQ(ALenum, &context->DeferUpdates, AL_FALSE))
1698 ALsizei pos;
1700 /* Tell the mixer to stop applying updates, then wait for any active
1701 * updating to finish, before providing updates.
1703 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_TRUE);
1704 while((ATOMIC_LOAD(&context->UpdateCount, almemory_order_acquire)&1) != 0)
1705 althrd_yield();
1707 UpdateListenerProps(context);
1708 UpdateAllEffectSlotProps(context);
1710 LockUIntMapRead(&context->SourceMap);
1711 V0(device->Backend,lock)();
1712 for(pos = 0;pos < context->VoiceCount;pos++)
1714 ALvoice *voice = context->Voices[pos];
1715 ALsource *source = ATOMIC_LOAD(&voice->Source, almemory_order_acquire);
1716 if(source && source->OffsetType != AL_NONE)
1718 WriteLock(&source->queue_lock);
1719 ApplyOffset(source, voice);
1720 WriteUnlock(&source->queue_lock);
1723 for(pos = 0;pos < context->SourceMap.size;pos++)
1725 ALsource *source = context->SourceMap.values[pos];
1726 ALenum new_state = source->new_state;
1727 source->new_state = AL_NONE;
1728 if(new_state)
1729 SetSourceState(source, context, new_state);
1731 V0(device->Backend,unlock)();
1732 UnlockUIntMapRead(&context->SourceMap);
1734 UpdateAllSourceProps(context);
1736 /* Now with all updates declared, let the mixer continue applying them
1737 * so they all happen at once.
1739 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_FALSE);
1741 ReadUnlock(&context->PropLock);
1745 /* alcSetError
1747 * Stores the latest ALC device error
1749 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1751 WARN("Error generated on device %p, code 0x%04x\n", device, errorCode);
1752 if(TrapALCError)
1754 #ifdef _WIN32
1755 /* DebugBreak() will cause an exception if there is no debugger */
1756 if(IsDebuggerPresent())
1757 DebugBreak();
1758 #elif defined(SIGTRAP)
1759 raise(SIGTRAP);
1760 #endif
1763 if(device)
1764 ATOMIC_STORE_SEQ(&device->LastError, errorCode);
1765 else
1766 ATOMIC_STORE_SEQ(&LastNullDeviceError, errorCode);
1770 /* UpdateClockBase
1772 * Updates the device's base clock time with however many samples have been
1773 * done. This is used so frequency changes on the device don't cause the time
1774 * to jump forward or back. Must not be called while the device is running/
1775 * mixing.
1777 static inline void UpdateClockBase(ALCdevice *device)
1779 IncrementRef(&device->MixCount);
1780 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1781 device->SamplesDone = 0;
1782 IncrementRef(&device->MixCount);
1785 /* UpdateDeviceParams
1787 * Updates device parameters according to the attribute list (caller is
1788 * responsible for holding the list lock).
1790 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1792 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1793 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1794 const ALsizei old_sends = device->NumAuxSends;
1795 ALsizei new_sends = device->NumAuxSends;
1796 enum DevFmtChannels oldChans;
1797 enum DevFmtType oldType;
1798 ALboolean update_failed;
1799 ALCsizei hrtf_id = -1;
1800 ALCcontext *context;
1801 ALCuint oldFreq;
1802 FPUCtl oldMode;
1803 size_t size;
1804 ALCsizei i;
1806 // Check for attributes
1807 if(device->Type == Loopback)
1809 ALCsizei numMono, numStereo, numSends;
1810 ALCenum alayout = AL_NONE;
1811 ALCenum ascale = AL_NONE;
1812 ALCenum schans = AL_NONE;
1813 ALCenum stype = AL_NONE;
1814 ALCsizei attrIdx = 0;
1815 ALCsizei aorder = 0;
1816 ALCuint freq = 0;
1818 if(!attrList)
1820 WARN("Missing attributes for loopback device\n");
1821 return ALC_INVALID_VALUE;
1824 numMono = device->NumMonoSources;
1825 numStereo = device->NumStereoSources;
1826 numSends = old_sends;
1828 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1829 while(attrList[attrIdx])
1831 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1833 schans = attrList[attrIdx + 1];
1834 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1835 if(!IsValidALCChannels(schans))
1836 return ALC_INVALID_VALUE;
1839 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1841 stype = attrList[attrIdx + 1];
1842 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1843 if(!IsValidALCType(stype))
1844 return ALC_INVALID_VALUE;
1847 if(attrList[attrIdx] == ALC_FREQUENCY)
1849 freq = attrList[attrIdx + 1];
1850 TRACE_ATTR(ALC_FREQUENCY, freq);
1851 if(freq < MIN_OUTPUT_RATE)
1852 return ALC_INVALID_VALUE;
1855 if(attrList[attrIdx] == ALC_AMBISONIC_LAYOUT_SOFT)
1857 alayout = attrList[attrIdx + 1];
1858 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1859 if(!IsValidAmbiLayout(alayout))
1860 return ALC_INVALID_VALUE;
1863 if(attrList[attrIdx] == ALC_AMBISONIC_SCALING_SOFT)
1865 ascale = attrList[attrIdx + 1];
1866 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1867 if(!IsValidAmbiScaling(ascale))
1868 return ALC_INVALID_VALUE;
1871 if(attrList[attrIdx] == ALC_AMBISONIC_ORDER_SOFT)
1873 aorder = attrList[attrIdx + 1];
1874 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1875 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1876 return ALC_INVALID_VALUE;
1879 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1881 numStereo = attrList[attrIdx + 1];
1882 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1884 numStereo = clampi(numStereo, 0, device->SourcesMax);
1885 numMono = device->SourcesMax - numStereo;
1888 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1890 numSends = attrList[attrIdx + 1];
1891 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1892 numSends = clampi(numSends, 0, MAX_SENDS);
1895 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1897 ALCint val = attrList[attrIdx + 1];
1898 TRACE_ATTR(ALC_HRTF_SOFT, val);
1899 if(val == ALC_FALSE)
1900 hrtf_appreq = Hrtf_Disable;
1901 else if(val == ALC_TRUE)
1902 hrtf_appreq = Hrtf_Enable;
1903 else
1904 hrtf_appreq = Hrtf_Default;
1907 if(attrList[attrIdx] == ALC_HRTF_ID_SOFT)
1909 hrtf_id = attrList[attrIdx + 1];
1910 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1913 attrIdx += 2;
1915 #undef TRACE_ATTR
1917 if(!schans || !stype || !freq)
1919 WARN("Missing format for loopback device\n");
1920 return ALC_INVALID_VALUE;
1922 if(schans == ALC_BFORMAT3D_SOFT && (!alayout || !ascale || !aorder))
1924 WARN("Missing ambisonic info for loopback device\n");
1925 return ALC_INVALID_VALUE;
1928 if((device->Flags&DEVICE_RUNNING))
1929 V0(device->Backend,stop)();
1930 device->Flags &= ~DEVICE_RUNNING;
1932 UpdateClockBase(device);
1934 if(schans == ALC_BFORMAT3D_SOFT)
1936 device->FmtChans = DevFmtAmbi1 + aorder;
1937 device->AmbiLayout = alayout;
1938 device->AmbiScale = ascale;
1940 else
1941 device->FmtChans = schans;
1942 device->Frequency = freq;
1943 device->FmtType = stype;
1944 device->NumMonoSources = numMono;
1945 device->NumStereoSources = numStereo;
1947 if(ConfigValueInt(NULL, NULL, "sends", &new_sends))
1948 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1949 else
1950 new_sends = numSends;
1952 else if(attrList && attrList[0])
1954 ALCsizei numMono, numStereo, numSends;
1955 ALCsizei attrIdx = 0;
1956 ALCuint freq;
1958 /* If a context is already running on the device, stop playback so the
1959 * device attributes can be updated. */
1960 if((device->Flags&DEVICE_RUNNING))
1961 V0(device->Backend,stop)();
1962 device->Flags &= ~DEVICE_RUNNING;
1964 UpdateClockBase(device);
1966 freq = device->Frequency;
1967 numMono = device->NumMonoSources;
1968 numStereo = device->NumStereoSources;
1969 numSends = old_sends;
1971 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1972 while(attrList[attrIdx])
1974 if(attrList[attrIdx] == ALC_FREQUENCY)
1976 freq = attrList[attrIdx + 1];
1977 TRACE_ATTR(ALC_FREQUENCY, freq);
1978 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1981 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1983 numStereo = attrList[attrIdx + 1];
1984 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1986 numStereo = clampi(numStereo, 0, device->SourcesMax);
1987 numMono = device->SourcesMax - numStereo;
1990 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1992 numSends = attrList[attrIdx + 1];
1993 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1994 numSends = clampi(numSends, 0, MAX_SENDS);
1997 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1999 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
2000 if(attrList[attrIdx + 1] == ALC_FALSE)
2001 hrtf_appreq = Hrtf_Disable;
2002 else if(attrList[attrIdx + 1] == ALC_TRUE)
2003 hrtf_appreq = Hrtf_Enable;
2004 else
2005 hrtf_appreq = Hrtf_Default;
2008 if(attrList[attrIdx] == ALC_HRTF_ID_SOFT)
2010 hrtf_id = attrList[attrIdx + 1];
2011 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
2014 attrIdx += 2;
2016 #undef TRACE_ATTR
2018 ConfigValueUInt(al_string_get_cstr(device->DeviceName), NULL, "frequency", &freq);
2019 freq = maxu(freq, MIN_OUTPUT_RATE);
2021 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
2022 device->Frequency;
2023 /* SSE and Neon do best with the update size being a multiple of 4 */
2024 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
2025 device->UpdateSize = (device->UpdateSize+3)&~3;
2027 device->Frequency = freq;
2028 device->NumMonoSources = numMono;
2029 device->NumStereoSources = numStereo;
2031 if(ConfigValueInt(al_string_get_cstr(device->DeviceName), NULL, "sends", &new_sends))
2032 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
2033 else
2034 new_sends = numSends;
2037 if((device->Flags&DEVICE_RUNNING))
2038 return ALC_NO_ERROR;
2040 al_free(device->Uhj_Encoder);
2041 device->Uhj_Encoder = NULL;
2043 al_free(device->Bs2b);
2044 device->Bs2b = NULL;
2046 al_free(device->ChannelDelay[0].Buffer);
2047 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2049 device->ChannelDelay[i].Length = 0;
2050 device->ChannelDelay[i].Buffer = NULL;
2053 al_free(device->Dry.Buffer);
2054 device->Dry.Buffer = NULL;
2055 device->Dry.NumChannels = 0;
2056 device->FOAOut.Buffer = NULL;
2057 device->FOAOut.NumChannels = 0;
2058 device->RealOut.Buffer = NULL;
2059 device->RealOut.NumChannels = 0;
2061 UpdateClockBase(device);
2063 /*************************************************************************
2064 * Update device format request if HRTF is requested
2066 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
2067 if(device->Type != Loopback)
2069 const char *hrtf;
2070 if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "hrtf", &hrtf))
2072 if(strcasecmp(hrtf, "true") == 0)
2073 hrtf_userreq = Hrtf_Enable;
2074 else if(strcasecmp(hrtf, "false") == 0)
2075 hrtf_userreq = Hrtf_Disable;
2076 else if(strcasecmp(hrtf, "auto") != 0)
2077 ERR("Unexpected hrtf value: %s\n", hrtf);
2080 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
2082 if(VECTOR_SIZE(device->HrtfList) == 0)
2084 VECTOR_DEINIT(device->HrtfList);
2085 device->HrtfList = EnumerateHrtf(device->DeviceName);
2087 if(VECTOR_SIZE(device->HrtfList) > 0)
2089 device->FmtChans = DevFmtStereo;
2090 if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->HrtfList))
2091 device->Frequency = VECTOR_ELEM(device->HrtfList, hrtf_id).hrtf->sampleRate;
2092 else
2093 device->Frequency = VECTOR_ELEM(device->HrtfList, 0).hrtf->sampleRate;
2094 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
2096 else
2098 hrtf_userreq = Hrtf_Default;
2099 hrtf_appreq = Hrtf_Disable;
2100 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2104 else if(hrtf_appreq == Hrtf_Enable)
2106 size_t i = VECTOR_SIZE(device->HrtfList);
2107 /* Loopback device. We don't need to match to a specific HRTF entry
2108 * here. If the requested ID matches, we'll pick that later, if not,
2109 * we'll try to auto-select one anyway. Just make sure one exists
2110 * that'll work.
2112 if(device->FmtChans == DevFmtStereo)
2114 if(VECTOR_SIZE(device->HrtfList) == 0)
2116 VECTOR_DEINIT(device->HrtfList);
2117 device->HrtfList = EnumerateHrtf(device->DeviceName);
2119 for(i = 0;i < VECTOR_SIZE(device->HrtfList);i++)
2121 const struct Hrtf *hrtf = VECTOR_ELEM(device->HrtfList, i).hrtf;
2122 if(hrtf->sampleRate == device->Frequency)
2123 break;
2126 if(i == VECTOR_SIZE(device->HrtfList))
2128 ERR("Requested format not HRTF compatible: %s, %uhz\n",
2129 DevFmtChannelsString(device->FmtChans), device->Frequency);
2130 hrtf_appreq = Hrtf_Disable;
2131 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2135 oldFreq = device->Frequency;
2136 oldChans = device->FmtChans;
2137 oldType = device->FmtType;
2139 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2140 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
2141 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
2142 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
2143 device->UpdateSize, device->NumUpdates
2146 if(V0(device->Backend,reset)() == ALC_FALSE)
2147 return ALC_INVALID_DEVICE;
2149 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
2151 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2152 DevFmtChannelsString(device->FmtChans));
2153 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2155 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2157 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2158 DevFmtTypeString(device->FmtType));
2159 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2161 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2163 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2164 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2167 if((device->UpdateSize&3) != 0)
2169 if((CPUCapFlags&CPU_CAP_SSE))
2170 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2171 if((CPUCapFlags&CPU_CAP_NEON))
2172 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2175 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2176 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2177 device->Frequency, device->UpdateSize, device->NumUpdates
2180 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2181 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device->Dry.NumChannels,
2182 device->FOAOut.NumChannels, device->RealOut.NumChannels);
2184 /* Allocate extra channels for any post-filter output. */
2185 size = (device->Dry.NumChannels + device->FOAOut.NumChannels +
2186 device->RealOut.NumChannels)*sizeof(device->Dry.Buffer[0]);
2188 TRACE("Allocating "SZFMT" channels, "SZFMT" bytes\n", size/sizeof(device->Dry.Buffer[0]), size);
2189 device->Dry.Buffer = al_calloc(16, size);
2190 if(!device->Dry.Buffer)
2192 ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
2193 return ALC_INVALID_DEVICE;
2196 if(device->RealOut.NumChannels != 0)
2197 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels +
2198 device->FOAOut.NumChannels;
2199 else
2201 device->RealOut.Buffer = device->Dry.Buffer;
2202 device->RealOut.NumChannels = device->Dry.NumChannels;
2205 if(device->FOAOut.NumChannels != 0)
2206 device->FOAOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2207 else
2209 device->FOAOut.Buffer = device->Dry.Buffer;
2210 device->FOAOut.NumChannels = device->Dry.NumChannels;
2213 /* Need to delay returning failure until replacement Send arrays have been
2214 * allocated with the appropriate size.
2216 device->NumAuxSends = new_sends;
2217 update_failed = AL_FALSE;
2218 SetMixerFPUMode(&oldMode);
2219 if(device->DefaultSlot)
2221 ALeffectslot *slot = device->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);
2232 context = ATOMIC_LOAD_SEQ(&device->ContextList);
2233 while(context)
2235 ALsizei pos;
2237 WriteLock(&context->PropLock);
2238 LockUIntMapRead(&context->EffectSlotMap);
2239 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
2241 ALeffectslot *slot = context->EffectSlotMap.values[pos];
2242 ALeffectState *state = slot->Effect.State;
2244 state->OutBuffer = device->Dry.Buffer;
2245 state->OutChannels = device->Dry.NumChannels;
2246 if(V(state,deviceUpdate)(device) == AL_FALSE)
2247 update_failed = AL_TRUE;
2248 else
2249 UpdateEffectSlotProps(slot);
2251 UnlockUIntMapRead(&context->EffectSlotMap);
2253 LockUIntMapRead(&context->SourceMap);
2254 for(pos = 0;pos < context->SourceMap.size;pos++)
2256 ALsource *source = context->SourceMap.values[pos];
2257 struct ALsourceProps *props;
2259 if(old_sends != device->NumAuxSends)
2261 ALvoid *sends = al_calloc(16, device->NumAuxSends*sizeof(source->Send[0]));
2262 ALsizei s;
2264 memcpy(sends, source->Send,
2265 mini(device->NumAuxSends, old_sends)*sizeof(source->Send[0])
2267 for(s = device->NumAuxSends;s < old_sends;s++)
2269 if(source->Send[s].Slot)
2270 DecrementRef(&source->Send[s].Slot->ref);
2271 source->Send[s].Slot = NULL;
2273 al_free(source->Send);
2274 source->Send = sends;
2275 for(s = old_sends;s < device->NumAuxSends;s++)
2277 source->Send[s].Slot = NULL;
2278 source->Send[s].Gain = 1.0f;
2279 source->Send[s].GainHF = 1.0f;
2280 source->Send[s].HFReference = LOWPASSFREQREF;
2281 source->Send[s].GainLF = 1.0f;
2282 source->Send[s].LFReference = HIGHPASSFREQREF;
2286 source->NeedsUpdate = AL_TRUE;
2288 /* Clear any pre-existing source property structs, in case the
2289 * number of auxiliary sends changed. Playing (or paused) sources
2290 * will have updates respecified in UpdateAllSourceProps.
2292 props = ATOMIC_EXCHANGE_SEQ(struct ALsourceProps*, &source->Update, NULL);
2293 al_free(props);
2295 props = ATOMIC_EXCHANGE(struct ALsourceProps*, &source->FreeList, NULL,
2296 almemory_order_relaxed);
2297 while(props)
2299 struct ALsourceProps *next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
2300 al_free(props);
2301 props = next;
2304 AllocateVoices(context, context->MaxVoices, old_sends);
2305 for(pos = 0;pos < context->VoiceCount;pos++)
2307 ALvoice *voice = context->Voices[pos];
2308 if(ATOMIC_LOAD(&voice->Source, almemory_order_acquire) == NULL)
2309 continue;
2311 if(device->AvgSpeakerDist > 0.0f)
2313 /* Reinitialize the NFC filters for new parameters. */
2314 ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
2315 (device->AvgSpeakerDist * device->Frequency);
2316 for(i = 0;i < voice->NumChannels;i++)
2318 NfcFilterCreate1(&voice->Direct.Params[i].NFCtrlFilter[0], 0.0f, w1);
2319 NfcFilterCreate2(&voice->Direct.Params[i].NFCtrlFilter[1], 0.0f, w1);
2320 NfcFilterCreate3(&voice->Direct.Params[i].NFCtrlFilter[2], 0.0f, w1);
2324 UnlockUIntMapRead(&context->SourceMap);
2326 UpdateListenerProps(context);
2327 UpdateAllSourceProps(context);
2328 WriteUnlock(&context->PropLock);
2330 context = context->next;
2332 RestoreFPUMode(&oldMode);
2333 if(update_failed)
2334 return ALC_INVALID_DEVICE;
2336 if(!(device->Flags&DEVICE_PAUSED))
2338 if(V0(device->Backend,start)() == ALC_FALSE)
2339 return ALC_INVALID_DEVICE;
2340 device->Flags |= DEVICE_RUNNING;
2343 return ALC_NO_ERROR;
2346 /* FreeDevice
2348 * Frees the device structure, and destroys any objects the app failed to
2349 * delete. Called once there's no more references on the device.
2351 static ALCvoid FreeDevice(ALCdevice *device)
2353 ALsizei i;
2355 TRACE("%p\n", device);
2357 V0(device->Backend,close)();
2358 DELETE_OBJ(device->Backend);
2359 device->Backend = NULL;
2361 almtx_destroy(&device->BackendLock);
2363 if(device->DefaultSlot)
2365 DeinitEffectSlot(device->DefaultSlot);
2366 device->DefaultSlot = NULL;
2369 if(device->BufferMap.size > 0)
2371 WARN("(%p) Deleting %d Buffer%s\n", device, device->BufferMap.size,
2372 (device->BufferMap.size==1)?"":"s");
2373 ReleaseALBuffers(device);
2375 ResetUIntMap(&device->BufferMap);
2377 if(device->EffectMap.size > 0)
2379 WARN("(%p) Deleting %d Effect%s\n", device, device->EffectMap.size,
2380 (device->EffectMap.size==1)?"":"s");
2381 ReleaseALEffects(device);
2383 ResetUIntMap(&device->EffectMap);
2385 if(device->FilterMap.size > 0)
2387 WARN("(%p) Deleting %d Filter%s\n", device, device->FilterMap.size,
2388 (device->FilterMap.size==1)?"":"s");
2389 ReleaseALFilters(device);
2391 ResetUIntMap(&device->FilterMap);
2393 AL_STRING_DEINIT(device->HrtfName);
2394 FreeHrtfList(&device->HrtfList);
2395 al_free(device->Hrtf);
2396 device->Hrtf = NULL;
2398 al_free(device->Bs2b);
2399 device->Bs2b = NULL;
2401 al_free(device->Uhj_Encoder);
2402 device->Uhj_Encoder = NULL;
2404 bformatdec_free(device->AmbiDecoder);
2405 device->AmbiDecoder = NULL;
2407 ambiup_free(device->AmbiUp);
2408 device->AmbiUp = NULL;
2410 al_free(device->ChannelDelay[0].Buffer);
2411 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2413 device->ChannelDelay[i].Gain = 1.0f;
2414 device->ChannelDelay[i].Length = 0;
2415 device->ChannelDelay[i].Buffer = NULL;
2418 AL_STRING_DEINIT(device->DeviceName);
2420 al_free(device->Dry.Buffer);
2421 device->Dry.Buffer = NULL;
2422 device->Dry.NumChannels = 0;
2423 device->FOAOut.Buffer = NULL;
2424 device->FOAOut.NumChannels = 0;
2425 device->RealOut.Buffer = NULL;
2426 device->RealOut.NumChannels = 0;
2428 al_free(device);
2432 void ALCdevice_IncRef(ALCdevice *device)
2434 uint ref;
2435 ref = IncrementRef(&device->ref);
2436 TRACEREF("%p increasing refcount to %u\n", device, ref);
2439 void ALCdevice_DecRef(ALCdevice *device)
2441 uint ref;
2442 ref = DecrementRef(&device->ref);
2443 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2444 if(ref == 0) FreeDevice(device);
2447 /* VerifyDevice
2449 * Checks if the device handle is valid, and increments its ref count if so.
2451 static ALCboolean VerifyDevice(ALCdevice **device)
2453 ALCdevice *tmpDevice;
2455 LockLists();
2456 tmpDevice = ATOMIC_LOAD_SEQ(&DeviceList);
2457 while(tmpDevice)
2459 if(tmpDevice == *device)
2461 ALCdevice_IncRef(tmpDevice);
2462 UnlockLists();
2463 return ALC_TRUE;
2465 tmpDevice = tmpDevice->next;
2467 UnlockLists();
2469 *device = NULL;
2470 return ALC_FALSE;
2474 /* InitContext
2476 * Initializes context fields
2478 static ALvoid InitContext(ALCcontext *Context)
2480 ALlistener *listener = Context->Listener;
2482 //Initialise listener
2483 listener->Gain = 1.0f;
2484 listener->MetersPerUnit = 1.0f;
2485 listener->Position[0] = 0.0f;
2486 listener->Position[1] = 0.0f;
2487 listener->Position[2] = 0.0f;
2488 listener->Velocity[0] = 0.0f;
2489 listener->Velocity[1] = 0.0f;
2490 listener->Velocity[2] = 0.0f;
2491 listener->Forward[0] = 0.0f;
2492 listener->Forward[1] = 0.0f;
2493 listener->Forward[2] = -1.0f;
2494 listener->Up[0] = 0.0f;
2495 listener->Up[1] = 1.0f;
2496 listener->Up[2] = 0.0f;
2498 aluMatrixfSet(&listener->Params.Matrix,
2499 1.0f, 0.0f, 0.0f, 0.0f,
2500 0.0f, 1.0f, 0.0f, 0.0f,
2501 0.0f, 0.0f, 1.0f, 0.0f,
2502 0.0f, 0.0f, 0.0f, 1.0f
2504 aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2505 listener->Params.Gain = 1.0f;
2506 listener->Params.MetersPerUnit = 1.0f;
2507 listener->Params.DopplerFactor = 1.0f;
2508 listener->Params.SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2510 ATOMIC_INIT(&listener->Update, NULL);
2511 ATOMIC_INIT(&listener->FreeList, NULL);
2513 //Validate Context
2514 InitRef(&Context->UpdateCount, 0);
2515 ATOMIC_INIT(&Context->HoldUpdates, AL_FALSE);
2516 Context->GainBoost = 1.0f;
2517 RWLockInit(&Context->PropLock);
2518 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2519 InitUIntMap(&Context->SourceMap, Context->Device->SourcesMax);
2520 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2522 //Set globals
2523 Context->DistanceModel = DefaultDistanceModel;
2524 Context->SourceDistanceModel = AL_FALSE;
2525 Context->DopplerFactor = 1.0f;
2526 Context->DopplerVelocity = 1.0f;
2527 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2528 ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
2530 Context->ExtensionList = alExtList;
2534 /* FreeContext
2536 * Cleans up the context, and destroys any remaining objects the app failed to
2537 * delete. Called once there's no more references on the context.
2539 static void FreeContext(ALCcontext *context)
2541 ALlistener *listener = context->Listener;
2542 struct ALlistenerProps *lprops;
2543 size_t count;
2545 TRACE("%p\n", context);
2547 if(context->SourceMap.size > 0)
2549 WARN("(%p) Deleting %d Source%s\n", context, context->SourceMap.size,
2550 (context->SourceMap.size==1)?"":"s");
2551 ReleaseALSources(context);
2553 ResetUIntMap(&context->SourceMap);
2555 if(context->EffectSlotMap.size > 0)
2557 WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context, context->EffectSlotMap.size,
2558 (context->EffectSlotMap.size==1)?"":"s");
2559 ReleaseALAuxiliaryEffectSlots(context);
2561 ResetUIntMap(&context->EffectSlotMap);
2563 al_free(context->Voices);
2564 context->Voices = NULL;
2565 context->VoiceCount = 0;
2566 context->MaxVoices = 0;
2568 if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != NULL)
2570 TRACE("Freed unapplied listener update %p\n", lprops);
2571 al_free(lprops);
2573 count = 0;
2574 lprops = ATOMIC_LOAD(&listener->FreeList, almemory_order_acquire);
2575 while(lprops)
2577 struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_acquire);
2578 al_free(lprops);
2579 lprops = next;
2580 ++count;
2582 TRACE("Freed "SZFMT" listener property object%s\n", count, (count==1)?"":"s");
2584 ALCdevice_DecRef(context->Device);
2585 context->Device = NULL;
2587 //Invalidate context
2588 memset(context, 0, sizeof(ALCcontext));
2589 al_free(context);
2592 /* ReleaseContext
2594 * Removes the context reference from the given device and removes it from
2595 * being current on the running thread or globally.
2597 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
2599 ALCcontext *origctx;
2601 if(altss_get(LocalContext) == context)
2603 WARN("%p released while current on thread\n", context);
2604 altss_set(LocalContext, NULL);
2605 ALCcontext_DecRef(context);
2608 origctx = context;
2609 if(ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext*, &GlobalContext, &origctx, NULL))
2610 ALCcontext_DecRef(context);
2612 ALCdevice_Lock(device);
2613 origctx = context;
2614 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext*, &device->ContextList,
2615 &origctx, context->next))
2617 ALCcontext *volatile*list = &origctx->next;
2618 while(*list)
2620 if(*list == context)
2622 *list = (*list)->next;
2623 break;
2625 list = &(*list)->next;
2628 ALCdevice_Unlock(device);
2630 ALCcontext_DecRef(context);
2633 void ALCcontext_IncRef(ALCcontext *context)
2635 uint ref = IncrementRef(&context->ref);
2636 TRACEREF("%p increasing refcount to %u\n", context, ref);
2639 void ALCcontext_DecRef(ALCcontext *context)
2641 uint ref = DecrementRef(&context->ref);
2642 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2643 if(ref == 0) FreeContext(context);
2646 static void ReleaseThreadCtx(void *ptr)
2648 ALCcontext *context = ptr;
2649 uint ref = DecrementRef(&context->ref);
2650 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2651 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2654 /* VerifyContext
2656 * Checks that the given context is valid, and increments its reference count.
2658 static ALCboolean VerifyContext(ALCcontext **context)
2660 ALCdevice *dev;
2662 LockLists();
2663 dev = ATOMIC_LOAD_SEQ(&DeviceList);
2664 while(dev)
2666 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList, almemory_order_acquire);
2667 while(ctx)
2669 if(ctx == *context)
2671 ALCcontext_IncRef(ctx);
2672 UnlockLists();
2673 return ALC_TRUE;
2675 ctx = ctx->next;
2677 dev = dev->next;
2679 UnlockLists();
2681 *context = NULL;
2682 return ALC_FALSE;
2686 /* GetContextRef
2688 * Returns the currently active context for this thread, and adds a reference
2689 * without locking it.
2691 ALCcontext *GetContextRef(void)
2693 ALCcontext *context;
2695 context = altss_get(LocalContext);
2696 if(context)
2697 ALCcontext_IncRef(context);
2698 else
2700 LockLists();
2701 context = ATOMIC_LOAD_SEQ(&GlobalContext);
2702 if(context)
2703 ALCcontext_IncRef(context);
2704 UnlockLists();
2707 return context;
2711 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
2713 ALCdevice *device = context->Device;
2714 ALsizei num_sends = device->NumAuxSends;
2715 struct ALsourceProps *props;
2716 size_t sizeof_props;
2717 size_t sizeof_voice;
2718 ALvoice **voices;
2719 ALvoice *voice;
2720 ALsizei v = 0;
2721 size_t size;
2723 if(num_voices == context->MaxVoices && num_sends == old_sends)
2724 return;
2726 /* Allocate the voice pointers, voices, and the voices' stored source
2727 * property set (including the dynamically-sized Send[] array) in one
2728 * chunk.
2730 sizeof_props = RoundUp(offsetof(struct ALsourceProps, Send[num_sends]), 16);
2731 sizeof_voice = RoundUp(offsetof(ALvoice, Send[num_sends]), 16);
2732 size = sizeof(ALvoice*) + sizeof_voice + sizeof_props;
2734 voices = al_calloc(16, RoundUp(size*num_voices, 16));
2735 /* The voice and property objects are stored interleaved since they're
2736 * paired together.
2738 voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
2739 props = (struct ALsourceProps*)((char*)voice + sizeof_voice);
2741 if(context->Voices)
2743 ALsizei v_count = mini(context->VoiceCount, num_voices);
2744 for(;v < v_count;v++)
2746 ALsizei s_count = mini(old_sends, num_sends);
2747 ALsizei i;
2749 /* Copy the old voice data and source property set to the new
2750 * storage.
2752 *voice = *(context->Voices[v]);
2753 for(i = 0;i < s_count;i++)
2754 voice->Send[i] = context->Voices[v]->Send[i];
2755 *props = *(context->Voices[v]->Props);
2756 for(i = 0;i < s_count;i++)
2757 props->Send[i] = context->Voices[v]->Props->Send[i];
2759 /* Set this voice's property set pointer and voice reference. */
2760 voice->Props = props;
2761 voices[v] = voice;
2763 /* Increment pointers to the next storage space. */
2764 voice = (ALvoice*)((char*)props + sizeof_props);
2765 props = (struct ALsourceProps*)((char*)voice + sizeof_voice);
2768 /* Finish setting the voices' property set pointers and references. */
2769 for(;v < num_voices;v++)
2771 voice->Props = props;
2772 voices[v] = voice;
2774 voice = (ALvoice*)((char*)props + sizeof_props);
2775 props = (struct ALsourceProps*)((char*)voice + sizeof_voice);
2778 al_free(context->Voices);
2779 context->Voices = voices;
2780 context->MaxVoices = num_voices;
2781 context->VoiceCount = mini(context->VoiceCount, num_voices);
2785 /************************************************
2786 * Standard ALC functions
2787 ************************************************/
2789 /* alcGetError
2791 * Return last ALC generated error code for the given device
2793 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2795 ALCenum errorCode;
2797 if(VerifyDevice(&device))
2799 errorCode = ATOMIC_EXCHANGE_SEQ(ALCenum, &device->LastError, ALC_NO_ERROR);
2800 ALCdevice_DecRef(device);
2802 else
2803 errorCode = ATOMIC_EXCHANGE_SEQ(ALCenum, &LastNullDeviceError, ALC_NO_ERROR);
2805 return errorCode;
2809 /* alcSuspendContext
2811 * Suspends updates for the given context
2813 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2815 if(!SuspendDefers)
2816 return;
2818 if(!VerifyContext(&context))
2819 alcSetError(NULL, ALC_INVALID_CONTEXT);
2820 else
2822 ALCcontext_DeferUpdates(context, DeferAllowPlay);
2823 ALCcontext_DecRef(context);
2827 /* alcProcessContext
2829 * Resumes processing updates for the given context
2831 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2833 if(!SuspendDefers)
2834 return;
2836 if(!VerifyContext(&context))
2837 alcSetError(NULL, ALC_INVALID_CONTEXT);
2838 else
2840 ALCcontext_ProcessUpdates(context);
2841 ALCcontext_DecRef(context);
2846 /* alcGetString
2848 * Returns information about the device, and error strings
2850 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2852 const ALCchar *value = NULL;
2854 switch(param)
2856 case ALC_NO_ERROR:
2857 value = alcNoError;
2858 break;
2860 case ALC_INVALID_ENUM:
2861 value = alcErrInvalidEnum;
2862 break;
2864 case ALC_INVALID_VALUE:
2865 value = alcErrInvalidValue;
2866 break;
2868 case ALC_INVALID_DEVICE:
2869 value = alcErrInvalidDevice;
2870 break;
2872 case ALC_INVALID_CONTEXT:
2873 value = alcErrInvalidContext;
2874 break;
2876 case ALC_OUT_OF_MEMORY:
2877 value = alcErrOutOfMemory;
2878 break;
2880 case ALC_DEVICE_SPECIFIER:
2881 value = alcDefaultName;
2882 break;
2884 case ALC_ALL_DEVICES_SPECIFIER:
2885 if(VerifyDevice(&Device))
2887 value = al_string_get_cstr(Device->DeviceName);
2888 ALCdevice_DecRef(Device);
2890 else
2892 ProbeAllDevicesList();
2893 value = al_string_get_cstr(alcAllDevicesList);
2895 break;
2897 case ALC_CAPTURE_DEVICE_SPECIFIER:
2898 if(VerifyDevice(&Device))
2900 value = al_string_get_cstr(Device->DeviceName);
2901 ALCdevice_DecRef(Device);
2903 else
2905 ProbeCaptureDeviceList();
2906 value = al_string_get_cstr(alcCaptureDeviceList);
2908 break;
2910 /* Default devices are always first in the list */
2911 case ALC_DEFAULT_DEVICE_SPECIFIER:
2912 value = alcDefaultName;
2913 break;
2915 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2916 if(al_string_empty(alcAllDevicesList))
2917 ProbeAllDevicesList();
2919 VerifyDevice(&Device);
2921 free(alcDefaultAllDevicesSpecifier);
2922 alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2923 if(!alcDefaultAllDevicesSpecifier)
2924 alcSetError(Device, ALC_OUT_OF_MEMORY);
2926 value = alcDefaultAllDevicesSpecifier;
2927 if(Device) ALCdevice_DecRef(Device);
2928 break;
2930 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2931 if(al_string_empty(alcCaptureDeviceList))
2932 ProbeCaptureDeviceList();
2934 VerifyDevice(&Device);
2936 free(alcCaptureDefaultDeviceSpecifier);
2937 alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcCaptureDeviceList));
2938 if(!alcCaptureDefaultDeviceSpecifier)
2939 alcSetError(Device, ALC_OUT_OF_MEMORY);
2941 value = alcCaptureDefaultDeviceSpecifier;
2942 if(Device) ALCdevice_DecRef(Device);
2943 break;
2945 case ALC_EXTENSIONS:
2946 if(!VerifyDevice(&Device))
2947 value = alcNoDeviceExtList;
2948 else
2950 value = alcExtensionList;
2951 ALCdevice_DecRef(Device);
2953 break;
2955 case ALC_HRTF_SPECIFIER_SOFT:
2956 if(!VerifyDevice(&Device))
2957 alcSetError(NULL, ALC_INVALID_DEVICE);
2958 else
2960 almtx_lock(&Device->BackendLock);
2961 value = (Device->HrtfHandle ? al_string_get_cstr(Device->HrtfName) : "");
2962 almtx_unlock(&Device->BackendLock);
2963 ALCdevice_DecRef(Device);
2965 break;
2967 default:
2968 VerifyDevice(&Device);
2969 alcSetError(Device, ALC_INVALID_ENUM);
2970 if(Device) ALCdevice_DecRef(Device);
2971 break;
2974 return value;
2978 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
2980 if(device->Type == Loopback && device->FmtChans >= DevFmtAmbi1 &&
2981 device->FmtChans <= DevFmtAmbi3)
2982 return 23;
2983 return 17;
2986 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2988 ALCsizei i;
2990 if(size <= 0 || values == NULL)
2992 alcSetError(device, ALC_INVALID_VALUE);
2993 return 0;
2996 if(!device)
2998 switch(param)
3000 case ALC_MAJOR_VERSION:
3001 values[0] = alcMajorVersion;
3002 return 1;
3003 case ALC_MINOR_VERSION:
3004 values[0] = alcMinorVersion;
3005 return 1;
3007 case ALC_ATTRIBUTES_SIZE:
3008 case ALC_ALL_ATTRIBUTES:
3009 case ALC_FREQUENCY:
3010 case ALC_REFRESH:
3011 case ALC_SYNC:
3012 case ALC_MONO_SOURCES:
3013 case ALC_STEREO_SOURCES:
3014 case ALC_CAPTURE_SAMPLES:
3015 case ALC_FORMAT_CHANNELS_SOFT:
3016 case ALC_FORMAT_TYPE_SOFT:
3017 case ALC_AMBISONIC_LAYOUT_SOFT:
3018 case ALC_AMBISONIC_SCALING_SOFT:
3019 case ALC_AMBISONIC_ORDER_SOFT:
3020 alcSetError(NULL, ALC_INVALID_DEVICE);
3021 return 0;
3023 default:
3024 alcSetError(NULL, ALC_INVALID_ENUM);
3025 return 0;
3027 return 0;
3030 if(device->Type == Capture)
3032 switch(param)
3034 case ALC_CAPTURE_SAMPLES:
3035 almtx_lock(&device->BackendLock);
3036 values[0] = V0(device->Backend,availableSamples)();
3037 almtx_unlock(&device->BackendLock);
3038 return 1;
3040 case ALC_CONNECTED:
3041 values[0] = device->Connected;
3042 return 1;
3044 default:
3045 alcSetError(device, ALC_INVALID_ENUM);
3046 return 0;
3048 return 0;
3051 /* render device */
3052 switch(param)
3054 case ALC_MAJOR_VERSION:
3055 values[0] = alcMajorVersion;
3056 return 1;
3058 case ALC_MINOR_VERSION:
3059 values[0] = alcMinorVersion;
3060 return 1;
3062 case ALC_EFX_MAJOR_VERSION:
3063 values[0] = alcEFXMajorVersion;
3064 return 1;
3066 case ALC_EFX_MINOR_VERSION:
3067 values[0] = alcEFXMinorVersion;
3068 return 1;
3070 case ALC_ATTRIBUTES_SIZE:
3071 values[0] = NumAttrsForDevice(device);
3072 return 1;
3074 case ALC_ALL_ATTRIBUTES:
3075 if(size < NumAttrsForDevice(device))
3077 alcSetError(device, ALC_INVALID_VALUE);
3078 return 0;
3081 i = 0;
3082 almtx_lock(&device->BackendLock);
3083 values[i++] = ALC_FREQUENCY;
3084 values[i++] = device->Frequency;
3086 if(device->Type != Loopback)
3088 values[i++] = ALC_REFRESH;
3089 values[i++] = device->Frequency / device->UpdateSize;
3091 values[i++] = ALC_SYNC;
3092 values[i++] = ALC_FALSE;
3094 else
3096 if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3)
3098 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3099 values[i++] = ALC_BFORMAT3D_SOFT;
3101 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3102 values[i++] = device->AmbiLayout;
3104 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3105 values[i++] = device->AmbiScale;
3107 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3108 values[i++] = device->FmtChans-DevFmtAmbi1+1;
3110 else
3112 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3113 values[i++] = device->FmtChans;
3116 values[i++] = ALC_FORMAT_TYPE_SOFT;
3117 values[i++] = device->FmtType;
3120 values[i++] = ALC_MONO_SOURCES;
3121 values[i++] = device->NumMonoSources;
3123 values[i++] = ALC_STEREO_SOURCES;
3124 values[i++] = device->NumStereoSources;
3126 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3127 values[i++] = device->NumAuxSends;
3129 values[i++] = ALC_HRTF_SOFT;
3130 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3132 values[i++] = ALC_HRTF_STATUS_SOFT;
3133 values[i++] = device->HrtfStatus;
3134 almtx_unlock(&device->BackendLock);
3136 values[i++] = 0;
3137 return i;
3139 case ALC_FREQUENCY:
3140 values[0] = device->Frequency;
3141 return 1;
3143 case ALC_REFRESH:
3144 if(device->Type == Loopback)
3146 alcSetError(device, ALC_INVALID_DEVICE);
3147 return 0;
3149 almtx_lock(&device->BackendLock);
3150 values[0] = device->Frequency / device->UpdateSize;
3151 almtx_unlock(&device->BackendLock);
3152 return 1;
3154 case ALC_SYNC:
3155 if(device->Type == Loopback)
3157 alcSetError(device, ALC_INVALID_DEVICE);
3158 return 0;
3160 values[0] = ALC_FALSE;
3161 return 1;
3163 case ALC_FORMAT_CHANNELS_SOFT:
3164 if(device->Type != Loopback)
3166 alcSetError(device, ALC_INVALID_DEVICE);
3167 return 0;
3169 if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3)
3170 values[0] = ALC_BFORMAT3D_SOFT;
3171 else
3172 values[0] = device->FmtChans;
3173 return 1;
3175 case ALC_FORMAT_TYPE_SOFT:
3176 if(device->Type != Loopback)
3178 alcSetError(device, ALC_INVALID_DEVICE);
3179 return 0;
3181 values[0] = device->FmtType;
3182 return 1;
3184 case ALC_AMBISONIC_LAYOUT_SOFT:
3185 if(device->Type != Loopback || !(device->FmtChans >= DevFmtAmbi1 &&
3186 device->FmtChans <= DevFmtAmbi3))
3188 alcSetError(device, ALC_INVALID_DEVICE);
3189 return 0;
3191 values[0] = device->AmbiLayout;
3192 return 1;
3194 case ALC_AMBISONIC_SCALING_SOFT:
3195 if(device->Type != Loopback || !(device->FmtChans >= DevFmtAmbi1 &&
3196 device->FmtChans <= DevFmtAmbi3))
3198 alcSetError(device, ALC_INVALID_DEVICE);
3199 return 0;
3201 values[0] = device->AmbiScale;
3202 return 1;
3204 case ALC_AMBISONIC_ORDER_SOFT:
3205 if(device->Type != Loopback || !(device->FmtChans >= DevFmtAmbi1 &&
3206 device->FmtChans <= DevFmtAmbi3))
3208 alcSetError(device, ALC_INVALID_DEVICE);
3209 return 0;
3211 values[0] = device->FmtChans - DevFmtAmbi1 + 1;
3212 return 1;
3214 case ALC_MONO_SOURCES:
3215 values[0] = device->NumMonoSources;
3216 return 1;
3218 case ALC_STEREO_SOURCES:
3219 values[0] = device->NumStereoSources;
3220 return 1;
3222 case ALC_MAX_AUXILIARY_SENDS:
3223 values[0] = device->NumAuxSends;
3224 return 1;
3226 case ALC_CONNECTED:
3227 values[0] = device->Connected;
3228 return 1;
3230 case ALC_HRTF_SOFT:
3231 values[0] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3232 return 1;
3234 case ALC_HRTF_STATUS_SOFT:
3235 values[0] = device->HrtfStatus;
3236 return 1;
3238 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3239 almtx_lock(&device->BackendLock);
3240 FreeHrtfList(&device->HrtfList);
3241 device->HrtfList = EnumerateHrtf(device->DeviceName);
3242 values[0] = (ALCint)VECTOR_SIZE(device->HrtfList);
3243 almtx_unlock(&device->BackendLock);
3244 return 1;
3246 default:
3247 alcSetError(device, ALC_INVALID_ENUM);
3248 return 0;
3250 return 0;
3253 /* alcGetIntegerv
3255 * Returns information about the device and the version of OpenAL
3257 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3259 VerifyDevice(&device);
3260 if(size <= 0 || values == NULL)
3261 alcSetError(device, ALC_INVALID_VALUE);
3262 else
3263 GetIntegerv(device, param, size, values);
3264 if(device) ALCdevice_DecRef(device);
3267 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3269 ALCint *ivals;
3270 ALsizei i;
3272 VerifyDevice(&device);
3273 if(size <= 0 || values == NULL)
3274 alcSetError(device, ALC_INVALID_VALUE);
3275 else if(!device || device->Type == Capture)
3277 ivals = malloc(size * sizeof(ALCint));
3278 size = GetIntegerv(device, pname, size, ivals);
3279 for(i = 0;i < size;i++)
3280 values[i] = ivals[i];
3281 free(ivals);
3283 else /* render device */
3285 ClockLatency clock;
3286 ALuint64 basecount;
3287 ALuint samplecount;
3288 ALuint refcount;
3290 switch(pname)
3292 case ALC_ATTRIBUTES_SIZE:
3293 *values = 21;
3294 break;
3296 case ALC_ALL_ATTRIBUTES:
3297 if(size < 21)
3298 alcSetError(device, ALC_INVALID_VALUE);
3299 else
3301 i = 0;
3302 almtx_lock(&device->BackendLock);
3303 values[i++] = ALC_FREQUENCY;
3304 values[i++] = device->Frequency;
3306 if(device->Type != Loopback)
3308 values[i++] = ALC_REFRESH;
3309 values[i++] = device->Frequency / device->UpdateSize;
3311 values[i++] = ALC_SYNC;
3312 values[i++] = ALC_FALSE;
3314 else
3316 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3317 values[i++] = device->FmtChans;
3319 values[i++] = ALC_FORMAT_TYPE_SOFT;
3320 values[i++] = device->FmtType;
3323 values[i++] = ALC_MONO_SOURCES;
3324 values[i++] = device->NumMonoSources;
3326 values[i++] = ALC_STEREO_SOURCES;
3327 values[i++] = device->NumStereoSources;
3329 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3330 values[i++] = device->NumAuxSends;
3332 values[i++] = ALC_HRTF_SOFT;
3333 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3335 values[i++] = ALC_HRTF_STATUS_SOFT;
3336 values[i++] = device->HrtfStatus;
3338 clock = V0(device->Backend,getClockLatency)();
3339 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3340 values[i++] = clock.ClockTime;
3342 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3343 values[i++] = clock.Latency;
3344 almtx_unlock(&device->BackendLock);
3346 values[i++] = 0;
3348 break;
3350 case ALC_DEVICE_CLOCK_SOFT:
3351 almtx_lock(&device->BackendLock);
3352 do {
3353 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3354 althrd_yield();
3355 basecount = device->ClockBase;
3356 samplecount = device->SamplesDone;
3357 } while(refcount != ReadRef(&device->MixCount));
3358 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3359 almtx_unlock(&device->BackendLock);
3360 break;
3362 case ALC_DEVICE_LATENCY_SOFT:
3364 almtx_lock(&device->BackendLock);
3365 clock = V0(device->Backend,getClockLatency)();
3366 almtx_unlock(&device->BackendLock);
3367 *values = clock.Latency;
3369 break;
3371 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3372 if(size < 2)
3373 alcSetError(device, ALC_INVALID_VALUE);
3374 else
3376 ClockLatency clock;
3377 almtx_lock(&device->BackendLock);
3378 clock = V0(device->Backend,getClockLatency)();
3379 almtx_unlock(&device->BackendLock);
3380 values[0] = clock.ClockTime;
3381 values[1] = clock.Latency;
3383 break;
3385 default:
3386 ivals = malloc(size * sizeof(ALCint));
3387 size = GetIntegerv(device, pname, size, ivals);
3388 for(i = 0;i < size;i++)
3389 values[i] = ivals[i];
3390 free(ivals);
3391 break;
3394 if(device)
3395 ALCdevice_DecRef(device);
3399 /* alcIsExtensionPresent
3401 * Determines if there is support for a particular extension
3403 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3405 ALCboolean bResult = ALC_FALSE;
3407 VerifyDevice(&device);
3409 if(!extName)
3410 alcSetError(device, ALC_INVALID_VALUE);
3411 else
3413 size_t len = strlen(extName);
3414 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3415 while(ptr && *ptr)
3417 if(strncasecmp(ptr, extName, len) == 0 &&
3418 (ptr[len] == '\0' || isspace(ptr[len])))
3420 bResult = ALC_TRUE;
3421 break;
3423 if((ptr=strchr(ptr, ' ')) != NULL)
3425 do {
3426 ++ptr;
3427 } while(isspace(*ptr));
3431 if(device)
3432 ALCdevice_DecRef(device);
3433 return bResult;
3437 /* alcGetProcAddress
3439 * Retrieves the function address for a particular extension function
3441 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3443 ALCvoid *ptr = NULL;
3445 if(!funcName)
3447 VerifyDevice(&device);
3448 alcSetError(device, ALC_INVALID_VALUE);
3449 if(device) ALCdevice_DecRef(device);
3451 else
3453 size_t i = 0;
3454 for(i = 0;i < COUNTOF(alcFunctions);i++)
3456 if(strcmp(alcFunctions[i].funcName, funcName) == 0)
3458 ptr = alcFunctions[i].address;
3459 break;
3464 return ptr;
3468 /* alcGetEnumValue
3470 * Get the value for a particular ALC enumeration name
3472 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3474 ALCenum val = 0;
3476 if(!enumName)
3478 VerifyDevice(&device);
3479 alcSetError(device, ALC_INVALID_VALUE);
3480 if(device) ALCdevice_DecRef(device);
3482 else
3484 size_t i = 0;
3485 for(i = 0;i < COUNTOF(alcEnumerations);i++)
3487 if(strcmp(alcEnumerations[i].enumName, enumName) == 0)
3489 val = alcEnumerations[i].value;
3490 break;
3495 return val;
3499 /* alcCreateContext
3501 * Create and attach a context to the given device.
3503 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3505 ALCcontext *ALContext;
3506 ALfloat valf;
3507 ALCenum err;
3509 LockLists();
3510 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
3512 UnlockLists();
3513 alcSetError(device, ALC_INVALID_DEVICE);
3514 if(device) ALCdevice_DecRef(device);
3515 return NULL;
3517 almtx_lock(&device->BackendLock);
3518 UnlockLists();
3520 ATOMIC_STORE_SEQ(&device->LastError, ALC_NO_ERROR);
3522 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3523 if(ALContext)
3525 InitRef(&ALContext->ref, 1);
3526 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3528 ALContext->Device = device;
3529 ATOMIC_INIT(&ALContext->ActiveAuxSlotList, NULL);
3531 ALContext->Voices = NULL;
3532 ALContext->MaxVoices = 0;
3533 ALContext->VoiceCount = 0;
3534 AllocateVoices(ALContext, 256, device->NumAuxSends);
3536 if(!ALContext || !ALContext->Voices)
3538 almtx_unlock(&device->BackendLock);
3540 if(ALContext)
3542 al_free(ALContext->Voices);
3543 ALContext->Voices = NULL;
3545 al_free(ALContext);
3546 ALContext = NULL;
3549 alcSetError(device, ALC_OUT_OF_MEMORY);
3550 ALCdevice_DecRef(device);
3551 return NULL;
3554 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3556 almtx_unlock(&device->BackendLock);
3558 al_free(ALContext->Voices);
3559 ALContext->Voices = NULL;
3561 al_free(ALContext);
3562 ALContext = NULL;
3564 alcSetError(device, err);
3565 if(err == ALC_INVALID_DEVICE)
3567 V0(device->Backend,lock)();
3568 aluHandleDisconnect(device);
3569 V0(device->Backend,unlock)();
3571 ALCdevice_DecRef(device);
3572 return NULL;
3575 ALCdevice_IncRef(ALContext->Device);
3576 InitContext(ALContext);
3578 if(ConfigValueFloat(al_string_get_cstr(device->DeviceName), NULL, "volume-adjust", &valf))
3580 if(!isfinite(valf))
3581 ERR("volume-adjust must be finite: %f\n", valf);
3582 else
3584 ALfloat db = clampf(valf, -24.0f, 24.0f);
3585 if(db != valf)
3586 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3587 ALContext->GainBoost = powf(10.0f, db/20.0f);
3588 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3591 UpdateListenerProps(ALContext);
3594 ALCcontext *head = ATOMIC_LOAD_SEQ(&device->ContextList);
3595 do {
3596 ALContext->next = head;
3597 } while(ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCcontext*,
3598 &device->ContextList, &head, ALContext) == 0);
3600 almtx_unlock(&device->BackendLock);
3602 ALCdevice_DecRef(device);
3604 TRACE("Created context %p\n", ALContext);
3605 return ALContext;
3608 /* alcDestroyContext
3610 * Remove a context from its device
3612 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3614 ALCdevice *Device;
3616 LockLists();
3617 /* alcGetContextsDevice sets an error for invalid contexts */
3618 Device = alcGetContextsDevice(context);
3619 if(Device)
3621 almtx_lock(&Device->BackendLock);
3622 ReleaseContext(context, Device);
3623 if(!ATOMIC_LOAD_SEQ(&Device->ContextList))
3625 V0(Device->Backend,stop)();
3626 Device->Flags &= ~DEVICE_RUNNING;
3628 almtx_unlock(&Device->BackendLock);
3630 UnlockLists();
3634 /* alcGetCurrentContext
3636 * Returns the currently active context on the calling thread
3638 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3640 ALCcontext *Context = altss_get(LocalContext);
3641 if(!Context) Context = ATOMIC_LOAD_SEQ(&GlobalContext);
3642 return Context;
3645 /* alcGetThreadContext
3647 * Returns the currently active thread-local context
3649 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3651 return altss_get(LocalContext);
3655 /* alcMakeContextCurrent
3657 * Makes the given context the active process-wide context, and removes the
3658 * thread-local context for the calling thread.
3660 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3662 /* context must be valid or NULL */
3663 if(context && !VerifyContext(&context))
3665 alcSetError(NULL, ALC_INVALID_CONTEXT);
3666 return ALC_FALSE;
3668 /* context's reference count is already incremented */
3669 context = ATOMIC_EXCHANGE_SEQ(ALCcontext*, &GlobalContext, context);
3670 if(context) ALCcontext_DecRef(context);
3672 if((context=altss_get(LocalContext)) != NULL)
3674 altss_set(LocalContext, NULL);
3675 ALCcontext_DecRef(context);
3678 return ALC_TRUE;
3681 /* alcSetThreadContext
3683 * Makes the given context the active context for the current thread
3685 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3687 ALCcontext *old;
3689 /* context must be valid or NULL */
3690 if(context && !VerifyContext(&context))
3692 alcSetError(NULL, ALC_INVALID_CONTEXT);
3693 return ALC_FALSE;
3695 /* context's reference count is already incremented */
3696 old = altss_get(LocalContext);
3697 altss_set(LocalContext, context);
3698 if(old) ALCcontext_DecRef(old);
3700 return ALC_TRUE;
3704 /* alcGetContextsDevice
3706 * Returns the device that a particular context is attached to
3708 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3710 ALCdevice *Device;
3712 if(!VerifyContext(&Context))
3714 alcSetError(NULL, ALC_INVALID_CONTEXT);
3715 return NULL;
3717 Device = Context->Device;
3718 ALCcontext_DecRef(Context);
3720 return Device;
3724 /* alcOpenDevice
3726 * Opens the named device.
3728 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3730 const ALCchar *fmt;
3731 ALCdevice *device;
3732 ALCenum err;
3733 ALCsizei i;
3735 DO_INITCONFIG();
3737 if(!PlaybackBackend.name)
3739 alcSetError(NULL, ALC_INVALID_VALUE);
3740 return NULL;
3743 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
3744 #ifdef _WIN32
3745 /* Some old Windows apps hardcode these expecting OpenAL to use a
3746 * specific audio API, even when they're not enumerated. Creative's
3747 * router effectively ignores them too.
3749 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
3750 || strcasecmp(deviceName, "MMSYSTEM") == 0
3751 #endif
3753 deviceName = NULL;
3755 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3756 if(!device)
3758 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3759 return NULL;
3762 //Validate device
3763 InitRef(&device->ref, 1);
3764 device->Connected = ALC_TRUE;
3765 device->Type = Playback;
3766 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3768 device->Flags = 0;
3769 device->Bs2b = NULL;
3770 device->Uhj_Encoder = NULL;
3771 device->Hrtf = NULL;
3772 VECTOR_INIT(device->HrtfList);
3773 AL_STRING_INIT(device->HrtfName);
3774 device->Render_Mode = NormalRender;
3775 AL_STRING_INIT(device->DeviceName);
3776 device->Dry.Buffer = NULL;
3777 device->Dry.NumChannels = 0;
3778 device->FOAOut.Buffer = NULL;
3779 device->FOAOut.NumChannels = 0;
3780 device->RealOut.Buffer = NULL;
3781 device->RealOut.NumChannels = 0;
3782 device->AvgSpeakerDist = 0.0f;
3784 ATOMIC_INIT(&device->ContextList, NULL);
3786 device->ClockBase = 0;
3787 device->SamplesDone = 0;
3789 device->SourcesMax = 256;
3790 device->AuxiliaryEffectSlotMax = 64;
3791 device->NumAuxSends = DEFAULT_SENDS;
3793 InitUIntMap(&device->BufferMap, ~0);
3794 InitUIntMap(&device->EffectMap, ~0);
3795 InitUIntMap(&device->FilterMap, ~0);
3797 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
3799 device->ChannelDelay[i].Gain = 1.0f;
3800 device->ChannelDelay[i].Length = 0;
3801 device->ChannelDelay[i].Buffer = NULL;
3804 //Set output format
3805 device->FmtChans = DevFmtChannelsDefault;
3806 device->FmtType = DevFmtTypeDefault;
3807 device->Frequency = DEFAULT_OUTPUT_RATE;
3808 device->IsHeadphones = AL_FALSE;
3809 device->AmbiLayout = AmbiLayout_Default;
3810 device->AmbiScale = AmbiNorm_Default;
3811 device->NumUpdates = 3;
3812 device->UpdateSize = 1024;
3814 if(!PlaybackBackend.getFactory)
3815 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3816 ALCbackend_Playback);
3817 else
3819 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3820 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3822 if(!device->Backend)
3824 al_free(device);
3825 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3826 return NULL;
3830 if(ConfigValueStr(deviceName, NULL, "channels", &fmt))
3832 static const struct {
3833 const char name[16];
3834 enum DevFmtChannels chans;
3835 } chanlist[] = {
3836 { "mono", DevFmtMono },
3837 { "stereo", DevFmtStereo },
3838 { "quad", DevFmtQuad },
3839 { "surround51", DevFmtX51 },
3840 { "surround61", DevFmtX61 },
3841 { "surround71", DevFmtX71 },
3842 { "surround51rear", DevFmtX51Rear },
3843 { "ambi1", DevFmtAmbi1 },
3844 { "ambi2", DevFmtAmbi2 },
3845 { "ambi3", DevFmtAmbi3 },
3847 size_t i;
3849 for(i = 0;i < COUNTOF(chanlist);i++)
3851 if(strcasecmp(chanlist[i].name, fmt) == 0)
3853 device->FmtChans = chanlist[i].chans;
3854 device->Flags |= DEVICE_CHANNELS_REQUEST;
3855 break;
3858 if(i == COUNTOF(chanlist))
3859 ERR("Unsupported channels: %s\n", fmt);
3861 if(ConfigValueStr(deviceName, NULL, "sample-type", &fmt))
3863 static const struct {
3864 const char name[16];
3865 enum DevFmtType type;
3866 } typelist[] = {
3867 { "int8", DevFmtByte },
3868 { "uint8", DevFmtUByte },
3869 { "int16", DevFmtShort },
3870 { "uint16", DevFmtUShort },
3871 { "int32", DevFmtInt },
3872 { "uint32", DevFmtUInt },
3873 { "float32", DevFmtFloat },
3875 size_t i;
3877 for(i = 0;i < COUNTOF(typelist);i++)
3879 if(strcasecmp(typelist[i].name, fmt) == 0)
3881 device->FmtType = typelist[i].type;
3882 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3883 break;
3886 if(i == COUNTOF(typelist))
3887 ERR("Unsupported sample-type: %s\n", fmt);
3890 if(ConfigValueUInt(deviceName, NULL, "frequency", &device->Frequency))
3892 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3893 if(device->Frequency < MIN_OUTPUT_RATE)
3894 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3895 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3898 ConfigValueUInt(deviceName, NULL, "periods", &device->NumUpdates);
3899 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3901 ConfigValueUInt(deviceName, NULL, "period_size", &device->UpdateSize);
3902 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3903 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
3904 device->UpdateSize = (device->UpdateSize+3)&~3;
3906 ConfigValueUInt(deviceName, NULL, "sources", &device->SourcesMax);
3907 if(device->SourcesMax == 0) device->SourcesMax = 256;
3909 ConfigValueUInt(deviceName, NULL, "slots", &device->AuxiliaryEffectSlotMax);
3910 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
3912 if(ConfigValueInt(deviceName, NULL, "sends", &device->NumAuxSends))
3913 device->NumAuxSends = clampi(
3914 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
3917 device->NumStereoSources = 1;
3918 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3920 // Find a playback device to open
3921 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3923 DELETE_OBJ(device->Backend);
3924 al_free(device);
3925 alcSetError(NULL, err);
3926 return NULL;
3928 almtx_init(&device->BackendLock, almtx_plain);
3930 if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt))
3932 if(strcasecmp(fmt, "fuma") == 0)
3934 device->AmbiLayout = AmbiLayout_FuMa;
3935 device->AmbiScale = AmbiNorm_FuMa;
3937 else if(strcasecmp(fmt, "acn+sn3d") == 0)
3939 device->AmbiLayout = AmbiLayout_ACN;
3940 device->AmbiScale = AmbiNorm_SN3D;
3942 else if(strcasecmp(fmt, "acn+n3d") == 0)
3944 device->AmbiLayout = AmbiLayout_ACN;
3945 device->AmbiScale = AmbiNorm_N3D;
3947 else
3948 ERR("Unsupported ambi-format: %s\n", fmt);
3951 if(DefaultEffect.type != AL_EFFECT_NULL)
3953 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3954 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3956 device->DefaultSlot = NULL;
3957 ERR("Failed to initialize the default effect slot\n");
3959 else
3961 aluInitEffectPanning(device->DefaultSlot);
3962 if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3964 DeinitEffectSlot(device->DefaultSlot);
3965 device->DefaultSlot = NULL;
3966 ERR("Failed to initialize the default effect\n");
3972 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
3973 do {
3974 device->next = head;
3975 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device));
3978 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3979 return device;
3982 /* alcCloseDevice
3984 * Closes the given device.
3986 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3988 ALCdevice *iter, *origdev;
3989 ALCcontext *ctx;
3991 LockLists();
3992 iter = ATOMIC_LOAD_SEQ(&DeviceList);
3993 do {
3994 if(iter == device)
3995 break;
3996 } while((iter=iter->next) != NULL);
3997 if(!iter || iter->Type == Capture)
3999 alcSetError(iter, ALC_INVALID_DEVICE);
4000 UnlockLists();
4001 return ALC_FALSE;
4003 almtx_lock(&device->BackendLock);
4005 origdev = device;
4006 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice*, &DeviceList, &origdev, device->next))
4008 ALCdevice *volatile*list = &origdev->next;
4009 while(*list)
4011 if(*list == device)
4013 *list = (*list)->next;
4014 break;
4016 list = &(*list)->next;
4019 UnlockLists();
4021 ctx = ATOMIC_LOAD_SEQ(&device->ContextList);
4022 while(ctx != NULL)
4024 ALCcontext *next = ctx->next;
4025 WARN("Releasing context %p\n", ctx);
4026 ReleaseContext(ctx, device);
4027 ctx = next;
4029 if((device->Flags&DEVICE_RUNNING))
4030 V0(device->Backend,stop)();
4031 device->Flags &= ~DEVICE_RUNNING;
4032 almtx_unlock(&device->BackendLock);
4034 ALCdevice_DecRef(device);
4036 return ALC_TRUE;
4040 /************************************************
4041 * ALC capture functions
4042 ************************************************/
4043 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
4045 ALCdevice *device = NULL;
4046 ALCenum err;
4047 ALCsizei i;
4049 DO_INITCONFIG();
4051 if(!CaptureBackend.name)
4053 alcSetError(NULL, ALC_INVALID_VALUE);
4054 return NULL;
4057 if(samples <= 0)
4059 alcSetError(NULL, ALC_INVALID_VALUE);
4060 return NULL;
4063 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
4064 deviceName = NULL;
4066 device = al_calloc(16, sizeof(ALCdevice));
4067 if(!device)
4069 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4070 return NULL;
4073 //Validate device
4074 InitRef(&device->ref, 1);
4075 device->Connected = ALC_TRUE;
4076 device->Type = Capture;
4078 device->Hrtf = NULL;
4079 VECTOR_INIT(device->HrtfList);
4080 AL_STRING_INIT(device->HrtfName);
4082 AL_STRING_INIT(device->DeviceName);
4083 device->Dry.Buffer = NULL;
4084 device->Dry.NumChannels = 0;
4085 device->FOAOut.Buffer = NULL;
4086 device->FOAOut.NumChannels = 0;
4087 device->RealOut.Buffer = NULL;
4088 device->RealOut.NumChannels = 0;
4090 InitUIntMap(&device->BufferMap, ~0);
4091 InitUIntMap(&device->EffectMap, ~0);
4092 InitUIntMap(&device->FilterMap, ~0);
4094 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
4096 device->ChannelDelay[i].Gain = 1.0f;
4097 device->ChannelDelay[i].Length = 0;
4098 device->ChannelDelay[i].Buffer = NULL;
4101 if(!CaptureBackend.getFactory)
4102 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
4103 ALCbackend_Capture);
4104 else
4106 ALCbackendFactory *factory = CaptureBackend.getFactory();
4107 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
4109 if(!device->Backend)
4111 al_free(device);
4112 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4113 return NULL;
4116 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4117 device->Frequency = frequency;
4119 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
4120 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
4122 al_free(device);
4123 alcSetError(NULL, ALC_INVALID_ENUM);
4124 return NULL;
4126 device->IsHeadphones = AL_FALSE;
4127 device->AmbiLayout = AmbiLayout_Default;
4128 device->AmbiScale = AmbiNorm_Default;
4130 device->UpdateSize = samples;
4131 device->NumUpdates = 1;
4133 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4135 al_free(device);
4136 alcSetError(NULL, err);
4137 return NULL;
4139 almtx_init(&device->BackendLock, almtx_plain);
4142 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4143 do {
4144 device->next = head;
4145 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device));
4148 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
4149 return device;
4152 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
4154 ALCdevice *iter, *origdev;
4156 LockLists();
4157 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4158 do {
4159 if(iter == device)
4160 break;
4161 } while((iter=iter->next) != NULL);
4162 if(!iter || iter->Type != Capture)
4164 alcSetError(iter, ALC_INVALID_DEVICE);
4165 UnlockLists();
4166 return ALC_FALSE;
4169 origdev = device;
4170 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice*, &DeviceList, &origdev, device->next))
4172 ALCdevice *volatile*list = &origdev->next;
4173 while(*list)
4175 if(*list == device)
4177 *list = (*list)->next;
4178 break;
4180 list = &(*list)->next;
4183 UnlockLists();
4185 ALCdevice_DecRef(device);
4187 return ALC_TRUE;
4190 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
4192 if(!VerifyDevice(&device) || device->Type != Capture)
4193 alcSetError(device, ALC_INVALID_DEVICE);
4194 else
4196 almtx_lock(&device->BackendLock);
4197 if(!device->Connected)
4198 alcSetError(device, ALC_INVALID_DEVICE);
4199 else if(!(device->Flags&DEVICE_RUNNING))
4201 if(V0(device->Backend,start)())
4202 device->Flags |= DEVICE_RUNNING;
4203 else
4205 aluHandleDisconnect(device);
4206 alcSetError(device, ALC_INVALID_DEVICE);
4209 almtx_unlock(&device->BackendLock);
4212 if(device) ALCdevice_DecRef(device);
4215 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
4217 if(!VerifyDevice(&device) || device->Type != Capture)
4218 alcSetError(device, ALC_INVALID_DEVICE);
4219 else
4221 almtx_lock(&device->BackendLock);
4222 if((device->Flags&DEVICE_RUNNING))
4223 V0(device->Backend,stop)();
4224 device->Flags &= ~DEVICE_RUNNING;
4225 almtx_unlock(&device->BackendLock);
4228 if(device) ALCdevice_DecRef(device);
4231 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4233 if(!VerifyDevice(&device) || device->Type != Capture)
4234 alcSetError(device, ALC_INVALID_DEVICE);
4235 else
4237 ALCenum err = ALC_INVALID_VALUE;
4239 almtx_lock(&device->BackendLock);
4240 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
4241 err = V(device->Backend,captureSamples)(buffer, samples);
4242 almtx_unlock(&device->BackendLock);
4244 if(err != ALC_NO_ERROR)
4245 alcSetError(device, err);
4247 if(device) ALCdevice_DecRef(device);
4251 /************************************************
4252 * ALC loopback functions
4253 ************************************************/
4255 /* alcLoopbackOpenDeviceSOFT
4257 * Open a loopback device, for manual rendering.
4259 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
4261 ALCbackendFactory *factory;
4262 ALCdevice *device;
4263 ALCsizei i;
4265 DO_INITCONFIG();
4267 /* Make sure the device name, if specified, is us. */
4268 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
4270 alcSetError(NULL, ALC_INVALID_VALUE);
4271 return NULL;
4274 device = al_calloc(16, sizeof(ALCdevice));
4275 if(!device)
4277 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4278 return NULL;
4281 //Validate device
4282 InitRef(&device->ref, 1);
4283 device->Connected = ALC_TRUE;
4284 device->Type = Loopback;
4285 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
4287 device->Flags = 0;
4288 device->Hrtf = NULL;
4289 VECTOR_INIT(device->HrtfList);
4290 AL_STRING_INIT(device->HrtfName);
4291 device->Bs2b = NULL;
4292 device->Uhj_Encoder = NULL;
4293 device->Render_Mode = NormalRender;
4294 AL_STRING_INIT(device->DeviceName);
4295 device->Dry.Buffer = NULL;
4296 device->Dry.NumChannels = 0;
4297 device->FOAOut.Buffer = NULL;
4298 device->FOAOut.NumChannels = 0;
4299 device->RealOut.Buffer = NULL;
4300 device->RealOut.NumChannels = 0;
4301 device->AvgSpeakerDist = 0.0f;
4303 ATOMIC_INIT(&device->ContextList, NULL);
4305 device->ClockBase = 0;
4306 device->SamplesDone = 0;
4308 device->SourcesMax = 256;
4309 device->AuxiliaryEffectSlotMax = 64;
4310 device->NumAuxSends = DEFAULT_SENDS;
4312 InitUIntMap(&device->BufferMap, ~0);
4313 InitUIntMap(&device->EffectMap, ~0);
4314 InitUIntMap(&device->FilterMap, ~0);
4316 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
4318 device->ChannelDelay[i].Gain = 1.0f;
4319 device->ChannelDelay[i].Length = 0;
4320 device->ChannelDelay[i].Buffer = NULL;
4323 factory = ALCloopbackFactory_getFactory();
4324 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
4325 if(!device->Backend)
4327 al_free(device);
4328 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4329 return NULL;
4331 almtx_init(&device->BackendLock, almtx_plain);
4333 //Set output format
4334 device->NumUpdates = 0;
4335 device->UpdateSize = 0;
4337 device->Frequency = DEFAULT_OUTPUT_RATE;
4338 device->FmtChans = DevFmtChannelsDefault;
4339 device->FmtType = DevFmtTypeDefault;
4340 device->IsHeadphones = AL_FALSE;
4341 device->AmbiLayout = AmbiLayout_Default;
4342 device->AmbiScale = AmbiNorm_Default;
4344 ConfigValueUInt(NULL, NULL, "sources", &device->SourcesMax);
4345 if(device->SourcesMax == 0) device->SourcesMax = 256;
4347 ConfigValueUInt(NULL, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4348 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4350 if(ConfigValueInt(NULL, NULL, "sends", &device->NumAuxSends))
4351 device->NumAuxSends = clampi(
4352 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4355 device->NumStereoSources = 1;
4356 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4358 // Open the "backend"
4359 V(device->Backend,open)("Loopback");
4362 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4363 do {
4364 device->next = head;
4365 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device));
4368 TRACE("Created device %p\n", device);
4369 return device;
4372 /* alcIsRenderFormatSupportedSOFT
4374 * Determines if the loopback device supports the given format for rendering.
4376 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4378 ALCboolean ret = ALC_FALSE;
4380 if(!VerifyDevice(&device) || device->Type != Loopback)
4381 alcSetError(device, ALC_INVALID_DEVICE);
4382 else if(freq <= 0)
4383 alcSetError(device, ALC_INVALID_VALUE);
4384 else
4386 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4387 ret = ALC_TRUE;
4389 if(device) ALCdevice_DecRef(device);
4391 return ret;
4394 /* alcRenderSamplesSOFT
4396 * Renders some samples into a buffer, using the format last set by the
4397 * attributes given to alcCreateContext.
4399 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4401 if(!VerifyDevice(&device) || device->Type != Loopback)
4402 alcSetError(device, ALC_INVALID_DEVICE);
4403 else if(samples < 0 || (samples > 0 && buffer == NULL))
4404 alcSetError(device, ALC_INVALID_VALUE);
4405 else
4407 V0(device->Backend,lock)();
4408 aluMixData(device, buffer, samples);
4409 V0(device->Backend,unlock)();
4411 if(device) ALCdevice_DecRef(device);
4415 /************************************************
4416 * ALC loopback2 functions
4417 ************************************************/
4419 ALC_API ALCboolean ALC_APIENTRY alcIsAmbisonicFormatSupportedSOFT(ALCdevice *device, ALCenum layout, ALCenum scaling, ALsizei order)
4421 ALCboolean ret = ALC_FALSE;
4423 if(!VerifyDevice(&device) || device->Type != Loopback)
4424 alcSetError(device, ALC_INVALID_DEVICE);
4425 else if(order <= 0)
4426 alcSetError(device, ALC_INVALID_VALUE);
4427 else
4429 if(IsValidAmbiLayout(layout) && IsValidAmbiScaling(scaling) && order <= MAX_AMBI_ORDER)
4430 ret = ALC_TRUE;
4432 if(device) ALCdevice_DecRef(device);
4434 return ret;
4437 /************************************************
4438 * ALC DSP pause/resume functions
4439 ************************************************/
4441 /* alcDevicePauseSOFT
4443 * Pause the DSP to stop audio processing.
4445 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4447 if(!VerifyDevice(&device) || device->Type != Playback)
4448 alcSetError(device, ALC_INVALID_DEVICE);
4449 else
4451 almtx_lock(&device->BackendLock);
4452 if((device->Flags&DEVICE_RUNNING))
4453 V0(device->Backend,stop)();
4454 device->Flags &= ~DEVICE_RUNNING;
4455 device->Flags |= DEVICE_PAUSED;
4456 almtx_unlock(&device->BackendLock);
4458 if(device) ALCdevice_DecRef(device);
4461 /* alcDeviceResumeSOFT
4463 * Resume the DSP to restart audio processing.
4465 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4467 if(!VerifyDevice(&device) || device->Type != Playback)
4468 alcSetError(device, ALC_INVALID_DEVICE);
4469 else
4471 almtx_lock(&device->BackendLock);
4472 if((device->Flags&DEVICE_PAUSED))
4474 device->Flags &= ~DEVICE_PAUSED;
4475 if(ATOMIC_LOAD_SEQ(&device->ContextList) != NULL)
4477 if(V0(device->Backend,start)() != ALC_FALSE)
4478 device->Flags |= DEVICE_RUNNING;
4479 else
4481 alcSetError(device, ALC_INVALID_DEVICE);
4482 V0(device->Backend,lock)();
4483 aluHandleDisconnect(device);
4484 V0(device->Backend,unlock)();
4488 almtx_unlock(&device->BackendLock);
4490 if(device) ALCdevice_DecRef(device);
4494 /************************************************
4495 * ALC HRTF functions
4496 ************************************************/
4498 /* alcGetStringiSOFT
4500 * Gets a string parameter at the given index.
4502 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4504 const ALCchar *str = NULL;
4506 if(!VerifyDevice(&device) || device->Type == Capture)
4507 alcSetError(device, ALC_INVALID_DEVICE);
4508 else switch(paramName)
4510 case ALC_HRTF_SPECIFIER_SOFT:
4511 if(index >= 0 && (size_t)index < VECTOR_SIZE(device->HrtfList))
4512 str = al_string_get_cstr(VECTOR_ELEM(device->HrtfList, index).name);
4513 else
4514 alcSetError(device, ALC_INVALID_VALUE);
4515 break;
4517 default:
4518 alcSetError(device, ALC_INVALID_ENUM);
4519 break;
4521 if(device) ALCdevice_DecRef(device);
4523 return str;
4526 /* alcResetDeviceSOFT
4528 * Resets the given device output, using the specified attribute list.
4530 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4532 ALCenum err;
4534 LockLists();
4535 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
4537 UnlockLists();
4538 alcSetError(device, ALC_INVALID_DEVICE);
4539 if(device) ALCdevice_DecRef(device);
4540 return ALC_FALSE;
4542 almtx_lock(&device->BackendLock);
4543 UnlockLists();
4545 err = UpdateDeviceParams(device, attribs);
4546 almtx_unlock(&device->BackendLock);
4548 if(err != ALC_NO_ERROR)
4550 alcSetError(device, err);
4551 if(err == ALC_INVALID_DEVICE)
4553 V0(device->Backend,lock)();
4554 aluHandleDisconnect(device);
4555 V0(device->Backend,unlock)();
4557 ALCdevice_DecRef(device);
4558 return ALC_FALSE;
4560 ALCdevice_DecRef(device);
4562 return ALC_TRUE;