2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
37 #include "alAuxEffectSlot.h"
43 /************************************************
45 ************************************************/
46 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
47 static struct BackendInfo BackendList
[] = {
48 #ifdef HAVE_PULSEAUDIO
49 { "pulse", alc_pulse_init
, alc_pulse_deinit
, alc_pulse_probe
, EmptyFuncs
},
52 { "alsa", alc_alsa_init
, alc_alsa_deinit
, alc_alsa_probe
, EmptyFuncs
},
55 { "core", alc_ca_init
, alc_ca_deinit
, alc_ca_probe
, EmptyFuncs
},
58 { "oss", alc_oss_init
, alc_oss_deinit
, alc_oss_probe
, EmptyFuncs
},
61 { "solaris", alc_solaris_init
, alc_solaris_deinit
, alc_solaris_probe
, EmptyFuncs
},
64 { "sndio", alc_sndio_init
, alc_sndio_deinit
, alc_sndio_probe
, EmptyFuncs
},
67 { "mmdevapi", alcMMDevApiInit
, alcMMDevApiDeinit
, alcMMDevApiProbe
, EmptyFuncs
},
70 { "dsound", alcDSoundInit
, alcDSoundDeinit
, alcDSoundProbe
, EmptyFuncs
},
73 { "winmm", alcWinMMInit
, alcWinMMDeinit
, alcWinMMProbe
, EmptyFuncs
},
76 { "port", alc_pa_init
, alc_pa_deinit
, alc_pa_probe
, EmptyFuncs
},
79 { "opensl", alc_opensl_init
, alc_opensl_deinit
, alc_opensl_probe
, EmptyFuncs
},
82 { "null", alc_null_init
, alc_null_deinit
, alc_null_probe
, EmptyFuncs
},
84 { "wave", alc_wave_init
, alc_wave_deinit
, alc_wave_probe
, EmptyFuncs
},
87 { NULL
, NULL
, NULL
, NULL
, EmptyFuncs
}
89 static struct BackendInfo BackendLoopback
= {
90 "loopback", alc_loopback_init
, alc_loopback_deinit
, alc_loopback_probe
, EmptyFuncs
94 static struct BackendInfo PlaybackBackend
;
95 static struct BackendInfo CaptureBackend
;
97 /************************************************
98 * Functions, enums, and errors
99 ************************************************/
100 typedef struct ALCfunction
{
101 const ALCchar
*funcName
;
105 typedef struct ALCenums
{
106 const ALCchar
*enumName
;
110 #define DECL(x) { #x, (ALCvoid*)(x) }
111 static const ALCfunction alcFunctions
[] = {
112 DECL(alcCreateContext
),
113 DECL(alcMakeContextCurrent
),
114 DECL(alcProcessContext
),
115 DECL(alcSuspendContext
),
116 DECL(alcDestroyContext
),
117 DECL(alcGetCurrentContext
),
118 DECL(alcGetContextsDevice
),
120 DECL(alcCloseDevice
),
122 DECL(alcIsExtensionPresent
),
123 DECL(alcGetProcAddress
),
124 DECL(alcGetEnumValue
),
126 DECL(alcGetIntegerv
),
127 DECL(alcCaptureOpenDevice
),
128 DECL(alcCaptureCloseDevice
),
129 DECL(alcCaptureStart
),
130 DECL(alcCaptureStop
),
131 DECL(alcCaptureSamples
),
133 DECL(alcSetThreadContext
),
134 DECL(alcGetThreadContext
),
136 DECL(alcLoopbackOpenDeviceSOFT
),
137 DECL(alcIsRenderFormatSupportedSOFT
),
138 DECL(alcRenderSamplesSOFT
),
153 DECL(alIsExtensionPresent
),
154 DECL(alGetProcAddress
),
155 DECL(alGetEnumValue
),
162 DECL(alGetListenerf
),
163 DECL(alGetListener3f
),
164 DECL(alGetListenerfv
),
165 DECL(alGetListeneri
),
166 DECL(alGetListener3i
),
167 DECL(alGetListeneriv
),
169 DECL(alDeleteSources
),
185 DECL(alSourceRewindv
),
186 DECL(alSourcePausev
),
189 DECL(alSourceRewind
),
191 DECL(alSourceQueueBuffers
),
192 DECL(alSourceUnqueueBuffers
),
194 DECL(alDeleteBuffers
),
209 DECL(alDopplerFactor
),
210 DECL(alDopplerVelocity
),
211 DECL(alSpeedOfSound
),
212 DECL(alDistanceModel
),
215 DECL(alDeleteFilters
),
226 DECL(alDeleteEffects
),
236 DECL(alGenAuxiliaryEffectSlots
),
237 DECL(alDeleteAuxiliaryEffectSlots
),
238 DECL(alIsAuxiliaryEffectSlot
),
239 DECL(alAuxiliaryEffectSloti
),
240 DECL(alAuxiliaryEffectSlotiv
),
241 DECL(alAuxiliaryEffectSlotf
),
242 DECL(alAuxiliaryEffectSlotfv
),
243 DECL(alGetAuxiliaryEffectSloti
),
244 DECL(alGetAuxiliaryEffectSlotiv
),
245 DECL(alGetAuxiliaryEffectSlotf
),
246 DECL(alGetAuxiliaryEffectSlotfv
),
248 DECL(alBufferSubDataSOFT
),
250 DECL(alBufferSamplesSOFT
),
251 DECL(alBufferSubSamplesSOFT
),
252 DECL(alGetBufferSamplesSOFT
),
253 DECL(alIsBufferFormatSupportedSOFT
),
255 DECL(alDeferUpdatesSOFT
),
256 DECL(alProcessUpdatesSOFT
),
258 DECL(alGetSourcedSOFT
),
259 DECL(alGetSource3dSOFT
),
260 DECL(alGetSourcedvSOFT
),
261 DECL(alGetSourcei64SOFT
),
262 DECL(alGetSource3i64SOFT
),
263 DECL(alGetSourcei64vSOFT
),
269 #define DECL(x) { #x, (x) }
270 static const ALCenums enumeration
[] = {
275 DECL(ALC_MAJOR_VERSION
),
276 DECL(ALC_MINOR_VERSION
),
277 DECL(ALC_ATTRIBUTES_SIZE
),
278 DECL(ALC_ALL_ATTRIBUTES
),
279 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
280 DECL(ALC_DEVICE_SPECIFIER
),
281 DECL(ALC_ALL_DEVICES_SPECIFIER
),
282 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
283 DECL(ALC_EXTENSIONS
),
287 DECL(ALC_MONO_SOURCES
),
288 DECL(ALC_STEREO_SOURCES
),
289 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
290 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
291 DECL(ALC_CAPTURE_SAMPLES
),
294 DECL(ALC_EFX_MAJOR_VERSION
),
295 DECL(ALC_EFX_MINOR_VERSION
),
296 DECL(ALC_MAX_AUXILIARY_SENDS
),
298 DECL(ALC_FORMAT_CHANNELS_SOFT
),
299 DECL(ALC_FORMAT_TYPE_SOFT
),
302 DECL(ALC_STEREO_SOFT
),
304 DECL(ALC_5POINT1_SOFT
),
305 DECL(ALC_6POINT1_SOFT
),
306 DECL(ALC_7POINT1_SOFT
),
309 DECL(ALC_UNSIGNED_BYTE_SOFT
),
310 DECL(ALC_SHORT_SOFT
),
311 DECL(ALC_UNSIGNED_SHORT_SOFT
),
313 DECL(ALC_UNSIGNED_INT_SOFT
),
314 DECL(ALC_FLOAT_SOFT
),
317 DECL(ALC_INVALID_DEVICE
),
318 DECL(ALC_INVALID_CONTEXT
),
319 DECL(ALC_INVALID_ENUM
),
320 DECL(ALC_INVALID_VALUE
),
321 DECL(ALC_OUT_OF_MEMORY
),
329 DECL(AL_SOURCE_RELATIVE
),
330 DECL(AL_CONE_INNER_ANGLE
),
331 DECL(AL_CONE_OUTER_ANGLE
),
341 DECL(AL_ORIENTATION
),
342 DECL(AL_REFERENCE_DISTANCE
),
343 DECL(AL_ROLLOFF_FACTOR
),
344 DECL(AL_CONE_OUTER_GAIN
),
345 DECL(AL_MAX_DISTANCE
),
347 DECL(AL_SAMPLE_OFFSET
),
348 DECL(AL_SAMPLE_RW_OFFSETS_SOFT
),
349 DECL(AL_BYTE_OFFSET
),
350 DECL(AL_BYTE_RW_OFFSETS_SOFT
),
351 DECL(AL_SOURCE_TYPE
),
354 DECL(AL_UNDETERMINED
),
355 DECL(AL_METERS_PER_UNIT
),
356 DECL(AL_DIRECT_CHANNELS_SOFT
),
358 DECL(AL_DIRECT_FILTER
),
359 DECL(AL_AUXILIARY_SEND_FILTER
),
360 DECL(AL_AIR_ABSORPTION_FACTOR
),
361 DECL(AL_ROOM_ROLLOFF_FACTOR
),
362 DECL(AL_CONE_OUTER_GAINHF
),
363 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
364 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
365 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
367 DECL(AL_SOURCE_STATE
),
373 DECL(AL_BUFFERS_QUEUED
),
374 DECL(AL_BUFFERS_PROCESSED
),
376 DECL(AL_FORMAT_MONO8
),
377 DECL(AL_FORMAT_MONO16
),
378 DECL(AL_FORMAT_MONO_FLOAT32
),
379 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
380 DECL(AL_FORMAT_STEREO8
),
381 DECL(AL_FORMAT_STEREO16
),
382 DECL(AL_FORMAT_STEREO_FLOAT32
),
383 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
384 DECL(AL_FORMAT_MONO_IMA4
),
385 DECL(AL_FORMAT_STEREO_IMA4
),
386 DECL(AL_FORMAT_QUAD8_LOKI
),
387 DECL(AL_FORMAT_QUAD16_LOKI
),
388 DECL(AL_FORMAT_QUAD8
),
389 DECL(AL_FORMAT_QUAD16
),
390 DECL(AL_FORMAT_QUAD32
),
391 DECL(AL_FORMAT_51CHN8
),
392 DECL(AL_FORMAT_51CHN16
),
393 DECL(AL_FORMAT_51CHN32
),
394 DECL(AL_FORMAT_61CHN8
),
395 DECL(AL_FORMAT_61CHN16
),
396 DECL(AL_FORMAT_61CHN32
),
397 DECL(AL_FORMAT_71CHN8
),
398 DECL(AL_FORMAT_71CHN16
),
399 DECL(AL_FORMAT_71CHN32
),
400 DECL(AL_FORMAT_REAR8
),
401 DECL(AL_FORMAT_REAR16
),
402 DECL(AL_FORMAT_REAR32
),
403 DECL(AL_FORMAT_MONO_MULAW
),
404 DECL(AL_FORMAT_MONO_MULAW_EXT
),
405 DECL(AL_FORMAT_STEREO_MULAW
),
406 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
407 DECL(AL_FORMAT_QUAD_MULAW
),
408 DECL(AL_FORMAT_51CHN_MULAW
),
409 DECL(AL_FORMAT_61CHN_MULAW
),
410 DECL(AL_FORMAT_71CHN_MULAW
),
411 DECL(AL_FORMAT_REAR_MULAW
),
412 DECL(AL_FORMAT_MONO_ALAW_EXT
),
413 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
416 DECL(AL_MONO16_SOFT
),
417 DECL(AL_MONO32F_SOFT
),
418 DECL(AL_STEREO8_SOFT
),
419 DECL(AL_STEREO16_SOFT
),
420 DECL(AL_STEREO32F_SOFT
),
422 DECL(AL_QUAD16_SOFT
),
423 DECL(AL_QUAD32F_SOFT
),
425 DECL(AL_REAR16_SOFT
),
426 DECL(AL_REAR32F_SOFT
),
427 DECL(AL_5POINT1_8_SOFT
),
428 DECL(AL_5POINT1_16_SOFT
),
429 DECL(AL_5POINT1_32F_SOFT
),
430 DECL(AL_6POINT1_8_SOFT
),
431 DECL(AL_6POINT1_16_SOFT
),
432 DECL(AL_6POINT1_32F_SOFT
),
433 DECL(AL_7POINT1_8_SOFT
),
434 DECL(AL_7POINT1_16_SOFT
),
435 DECL(AL_7POINT1_32F_SOFT
),
438 DECL(AL_STEREO_SOFT
),
441 DECL(AL_5POINT1_SOFT
),
442 DECL(AL_6POINT1_SOFT
),
443 DECL(AL_7POINT1_SOFT
),
446 DECL(AL_UNSIGNED_BYTE_SOFT
),
448 DECL(AL_UNSIGNED_SHORT_SOFT
),
450 DECL(AL_UNSIGNED_INT_SOFT
),
452 DECL(AL_DOUBLE_SOFT
),
454 DECL(AL_UNSIGNED_BYTE3_SOFT
),
460 DECL(AL_INTERNAL_FORMAT_SOFT
),
461 DECL(AL_BYTE_LENGTH_SOFT
),
462 DECL(AL_SAMPLE_LENGTH_SOFT
),
463 DECL(AL_SEC_LENGTH_SOFT
),
470 DECL(AL_INVALID_NAME
),
471 DECL(AL_INVALID_ENUM
),
472 DECL(AL_INVALID_VALUE
),
473 DECL(AL_INVALID_OPERATION
),
474 DECL(AL_OUT_OF_MEMORY
),
481 DECL(AL_DOPPLER_FACTOR
),
482 DECL(AL_DOPPLER_VELOCITY
),
483 DECL(AL_DISTANCE_MODEL
),
484 DECL(AL_SPEED_OF_SOUND
),
485 DECL(AL_SOURCE_DISTANCE_MODEL
),
486 DECL(AL_DEFERRED_UPDATES_SOFT
),
488 DECL(AL_INVERSE_DISTANCE
),
489 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
490 DECL(AL_LINEAR_DISTANCE
),
491 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
492 DECL(AL_EXPONENT_DISTANCE
),
493 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
495 DECL(AL_FILTER_TYPE
),
496 DECL(AL_FILTER_NULL
),
497 DECL(AL_FILTER_LOWPASS
),
499 DECL(AL_FILTER_HIGHPASS
),
500 DECL(AL_FILTER_BANDPASS
),
503 DECL(AL_LOWPASS_GAIN
),
504 DECL(AL_LOWPASS_GAINHF
),
506 DECL(AL_EFFECT_TYPE
),
507 DECL(AL_EFFECT_NULL
),
508 DECL(AL_EFFECT_REVERB
),
509 DECL(AL_EFFECT_EAXREVERB
),
511 DECL(AL_EFFECT_CHORUS
),
512 DECL(AL_EFFECT_DISTORTION
),
514 DECL(AL_EFFECT_ECHO
),
516 DECL(AL_EFFECT_FLANGER
),
517 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
518 DECL(AL_EFFECT_VOCAL_MORPHER
),
519 DECL(AL_EFFECT_PITCH_SHIFTER
),
521 DECL(AL_EFFECT_RING_MODULATOR
),
523 DECL(AL_EFFECT_AUTOWAH
),
524 DECL(AL_EFFECT_COMPRESSOR
),
525 DECL(AL_EFFECT_EQUALIZER
),
527 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
528 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
530 DECL(AL_EAXREVERB_DENSITY
),
531 DECL(AL_EAXREVERB_DIFFUSION
),
532 DECL(AL_EAXREVERB_GAIN
),
533 DECL(AL_EAXREVERB_GAINHF
),
534 DECL(AL_EAXREVERB_GAINLF
),
535 DECL(AL_EAXREVERB_DECAY_TIME
),
536 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
537 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
538 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
539 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
540 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
541 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
542 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
543 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
544 DECL(AL_EAXREVERB_ECHO_TIME
),
545 DECL(AL_EAXREVERB_ECHO_DEPTH
),
546 DECL(AL_EAXREVERB_MODULATION_TIME
),
547 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
548 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
549 DECL(AL_EAXREVERB_HFREFERENCE
),
550 DECL(AL_EAXREVERB_LFREFERENCE
),
551 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
552 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
554 DECL(AL_REVERB_DENSITY
),
555 DECL(AL_REVERB_DIFFUSION
),
556 DECL(AL_REVERB_GAIN
),
557 DECL(AL_REVERB_GAINHF
),
558 DECL(AL_REVERB_DECAY_TIME
),
559 DECL(AL_REVERB_DECAY_HFRATIO
),
560 DECL(AL_REVERB_REFLECTIONS_GAIN
),
561 DECL(AL_REVERB_REFLECTIONS_DELAY
),
562 DECL(AL_REVERB_LATE_REVERB_GAIN
),
563 DECL(AL_REVERB_LATE_REVERB_DELAY
),
564 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
565 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
566 DECL(AL_REVERB_DECAY_HFLIMIT
),
569 DECL(AL_ECHO_LRDELAY
),
570 DECL(AL_ECHO_DAMPING
),
571 DECL(AL_ECHO_FEEDBACK
),
572 DECL(AL_ECHO_SPREAD
),
574 DECL(AL_RING_MODULATOR_FREQUENCY
),
575 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
576 DECL(AL_RING_MODULATOR_WAVEFORM
),
578 DECL(AL_DEDICATED_GAIN
),
584 static const ALCchar alcNoError
[] = "No Error";
585 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
586 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
587 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
588 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
589 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
592 /************************************************
594 ************************************************/
596 /* Enumerated device names */
597 static const ALCchar alcDefaultName
[] = "OpenAL Soft\0";
598 static ALCchar
*alcAllDevicesList
;
599 static ALCchar
*alcCaptureDeviceList
;
600 /* Sizes only include the first ending null character, not the second */
601 static size_t alcAllDevicesListSize
;
602 static size_t alcCaptureDeviceListSize
;
604 /* Default is always the first in the list */
605 static ALCchar
*alcDefaultAllDevicesSpecifier
;
606 static ALCchar
*alcCaptureDefaultDeviceSpecifier
;
608 /* Default context extensions */
609 static const ALchar alExtList
[] =
610 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
611 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
612 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
613 "AL_LOKI_quadriphonic AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data "
614 "AL_SOFTX_deferred_updates AL_SOFT_direct_channels AL_SOFT_loop_points";
616 static volatile ALCenum LastNullDeviceError
= ALC_NO_ERROR
;
618 /* Thread-local current context */
619 static pthread_key_t LocalContext
;
620 /* Process-wide current context */
621 static ALCcontext
*volatile GlobalContext
= NULL
;
623 /* Mixing thread piority level */
628 enum LogLevel LogLevel
= LogWarning
;
630 enum LogLevel LogLevel
= LogError
;
633 /* Flag to trap ALC device errors */
634 static ALCboolean TrapALCError
= ALC_FALSE
;
636 /* One-time configuration init control */
637 static pthread_once_t alc_config_once
= PTHREAD_ONCE_INIT
;
639 /* Default effect that applies to sources that don't have an effect on send 0 */
640 static ALeffect DefaultEffect
;
643 /************************************************
645 ************************************************/
646 static const ALCchar alcNoDeviceExtList
[] =
647 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
648 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
649 static const ALCchar alcExtensionList
[] =
650 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
651 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
652 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
653 static const ALCint alcMajorVersion
= 1;
654 static const ALCint alcMinorVersion
= 1;
656 static const ALCint alcEFXMajorVersion
= 1;
657 static const ALCint alcEFXMinorVersion
= 0;
660 /************************************************
662 ************************************************/
663 static ALCdevice
*volatile DeviceList
= NULL
;
665 static CRITICAL_SECTION ListLock
;
667 static void LockLists(void)
669 EnterCriticalSection(&ListLock
);
671 static void UnlockLists(void)
673 LeaveCriticalSection(&ListLock
);
676 /************************************************
677 * Library initialization
678 ************************************************/
680 static void alc_init(void);
681 static void alc_deinit(void);
682 static void alc_deinit_safe(void);
684 UIntMap TlsDestructor
;
686 #ifndef AL_LIBTYPE_STATIC
687 BOOL APIENTRY
DllMain(HINSTANCE hModule
,DWORD ul_reason_for_call
,LPVOID lpReserved
)
691 // Perform actions based on the reason for calling.
692 switch(ul_reason_for_call
)
694 case DLL_PROCESS_ATTACH
:
695 /* Pin the DLL so we won't get unloaded until the process terminates */
696 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
697 (WCHAR
*)hModule
, &hModule
);
698 InitUIntMap(&TlsDestructor
, ~0);
702 case DLL_THREAD_DETACH
:
703 LockUIntMapRead(&TlsDestructor
);
704 for(i
= 0;i
< TlsDestructor
.size
;i
++)
706 void *ptr
= pthread_getspecific(TlsDestructor
.array
[i
].key
);
707 void (*callback
)(void*) = (void(*)(void*))TlsDestructor
.array
[i
].value
;
711 UnlockUIntMapRead(&TlsDestructor
);
714 case DLL_PROCESS_DETACH
:
719 ResetUIntMap(&TlsDestructor
);
724 #elif defined(_MSC_VER)
725 #pragma section(".CRT$XCU",read)
726 static void alc_constructor(void);
727 static void alc_destructor(void);
728 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
730 static void alc_constructor(void)
732 atexit(alc_destructor
);
736 static void alc_destructor(void)
740 #elif defined(HAVE_GCC_DESTRUCTOR)
741 static void alc_init(void) __attribute__((constructor
));
742 static void alc_deinit(void) __attribute__((destructor
));
744 #error "No static initialization available on this platform!"
747 #elif defined(HAVE_GCC_DESTRUCTOR)
749 static void alc_init(void) __attribute__((constructor
));
750 static void alc_deinit(void) __attribute__((destructor
));
753 #error "No global initialization available on this platform!"
756 static void ReleaseThreadCtx(void *ptr
);
757 static void alc_init(void)
763 str
= getenv("__ALSOFT_HALF_ANGLE_CONES");
764 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
767 str
= getenv("__ALSOFT_REVERSE_Z");
768 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
771 pthread_key_create(&LocalContext
, ReleaseThreadCtx
);
772 InitializeCriticalSection(&ListLock
);
776 static void alc_initconfig(void)
778 const char *devs
, *str
;
783 str
= getenv("ALSOFT_LOGLEVEL");
786 long lvl
= strtol(str
, NULL
, 0);
787 if(lvl
>= NoLog
&& lvl
<= LogRef
)
791 str
= getenv("ALSOFT_LOGFILE");
794 FILE *logfile
= fopen(str
, "wat");
795 if(logfile
) LogFile
= logfile
;
796 else ERR("Failed to open log file '%s'\n", str
);
803 capfilter
|= CPU_CAP_SSE
;
806 capfilter
|= CPU_CAP_NEON
;
808 if(ConfigValueStr(NULL
, "disable-cpu-exts", &str
))
810 if(strcasecmp(str
, "all") == 0)
815 const char *next
= str
;
820 next
= strchr(str
, ',');
822 while(isspace(str
[0]))
824 if(!str
[0] || str
[0] == ',')
827 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
828 if(strncasecmp(str
, "sse", len
) == 0)
829 capfilter
&= ~CPU_CAP_SSE
;
830 else if(strncasecmp(str
, "neon", len
) == 0)
831 capfilter
&= ~CPU_CAP_NEON
;
833 WARN("Invalid CPU extension \"%s\"\n", str
);
837 FillCPUCaps(capfilter
);
844 ConfigValueInt(NULL
, "rt-prio", &RTPrioLevel
);
846 if(ConfigValueStr(NULL
, "resampler", &str
))
848 if(strcasecmp(str
, "point") == 0 || strcasecmp(str
, "none") == 0)
849 DefaultResampler
= PointResampler
;
850 else if(strcasecmp(str
, "linear") == 0)
851 DefaultResampler
= LinearResampler
;
852 else if(strcasecmp(str
, "cubic") == 0)
853 DefaultResampler
= CubicResampler
;
858 n
= strtol(str
, &end
, 0);
859 if(*end
== '\0' && (n
== PointResampler
|| n
== LinearResampler
|| n
== CubicResampler
))
860 DefaultResampler
= n
;
862 WARN("Invalid resampler: %s\n", str
);
866 str
= getenv("ALSOFT_TRAP_ERROR");
867 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
869 TrapALError
= AL_TRUE
;
870 TrapALCError
= AL_TRUE
;
874 str
= getenv("ALSOFT_TRAP_AL_ERROR");
875 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
876 TrapALError
= AL_TRUE
;
877 TrapALError
= GetConfigValueBool(NULL
, "trap-al-error", TrapALError
);
879 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
880 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
881 TrapALCError
= ALC_TRUE
;
882 TrapALCError
= GetConfigValueBool(NULL
, "trap-alc-error", TrapALCError
);
885 if(ConfigValueFloat("reverb", "boost", &valf
))
886 ReverbBoost
*= powf(10.0f
, valf
/ 20.0f
);
888 EmulateEAXReverb
= GetConfigValueBool("reverb", "emulate-eax", AL_FALSE
);
890 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
891 ConfigValueStr(NULL
, "drivers", &devs
))
895 const char *next
= devs
;
896 int endlist
, delitem
;
901 next
= strchr(devs
, ',');
903 delitem
= (devs
[0] == '-');
904 if(devs
[0] == '-') devs
++;
906 if(!devs
[0] || devs
[0] == ',')
913 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
914 for(n
= i
;BackendList
[n
].Init
;n
++)
916 if(len
== strlen(BackendList
[n
].name
) &&
917 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
922 BackendList
[n
] = BackendList
[n
+1];
924 } while(BackendList
[n
].Init
);
928 struct BackendInfo Bkp
= BackendList
[n
];
931 BackendList
[n
] = BackendList
[n
-1];
934 BackendList
[n
] = Bkp
;
945 BackendList
[i
].name
= NULL
;
946 BackendList
[i
].Init
= NULL
;
947 BackendList
[i
].Deinit
= NULL
;
948 BackendList
[i
].Probe
= NULL
;
952 for(i
= 0;BackendList
[i
].Init
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
954 if(!BackendList
[i
].Init(&BackendList
[i
].Funcs
))
956 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
960 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
961 if(BackendList
[i
].Funcs
.OpenPlayback
&& !PlaybackBackend
.name
)
963 PlaybackBackend
= BackendList
[i
];
964 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
966 if(BackendList
[i
].Funcs
.OpenCapture
&& !CaptureBackend
.name
)
968 CaptureBackend
= BackendList
[i
];
969 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
972 BackendLoopback
.Init(&BackendLoopback
.Funcs
);
974 if(ConfigValueStr(NULL
, "excludefx", &str
))
977 const char *next
= str
;
981 next
= strchr(str
, ',');
983 if(!str
[0] || next
== str
)
986 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
987 for(n
= 0;EffectList
[n
].name
;n
++)
989 if(len
== strlen(EffectList
[n
].name
) &&
990 strncmp(EffectList
[n
].name
, str
, len
) == 0)
991 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
996 InitEffect(&DefaultEffect
);
997 str
= getenv("ALSOFT_DEFAULT_REVERB");
998 if((str
&& str
[0]) || ConfigValueStr(NULL
, "default-reverb", &str
))
999 LoadReverbPreset(str
, &DefaultEffect
);
1001 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
1004 /************************************************
1005 * Library deinitialization
1006 ************************************************/
1007 static void alc_cleanup(void)
1011 free(alcAllDevicesList
); alcAllDevicesList
= NULL
;
1012 alcAllDevicesListSize
= 0;
1013 free(alcCaptureDeviceList
); alcCaptureDeviceList
= NULL
;
1014 alcCaptureDeviceListSize
= 0;
1016 free(alcDefaultAllDevicesSpecifier
);
1017 alcDefaultAllDevicesSpecifier
= NULL
;
1018 free(alcCaptureDefaultDeviceSpecifier
);
1019 alcCaptureDefaultDeviceSpecifier
= NULL
;
1021 if((dev
=ExchangePtr((XchgPtr
*)&DeviceList
, NULL
)) != NULL
)
1026 } while((dev
=dev
->next
) != NULL
);
1027 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1031 static void alc_deinit_safe(void)
1039 DeleteCriticalSection(&ListLock
);
1040 pthread_key_delete(LocalContext
);
1042 if(LogFile
!= stderr
)
1047 static void alc_deinit(void)
1053 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1054 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1056 for(i
= 0;BackendList
[i
].Deinit
;i
++)
1057 BackendList
[i
].Deinit();
1058 BackendLoopback
.Deinit();
1064 /************************************************
1065 * Device enumeration
1066 ************************************************/
1067 static void ProbeList(ALCchar
**list
, size_t *listsize
, enum DevProbe type
)
1076 if(type
== ALL_DEVICE_PROBE
&& PlaybackBackend
.Probe
)
1077 PlaybackBackend
.Probe(type
);
1078 else if(type
== CAPTURE_DEVICE_PROBE
&& CaptureBackend
.Probe
)
1079 CaptureBackend
.Probe(type
);
1083 static void ProbeAllDevicesList(void)
1084 { ProbeList(&alcAllDevicesList
, &alcAllDevicesListSize
, ALL_DEVICE_PROBE
); }
1085 static void ProbeCaptureDeviceList(void)
1086 { ProbeList(&alcCaptureDeviceList
, &alcCaptureDeviceListSize
, CAPTURE_DEVICE_PROBE
); }
1089 static void AppendList(const ALCchar
*name
, ALCchar
**List
, size_t *ListSize
)
1091 size_t len
= strlen(name
);
1097 temp
= realloc(*List
, (*ListSize
) + len
+ 2);
1100 ERR("Realloc failed to add %s!\n", name
);
1105 memcpy((*List
)+(*ListSize
), name
, len
+1);
1107 (*List
)[*ListSize
] = 0;
1110 #define DECL_APPEND_LIST_FUNC(type) \
1111 void Append##type##List(const ALCchar *name) \
1112 { AppendList(name, &alc##type##List, &alc##type##ListSize); }
1114 DECL_APPEND_LIST_FUNC(AllDevices
)
1115 DECL_APPEND_LIST_FUNC(CaptureDevice
)
1117 #undef DECL_APPEND_LIST_FUNC
1120 /************************************************
1121 * Device format information
1122 ************************************************/
1123 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1127 case DevFmtByte
: return "Signed Byte";
1128 case DevFmtUByte
: return "Unsigned Byte";
1129 case DevFmtShort
: return "Signed Short";
1130 case DevFmtUShort
: return "Unsigned Short";
1131 case DevFmtInt
: return "Signed Int";
1132 case DevFmtUInt
: return "Unsigned Int";
1133 case DevFmtFloat
: return "Float";
1135 return "(unknown type)";
1137 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1141 case DevFmtMono
: return "Mono";
1142 case DevFmtStereo
: return "Stereo";
1143 case DevFmtQuad
: return "Quadraphonic";
1144 case DevFmtX51
: return "5.1 Surround";
1145 case DevFmtX51Side
: return "5.1 Side";
1146 case DevFmtX61
: return "6.1 Surround";
1147 case DevFmtX71
: return "7.1 Surround";
1149 return "(unknown channels)";
1152 ALuint
BytesFromDevFmt(enum DevFmtType type
)
1156 case DevFmtByte
: return sizeof(ALbyte
);
1157 case DevFmtUByte
: return sizeof(ALubyte
);
1158 case DevFmtShort
: return sizeof(ALshort
);
1159 case DevFmtUShort
: return sizeof(ALushort
);
1160 case DevFmtInt
: return sizeof(ALint
);
1161 case DevFmtUInt
: return sizeof(ALuint
);
1162 case DevFmtFloat
: return sizeof(ALfloat
);
1166 ALuint
ChannelsFromDevFmt(enum DevFmtChannels chans
)
1170 case DevFmtMono
: return 1;
1171 case DevFmtStereo
: return 2;
1172 case DevFmtQuad
: return 4;
1173 case DevFmtX51
: return 6;
1174 case DevFmtX51Side
: return 6;
1175 case DevFmtX61
: return 7;
1176 case DevFmtX71
: return 8;
1181 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1182 enum DevFmtType
*type
)
1184 static const struct {
1186 enum DevFmtChannels channels
;
1187 enum DevFmtType type
;
1189 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1190 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1191 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1193 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1194 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1195 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1197 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1198 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1199 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1201 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1202 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1203 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1205 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1206 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1207 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1209 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1210 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1211 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1215 for(i
= 0;i
< COUNTOF(list
);i
++)
1217 if(list
[i
].format
== format
)
1219 *chans
= list
[i
].channels
;
1220 *type
= list
[i
].type
;
1228 static ALCboolean
IsValidALCType(ALCenum type
)
1233 case ALC_UNSIGNED_BYTE_SOFT
:
1234 case ALC_SHORT_SOFT
:
1235 case ALC_UNSIGNED_SHORT_SOFT
:
1237 case ALC_UNSIGNED_INT_SOFT
:
1238 case ALC_FLOAT_SOFT
:
1244 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1249 case ALC_STEREO_SOFT
:
1251 case ALC_5POINT1_SOFT
:
1252 case ALC_6POINT1_SOFT
:
1253 case ALC_7POINT1_SOFT
:
1260 /************************************************
1261 * Miscellaneous ALC helpers
1262 ************************************************/
1264 void ALCdevice_LockDefault(ALCdevice
*device
)
1266 EnterCriticalSection(&device
->Mutex
);
1268 void ALCdevice_UnlockDefault(ALCdevice
*device
)
1270 LeaveCriticalSection(&device
->Mutex
);
1272 ALint64
ALCdevice_GetLatencyDefault(ALCdevice
*device
)
1278 /* SetDefaultWFXChannelOrder
1280 * Sets the default channel order used by WaveFormatEx.
1282 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1284 switch(device
->FmtChans
)
1286 case DevFmtMono
: device
->DevChannels
[0] = FrontCenter
; break;
1288 case DevFmtStereo
: device
->DevChannels
[0] = FrontLeft
;
1289 device
->DevChannels
[1] = FrontRight
; break;
1291 case DevFmtQuad
: device
->DevChannels
[0] = FrontLeft
;
1292 device
->DevChannels
[1] = FrontRight
;
1293 device
->DevChannels
[2] = BackLeft
;
1294 device
->DevChannels
[3] = BackRight
; break;
1296 case DevFmtX51
: device
->DevChannels
[0] = FrontLeft
;
1297 device
->DevChannels
[1] = FrontRight
;
1298 device
->DevChannels
[2] = FrontCenter
;
1299 device
->DevChannels
[3] = LFE
;
1300 device
->DevChannels
[4] = BackLeft
;
1301 device
->DevChannels
[5] = BackRight
; break;
1303 case DevFmtX51Side
: device
->DevChannels
[0] = FrontLeft
;
1304 device
->DevChannels
[1] = FrontRight
;
1305 device
->DevChannels
[2] = FrontCenter
;
1306 device
->DevChannels
[3] = LFE
;
1307 device
->DevChannels
[4] = SideLeft
;
1308 device
->DevChannels
[5] = SideRight
; break;
1310 case DevFmtX61
: device
->DevChannels
[0] = FrontLeft
;
1311 device
->DevChannels
[1] = FrontRight
;
1312 device
->DevChannels
[2] = FrontCenter
;
1313 device
->DevChannels
[3] = LFE
;
1314 device
->DevChannels
[4] = BackCenter
;
1315 device
->DevChannels
[5] = SideLeft
;
1316 device
->DevChannels
[6] = SideRight
; break;
1318 case DevFmtX71
: device
->DevChannels
[0] = FrontLeft
;
1319 device
->DevChannels
[1] = FrontRight
;
1320 device
->DevChannels
[2] = FrontCenter
;
1321 device
->DevChannels
[3] = LFE
;
1322 device
->DevChannels
[4] = BackLeft
;
1323 device
->DevChannels
[5] = BackRight
;
1324 device
->DevChannels
[6] = SideLeft
;
1325 device
->DevChannels
[7] = SideRight
; break;
1329 /* SetDefaultChannelOrder
1331 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1333 void SetDefaultChannelOrder(ALCdevice
*device
)
1335 switch(device
->FmtChans
)
1337 case DevFmtX51
: device
->DevChannels
[0] = FrontLeft
;
1338 device
->DevChannels
[1] = FrontRight
;
1339 device
->DevChannels
[2] = BackLeft
;
1340 device
->DevChannels
[3] = BackRight
;
1341 device
->DevChannels
[4] = FrontCenter
;
1342 device
->DevChannels
[5] = LFE
;
1345 case DevFmtX71
: device
->DevChannels
[0] = FrontLeft
;
1346 device
->DevChannels
[1] = FrontRight
;
1347 device
->DevChannels
[2] = BackLeft
;
1348 device
->DevChannels
[3] = BackRight
;
1349 device
->DevChannels
[4] = FrontCenter
;
1350 device
->DevChannels
[5] = LFE
;
1351 device
->DevChannels
[6] = SideLeft
;
1352 device
->DevChannels
[7] = SideRight
;
1355 /* Same as WFX order */
1363 SetDefaultWFXChannelOrder(device
);
1369 * Stores the latest ALC device error
1371 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1376 /* DebugBreak() will cause an exception if there is no debugger */
1377 if(IsDebuggerPresent())
1379 #elif defined(SIGTRAP)
1385 device
->LastError
= errorCode
;
1387 LastNullDeviceError
= errorCode
;
1391 /* UpdateDeviceParams
1393 * Updates device parameters according to the attribute list (caller is
1394 * responsible for holding the list lock).
1396 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1398 ALCcontext
*context
;
1399 enum DevFmtChannels oldChans
;
1400 enum DevFmtType oldType
;
1405 // Check for attributes
1406 if(device
->Type
== Loopback
)
1412 GotAll
= GotFreq
|GotChans
|GotType
1414 ALCuint freq
, numMono
, numStereo
, numSends
;
1415 enum DevFmtChannels schans
;
1416 enum DevFmtType stype
;
1417 ALCuint attrIdx
= 0;
1422 WARN("Missing attributes for loopback device\n");
1423 return ALC_INVALID_VALUE
;
1426 numMono
= device
->NumMonoSources
;
1427 numStereo
= device
->NumStereoSources
;
1428 numSends
= device
->NumAuxSends
;
1429 schans
= device
->FmtChans
;
1430 stype
= device
->FmtType
;
1431 freq
= device
->Frequency
;
1433 while(attrList
[attrIdx
])
1435 if(attrList
[attrIdx
] == ALC_FORMAT_CHANNELS_SOFT
)
1437 ALCint val
= attrList
[attrIdx
+ 1];
1438 if(!IsValidALCChannels(val
) || !ChannelsFromDevFmt(val
))
1439 return ALC_INVALID_VALUE
;
1444 if(attrList
[attrIdx
] == ALC_FORMAT_TYPE_SOFT
)
1446 ALCint val
= attrList
[attrIdx
+ 1];
1447 if(!IsValidALCType(val
) || !BytesFromDevFmt(val
))
1448 return ALC_INVALID_VALUE
;
1453 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1455 freq
= attrList
[attrIdx
+ 1];
1456 if(freq
< MIN_OUTPUT_RATE
)
1457 return ALC_INVALID_VALUE
;
1461 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1463 numStereo
= attrList
[attrIdx
+ 1];
1464 if(numStereo
> device
->MaxNoOfSources
)
1465 numStereo
= device
->MaxNoOfSources
;
1467 numMono
= device
->MaxNoOfSources
- numStereo
;
1470 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
1471 numSends
= attrList
[attrIdx
+ 1];
1476 if(gotFmt
!= GotAll
)
1478 WARN("Missing format for loopback device\n");
1479 return ALC_INVALID_VALUE
;
1482 ConfigValueUInt(NULL
, "sends", &numSends
);
1483 numSends
= minu(MAX_SENDS
, numSends
);
1485 if((device
->Flags
&DEVICE_RUNNING
))
1486 ALCdevice_StopPlayback(device
);
1487 device
->Flags
&= ~DEVICE_RUNNING
;
1489 device
->Frequency
= freq
;
1490 device
->FmtChans
= schans
;
1491 device
->FmtType
= stype
;
1492 device
->NumMonoSources
= numMono
;
1493 device
->NumStereoSources
= numStereo
;
1494 device
->NumAuxSends
= numSends
;
1496 else if(attrList
&& attrList
[0])
1498 ALCuint freq
, numMono
, numStereo
, numSends
;
1499 ALCuint attrIdx
= 0;
1501 /* If a context is already running on the device, stop playback so the
1502 * device attributes can be updated. */
1503 if((device
->Flags
&DEVICE_RUNNING
))
1504 ALCdevice_StopPlayback(device
);
1505 device
->Flags
&= ~DEVICE_RUNNING
;
1507 freq
= device
->Frequency
;
1508 numMono
= device
->NumMonoSources
;
1509 numStereo
= device
->NumStereoSources
;
1510 numSends
= device
->NumAuxSends
;
1512 while(attrList
[attrIdx
])
1514 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1516 freq
= attrList
[attrIdx
+ 1];
1517 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1520 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1522 numStereo
= attrList
[attrIdx
+ 1];
1523 if(numStereo
> device
->MaxNoOfSources
)
1524 numStereo
= device
->MaxNoOfSources
;
1526 numMono
= device
->MaxNoOfSources
- numStereo
;
1529 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
1530 numSends
= attrList
[attrIdx
+ 1];
1535 ConfigValueUInt(NULL
, "frequency", &freq
);
1536 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
1538 ConfigValueUInt(NULL
, "sends", &numSends
);
1539 numSends
= minu(MAX_SENDS
, numSends
);
1541 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
1543 /* SSE does best with the update size being a multiple of 4 */
1544 if((CPUCapFlags
&CPU_CAP_SSE
))
1545 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
1547 device
->Frequency
= freq
;
1548 device
->NumMonoSources
= numMono
;
1549 device
->NumStereoSources
= numStereo
;
1550 device
->NumAuxSends
= numSends
;
1553 if((device
->Flags
&DEVICE_RUNNING
))
1554 return ALC_NO_ERROR
;
1556 oldFreq
= device
->Frequency
;
1557 oldChans
= device
->FmtChans
;
1558 oldType
= device
->FmtType
;
1560 TRACE("Pre-reset: %s%s, %s%s, %uhz%s, %u update size x%d\n",
1561 DevFmtChannelsString(device
->FmtChans
),
1562 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?" (requested)":"",
1563 DevFmtTypeString(device
->FmtType
),
1564 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?" (requested)":"",
1566 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?" (requested)":"",
1567 device
->UpdateSize
, device
->NumUpdates
);
1569 if(ALCdevice_ResetPlayback(device
) == ALC_FALSE
)
1570 return ALC_INVALID_DEVICE
;
1572 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
1574 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
1575 DevFmtChannelsString(device
->FmtChans
));
1576 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
1578 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
1580 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
1581 DevFmtTypeString(device
->FmtType
));
1582 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
1584 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
1586 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
1587 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
1590 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
1591 DevFmtChannelsString(device
->FmtChans
),
1592 DevFmtTypeString(device
->FmtType
), device
->Frequency
,
1593 device
->UpdateSize
, device
->NumUpdates
);
1595 aluInitPanning(device
);
1597 for(i
= 0;i
< MaxChannels
;i
++)
1599 device
->ClickRemoval
[i
] = 0.0f
;
1600 device
->PendingClicks
[i
] = 0.0f
;
1603 device
->Hrtf
= NULL
;
1604 if(device
->Type
!= Loopback
&& GetConfigValueBool(NULL
, "hrtf", AL_FALSE
))
1605 device
->Hrtf
= GetHrtf(device
);
1606 TRACE("HRTF %s\n", device
->Hrtf
?"enabled":"disabled");
1608 if(!device
->Hrtf
&& device
->Bs2bLevel
> 0 && device
->Bs2bLevel
<= 6)
1612 device
->Bs2b
= calloc(1, sizeof(*device
->Bs2b
));
1613 bs2b_clear(device
->Bs2b
);
1615 bs2b_set_srate(device
->Bs2b
, device
->Frequency
);
1616 bs2b_set_level(device
->Bs2b
, device
->Bs2bLevel
);
1617 TRACE("BS2B level %d\n", device
->Bs2bLevel
);
1622 device
->Bs2b
= NULL
;
1623 TRACE("BS2B disabled\n");
1626 device
->Flags
&= ~DEVICE_WIDE_STEREO
;
1627 if(device
->Type
!= Loopback
&& !device
->Hrtf
&& GetConfigValueBool(NULL
, "wide-stereo", AL_FALSE
))
1628 device
->Flags
|= DEVICE_WIDE_STEREO
;
1630 if(!device
->Hrtf
&& (device
->UpdateSize
&3))
1632 if((CPUCapFlags
&CPU_CAP_SSE
))
1633 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
1636 SetMixerFPUMode(&oldMode
);
1637 ALCdevice_Lock(device
);
1638 context
= device
->ContextList
;
1643 context
->UpdateSources
= AL_FALSE
;
1644 LockUIntMapRead(&context
->EffectSlotMap
);
1645 for(pos
= 0;pos
< context
->EffectSlotMap
.size
;pos
++)
1647 ALeffectslot
*slot
= context
->EffectSlotMap
.array
[pos
].value
;
1649 if(ALeffectState_DeviceUpdate(slot
->EffectState
, device
) == AL_FALSE
)
1651 UnlockUIntMapRead(&context
->EffectSlotMap
);
1652 ALCdevice_Unlock(device
);
1653 RestoreFPUMode(&oldMode
);
1654 return ALC_INVALID_DEVICE
;
1656 slot
->NeedsUpdate
= AL_FALSE
;
1657 ALeffectState_Update(slot
->EffectState
, device
, slot
);
1659 UnlockUIntMapRead(&context
->EffectSlotMap
);
1661 LockUIntMapRead(&context
->SourceMap
);
1662 for(pos
= 0;pos
< context
->SourceMap
.size
;pos
++)
1664 ALsource
*source
= context
->SourceMap
.array
[pos
].value
;
1665 ALuint s
= device
->NumAuxSends
;
1666 while(s
< MAX_SENDS
)
1668 if(source
->Send
[s
].Slot
)
1669 DecrementRef(&source
->Send
[s
].Slot
->ref
);
1670 source
->Send
[s
].Slot
= NULL
;
1671 source
->Send
[s
].Gain
= 1.0f
;
1672 source
->Send
[s
].GainHF
= 1.0f
;
1675 source
->NeedsUpdate
= AL_FALSE
;
1676 ALsource_Update(source
, context
);
1678 UnlockUIntMapRead(&context
->SourceMap
);
1680 context
= context
->next
;
1682 if(device
->DefaultSlot
)
1684 ALeffectslot
*slot
= device
->DefaultSlot
;
1686 if(ALeffectState_DeviceUpdate(slot
->EffectState
, device
) == AL_FALSE
)
1688 ALCdevice_Unlock(device
);
1689 RestoreFPUMode(&oldMode
);
1690 return ALC_INVALID_DEVICE
;
1692 slot
->NeedsUpdate
= AL_FALSE
;
1693 ALeffectState_Update(slot
->EffectState
, device
, slot
);
1695 ALCdevice_Unlock(device
);
1696 RestoreFPUMode(&oldMode
);
1698 if(ALCdevice_StartPlayback(device
) == ALC_FALSE
)
1699 return ALC_INVALID_DEVICE
;
1700 device
->Flags
|= DEVICE_RUNNING
;
1702 return ALC_NO_ERROR
;
1707 * Frees the device structure, and destroys any objects the app failed to
1708 * delete. Called once there's no more references on the device.
1710 static ALCvoid
FreeDevice(ALCdevice
*device
)
1712 TRACE("%p\n", device
);
1714 if(device
->Type
!= Capture
)
1715 ALCdevice_ClosePlayback(device
);
1717 ALCdevice_CloseCapture(device
);
1719 if(device
->DefaultSlot
)
1721 ALeffectState_Destroy(device
->DefaultSlot
->EffectState
);
1722 device
->DefaultSlot
->EffectState
= NULL
;
1725 if(device
->BufferMap
.size
> 0)
1727 WARN("(%p) Deleting %d Buffer(s)\n", device
, device
->BufferMap
.size
);
1728 ReleaseALBuffers(device
);
1730 ResetUIntMap(&device
->BufferMap
);
1732 if(device
->EffectMap
.size
> 0)
1734 WARN("(%p) Deleting %d Effect(s)\n", device
, device
->EffectMap
.size
);
1735 ReleaseALEffects(device
);
1737 ResetUIntMap(&device
->EffectMap
);
1739 if(device
->FilterMap
.size
> 0)
1741 WARN("(%p) Deleting %d Filter(s)\n", device
, device
->FilterMap
.size
);
1742 ReleaseALFilters(device
);
1744 ResetUIntMap(&device
->FilterMap
);
1747 device
->Bs2b
= NULL
;
1749 free(device
->DeviceName
);
1750 device
->DeviceName
= NULL
;
1752 DeleteCriticalSection(&device
->Mutex
);
1758 void ALCdevice_IncRef(ALCdevice
*device
)
1761 ref
= IncrementRef(&device
->ref
);
1762 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
1765 void ALCdevice_DecRef(ALCdevice
*device
)
1768 ref
= DecrementRef(&device
->ref
);
1769 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
1770 if(ref
== 0) FreeDevice(device
);
1775 * Checks if the device handle is valid, and increments its ref count if so.
1777 static ALCdevice
*VerifyDevice(ALCdevice
*device
)
1779 ALCdevice
*tmpDevice
;
1785 tmpDevice
= DeviceList
;
1786 while(tmpDevice
&& tmpDevice
!= device
)
1787 tmpDevice
= tmpDevice
->next
;
1790 ALCdevice_IncRef(tmpDevice
);
1798 * Initializes context fields
1800 static ALvoid
InitContext(ALCcontext
*Context
)
1804 //Initialise listener
1805 Context
->Listener
.Gain
= 1.0f
;
1806 Context
->Listener
.MetersPerUnit
= 1.0f
;
1807 Context
->Listener
.Position
[0] = 0.0f
;
1808 Context
->Listener
.Position
[1] = 0.0f
;
1809 Context
->Listener
.Position
[2] = 0.0f
;
1810 Context
->Listener
.Velocity
[0] = 0.0f
;
1811 Context
->Listener
.Velocity
[1] = 0.0f
;
1812 Context
->Listener
.Velocity
[2] = 0.0f
;
1813 Context
->Listener
.Forward
[0] = 0.0f
;
1814 Context
->Listener
.Forward
[1] = 0.0f
;
1815 Context
->Listener
.Forward
[2] = -1.0f
;
1816 Context
->Listener
.Up
[0] = 0.0f
;
1817 Context
->Listener
.Up
[1] = 1.0f
;
1818 Context
->Listener
.Up
[2] = 0.0f
;
1819 for(i
= 0;i
< 4;i
++)
1821 for(j
= 0;j
< 4;j
++)
1822 Context
->Listener
.Matrix
[i
][j
] = ((i
==j
) ? 1.0f
: 0.0f
);
1826 Context
->LastError
= AL_NO_ERROR
;
1827 Context
->UpdateSources
= AL_FALSE
;
1828 Context
->ActiveSourceCount
= 0;
1829 InitUIntMap(&Context
->SourceMap
, Context
->Device
->MaxNoOfSources
);
1830 InitUIntMap(&Context
->EffectSlotMap
, Context
->Device
->AuxiliaryEffectSlotMax
);
1833 Context
->DistanceModel
= AL_INVERSE_DISTANCE_CLAMPED
;
1834 Context
->SourceDistanceModel
= AL_FALSE
;
1835 Context
->DopplerFactor
= 1.0f
;
1836 Context
->DopplerVelocity
= 1.0f
;
1837 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
1838 Context
->DeferUpdates
= AL_FALSE
;
1840 Context
->ExtensionList
= alExtList
;
1846 * Cleans up the context, and destroys any remaining objects the app failed to
1847 * delete. Called once there's no more references on the context.
1849 static ALCvoid
FreeContext(ALCcontext
*context
)
1851 TRACE("%p\n", context
);
1853 if(context
->SourceMap
.size
> 0)
1855 ERR("(%p) Deleting %d Source(s)\n", context
, context
->SourceMap
.size
);
1856 ReleaseALSources(context
);
1858 ResetUIntMap(&context
->SourceMap
);
1860 if(context
->EffectSlotMap
.size
> 0)
1862 ERR("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context
, context
->EffectSlotMap
.size
);
1863 ReleaseALAuxiliaryEffectSlots(context
);
1865 ResetUIntMap(&context
->EffectSlotMap
);
1867 context
->ActiveSourceCount
= 0;
1868 free(context
->ActiveSources
);
1869 context
->ActiveSources
= NULL
;
1870 context
->MaxActiveSources
= 0;
1872 context
->ActiveEffectSlotCount
= 0;
1873 free(context
->ActiveEffectSlots
);
1874 context
->ActiveEffectSlots
= NULL
;
1875 context
->MaxActiveEffectSlots
= 0;
1877 ALCdevice_DecRef(context
->Device
);
1878 context
->Device
= NULL
;
1880 //Invalidate context
1881 memset(context
, 0, sizeof(ALCcontext
));
1887 * Removes the context reference from the given device and removes it from
1888 * being current on the running thread or globally.
1890 static void ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
1892 ALCcontext
*volatile*tmp_ctx
;
1894 if(pthread_getspecific(LocalContext
) == context
)
1896 WARN("%p released while current on thread\n", context
);
1897 pthread_setspecific(LocalContext
, NULL
);
1898 ALCcontext_DecRef(context
);
1901 if(CompExchangePtr((XchgPtr
*)&GlobalContext
, context
, NULL
))
1902 ALCcontext_DecRef(context
);
1904 ALCdevice_Lock(device
);
1905 tmp_ctx
= &device
->ContextList
;
1908 if(CompExchangePtr((XchgPtr
*)tmp_ctx
, context
, context
->next
))
1910 tmp_ctx
= &(*tmp_ctx
)->next
;
1912 ALCdevice_Unlock(device
);
1914 ALCcontext_DecRef(context
);
1917 void ALCcontext_IncRef(ALCcontext
*context
)
1920 ref
= IncrementRef(&context
->ref
);
1921 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
1924 void ALCcontext_DecRef(ALCcontext
*context
)
1927 ref
= DecrementRef(&context
->ref
);
1928 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
1929 if(ref
== 0) FreeContext(context
);
1932 static void ReleaseThreadCtx(void *ptr
)
1934 WARN("%p current for thread being destroyed\n", ptr
);
1935 ALCcontext_DecRef(ptr
);
1940 * Checks that the given context is valid, and increments its reference count.
1942 static ALCcontext
*VerifyContext(ALCcontext
*context
)
1950 ALCcontext
*tmp_ctx
= dev
->ContextList
;
1953 if(tmp_ctx
== context
)
1955 ALCcontext_IncRef(tmp_ctx
);
1959 tmp_ctx
= tmp_ctx
->next
;
1971 * Returns the currently active context for this thread, and adds a reference
1972 * without locking it.
1974 ALCcontext
*GetContextRef(void)
1976 ALCcontext
*context
;
1978 context
= pthread_getspecific(LocalContext
);
1980 ALCcontext_IncRef(context
);
1984 context
= GlobalContext
;
1986 ALCcontext_IncRef(context
);
1994 /************************************************
1995 * Standard ALC functions
1996 ************************************************/
2000 * Return last ALC generated error code for the given device
2002 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2006 if(VerifyDevice(device
))
2008 errorCode
= ExchangeInt(&device
->LastError
, ALC_NO_ERROR
);
2009 ALCdevice_DecRef(device
);
2012 errorCode
= ExchangeInt(&LastNullDeviceError
, ALC_NO_ERROR
);
2018 /* alcSuspendContext
2022 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*Context
)
2027 /* alcProcessContext
2031 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*Context
)
2039 * Returns information about the device, and error strings
2041 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2043 const ALCchar
*value
= NULL
;
2051 case ALC_INVALID_ENUM
:
2052 value
= alcErrInvalidEnum
;
2055 case ALC_INVALID_VALUE
:
2056 value
= alcErrInvalidValue
;
2059 case ALC_INVALID_DEVICE
:
2060 value
= alcErrInvalidDevice
;
2063 case ALC_INVALID_CONTEXT
:
2064 value
= alcErrInvalidContext
;
2067 case ALC_OUT_OF_MEMORY
:
2068 value
= alcErrOutOfMemory
;
2071 case ALC_DEVICE_SPECIFIER
:
2072 value
= alcDefaultName
;
2075 case ALC_ALL_DEVICES_SPECIFIER
:
2076 if(VerifyDevice(Device
))
2078 value
= Device
->DeviceName
;
2079 ALCdevice_DecRef(Device
);
2083 ProbeAllDevicesList();
2084 value
= alcAllDevicesList
;
2088 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2089 if(VerifyDevice(Device
))
2091 value
= Device
->DeviceName
;
2092 ALCdevice_DecRef(Device
);
2096 ProbeCaptureDeviceList();
2097 value
= alcCaptureDeviceList
;
2101 /* Default devices are always first in the list */
2102 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2103 value
= alcDefaultName
;
2106 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2107 if(!alcAllDevicesList
)
2108 ProbeAllDevicesList();
2110 Device
= VerifyDevice(Device
);
2112 free(alcDefaultAllDevicesSpecifier
);
2113 alcDefaultAllDevicesSpecifier
= strdup(alcAllDevicesList
?
2114 alcAllDevicesList
: "");
2115 if(!alcDefaultAllDevicesSpecifier
)
2116 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2118 value
= alcDefaultAllDevicesSpecifier
;
2119 if(Device
) ALCdevice_DecRef(Device
);
2122 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2123 if(!alcCaptureDeviceList
)
2124 ProbeCaptureDeviceList();
2126 Device
= VerifyDevice(Device
);
2128 free(alcCaptureDefaultDeviceSpecifier
);
2129 alcCaptureDefaultDeviceSpecifier
= strdup(alcCaptureDeviceList
?
2130 alcCaptureDeviceList
: "");
2131 if(!alcCaptureDefaultDeviceSpecifier
)
2132 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2134 value
= alcCaptureDefaultDeviceSpecifier
;
2135 if(Device
) ALCdevice_DecRef(Device
);
2138 case ALC_EXTENSIONS
:
2139 if(!VerifyDevice(Device
))
2140 value
= alcNoDeviceExtList
;
2143 value
= alcExtensionList
;
2144 ALCdevice_DecRef(Device
);
2149 Device
= VerifyDevice(Device
);
2150 alcSetError(Device
, ALC_INVALID_ENUM
);
2151 if(Device
) ALCdevice_DecRef(Device
);
2161 * Returns information about the device and the version of OpenAL
2163 ALC_API ALCvoid ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
,ALCenum param
,ALsizei size
,ALCint
*data
)
2165 device
= VerifyDevice(device
);
2167 if(size
== 0 || data
== NULL
)
2169 alcSetError(device
, ALC_INVALID_VALUE
);
2170 if(device
) ALCdevice_DecRef(device
);
2178 case ALC_MAJOR_VERSION
:
2179 *data
= alcMajorVersion
;
2181 case ALC_MINOR_VERSION
:
2182 *data
= alcMinorVersion
;
2185 case ALC_ATTRIBUTES_SIZE
:
2186 case ALC_ALL_ATTRIBUTES
:
2190 case ALC_MONO_SOURCES
:
2191 case ALC_STEREO_SOURCES
:
2192 case ALC_CAPTURE_SAMPLES
:
2193 case ALC_FORMAT_CHANNELS_SOFT
:
2194 case ALC_FORMAT_TYPE_SOFT
:
2195 alcSetError(NULL
, ALC_INVALID_DEVICE
);
2199 alcSetError(NULL
, ALC_INVALID_ENUM
);
2203 else if(device
->Type
== Capture
)
2207 case ALC_CAPTURE_SAMPLES
:
2208 ALCdevice_Lock(device
);
2209 *data
= ALCdevice_AvailableSamples(device
);
2210 ALCdevice_Unlock(device
);
2214 *data
= device
->Connected
;
2218 alcSetError(device
, ALC_INVALID_ENUM
);
2222 else /* render device */
2226 case ALC_MAJOR_VERSION
:
2227 *data
= alcMajorVersion
;
2230 case ALC_MINOR_VERSION
:
2231 *data
= alcMinorVersion
;
2234 case ALC_EFX_MAJOR_VERSION
:
2235 *data
= alcEFXMajorVersion
;
2238 case ALC_EFX_MINOR_VERSION
:
2239 *data
= alcEFXMinorVersion
;
2242 case ALC_ATTRIBUTES_SIZE
:
2246 case ALC_ALL_ATTRIBUTES
:
2248 alcSetError(device
, ALC_INVALID_VALUE
);
2253 data
[i
++] = ALC_FREQUENCY
;
2254 data
[i
++] = device
->Frequency
;
2256 if(device
->Type
!= Loopback
)
2258 data
[i
++] = ALC_REFRESH
;
2259 data
[i
++] = device
->Frequency
/ device
->UpdateSize
;
2261 data
[i
++] = ALC_SYNC
;
2262 data
[i
++] = ALC_FALSE
;
2266 data
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
2267 data
[i
++] = device
->FmtChans
;
2269 data
[i
++] = ALC_FORMAT_TYPE_SOFT
;
2270 data
[i
++] = device
->FmtType
;
2273 data
[i
++] = ALC_MONO_SOURCES
;
2274 data
[i
++] = device
->NumMonoSources
;
2276 data
[i
++] = ALC_STEREO_SOURCES
;
2277 data
[i
++] = device
->NumStereoSources
;
2279 data
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
2280 data
[i
++] = device
->NumAuxSends
;
2287 *data
= device
->Frequency
;
2291 if(device
->Type
== Loopback
)
2292 alcSetError(device
, ALC_INVALID_DEVICE
);
2294 *data
= device
->Frequency
/ device
->UpdateSize
;
2298 if(device
->Type
== Loopback
)
2299 alcSetError(device
, ALC_INVALID_DEVICE
);
2304 case ALC_FORMAT_CHANNELS_SOFT
:
2305 if(device
->Type
!= Loopback
)
2306 alcSetError(device
, ALC_INVALID_DEVICE
);
2308 *data
= device
->FmtChans
;
2311 case ALC_FORMAT_TYPE_SOFT
:
2312 if(device
->Type
!= Loopback
)
2313 alcSetError(device
, ALC_INVALID_DEVICE
);
2315 *data
= device
->FmtType
;
2318 case ALC_MONO_SOURCES
:
2319 *data
= device
->NumMonoSources
;
2322 case ALC_STEREO_SOURCES
:
2323 *data
= device
->NumStereoSources
;
2326 case ALC_MAX_AUXILIARY_SENDS
:
2327 *data
= device
->NumAuxSends
;
2331 *data
= device
->Connected
;
2335 alcSetError(device
, ALC_INVALID_ENUM
);
2340 ALCdevice_DecRef(device
);
2344 /* alcIsExtensionPresent
2346 * Determines if there is support for a particular extension
2348 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
2350 ALCboolean bResult
= ALC_FALSE
;
2352 device
= VerifyDevice(device
);
2355 alcSetError(device
, ALC_INVALID_VALUE
);
2358 size_t len
= strlen(extName
);
2359 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
2362 if(strncasecmp(ptr
, extName
, len
) == 0 &&
2363 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
2368 if((ptr
=strchr(ptr
, ' ')) != NULL
)
2372 } while(isspace(*ptr
));
2377 ALCdevice_DecRef(device
);
2382 /* alcGetProcAddress
2384 * Retrieves the function address for a particular extension function
2386 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
2388 ALCvoid
*ptr
= NULL
;
2392 device
= VerifyDevice(device
);
2393 alcSetError(device
, ALC_INVALID_VALUE
);
2394 if(device
) ALCdevice_DecRef(device
);
2399 while(alcFunctions
[i
].funcName
&& strcmp(alcFunctions
[i
].funcName
, funcName
) != 0)
2401 ptr
= alcFunctions
[i
].address
;
2410 * Get the value for a particular ALC enumeration name
2412 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
2418 device
= VerifyDevice(device
);
2419 alcSetError(device
, ALC_INVALID_VALUE
);
2420 if(device
) ALCdevice_DecRef(device
);
2425 while(enumeration
[i
].enumName
&& strcmp(enumeration
[i
].enumName
, enumName
) != 0)
2427 val
= enumeration
[i
].value
;
2436 * Create and attach a context to the given device.
2438 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
2440 ALCcontext
*ALContext
;
2444 if(!(device
=VerifyDevice(device
)) || device
->Type
== Capture
|| !device
->Connected
)
2447 alcSetError(device
, ALC_INVALID_DEVICE
);
2448 if(device
) ALCdevice_DecRef(device
);
2452 device
->LastError
= ALC_NO_ERROR
;
2454 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
2457 alcSetError(device
, err
);
2458 if(err
== ALC_INVALID_DEVICE
)
2459 aluHandleDisconnect(device
);
2460 ALCdevice_DecRef(device
);
2464 ALContext
= calloc(1, sizeof(ALCcontext
));
2469 ALContext
->MaxActiveSources
= 256;
2470 ALContext
->ActiveSources
= malloc(sizeof(ALContext
->ActiveSources
[0]) *
2471 ALContext
->MaxActiveSources
);
2473 if(!ALContext
|| !ALContext
->ActiveSources
)
2475 if(!device
->ContextList
)
2477 ALCdevice_StopPlayback(device
);
2478 device
->Flags
&= ~DEVICE_RUNNING
;
2485 alcSetError(device
, ALC_OUT_OF_MEMORY
);
2486 ALCdevice_DecRef(device
);
2490 ALContext
->Device
= device
;
2491 ALCdevice_IncRef(device
);
2492 InitContext(ALContext
);
2495 ALContext
->next
= device
->ContextList
;
2496 } while(!CompExchangePtr((XchgPtr
*)&device
->ContextList
, ALContext
->next
, ALContext
));
2499 ALCdevice_DecRef(device
);
2501 TRACE("Created context %p\n", ALContext
);
2505 /* alcDestroyContext
2507 * Remove a context from its device
2509 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
2514 /* alcGetContextsDevice sets an error for invalid contexts */
2515 Device
= alcGetContextsDevice(context
);
2518 ReleaseContext(context
, Device
);
2519 if(!Device
->ContextList
)
2521 ALCdevice_StopPlayback(Device
);
2522 Device
->Flags
&= ~DEVICE_RUNNING
;
2529 /* alcGetCurrentContext
2531 * Returns the currently active context on the calling thread
2533 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
2535 ALCcontext
*Context
;
2537 Context
= pthread_getspecific(LocalContext
);
2538 if(!Context
) Context
= GlobalContext
;
2543 /* alcGetThreadContext
2545 * Returns the currently active thread-local context
2547 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
2549 ALCcontext
*Context
;
2550 Context
= pthread_getspecific(LocalContext
);
2555 /* alcMakeContextCurrent
2557 * Makes the given context the active process-wide context, and removes the
2558 * thread-local context for the calling thread.
2560 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
2562 /* context must be valid or NULL */
2563 if(context
&& !(context
=VerifyContext(context
)))
2565 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2568 /* context's reference count is already incremented */
2569 context
= ExchangePtr((XchgPtr
*)&GlobalContext
, context
);
2570 if(context
) ALCcontext_DecRef(context
);
2572 if((context
=pthread_getspecific(LocalContext
)) != NULL
)
2574 pthread_setspecific(LocalContext
, NULL
);
2575 ALCcontext_DecRef(context
);
2581 /* alcSetThreadContext
2583 * Makes the given context the active context for the current thread
2585 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
2589 /* context must be valid or NULL */
2590 if(context
&& !(context
=VerifyContext(context
)))
2592 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2595 /* context's reference count is already incremented */
2596 old
= pthread_getspecific(LocalContext
);
2597 pthread_setspecific(LocalContext
, context
);
2598 if(old
) ALCcontext_DecRef(old
);
2604 /* alcGetContextsDevice
2606 * Returns the device that a particular context is attached to
2608 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
2612 if(!(Context
=VerifyContext(Context
)))
2614 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2617 Device
= Context
->Device
;
2618 ALCcontext_DecRef(Context
);
2626 * Opens the named device.
2628 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
2636 if(!PlaybackBackend
.name
)
2638 alcSetError(NULL
, ALC_INVALID_VALUE
);
2642 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
2645 device
= al_calloc(16, sizeof(ALCdevice
)+15+sizeof(ALeffectslot
));
2648 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
2653 device
->Funcs
= &PlaybackBackend
.Funcs
;
2655 device
->Connected
= ALC_TRUE
;
2656 device
->Type
= Playback
;
2657 InitializeCriticalSection(&device
->Mutex
);
2658 device
->LastError
= ALC_NO_ERROR
;
2661 device
->Bs2b
= NULL
;
2662 device
->Bs2bLevel
= 0;
2663 device
->DeviceName
= NULL
;
2665 device
->ContextList
= NULL
;
2667 device
->MaxNoOfSources
= 256;
2668 device
->AuxiliaryEffectSlotMax
= 4;
2669 device
->NumAuxSends
= MAX_SENDS
;
2671 InitUIntMap(&device
->BufferMap
, ~0);
2672 InitUIntMap(&device
->EffectMap
, ~0);
2673 InitUIntMap(&device
->FilterMap
, ~0);
2676 device
->FmtChans
= DevFmtChannelsDefault
;
2677 device
->FmtType
= DevFmtTypeDefault
;
2678 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
2679 device
->NumUpdates
= 4;
2680 device
->UpdateSize
= 1024;
2682 if(ConfigValueStr(NULL
, "channels", &fmt
))
2684 static const struct {
2685 const char name
[16];
2686 enum DevFmtChannels chans
;
2688 { "mono", DevFmtMono
},
2689 { "stereo", DevFmtStereo
},
2690 { "quad", DevFmtQuad
},
2691 { "surround51", DevFmtX51
},
2692 { "surround61", DevFmtX61
},
2693 { "surround71", DevFmtX71
},
2697 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
2699 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
2701 device
->FmtChans
= chanlist
[i
].chans
;
2702 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
2706 if(i
== COUNTOF(chanlist
))
2707 ERR("Unsupported channels: %s\n", fmt
);
2709 if(ConfigValueStr(NULL
, "sample-type", &fmt
))
2711 static const struct {
2712 const char name
[16];
2713 enum DevFmtType type
;
2715 { "int8", DevFmtByte
},
2716 { "uint8", DevFmtUByte
},
2717 { "int16", DevFmtShort
},
2718 { "uint16", DevFmtUShort
},
2719 { "int32", DevFmtInt
},
2720 { "uint32", DevFmtUInt
},
2721 { "float32", DevFmtFloat
},
2725 for(i
= 0;i
< COUNTOF(typelist
);i
++)
2727 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
2729 device
->FmtType
= typelist
[i
].type
;
2730 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
2734 if(i
== COUNTOF(typelist
))
2735 ERR("Unsupported sample-type: %s\n", fmt
);
2737 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
2738 if((device
->Flags
&DEVICE_FORMAT_REQUEST
) != DEVICE_FORMAT_REQUEST
&&
2739 ConfigValueStr(NULL
, "format", &fmt
))
2741 static const struct {
2742 const char name
[32];
2743 enum DevFmtChannels channels
;
2744 enum DevFmtType type
;
2746 { "AL_FORMAT_MONO32", DevFmtMono
, DevFmtFloat
},
2747 { "AL_FORMAT_STEREO32", DevFmtStereo
, DevFmtFloat
},
2748 { "AL_FORMAT_QUAD32", DevFmtQuad
, DevFmtFloat
},
2749 { "AL_FORMAT_51CHN32", DevFmtX51
, DevFmtFloat
},
2750 { "AL_FORMAT_61CHN32", DevFmtX61
, DevFmtFloat
},
2751 { "AL_FORMAT_71CHN32", DevFmtX71
, DevFmtFloat
},
2753 { "AL_FORMAT_MONO16", DevFmtMono
, DevFmtShort
},
2754 { "AL_FORMAT_STEREO16", DevFmtStereo
, DevFmtShort
},
2755 { "AL_FORMAT_QUAD16", DevFmtQuad
, DevFmtShort
},
2756 { "AL_FORMAT_51CHN16", DevFmtX51
, DevFmtShort
},
2757 { "AL_FORMAT_61CHN16", DevFmtX61
, DevFmtShort
},
2758 { "AL_FORMAT_71CHN16", DevFmtX71
, DevFmtShort
},
2760 { "AL_FORMAT_MONO8", DevFmtMono
, DevFmtByte
},
2761 { "AL_FORMAT_STEREO8", DevFmtStereo
, DevFmtByte
},
2762 { "AL_FORMAT_QUAD8", DevFmtQuad
, DevFmtByte
},
2763 { "AL_FORMAT_51CHN8", DevFmtX51
, DevFmtByte
},
2764 { "AL_FORMAT_61CHN8", DevFmtX61
, DevFmtByte
},
2765 { "AL_FORMAT_71CHN8", DevFmtX71
, DevFmtByte
}
2769 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
2770 for(i
= 0;i
< COUNTOF(formats
);i
++)
2772 if(strcasecmp(fmt
, formats
[i
].name
) == 0)
2774 if(!(device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2775 device
->FmtChans
= formats
[i
].channels
;
2776 if(!(device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2777 device
->FmtType
= formats
[i
].type
;
2778 device
->Flags
|= DEVICE_FORMAT_REQUEST
;
2782 if(i
== COUNTOF(formats
))
2783 ERR("Unsupported format: %s\n", fmt
);
2785 #undef DEVICE_FORMAT_REQUEST
2787 if(ConfigValueUInt(NULL
, "frequency", &device
->Frequency
))
2789 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
2790 if(device
->Frequency
< MIN_OUTPUT_RATE
)
2791 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
2792 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
2795 ConfigValueUInt(NULL
, "periods", &device
->NumUpdates
);
2796 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
2798 ConfigValueUInt(NULL
, "period_size", &device
->UpdateSize
);
2799 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
2800 if((CPUCapFlags
&CPU_CAP_SSE
))
2801 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
2803 ConfigValueUInt(NULL
, "sources", &device
->MaxNoOfSources
);
2804 if(device
->MaxNoOfSources
== 0) device
->MaxNoOfSources
= 256;
2806 ConfigValueUInt(NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
2807 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 4;
2809 ConfigValueUInt(NULL
, "sends", &device
->NumAuxSends
);
2810 if(device
->NumAuxSends
> MAX_SENDS
) device
->NumAuxSends
= MAX_SENDS
;
2812 ConfigValueInt(NULL
, "cf_level", &device
->Bs2bLevel
);
2814 device
->NumStereoSources
= 1;
2815 device
->NumMonoSources
= device
->MaxNoOfSources
- device
->NumStereoSources
;
2817 // Find a playback device to open
2818 if((err
=ALCdevice_OpenPlayback(device
, deviceName
)) != ALC_NO_ERROR
)
2820 DeleteCriticalSection(&device
->Mutex
);
2822 alcSetError(NULL
, err
);
2826 if(DefaultEffect
.type
!= AL_EFFECT_NULL
)
2828 device
->DefaultSlot
= (ALeffectslot
*)(((ALintptrEXT
)(device
+1)+15)&~15);
2829 if(InitEffectSlot(device
->DefaultSlot
) != AL_NO_ERROR
)
2831 device
->DefaultSlot
= NULL
;
2832 ERR("Failed to initialize the default effect slot\n");
2834 else if(InitializeEffect(device
, device
->DefaultSlot
, &DefaultEffect
) != AL_NO_ERROR
)
2836 ALeffectState_Destroy(device
->DefaultSlot
->EffectState
);
2837 device
->DefaultSlot
= NULL
;
2838 ERR("Failed to initialize the default effect\n");
2843 device
->next
= DeviceList
;
2844 } while(!CompExchangePtr((XchgPtr
*)&DeviceList
, device
->next
, device
));
2846 TRACE("Created device %p, \"%s\"\n", device
, device
->DeviceName
);
2852 * Closes the given device.
2854 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*Device
)
2856 ALCdevice
*volatile*list
;
2861 while(*list
&& *list
!= Device
)
2862 list
= &(*list
)->next
;
2864 if(!*list
|| (*list
)->Type
== Capture
)
2866 alcSetError(*list
, ALC_INVALID_DEVICE
);
2871 *list
= (*list
)->next
;
2874 while((ctx
=Device
->ContextList
) != NULL
)
2876 WARN("Releasing context %p\n", ctx
);
2877 ReleaseContext(ctx
, Device
);
2879 if((Device
->Flags
&DEVICE_RUNNING
))
2880 ALCdevice_StopPlayback(Device
);
2881 Device
->Flags
&= ~DEVICE_RUNNING
;
2883 ALCdevice_DecRef(Device
);
2889 /************************************************
2890 * ALC capture functions
2891 ************************************************/
2892 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
2894 ALCdevice
*device
= NULL
;
2899 if(!CaptureBackend
.name
)
2901 alcSetError(NULL
, ALC_INVALID_VALUE
);
2907 alcSetError(NULL
, ALC_INVALID_VALUE
);
2911 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
2914 device
= al_calloc(16, sizeof(ALCdevice
));
2917 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
2922 device
->Funcs
= &CaptureBackend
.Funcs
;
2924 device
->Connected
= ALC_TRUE
;
2925 device
->Type
= Capture
;
2926 InitializeCriticalSection(&device
->Mutex
);
2928 InitUIntMap(&device
->BufferMap
, ~0);
2929 InitUIntMap(&device
->EffectMap
, ~0);
2930 InitUIntMap(&device
->FilterMap
, ~0);
2932 device
->DeviceName
= NULL
;
2934 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
2935 device
->Frequency
= frequency
;
2937 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
2938 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
2940 DeleteCriticalSection(&device
->Mutex
);
2942 alcSetError(NULL
, ALC_INVALID_ENUM
);
2946 device
->UpdateSize
= samples
;
2947 device
->NumUpdates
= 1;
2949 if((err
=ALCdevice_OpenCapture(device
, deviceName
)) != ALC_NO_ERROR
)
2951 DeleteCriticalSection(&device
->Mutex
);
2953 alcSetError(NULL
, err
);
2958 device
->next
= DeviceList
;
2959 } while(!CompExchangePtr((XchgPtr
*)&DeviceList
, device
->next
, device
));
2961 TRACE("Created device %p\n", device
);
2965 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*Device
)
2967 ALCdevice
*volatile*list
;
2971 while(*list
&& *list
!= Device
)
2972 list
= &(*list
)->next
;
2974 if(!*list
|| (*list
)->Type
!= Capture
)
2976 alcSetError(*list
, ALC_INVALID_DEVICE
);
2981 *list
= (*list
)->next
;
2984 ALCdevice_DecRef(Device
);
2989 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
2991 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Capture
)
2992 alcSetError(device
, ALC_INVALID_DEVICE
);
2995 ALCdevice_Lock(device
);
2996 if(device
->Connected
)
2998 if(!(device
->Flags
&DEVICE_RUNNING
))
2999 ALCdevice_StartCapture(device
);
3000 device
->Flags
|= DEVICE_RUNNING
;
3002 ALCdevice_Unlock(device
);
3005 if(device
) ALCdevice_DecRef(device
);
3008 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
3010 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Capture
)
3011 alcSetError(device
, ALC_INVALID_DEVICE
);
3014 ALCdevice_Lock(device
);
3015 if((device
->Flags
&DEVICE_RUNNING
))
3016 ALCdevice_StopCapture(device
);
3017 device
->Flags
&= ~DEVICE_RUNNING
;
3018 ALCdevice_Unlock(device
);
3021 if(device
) ALCdevice_DecRef(device
);
3024 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
3026 if(!(device
=VerifyDevice(device
)) && device
->Type
!= Capture
)
3027 alcSetError(device
, ALC_INVALID_DEVICE
);
3030 ALCenum err
= ALC_INVALID_VALUE
;
3032 ALCdevice_Lock(device
);
3033 if(samples
>= 0 && ALCdevice_AvailableSamples(device
) >= (ALCuint
)samples
)
3034 err
= ALCdevice_CaptureSamples(device
, buffer
, samples
);
3035 ALCdevice_Unlock(device
);
3037 if(err
!= ALC_NO_ERROR
)
3038 alcSetError(device
, err
);
3040 if(device
) ALCdevice_DecRef(device
);
3044 /************************************************
3045 * ALC loopback functions
3046 ************************************************/
3048 /* alcLoopbackOpenDeviceSOFT
3050 * Open a loopback device, for manual rendering.
3052 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
3058 /* Make sure the device name, if specified, is us. */
3059 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
3061 alcSetError(NULL
, ALC_INVALID_VALUE
);
3065 device
= al_calloc(16, sizeof(ALCdevice
));
3068 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3073 device
->Funcs
= &BackendLoopback
.Funcs
;
3075 device
->Connected
= ALC_TRUE
;
3076 device
->Type
= Loopback
;
3077 InitializeCriticalSection(&device
->Mutex
);
3078 device
->LastError
= ALC_NO_ERROR
;
3081 device
->Bs2b
= NULL
;
3082 device
->Bs2bLevel
= 0;
3083 device
->DeviceName
= NULL
;
3085 device
->ContextList
= NULL
;
3087 device
->MaxNoOfSources
= 256;
3088 device
->AuxiliaryEffectSlotMax
= 4;
3089 device
->NumAuxSends
= MAX_SENDS
;
3091 InitUIntMap(&device
->BufferMap
, ~0);
3092 InitUIntMap(&device
->EffectMap
, ~0);
3093 InitUIntMap(&device
->FilterMap
, ~0);
3096 device
->NumUpdates
= 0;
3097 device
->UpdateSize
= 0;
3099 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3100 device
->FmtChans
= DevFmtChannelsDefault
;
3101 device
->FmtType
= DevFmtTypeDefault
;
3103 ConfigValueUInt(NULL
, "sources", &device
->MaxNoOfSources
);
3104 if(device
->MaxNoOfSources
== 0) device
->MaxNoOfSources
= 256;
3106 ConfigValueUInt(NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
3107 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 4;
3109 ConfigValueUInt(NULL
, "sends", &device
->NumAuxSends
);
3110 if(device
->NumAuxSends
> MAX_SENDS
) device
->NumAuxSends
= MAX_SENDS
;
3112 device
->NumStereoSources
= 1;
3113 device
->NumMonoSources
= device
->MaxNoOfSources
- device
->NumStereoSources
;
3115 // Open the "backend"
3116 ALCdevice_OpenPlayback(device
, "Loopback");
3118 device
->next
= DeviceList
;
3119 } while(!CompExchangePtr((XchgPtr
*)&DeviceList
, device
->next
, device
));
3121 TRACE("Created device %p\n", device
);
3125 /* alcIsRenderFormatSupportedSOFT
3127 * Determines if the loopback device supports the given format for rendering.
3129 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
3131 ALCboolean ret
= ALC_FALSE
;
3133 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Loopback
)
3134 alcSetError(device
, ALC_INVALID_DEVICE
);
3136 alcSetError(device
, ALC_INVALID_VALUE
);
3139 if(IsValidALCType(type
) && BytesFromDevFmt(type
) > 0 &&
3140 IsValidALCChannels(channels
) && ChannelsFromDevFmt(channels
) > 0 &&
3141 freq
>= MIN_OUTPUT_RATE
)
3144 if(device
) ALCdevice_DecRef(device
);
3149 /* alcRenderSamplesSOFT
3151 * Renders some samples into a buffer, using the format last set by the
3152 * attributes given to alcCreateContext.
3154 ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
3156 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Loopback
)
3157 alcSetError(device
, ALC_INVALID_DEVICE
);
3158 else if(samples
< 0 || (samples
> 0 && buffer
== NULL
))
3159 alcSetError(device
, ALC_INVALID_VALUE
);
3161 aluMixData(device
, buffer
, samples
);
3162 if(device
) ALCdevice_DecRef(device
);