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(alGetSourcei64SOFT
),
259 DECL(alGetSource3i64SOFT
),
260 DECL(alGetSourcei64vSOFT
),
266 #define DECL(x) { #x, (x) }
267 static const ALCenums enumeration
[] = {
272 DECL(ALC_MAJOR_VERSION
),
273 DECL(ALC_MINOR_VERSION
),
274 DECL(ALC_ATTRIBUTES_SIZE
),
275 DECL(ALC_ALL_ATTRIBUTES
),
276 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
277 DECL(ALC_DEVICE_SPECIFIER
),
278 DECL(ALC_ALL_DEVICES_SPECIFIER
),
279 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
280 DECL(ALC_EXTENSIONS
),
284 DECL(ALC_MONO_SOURCES
),
285 DECL(ALC_STEREO_SOURCES
),
286 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
287 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
288 DECL(ALC_CAPTURE_SAMPLES
),
291 DECL(ALC_EFX_MAJOR_VERSION
),
292 DECL(ALC_EFX_MINOR_VERSION
),
293 DECL(ALC_MAX_AUXILIARY_SENDS
),
295 DECL(ALC_FORMAT_CHANNELS_SOFT
),
296 DECL(ALC_FORMAT_TYPE_SOFT
),
299 DECL(ALC_STEREO_SOFT
),
301 DECL(ALC_5POINT1_SOFT
),
302 DECL(ALC_6POINT1_SOFT
),
303 DECL(ALC_7POINT1_SOFT
),
306 DECL(ALC_UNSIGNED_BYTE_SOFT
),
307 DECL(ALC_SHORT_SOFT
),
308 DECL(ALC_UNSIGNED_SHORT_SOFT
),
310 DECL(ALC_UNSIGNED_INT_SOFT
),
311 DECL(ALC_FLOAT_SOFT
),
314 DECL(ALC_INVALID_DEVICE
),
315 DECL(ALC_INVALID_CONTEXT
),
316 DECL(ALC_INVALID_ENUM
),
317 DECL(ALC_INVALID_VALUE
),
318 DECL(ALC_OUT_OF_MEMORY
),
326 DECL(AL_SOURCE_RELATIVE
),
327 DECL(AL_CONE_INNER_ANGLE
),
328 DECL(AL_CONE_OUTER_ANGLE
),
338 DECL(AL_ORIENTATION
),
339 DECL(AL_REFERENCE_DISTANCE
),
340 DECL(AL_ROLLOFF_FACTOR
),
341 DECL(AL_CONE_OUTER_GAIN
),
342 DECL(AL_MAX_DISTANCE
),
344 DECL(AL_SAMPLE_OFFSET
),
345 DECL(AL_SAMPLE_RW_OFFSETS_SOFT
),
346 DECL(AL_BYTE_OFFSET
),
347 DECL(AL_BYTE_RW_OFFSETS_SOFT
),
348 DECL(AL_SOURCE_TYPE
),
351 DECL(AL_UNDETERMINED
),
352 DECL(AL_METERS_PER_UNIT
),
353 DECL(AL_DIRECT_CHANNELS_SOFT
),
355 DECL(AL_DIRECT_FILTER
),
356 DECL(AL_AUXILIARY_SEND_FILTER
),
357 DECL(AL_AIR_ABSORPTION_FACTOR
),
358 DECL(AL_ROOM_ROLLOFF_FACTOR
),
359 DECL(AL_CONE_OUTER_GAINHF
),
360 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
361 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
362 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
364 DECL(AL_SOURCE_STATE
),
370 DECL(AL_BUFFERS_QUEUED
),
371 DECL(AL_BUFFERS_PROCESSED
),
373 DECL(AL_FORMAT_MONO8
),
374 DECL(AL_FORMAT_MONO16
),
375 DECL(AL_FORMAT_MONO_FLOAT32
),
376 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
377 DECL(AL_FORMAT_STEREO8
),
378 DECL(AL_FORMAT_STEREO16
),
379 DECL(AL_FORMAT_STEREO_FLOAT32
),
380 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
381 DECL(AL_FORMAT_MONO_IMA4
),
382 DECL(AL_FORMAT_STEREO_IMA4
),
383 DECL(AL_FORMAT_QUAD8_LOKI
),
384 DECL(AL_FORMAT_QUAD16_LOKI
),
385 DECL(AL_FORMAT_QUAD8
),
386 DECL(AL_FORMAT_QUAD16
),
387 DECL(AL_FORMAT_QUAD32
),
388 DECL(AL_FORMAT_51CHN8
),
389 DECL(AL_FORMAT_51CHN16
),
390 DECL(AL_FORMAT_51CHN32
),
391 DECL(AL_FORMAT_61CHN8
),
392 DECL(AL_FORMAT_61CHN16
),
393 DECL(AL_FORMAT_61CHN32
),
394 DECL(AL_FORMAT_71CHN8
),
395 DECL(AL_FORMAT_71CHN16
),
396 DECL(AL_FORMAT_71CHN32
),
397 DECL(AL_FORMAT_REAR8
),
398 DECL(AL_FORMAT_REAR16
),
399 DECL(AL_FORMAT_REAR32
),
400 DECL(AL_FORMAT_MONO_MULAW
),
401 DECL(AL_FORMAT_MONO_MULAW_EXT
),
402 DECL(AL_FORMAT_STEREO_MULAW
),
403 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
404 DECL(AL_FORMAT_QUAD_MULAW
),
405 DECL(AL_FORMAT_51CHN_MULAW
),
406 DECL(AL_FORMAT_61CHN_MULAW
),
407 DECL(AL_FORMAT_71CHN_MULAW
),
408 DECL(AL_FORMAT_REAR_MULAW
),
409 DECL(AL_FORMAT_MONO_ALAW_EXT
),
410 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
413 DECL(AL_MONO16_SOFT
),
414 DECL(AL_MONO32F_SOFT
),
415 DECL(AL_STEREO8_SOFT
),
416 DECL(AL_STEREO16_SOFT
),
417 DECL(AL_STEREO32F_SOFT
),
419 DECL(AL_QUAD16_SOFT
),
420 DECL(AL_QUAD32F_SOFT
),
422 DECL(AL_REAR16_SOFT
),
423 DECL(AL_REAR32F_SOFT
),
424 DECL(AL_5POINT1_8_SOFT
),
425 DECL(AL_5POINT1_16_SOFT
),
426 DECL(AL_5POINT1_32F_SOFT
),
427 DECL(AL_6POINT1_8_SOFT
),
428 DECL(AL_6POINT1_16_SOFT
),
429 DECL(AL_6POINT1_32F_SOFT
),
430 DECL(AL_7POINT1_8_SOFT
),
431 DECL(AL_7POINT1_16_SOFT
),
432 DECL(AL_7POINT1_32F_SOFT
),
435 DECL(AL_STEREO_SOFT
),
438 DECL(AL_5POINT1_SOFT
),
439 DECL(AL_6POINT1_SOFT
),
440 DECL(AL_7POINT1_SOFT
),
443 DECL(AL_UNSIGNED_BYTE_SOFT
),
445 DECL(AL_UNSIGNED_SHORT_SOFT
),
447 DECL(AL_UNSIGNED_INT_SOFT
),
449 DECL(AL_DOUBLE_SOFT
),
451 DECL(AL_UNSIGNED_BYTE3_SOFT
),
457 DECL(AL_INTERNAL_FORMAT_SOFT
),
458 DECL(AL_BYTE_LENGTH_SOFT
),
459 DECL(AL_SAMPLE_LENGTH_SOFT
),
460 DECL(AL_SEC_LENGTH_SOFT
),
467 DECL(AL_INVALID_NAME
),
468 DECL(AL_INVALID_ENUM
),
469 DECL(AL_INVALID_VALUE
),
470 DECL(AL_INVALID_OPERATION
),
471 DECL(AL_OUT_OF_MEMORY
),
478 DECL(AL_DOPPLER_FACTOR
),
479 DECL(AL_DOPPLER_VELOCITY
),
480 DECL(AL_DISTANCE_MODEL
),
481 DECL(AL_SPEED_OF_SOUND
),
482 DECL(AL_SOURCE_DISTANCE_MODEL
),
483 DECL(AL_DEFERRED_UPDATES_SOFT
),
485 DECL(AL_INVERSE_DISTANCE
),
486 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
487 DECL(AL_LINEAR_DISTANCE
),
488 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
489 DECL(AL_EXPONENT_DISTANCE
),
490 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
492 DECL(AL_FILTER_TYPE
),
493 DECL(AL_FILTER_NULL
),
494 DECL(AL_FILTER_LOWPASS
),
496 DECL(AL_FILTER_HIGHPASS
),
497 DECL(AL_FILTER_BANDPASS
),
500 DECL(AL_LOWPASS_GAIN
),
501 DECL(AL_LOWPASS_GAINHF
),
503 DECL(AL_EFFECT_TYPE
),
504 DECL(AL_EFFECT_NULL
),
505 DECL(AL_EFFECT_REVERB
),
506 DECL(AL_EFFECT_EAXREVERB
),
508 DECL(AL_EFFECT_CHORUS
),
509 DECL(AL_EFFECT_DISTORTION
),
511 DECL(AL_EFFECT_ECHO
),
513 DECL(AL_EFFECT_FLANGER
),
514 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
515 DECL(AL_EFFECT_VOCAL_MORPHER
),
516 DECL(AL_EFFECT_PITCH_SHIFTER
),
518 DECL(AL_EFFECT_RING_MODULATOR
),
520 DECL(AL_EFFECT_AUTOWAH
),
521 DECL(AL_EFFECT_COMPRESSOR
),
522 DECL(AL_EFFECT_EQUALIZER
),
524 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
525 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
527 DECL(AL_EAXREVERB_DENSITY
),
528 DECL(AL_EAXREVERB_DIFFUSION
),
529 DECL(AL_EAXREVERB_GAIN
),
530 DECL(AL_EAXREVERB_GAINHF
),
531 DECL(AL_EAXREVERB_GAINLF
),
532 DECL(AL_EAXREVERB_DECAY_TIME
),
533 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
534 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
535 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
536 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
537 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
538 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
539 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
540 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
541 DECL(AL_EAXREVERB_ECHO_TIME
),
542 DECL(AL_EAXREVERB_ECHO_DEPTH
),
543 DECL(AL_EAXREVERB_MODULATION_TIME
),
544 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
545 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
546 DECL(AL_EAXREVERB_HFREFERENCE
),
547 DECL(AL_EAXREVERB_LFREFERENCE
),
548 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
549 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
551 DECL(AL_REVERB_DENSITY
),
552 DECL(AL_REVERB_DIFFUSION
),
553 DECL(AL_REVERB_GAIN
),
554 DECL(AL_REVERB_GAINHF
),
555 DECL(AL_REVERB_DECAY_TIME
),
556 DECL(AL_REVERB_DECAY_HFRATIO
),
557 DECL(AL_REVERB_REFLECTIONS_GAIN
),
558 DECL(AL_REVERB_REFLECTIONS_DELAY
),
559 DECL(AL_REVERB_LATE_REVERB_GAIN
),
560 DECL(AL_REVERB_LATE_REVERB_DELAY
),
561 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
562 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
563 DECL(AL_REVERB_DECAY_HFLIMIT
),
566 DECL(AL_ECHO_LRDELAY
),
567 DECL(AL_ECHO_DAMPING
),
568 DECL(AL_ECHO_FEEDBACK
),
569 DECL(AL_ECHO_SPREAD
),
571 DECL(AL_RING_MODULATOR_FREQUENCY
),
572 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
573 DECL(AL_RING_MODULATOR_WAVEFORM
),
575 DECL(AL_DEDICATED_GAIN
),
581 static const ALCchar alcNoError
[] = "No Error";
582 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
583 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
584 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
585 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
586 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
589 /************************************************
591 ************************************************/
593 /* Enumerated device names */
594 static const ALCchar alcDefaultName
[] = "OpenAL Soft\0";
595 static ALCchar
*alcAllDevicesList
;
596 static ALCchar
*alcCaptureDeviceList
;
597 /* Sizes only include the first ending null character, not the second */
598 static size_t alcAllDevicesListSize
;
599 static size_t alcCaptureDeviceListSize
;
601 /* Default is always the first in the list */
602 static ALCchar
*alcDefaultAllDevicesSpecifier
;
603 static ALCchar
*alcCaptureDefaultDeviceSpecifier
;
605 /* Default context extensions */
606 static const ALchar alExtList
[] =
607 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
608 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
609 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
610 "AL_LOKI_quadriphonic AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data "
611 "AL_SOFTX_deferred_updates AL_SOFT_direct_channels AL_SOFT_loop_points";
613 static volatile ALCenum LastNullDeviceError
= ALC_NO_ERROR
;
615 /* Thread-local current context */
616 static pthread_key_t LocalContext
;
617 /* Process-wide current context */
618 static ALCcontext
*volatile GlobalContext
= NULL
;
620 /* Mixing thread piority level */
625 enum LogLevel LogLevel
= LogWarning
;
627 enum LogLevel LogLevel
= LogError
;
630 /* Flag to trap ALC device errors */
631 static ALCboolean TrapALCError
= ALC_FALSE
;
633 /* One-time configuration init control */
634 static pthread_once_t alc_config_once
= PTHREAD_ONCE_INIT
;
636 /* Default effect that applies to sources that don't have an effect on send 0 */
637 static ALeffect DefaultEffect
;
640 /************************************************
642 ************************************************/
643 static const ALCchar alcNoDeviceExtList
[] =
644 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
645 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
646 static const ALCchar alcExtensionList
[] =
647 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
648 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
649 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
650 static const ALCint alcMajorVersion
= 1;
651 static const ALCint alcMinorVersion
= 1;
653 static const ALCint alcEFXMajorVersion
= 1;
654 static const ALCint alcEFXMinorVersion
= 0;
657 /************************************************
659 ************************************************/
660 static ALCdevice
*volatile DeviceList
= NULL
;
662 static CRITICAL_SECTION ListLock
;
664 static void LockLists(void)
666 EnterCriticalSection(&ListLock
);
668 static void UnlockLists(void)
670 LeaveCriticalSection(&ListLock
);
673 /************************************************
674 * Library initialization
675 ************************************************/
677 static void alc_init(void);
678 static void alc_deinit(void);
679 static void alc_deinit_safe(void);
681 UIntMap TlsDestructor
;
683 #ifndef AL_LIBTYPE_STATIC
684 BOOL APIENTRY
DllMain(HINSTANCE hModule
,DWORD ul_reason_for_call
,LPVOID lpReserved
)
688 // Perform actions based on the reason for calling.
689 switch(ul_reason_for_call
)
691 case DLL_PROCESS_ATTACH
:
692 /* Pin the DLL so we won't get unloaded until the process terminates */
693 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
694 (WCHAR
*)hModule
, &hModule
);
695 InitUIntMap(&TlsDestructor
, ~0);
699 case DLL_THREAD_DETACH
:
700 LockUIntMapRead(&TlsDestructor
);
701 for(i
= 0;i
< TlsDestructor
.size
;i
++)
703 void *ptr
= pthread_getspecific(TlsDestructor
.array
[i
].key
);
704 void (*callback
)(void*) = (void(*)(void*))TlsDestructor
.array
[i
].value
;
708 UnlockUIntMapRead(&TlsDestructor
);
711 case DLL_PROCESS_DETACH
:
716 ResetUIntMap(&TlsDestructor
);
721 #elif defined(_MSC_VER)
722 #pragma section(".CRT$XCU",read)
723 static void alc_constructor(void);
724 static void alc_destructor(void);
725 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
727 static void alc_constructor(void)
729 atexit(alc_destructor
);
733 static void alc_destructor(void)
737 #elif defined(HAVE_GCC_DESTRUCTOR)
738 static void alc_init(void) __attribute__((constructor
));
739 static void alc_deinit(void) __attribute__((destructor
));
741 #error "No static initialization available on this platform!"
744 #elif defined(HAVE_GCC_DESTRUCTOR)
746 static void alc_init(void) __attribute__((constructor
));
747 static void alc_deinit(void) __attribute__((destructor
));
750 #error "No global initialization available on this platform!"
753 static void ReleaseThreadCtx(void *ptr
);
754 static void alc_init(void)
760 str
= getenv("__ALSOFT_HALF_ANGLE_CONES");
761 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
764 str
= getenv("__ALSOFT_REVERSE_Z");
765 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
768 pthread_key_create(&LocalContext
, ReleaseThreadCtx
);
769 InitializeCriticalSection(&ListLock
);
773 static void alc_initconfig(void)
775 const char *devs
, *str
;
780 str
= getenv("ALSOFT_LOGLEVEL");
783 long lvl
= strtol(str
, NULL
, 0);
784 if(lvl
>= NoLog
&& lvl
<= LogRef
)
788 str
= getenv("ALSOFT_LOGFILE");
791 FILE *logfile
= fopen(str
, "wat");
792 if(logfile
) LogFile
= logfile
;
793 else ERR("Failed to open log file '%s'\n", str
);
800 capfilter
|= CPU_CAP_SSE
;
803 capfilter
|= CPU_CAP_NEON
;
805 if(ConfigValueStr(NULL
, "disable-cpu-exts", &str
))
807 if(strcasecmp(str
, "all") == 0)
812 const char *next
= str
;
817 next
= strchr(str
, ',');
819 while(isspace(str
[0]))
821 if(!str
[0] || str
[0] == ',')
824 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
825 if(strncasecmp(str
, "sse", len
) == 0)
826 capfilter
&= ~CPU_CAP_SSE
;
827 else if(strncasecmp(str
, "neon", len
) == 0)
828 capfilter
&= ~CPU_CAP_NEON
;
830 WARN("Invalid CPU extension \"%s\"\n", str
);
834 FillCPUCaps(capfilter
);
843 ConfigValueInt(NULL
, "rt-prio", &RTPrioLevel
);
845 if(ConfigValueStr(NULL
, "resampler", &str
))
847 if(strcasecmp(str
, "point") == 0 || strcasecmp(str
, "none") == 0)
848 DefaultResampler
= PointResampler
;
849 else if(strcasecmp(str
, "linear") == 0)
850 DefaultResampler
= LinearResampler
;
851 else if(strcasecmp(str
, "cubic") == 0)
852 DefaultResampler
= CubicResampler
;
857 n
= strtol(str
, &end
, 0);
858 if(*end
== '\0' && (n
== PointResampler
|| n
== LinearResampler
|| n
== CubicResampler
))
859 DefaultResampler
= n
;
861 WARN("Invalid resampler: %s\n", str
);
865 str
= getenv("ALSOFT_TRAP_ERROR");
866 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
868 TrapALError
= AL_TRUE
;
869 TrapALCError
= AL_TRUE
;
873 str
= getenv("ALSOFT_TRAP_AL_ERROR");
874 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
875 TrapALError
= AL_TRUE
;
876 TrapALError
= GetConfigValueBool(NULL
, "trap-al-error", TrapALError
);
878 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
879 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
880 TrapALCError
= ALC_TRUE
;
881 TrapALCError
= GetConfigValueBool(NULL
, "trap-alc-error", TrapALCError
);
884 if(ConfigValueFloat("reverb", "boost", &valf
))
885 ReverbBoost
*= powf(10.0f
, valf
/ 20.0f
);
887 EmulateEAXReverb
= GetConfigValueBool("reverb", "emulate-eax", AL_FALSE
);
889 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
890 ConfigValueStr(NULL
, "drivers", &devs
))
894 const char *next
= devs
;
895 int endlist
, delitem
;
900 next
= strchr(devs
, ',');
902 delitem
= (devs
[0] == '-');
903 if(devs
[0] == '-') devs
++;
905 if(!devs
[0] || devs
[0] == ',')
912 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
913 for(n
= i
;BackendList
[n
].Init
;n
++)
915 if(len
== strlen(BackendList
[n
].name
) &&
916 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
921 BackendList
[n
] = BackendList
[n
+1];
923 } while(BackendList
[n
].Init
);
927 struct BackendInfo Bkp
= BackendList
[n
];
930 BackendList
[n
] = BackendList
[n
-1];
933 BackendList
[n
] = Bkp
;
944 BackendList
[i
].name
= NULL
;
945 BackendList
[i
].Init
= NULL
;
946 BackendList
[i
].Deinit
= NULL
;
947 BackendList
[i
].Probe
= NULL
;
951 for(i
= 0;BackendList
[i
].Init
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
953 if(!BackendList
[i
].Init(&BackendList
[i
].Funcs
))
955 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
959 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
960 if(BackendList
[i
].Funcs
.OpenPlayback
&& !PlaybackBackend
.name
)
962 PlaybackBackend
= BackendList
[i
];
963 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
965 if(BackendList
[i
].Funcs
.OpenCapture
&& !CaptureBackend
.name
)
967 CaptureBackend
= BackendList
[i
];
968 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
971 BackendLoopback
.Init(&BackendLoopback
.Funcs
);
973 if(ConfigValueStr(NULL
, "excludefx", &str
))
976 const char *next
= str
;
980 next
= strchr(str
, ',');
982 if(!str
[0] || next
== str
)
985 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
986 for(n
= 0;EffectList
[n
].name
;n
++)
988 if(len
== strlen(EffectList
[n
].name
) &&
989 strncmp(EffectList
[n
].name
, str
, len
) == 0)
990 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
995 InitEffect(&DefaultEffect
);
996 str
= getenv("ALSOFT_DEFAULT_REVERB");
997 if((str
&& str
[0]) || ConfigValueStr(NULL
, "default-reverb", &str
))
998 LoadReverbPreset(str
, &DefaultEffect
);
1000 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
1003 /************************************************
1004 * Library deinitialization
1005 ************************************************/
1006 static void alc_cleanup(void)
1010 free(alcAllDevicesList
); alcAllDevicesList
= NULL
;
1011 alcAllDevicesListSize
= 0;
1012 free(alcCaptureDeviceList
); alcCaptureDeviceList
= NULL
;
1013 alcCaptureDeviceListSize
= 0;
1015 free(alcDefaultAllDevicesSpecifier
);
1016 alcDefaultAllDevicesSpecifier
= NULL
;
1017 free(alcCaptureDefaultDeviceSpecifier
);
1018 alcCaptureDefaultDeviceSpecifier
= NULL
;
1020 if((dev
=ExchangePtr((XchgPtr
*)&DeviceList
, NULL
)) != NULL
)
1025 } while((dev
=dev
->next
) != NULL
);
1026 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1030 static void alc_deinit_safe(void)
1038 DeleteCriticalSection(&ListLock
);
1039 pthread_key_delete(LocalContext
);
1041 if(LogFile
!= stderr
)
1046 static void alc_deinit(void)
1052 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1053 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1055 for(i
= 0;BackendList
[i
].Deinit
;i
++)
1056 BackendList
[i
].Deinit();
1057 BackendLoopback
.Deinit();
1063 /************************************************
1064 * Device enumeration
1065 ************************************************/
1066 static void ProbeList(ALCchar
**list
, size_t *listsize
, enum DevProbe type
)
1075 if(type
== ALL_DEVICE_PROBE
&& PlaybackBackend
.Probe
)
1076 PlaybackBackend
.Probe(type
);
1077 else if(type
== CAPTURE_DEVICE_PROBE
&& CaptureBackend
.Probe
)
1078 CaptureBackend
.Probe(type
);
1082 static void ProbeAllDevicesList(void)
1083 { ProbeList(&alcAllDevicesList
, &alcAllDevicesListSize
, ALL_DEVICE_PROBE
); }
1084 static void ProbeCaptureDeviceList(void)
1085 { ProbeList(&alcCaptureDeviceList
, &alcCaptureDeviceListSize
, CAPTURE_DEVICE_PROBE
); }
1088 static void AppendList(const ALCchar
*name
, ALCchar
**List
, size_t *ListSize
)
1090 size_t len
= strlen(name
);
1096 temp
= realloc(*List
, (*ListSize
) + len
+ 2);
1099 ERR("Realloc failed to add %s!\n", name
);
1104 memcpy((*List
)+(*ListSize
), name
, len
+1);
1106 (*List
)[*ListSize
] = 0;
1109 #define DECL_APPEND_LIST_FUNC(type) \
1110 void Append##type##List(const ALCchar *name) \
1111 { AppendList(name, &alc##type##List, &alc##type##ListSize); }
1113 DECL_APPEND_LIST_FUNC(AllDevices
)
1114 DECL_APPEND_LIST_FUNC(CaptureDevice
)
1116 #undef DECL_APPEND_LIST_FUNC
1119 /************************************************
1120 * Device format information
1121 ************************************************/
1122 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1126 case DevFmtByte
: return "Signed Byte";
1127 case DevFmtUByte
: return "Unsigned Byte";
1128 case DevFmtShort
: return "Signed Short";
1129 case DevFmtUShort
: return "Unsigned Short";
1130 case DevFmtInt
: return "Signed Int";
1131 case DevFmtUInt
: return "Unsigned Int";
1132 case DevFmtFloat
: return "Float";
1134 return "(unknown type)";
1136 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1140 case DevFmtMono
: return "Mono";
1141 case DevFmtStereo
: return "Stereo";
1142 case DevFmtQuad
: return "Quadraphonic";
1143 case DevFmtX51
: return "5.1 Surround";
1144 case DevFmtX51Side
: return "5.1 Side";
1145 case DevFmtX61
: return "6.1 Surround";
1146 case DevFmtX71
: return "7.1 Surround";
1148 return "(unknown channels)";
1151 ALuint
BytesFromDevFmt(enum DevFmtType type
)
1155 case DevFmtByte
: return sizeof(ALbyte
);
1156 case DevFmtUByte
: return sizeof(ALubyte
);
1157 case DevFmtShort
: return sizeof(ALshort
);
1158 case DevFmtUShort
: return sizeof(ALushort
);
1159 case DevFmtInt
: return sizeof(ALint
);
1160 case DevFmtUInt
: return sizeof(ALuint
);
1161 case DevFmtFloat
: return sizeof(ALfloat
);
1165 ALuint
ChannelsFromDevFmt(enum DevFmtChannels chans
)
1169 case DevFmtMono
: return 1;
1170 case DevFmtStereo
: return 2;
1171 case DevFmtQuad
: return 4;
1172 case DevFmtX51
: return 6;
1173 case DevFmtX51Side
: return 6;
1174 case DevFmtX61
: return 7;
1175 case DevFmtX71
: return 8;
1180 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1181 enum DevFmtType
*type
)
1183 static const struct {
1185 enum DevFmtChannels channels
;
1186 enum DevFmtType type
;
1188 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1189 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1190 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1192 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1193 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1194 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1196 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1197 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1198 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1200 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1201 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1202 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1204 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1205 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1206 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1208 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1209 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1210 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1214 for(i
= 0;i
< COUNTOF(list
);i
++)
1216 if(list
[i
].format
== format
)
1218 *chans
= list
[i
].channels
;
1219 *type
= list
[i
].type
;
1227 static ALCboolean
IsValidALCType(ALCenum type
)
1232 case ALC_UNSIGNED_BYTE_SOFT
:
1233 case ALC_SHORT_SOFT
:
1234 case ALC_UNSIGNED_SHORT_SOFT
:
1236 case ALC_UNSIGNED_INT_SOFT
:
1237 case ALC_FLOAT_SOFT
:
1243 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1248 case ALC_STEREO_SOFT
:
1250 case ALC_5POINT1_SOFT
:
1251 case ALC_6POINT1_SOFT
:
1252 case ALC_7POINT1_SOFT
:
1259 /************************************************
1260 * Miscellaneous ALC helpers
1261 ************************************************/
1263 void ALCdevice_LockDefault(ALCdevice
*device
)
1265 EnterCriticalSection(&device
->Mutex
);
1267 void ALCdevice_UnlockDefault(ALCdevice
*device
)
1269 LeaveCriticalSection(&device
->Mutex
);
1271 ALint64
ALCdevice_GetLatencyDefault(ALCdevice
*device
)
1277 /* SetDefaultWFXChannelOrder
1279 * Sets the default channel order used by WaveFormatEx.
1281 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1283 switch(device
->FmtChans
)
1285 case DevFmtMono
: device
->DevChannels
[0] = FrontCenter
; break;
1287 case DevFmtStereo
: device
->DevChannels
[0] = FrontLeft
;
1288 device
->DevChannels
[1] = FrontRight
; break;
1290 case DevFmtQuad
: device
->DevChannels
[0] = FrontLeft
;
1291 device
->DevChannels
[1] = FrontRight
;
1292 device
->DevChannels
[2] = BackLeft
;
1293 device
->DevChannels
[3] = BackRight
; break;
1295 case DevFmtX51
: device
->DevChannels
[0] = FrontLeft
;
1296 device
->DevChannels
[1] = FrontRight
;
1297 device
->DevChannels
[2] = FrontCenter
;
1298 device
->DevChannels
[3] = LFE
;
1299 device
->DevChannels
[4] = BackLeft
;
1300 device
->DevChannels
[5] = BackRight
; break;
1302 case DevFmtX51Side
: device
->DevChannels
[0] = FrontLeft
;
1303 device
->DevChannels
[1] = FrontRight
;
1304 device
->DevChannels
[2] = FrontCenter
;
1305 device
->DevChannels
[3] = LFE
;
1306 device
->DevChannels
[4] = SideLeft
;
1307 device
->DevChannels
[5] = SideRight
; break;
1309 case DevFmtX61
: device
->DevChannels
[0] = FrontLeft
;
1310 device
->DevChannels
[1] = FrontRight
;
1311 device
->DevChannels
[2] = FrontCenter
;
1312 device
->DevChannels
[3] = LFE
;
1313 device
->DevChannels
[4] = BackCenter
;
1314 device
->DevChannels
[5] = SideLeft
;
1315 device
->DevChannels
[6] = SideRight
; break;
1317 case DevFmtX71
: device
->DevChannels
[0] = FrontLeft
;
1318 device
->DevChannels
[1] = FrontRight
;
1319 device
->DevChannels
[2] = FrontCenter
;
1320 device
->DevChannels
[3] = LFE
;
1321 device
->DevChannels
[4] = BackLeft
;
1322 device
->DevChannels
[5] = BackRight
;
1323 device
->DevChannels
[6] = SideLeft
;
1324 device
->DevChannels
[7] = SideRight
; break;
1328 /* SetDefaultChannelOrder
1330 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1332 void SetDefaultChannelOrder(ALCdevice
*device
)
1334 switch(device
->FmtChans
)
1336 case DevFmtX51
: device
->DevChannels
[0] = FrontLeft
;
1337 device
->DevChannels
[1] = FrontRight
;
1338 device
->DevChannels
[2] = BackLeft
;
1339 device
->DevChannels
[3] = BackRight
;
1340 device
->DevChannels
[4] = FrontCenter
;
1341 device
->DevChannels
[5] = LFE
;
1344 case DevFmtX71
: device
->DevChannels
[0] = FrontLeft
;
1345 device
->DevChannels
[1] = FrontRight
;
1346 device
->DevChannels
[2] = BackLeft
;
1347 device
->DevChannels
[3] = BackRight
;
1348 device
->DevChannels
[4] = FrontCenter
;
1349 device
->DevChannels
[5] = LFE
;
1350 device
->DevChannels
[6] = SideLeft
;
1351 device
->DevChannels
[7] = SideRight
;
1354 /* Same as WFX order */
1362 SetDefaultWFXChannelOrder(device
);
1368 * Stores the latest ALC device error
1370 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1375 /* DebugBreak() will cause an exception if there is no debugger */
1376 if(IsDebuggerPresent())
1378 #elif defined(SIGTRAP)
1384 device
->LastError
= errorCode
;
1386 LastNullDeviceError
= errorCode
;
1390 /* UpdateDeviceParams
1392 * Updates device parameters according to the attribute list (caller is
1393 * responsible for holding the list lock).
1395 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1397 ALCcontext
*context
;
1398 enum DevFmtChannels oldChans
;
1399 enum DevFmtType oldType
;
1404 // Check for attributes
1405 if(device
->Type
== Loopback
)
1411 GotAll
= GotFreq
|GotChans
|GotType
1413 ALCuint freq
, numMono
, numStereo
, numSends
;
1414 enum DevFmtChannels schans
;
1415 enum DevFmtType stype
;
1416 ALCuint attrIdx
= 0;
1421 WARN("Missing attributes for loopback device\n");
1422 return ALC_INVALID_VALUE
;
1425 numMono
= device
->NumMonoSources
;
1426 numStereo
= device
->NumStereoSources
;
1427 numSends
= device
->NumAuxSends
;
1428 schans
= device
->FmtChans
;
1429 stype
= device
->FmtType
;
1430 freq
= device
->Frequency
;
1432 while(attrList
[attrIdx
])
1434 if(attrList
[attrIdx
] == ALC_FORMAT_CHANNELS_SOFT
)
1436 ALCint val
= attrList
[attrIdx
+ 1];
1437 if(!IsValidALCChannels(val
) || !ChannelsFromDevFmt(val
))
1438 return ALC_INVALID_VALUE
;
1443 if(attrList
[attrIdx
] == ALC_FORMAT_TYPE_SOFT
)
1445 ALCint val
= attrList
[attrIdx
+ 1];
1446 if(!IsValidALCType(val
) || !BytesFromDevFmt(val
))
1447 return ALC_INVALID_VALUE
;
1452 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1454 freq
= attrList
[attrIdx
+ 1];
1455 if(freq
< MIN_OUTPUT_RATE
)
1456 return ALC_INVALID_VALUE
;
1460 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1462 numStereo
= attrList
[attrIdx
+ 1];
1463 if(numStereo
> device
->MaxNoOfSources
)
1464 numStereo
= device
->MaxNoOfSources
;
1466 numMono
= device
->MaxNoOfSources
- numStereo
;
1469 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
1470 numSends
= attrList
[attrIdx
+ 1];
1475 if(gotFmt
!= GotAll
)
1477 WARN("Missing format for loopback device\n");
1478 return ALC_INVALID_VALUE
;
1481 ConfigValueUInt(NULL
, "sends", &numSends
);
1482 numSends
= minu(MAX_SENDS
, numSends
);
1484 if((device
->Flags
&DEVICE_RUNNING
))
1485 ALCdevice_StopPlayback(device
);
1486 device
->Flags
&= ~DEVICE_RUNNING
;
1488 device
->Frequency
= freq
;
1489 device
->FmtChans
= schans
;
1490 device
->FmtType
= stype
;
1491 device
->NumMonoSources
= numMono
;
1492 device
->NumStereoSources
= numStereo
;
1493 device
->NumAuxSends
= numSends
;
1495 else if(attrList
&& attrList
[0])
1497 ALCuint freq
, numMono
, numStereo
, numSends
;
1498 ALCuint attrIdx
= 0;
1500 /* If a context is already running on the device, stop playback so the
1501 * device attributes can be updated. */
1502 if((device
->Flags
&DEVICE_RUNNING
))
1503 ALCdevice_StopPlayback(device
);
1504 device
->Flags
&= ~DEVICE_RUNNING
;
1506 freq
= device
->Frequency
;
1507 numMono
= device
->NumMonoSources
;
1508 numStereo
= device
->NumStereoSources
;
1509 numSends
= device
->NumAuxSends
;
1511 while(attrList
[attrIdx
])
1513 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1515 freq
= attrList
[attrIdx
+ 1];
1516 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1519 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1521 numStereo
= attrList
[attrIdx
+ 1];
1522 if(numStereo
> device
->MaxNoOfSources
)
1523 numStereo
= device
->MaxNoOfSources
;
1525 numMono
= device
->MaxNoOfSources
- numStereo
;
1528 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
1529 numSends
= attrList
[attrIdx
+ 1];
1534 ConfigValueUInt(NULL
, "frequency", &freq
);
1535 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
1537 ConfigValueUInt(NULL
, "sends", &numSends
);
1538 numSends
= minu(MAX_SENDS
, numSends
);
1540 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
1543 device
->Frequency
= freq
;
1544 device
->NumMonoSources
= numMono
;
1545 device
->NumStereoSources
= numStereo
;
1546 device
->NumAuxSends
= numSends
;
1549 if((device
->Flags
&DEVICE_RUNNING
))
1550 return ALC_NO_ERROR
;
1552 oldFreq
= device
->Frequency
;
1553 oldChans
= device
->FmtChans
;
1554 oldType
= device
->FmtType
;
1556 TRACE("Format pre-setup: %s%s, %s%s, %uhz%s, %u update size x%d\n",
1557 DevFmtChannelsString(device
->FmtChans
),
1558 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?" (requested)":"",
1559 DevFmtTypeString(device
->FmtType
),
1560 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?" (requested)":"",
1562 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?" (requested)":"",
1563 device
->UpdateSize
, device
->NumUpdates
);
1565 if(ALCdevice_ResetPlayback(device
) == ALC_FALSE
)
1566 return ALC_INVALID_DEVICE
;
1568 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
1570 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
1571 DevFmtChannelsString(device
->FmtChans
));
1572 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
1574 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
1576 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
1577 DevFmtTypeString(device
->FmtType
));
1578 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
1580 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
1582 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
1583 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
1586 TRACE("Format post-setup: %s, %s, %uhz, %u update size x%d\n",
1587 DevFmtChannelsString(device
->FmtChans
),
1588 DevFmtTypeString(device
->FmtType
), device
->Frequency
,
1589 device
->UpdateSize
, device
->NumUpdates
);
1591 aluInitPanning(device
);
1593 for(i
= 0;i
< MaxChannels
;i
++)
1595 device
->ClickRemoval
[i
] = 0.0f
;
1596 device
->PendingClicks
[i
] = 0.0f
;
1599 device
->Hrtf
= NULL
;
1600 if(device
->Type
!= Loopback
&& GetConfigValueBool(NULL
, "hrtf", AL_FALSE
))
1601 device
->Hrtf
= GetHrtf(device
);
1602 TRACE("HRTF %s\n", device
->Hrtf
?"enabled":"disabled");
1604 if(!device
->Hrtf
&& device
->Bs2bLevel
> 0 && device
->Bs2bLevel
<= 6)
1608 device
->Bs2b
= calloc(1, sizeof(*device
->Bs2b
));
1609 bs2b_clear(device
->Bs2b
);
1611 bs2b_set_srate(device
->Bs2b
, device
->Frequency
);
1612 bs2b_set_level(device
->Bs2b
, device
->Bs2bLevel
);
1613 TRACE("BS2B level %d\n", device
->Bs2bLevel
);
1618 device
->Bs2b
= NULL
;
1619 TRACE("BS2B disabled\n");
1622 device
->Flags
&= ~DEVICE_WIDE_STEREO
;
1623 if(device
->Type
!= Loopback
&& !device
->Hrtf
&& GetConfigValueBool(NULL
, "wide-stereo", AL_FALSE
))
1624 device
->Flags
|= DEVICE_WIDE_STEREO
;
1626 oldMode
= SetMixerFPUMode();
1627 ALCdevice_Lock(device
);
1628 context
= device
->ContextList
;
1633 context
->UpdateSources
= AL_FALSE
;
1634 LockUIntMapRead(&context
->EffectSlotMap
);
1635 for(pos
= 0;pos
< context
->EffectSlotMap
.size
;pos
++)
1637 ALeffectslot
*slot
= context
->EffectSlotMap
.array
[pos
].value
;
1639 if(ALeffectState_DeviceUpdate(slot
->EffectState
, device
) == AL_FALSE
)
1641 UnlockUIntMapRead(&context
->EffectSlotMap
);
1642 ALCdevice_Unlock(device
);
1643 RestoreFPUMode(oldMode
);
1644 return ALC_INVALID_DEVICE
;
1646 slot
->NeedsUpdate
= AL_FALSE
;
1647 ALeffectState_Update(slot
->EffectState
, device
, slot
);
1649 UnlockUIntMapRead(&context
->EffectSlotMap
);
1651 LockUIntMapRead(&context
->SourceMap
);
1652 for(pos
= 0;pos
< context
->SourceMap
.size
;pos
++)
1654 ALsource
*source
= context
->SourceMap
.array
[pos
].value
;
1655 ALuint s
= device
->NumAuxSends
;
1656 while(s
< MAX_SENDS
)
1658 if(source
->Send
[s
].Slot
)
1659 DecrementRef(&source
->Send
[s
].Slot
->ref
);
1660 source
->Send
[s
].Slot
= NULL
;
1661 source
->Send
[s
].Gain
= 1.0f
;
1662 source
->Send
[s
].GainHF
= 1.0f
;
1665 source
->NeedsUpdate
= AL_FALSE
;
1666 ALsource_Update(source
, context
);
1668 UnlockUIntMapRead(&context
->SourceMap
);
1670 context
= context
->next
;
1672 if(device
->DefaultSlot
)
1674 ALeffectslot
*slot
= device
->DefaultSlot
;
1676 if(ALeffectState_DeviceUpdate(slot
->EffectState
, device
) == AL_FALSE
)
1678 ALCdevice_Unlock(device
);
1679 RestoreFPUMode(oldMode
);
1680 return ALC_INVALID_DEVICE
;
1682 slot
->NeedsUpdate
= AL_FALSE
;
1683 ALeffectState_Update(slot
->EffectState
, device
, slot
);
1685 ALCdevice_Unlock(device
);
1686 RestoreFPUMode(oldMode
);
1688 if(ALCdevice_StartPlayback(device
) == ALC_FALSE
)
1689 return ALC_INVALID_DEVICE
;
1690 device
->Flags
|= DEVICE_RUNNING
;
1692 return ALC_NO_ERROR
;
1697 * Frees the device structure, and destroys any objects the app failed to
1698 * delete. Called once there's no more references on the device.
1700 static ALCvoid
FreeDevice(ALCdevice
*device
)
1702 TRACE("%p\n", device
);
1704 if(device
->Type
!= Capture
)
1705 ALCdevice_ClosePlayback(device
);
1707 ALCdevice_CloseCapture(device
);
1709 if(device
->DefaultSlot
)
1711 ALeffectState_Destroy(device
->DefaultSlot
->EffectState
);
1712 device
->DefaultSlot
->EffectState
= NULL
;
1715 if(device
->BufferMap
.size
> 0)
1717 WARN("(%p) Deleting %d Buffer(s)\n", device
, device
->BufferMap
.size
);
1718 ReleaseALBuffers(device
);
1720 ResetUIntMap(&device
->BufferMap
);
1722 if(device
->EffectMap
.size
> 0)
1724 WARN("(%p) Deleting %d Effect(s)\n", device
, device
->EffectMap
.size
);
1725 ReleaseALEffects(device
);
1727 ResetUIntMap(&device
->EffectMap
);
1729 if(device
->FilterMap
.size
> 0)
1731 WARN("(%p) Deleting %d Filter(s)\n", device
, device
->FilterMap
.size
);
1732 ReleaseALFilters(device
);
1734 ResetUIntMap(&device
->FilterMap
);
1737 device
->Bs2b
= NULL
;
1739 free(device
->DeviceName
);
1740 device
->DeviceName
= NULL
;
1742 DeleteCriticalSection(&device
->Mutex
);
1748 void ALCdevice_IncRef(ALCdevice
*device
)
1751 ref
= IncrementRef(&device
->ref
);
1752 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
1755 void ALCdevice_DecRef(ALCdevice
*device
)
1758 ref
= DecrementRef(&device
->ref
);
1759 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
1760 if(ref
== 0) FreeDevice(device
);
1765 * Checks if the device handle is valid, and increments its ref count if so.
1767 static ALCdevice
*VerifyDevice(ALCdevice
*device
)
1769 ALCdevice
*tmpDevice
;
1775 tmpDevice
= DeviceList
;
1776 while(tmpDevice
&& tmpDevice
!= device
)
1777 tmpDevice
= tmpDevice
->next
;
1780 ALCdevice_IncRef(tmpDevice
);
1788 * Initializes context fields
1790 static ALvoid
InitContext(ALCcontext
*Context
)
1794 //Initialise listener
1795 Context
->Listener
.Gain
= 1.0f
;
1796 Context
->Listener
.MetersPerUnit
= 1.0f
;
1797 Context
->Listener
.Position
[0] = 0.0f
;
1798 Context
->Listener
.Position
[1] = 0.0f
;
1799 Context
->Listener
.Position
[2] = 0.0f
;
1800 Context
->Listener
.Velocity
[0] = 0.0f
;
1801 Context
->Listener
.Velocity
[1] = 0.0f
;
1802 Context
->Listener
.Velocity
[2] = 0.0f
;
1803 Context
->Listener
.Forward
[0] = 0.0f
;
1804 Context
->Listener
.Forward
[1] = 0.0f
;
1805 Context
->Listener
.Forward
[2] = -1.0f
;
1806 Context
->Listener
.Up
[0] = 0.0f
;
1807 Context
->Listener
.Up
[1] = 1.0f
;
1808 Context
->Listener
.Up
[2] = 0.0f
;
1809 for(i
= 0;i
< 4;i
++)
1811 for(j
= 0;j
< 4;j
++)
1812 Context
->Listener
.Matrix
[i
][j
] = ((i
==j
) ? 1.0f
: 0.0f
);
1816 Context
->LastError
= AL_NO_ERROR
;
1817 Context
->UpdateSources
= AL_FALSE
;
1818 Context
->ActiveSourceCount
= 0;
1819 InitUIntMap(&Context
->SourceMap
, Context
->Device
->MaxNoOfSources
);
1820 InitUIntMap(&Context
->EffectSlotMap
, Context
->Device
->AuxiliaryEffectSlotMax
);
1823 Context
->DistanceModel
= AL_INVERSE_DISTANCE_CLAMPED
;
1824 Context
->SourceDistanceModel
= AL_FALSE
;
1825 Context
->DopplerFactor
= 1.0f
;
1826 Context
->DopplerVelocity
= 1.0f
;
1827 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
1828 Context
->DeferUpdates
= AL_FALSE
;
1830 Context
->ExtensionList
= alExtList
;
1836 * Cleans up the context, and destroys any remaining objects the app failed to
1837 * delete. Called once there's no more references on the context.
1839 static ALCvoid
FreeContext(ALCcontext
*context
)
1841 TRACE("%p\n", context
);
1843 if(context
->SourceMap
.size
> 0)
1845 ERR("(%p) Deleting %d Source(s)\n", context
, context
->SourceMap
.size
);
1846 ReleaseALSources(context
);
1848 ResetUIntMap(&context
->SourceMap
);
1850 if(context
->EffectSlotMap
.size
> 0)
1852 ERR("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context
, context
->EffectSlotMap
.size
);
1853 ReleaseALAuxiliaryEffectSlots(context
);
1855 ResetUIntMap(&context
->EffectSlotMap
);
1857 context
->ActiveSourceCount
= 0;
1858 free(context
->ActiveSources
);
1859 context
->ActiveSources
= NULL
;
1860 context
->MaxActiveSources
= 0;
1862 context
->ActiveEffectSlotCount
= 0;
1863 free(context
->ActiveEffectSlots
);
1864 context
->ActiveEffectSlots
= NULL
;
1865 context
->MaxActiveEffectSlots
= 0;
1867 ALCdevice_DecRef(context
->Device
);
1868 context
->Device
= NULL
;
1870 //Invalidate context
1871 memset(context
, 0, sizeof(ALCcontext
));
1877 * Removes the context reference from the given device and removes it from
1878 * being current on the running thread or globally.
1880 static void ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
1882 ALCcontext
*volatile*tmp_ctx
;
1884 if(pthread_getspecific(LocalContext
) == context
)
1886 WARN("%p released while current on thread\n", context
);
1887 pthread_setspecific(LocalContext
, NULL
);
1888 ALCcontext_DecRef(context
);
1891 if(CompExchangePtr((XchgPtr
*)&GlobalContext
, context
, NULL
))
1892 ALCcontext_DecRef(context
);
1894 ALCdevice_Lock(device
);
1895 tmp_ctx
= &device
->ContextList
;
1898 if(CompExchangePtr((XchgPtr
*)tmp_ctx
, context
, context
->next
))
1900 tmp_ctx
= &(*tmp_ctx
)->next
;
1902 ALCdevice_Unlock(device
);
1904 ALCcontext_DecRef(context
);
1907 void ALCcontext_IncRef(ALCcontext
*context
)
1910 ref
= IncrementRef(&context
->ref
);
1911 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
1914 void ALCcontext_DecRef(ALCcontext
*context
)
1917 ref
= DecrementRef(&context
->ref
);
1918 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
1919 if(ref
== 0) FreeContext(context
);
1922 static void ReleaseThreadCtx(void *ptr
)
1924 WARN("%p current for thread being destroyed\n", ptr
);
1925 ALCcontext_DecRef(ptr
);
1930 * Checks that the given context is valid, and increments its reference count.
1932 static ALCcontext
*VerifyContext(ALCcontext
*context
)
1940 ALCcontext
*tmp_ctx
= dev
->ContextList
;
1943 if(tmp_ctx
== context
)
1945 ALCcontext_IncRef(tmp_ctx
);
1949 tmp_ctx
= tmp_ctx
->next
;
1961 * Returns the currently active context for this thread, and adds a reference
1962 * without locking it.
1964 ALCcontext
*GetContextRef(void)
1966 ALCcontext
*context
;
1968 context
= pthread_getspecific(LocalContext
);
1970 ALCcontext_IncRef(context
);
1974 context
= GlobalContext
;
1976 ALCcontext_IncRef(context
);
1984 /************************************************
1985 * Standard ALC functions
1986 ************************************************/
1990 * Return last ALC generated error code for the given device
1992 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
1996 if(VerifyDevice(device
))
1998 errorCode
= ExchangeInt(&device
->LastError
, ALC_NO_ERROR
);
1999 ALCdevice_DecRef(device
);
2002 errorCode
= ExchangeInt(&LastNullDeviceError
, ALC_NO_ERROR
);
2008 /* alcSuspendContext
2012 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*Context
)
2017 /* alcProcessContext
2021 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*Context
)
2029 * Returns information about the device, and error strings
2031 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2033 const ALCchar
*value
= NULL
;
2041 case ALC_INVALID_ENUM
:
2042 value
= alcErrInvalidEnum
;
2045 case ALC_INVALID_VALUE
:
2046 value
= alcErrInvalidValue
;
2049 case ALC_INVALID_DEVICE
:
2050 value
= alcErrInvalidDevice
;
2053 case ALC_INVALID_CONTEXT
:
2054 value
= alcErrInvalidContext
;
2057 case ALC_OUT_OF_MEMORY
:
2058 value
= alcErrOutOfMemory
;
2061 case ALC_DEVICE_SPECIFIER
:
2062 value
= alcDefaultName
;
2065 case ALC_ALL_DEVICES_SPECIFIER
:
2066 if(VerifyDevice(Device
))
2068 value
= Device
->DeviceName
;
2069 ALCdevice_DecRef(Device
);
2073 ProbeAllDevicesList();
2074 value
= alcAllDevicesList
;
2078 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2079 if(VerifyDevice(Device
))
2081 value
= Device
->DeviceName
;
2082 ALCdevice_DecRef(Device
);
2086 ProbeCaptureDeviceList();
2087 value
= alcCaptureDeviceList
;
2091 /* Default devices are always first in the list */
2092 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2093 value
= alcDefaultName
;
2096 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2097 if(!alcAllDevicesList
)
2098 ProbeAllDevicesList();
2100 Device
= VerifyDevice(Device
);
2102 free(alcDefaultAllDevicesSpecifier
);
2103 alcDefaultAllDevicesSpecifier
= strdup(alcAllDevicesList
?
2104 alcAllDevicesList
: "");
2105 if(!alcDefaultAllDevicesSpecifier
)
2106 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2108 value
= alcDefaultAllDevicesSpecifier
;
2109 if(Device
) ALCdevice_DecRef(Device
);
2112 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2113 if(!alcCaptureDeviceList
)
2114 ProbeCaptureDeviceList();
2116 Device
= VerifyDevice(Device
);
2118 free(alcCaptureDefaultDeviceSpecifier
);
2119 alcCaptureDefaultDeviceSpecifier
= strdup(alcCaptureDeviceList
?
2120 alcCaptureDeviceList
: "");
2121 if(!alcCaptureDefaultDeviceSpecifier
)
2122 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2124 value
= alcCaptureDefaultDeviceSpecifier
;
2125 if(Device
) ALCdevice_DecRef(Device
);
2128 case ALC_EXTENSIONS
:
2129 if(!VerifyDevice(Device
))
2130 value
= alcNoDeviceExtList
;
2133 value
= alcExtensionList
;
2134 ALCdevice_DecRef(Device
);
2139 Device
= VerifyDevice(Device
);
2140 alcSetError(Device
, ALC_INVALID_ENUM
);
2141 if(Device
) ALCdevice_DecRef(Device
);
2151 * Returns information about the device and the version of OpenAL
2153 ALC_API ALCvoid ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
,ALCenum param
,ALsizei size
,ALCint
*data
)
2155 device
= VerifyDevice(device
);
2157 if(size
== 0 || data
== NULL
)
2159 alcSetError(device
, ALC_INVALID_VALUE
);
2160 if(device
) ALCdevice_DecRef(device
);
2168 case ALC_MAJOR_VERSION
:
2169 *data
= alcMajorVersion
;
2171 case ALC_MINOR_VERSION
:
2172 *data
= alcMinorVersion
;
2175 case ALC_ATTRIBUTES_SIZE
:
2176 case ALC_ALL_ATTRIBUTES
:
2180 case ALC_MONO_SOURCES
:
2181 case ALC_STEREO_SOURCES
:
2182 case ALC_CAPTURE_SAMPLES
:
2183 case ALC_FORMAT_CHANNELS_SOFT
:
2184 case ALC_FORMAT_TYPE_SOFT
:
2185 alcSetError(NULL
, ALC_INVALID_DEVICE
);
2189 alcSetError(NULL
, ALC_INVALID_ENUM
);
2193 else if(device
->Type
== Capture
)
2197 case ALC_CAPTURE_SAMPLES
:
2199 /* Re-validate the device since it may have been closed */
2200 ALCdevice_DecRef(device
);
2201 if((device
=VerifyDevice(device
)) != NULL
)
2202 *data
= ALCdevice_AvailableSamples(device
);
2204 alcSetError(NULL
, ALC_INVALID_DEVICE
);
2209 *data
= device
->Connected
;
2213 alcSetError(device
, ALC_INVALID_ENUM
);
2217 else /* render device */
2221 case ALC_MAJOR_VERSION
:
2222 *data
= alcMajorVersion
;
2225 case ALC_MINOR_VERSION
:
2226 *data
= alcMinorVersion
;
2229 case ALC_EFX_MAJOR_VERSION
:
2230 *data
= alcEFXMajorVersion
;
2233 case ALC_EFX_MINOR_VERSION
:
2234 *data
= alcEFXMinorVersion
;
2237 case ALC_ATTRIBUTES_SIZE
:
2241 case ALC_ALL_ATTRIBUTES
:
2243 alcSetError(device
, ALC_INVALID_VALUE
);
2248 data
[i
++] = ALC_FREQUENCY
;
2249 data
[i
++] = device
->Frequency
;
2251 if(device
->Type
!= Loopback
)
2253 data
[i
++] = ALC_REFRESH
;
2254 data
[i
++] = device
->Frequency
/ device
->UpdateSize
;
2256 data
[i
++] = ALC_SYNC
;
2257 data
[i
++] = ALC_FALSE
;
2261 data
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
2262 data
[i
++] = device
->FmtChans
;
2264 data
[i
++] = ALC_FORMAT_TYPE_SOFT
;
2265 data
[i
++] = device
->FmtType
;
2268 data
[i
++] = ALC_MONO_SOURCES
;
2269 data
[i
++] = device
->NumMonoSources
;
2271 data
[i
++] = ALC_STEREO_SOURCES
;
2272 data
[i
++] = device
->NumStereoSources
;
2274 data
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
2275 data
[i
++] = device
->NumAuxSends
;
2282 *data
= device
->Frequency
;
2286 if(device
->Type
== Loopback
)
2287 alcSetError(device
, ALC_INVALID_DEVICE
);
2289 *data
= device
->Frequency
/ device
->UpdateSize
;
2293 if(device
->Type
== Loopback
)
2294 alcSetError(device
, ALC_INVALID_DEVICE
);
2299 case ALC_FORMAT_CHANNELS_SOFT
:
2300 if(device
->Type
!= Loopback
)
2301 alcSetError(device
, ALC_INVALID_DEVICE
);
2303 *data
= device
->FmtChans
;
2306 case ALC_FORMAT_TYPE_SOFT
:
2307 if(device
->Type
!= Loopback
)
2308 alcSetError(device
, ALC_INVALID_DEVICE
);
2310 *data
= device
->FmtType
;
2313 case ALC_MONO_SOURCES
:
2314 *data
= device
->NumMonoSources
;
2317 case ALC_STEREO_SOURCES
:
2318 *data
= device
->NumStereoSources
;
2321 case ALC_MAX_AUXILIARY_SENDS
:
2322 *data
= device
->NumAuxSends
;
2326 *data
= device
->Connected
;
2330 alcSetError(device
, ALC_INVALID_ENUM
);
2335 ALCdevice_DecRef(device
);
2339 /* alcIsExtensionPresent
2341 * Determines if there is support for a particular extension
2343 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
2345 ALCboolean bResult
= ALC_FALSE
;
2347 device
= VerifyDevice(device
);
2350 alcSetError(device
, ALC_INVALID_VALUE
);
2353 size_t len
= strlen(extName
);
2354 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
2357 if(strncasecmp(ptr
, extName
, len
) == 0 &&
2358 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
2363 if((ptr
=strchr(ptr
, ' ')) != NULL
)
2367 } while(isspace(*ptr
));
2372 ALCdevice_DecRef(device
);
2377 /* alcGetProcAddress
2379 * Retrieves the function address for a particular extension function
2381 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
2383 ALCvoid
*ptr
= NULL
;
2387 device
= VerifyDevice(device
);
2388 alcSetError(device
, ALC_INVALID_VALUE
);
2389 if(device
) ALCdevice_DecRef(device
);
2394 while(alcFunctions
[i
].funcName
&& strcmp(alcFunctions
[i
].funcName
, funcName
) != 0)
2396 ptr
= alcFunctions
[i
].address
;
2405 * Get the value for a particular ALC enumeration name
2407 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
2413 device
= VerifyDevice(device
);
2414 alcSetError(device
, ALC_INVALID_VALUE
);
2415 if(device
) ALCdevice_DecRef(device
);
2420 while(enumeration
[i
].enumName
&& strcmp(enumeration
[i
].enumName
, enumName
) != 0)
2422 val
= enumeration
[i
].value
;
2431 * Create and attach a context to the given device.
2433 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
2435 ALCcontext
*ALContext
;
2439 if(!(device
=VerifyDevice(device
)) || device
->Type
== Capture
|| !device
->Connected
)
2442 alcSetError(device
, ALC_INVALID_DEVICE
);
2443 if(device
) ALCdevice_DecRef(device
);
2447 device
->LastError
= ALC_NO_ERROR
;
2449 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
2452 alcSetError(device
, err
);
2453 if(err
== ALC_INVALID_DEVICE
)
2454 aluHandleDisconnect(device
);
2455 ALCdevice_DecRef(device
);
2459 ALContext
= calloc(1, sizeof(ALCcontext
));
2464 ALContext
->MaxActiveSources
= 256;
2465 ALContext
->ActiveSources
= malloc(sizeof(ALContext
->ActiveSources
[0]) *
2466 ALContext
->MaxActiveSources
);
2468 if(!ALContext
|| !ALContext
->ActiveSources
)
2470 if(!device
->ContextList
)
2472 ALCdevice_StopPlayback(device
);
2473 device
->Flags
&= ~DEVICE_RUNNING
;
2480 alcSetError(device
, ALC_OUT_OF_MEMORY
);
2481 ALCdevice_DecRef(device
);
2485 ALContext
->Device
= device
;
2486 ALCdevice_IncRef(device
);
2487 InitContext(ALContext
);
2490 ALContext
->next
= device
->ContextList
;
2491 } while(!CompExchangePtr((XchgPtr
*)&device
->ContextList
, ALContext
->next
, ALContext
));
2494 ALCdevice_DecRef(device
);
2496 TRACE("Created context %p\n", ALContext
);
2500 /* alcDestroyContext
2502 * Remove a context from its device
2504 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
2509 /* alcGetContextsDevice sets an error for invalid contexts */
2510 Device
= alcGetContextsDevice(context
);
2513 ReleaseContext(context
, Device
);
2514 if(!Device
->ContextList
)
2516 ALCdevice_StopPlayback(Device
);
2517 Device
->Flags
&= ~DEVICE_RUNNING
;
2524 /* alcGetCurrentContext
2526 * Returns the currently active context on the calling thread
2528 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
2530 ALCcontext
*Context
;
2532 Context
= pthread_getspecific(LocalContext
);
2533 if(!Context
) Context
= GlobalContext
;
2538 /* alcGetThreadContext
2540 * Returns the currently active thread-local context
2542 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
2544 ALCcontext
*Context
;
2545 Context
= pthread_getspecific(LocalContext
);
2550 /* alcMakeContextCurrent
2552 * Makes the given context the active process-wide context, and removes the
2553 * thread-local context for the calling thread.
2555 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
2557 /* context must be valid or NULL */
2558 if(context
&& !(context
=VerifyContext(context
)))
2560 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2563 /* context's reference count is already incremented */
2564 context
= ExchangePtr((XchgPtr
*)&GlobalContext
, context
);
2565 if(context
) ALCcontext_DecRef(context
);
2567 if((context
=pthread_getspecific(LocalContext
)) != NULL
)
2569 pthread_setspecific(LocalContext
, NULL
);
2570 ALCcontext_DecRef(context
);
2576 /* alcSetThreadContext
2578 * Makes the given context the active context for the current thread
2580 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
2584 /* context must be valid or NULL */
2585 if(context
&& !(context
=VerifyContext(context
)))
2587 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2590 /* context's reference count is already incremented */
2591 old
= pthread_getspecific(LocalContext
);
2592 pthread_setspecific(LocalContext
, context
);
2593 if(old
) ALCcontext_DecRef(old
);
2599 /* alcGetContextsDevice
2601 * Returns the device that a particular context is attached to
2603 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
2607 if(!(Context
=VerifyContext(Context
)))
2609 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2612 Device
= Context
->Device
;
2613 ALCcontext_DecRef(Context
);
2621 * Opens the named device.
2623 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
2631 if(!PlaybackBackend
.name
)
2633 alcSetError(NULL
, ALC_INVALID_VALUE
);
2637 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
2640 device
= calloc(1, sizeof(ALCdevice
)+sizeof(ALeffectslot
));
2643 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
2648 device
->Funcs
= &PlaybackBackend
.Funcs
;
2650 device
->Connected
= ALC_TRUE
;
2651 device
->Type
= Playback
;
2652 InitializeCriticalSection(&device
->Mutex
);
2653 device
->LastError
= ALC_NO_ERROR
;
2656 device
->Bs2b
= NULL
;
2657 device
->Bs2bLevel
= 0;
2658 device
->DeviceName
= NULL
;
2660 device
->ContextList
= NULL
;
2662 device
->MaxNoOfSources
= 256;
2663 device
->AuxiliaryEffectSlotMax
= 4;
2664 device
->NumAuxSends
= MAX_SENDS
;
2666 InitUIntMap(&device
->BufferMap
, ~0);
2667 InitUIntMap(&device
->EffectMap
, ~0);
2668 InitUIntMap(&device
->FilterMap
, ~0);
2671 device
->FmtChans
= DevFmtChannelsDefault
;
2672 device
->FmtType
= DevFmtTypeDefault
;
2673 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
2674 device
->NumUpdates
= 4;
2675 device
->UpdateSize
= 1024;
2677 if(ConfigValueStr(NULL
, "channels", &fmt
))
2679 static const struct {
2680 const char name
[16];
2681 enum DevFmtChannels chans
;
2683 { "mono", DevFmtMono
},
2684 { "stereo", DevFmtStereo
},
2685 { "quad", DevFmtQuad
},
2686 { "surround51", DevFmtX51
},
2687 { "surround61", DevFmtX61
},
2688 { "surround71", DevFmtX71
},
2692 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
2694 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
2696 device
->FmtChans
= chanlist
[i
].chans
;
2697 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
2701 if(i
== COUNTOF(chanlist
))
2702 ERR("Unsupported channels: %s\n", fmt
);
2704 if(ConfigValueStr(NULL
, "sample-type", &fmt
))
2706 static const struct {
2707 const char name
[16];
2708 enum DevFmtType type
;
2710 { "int8", DevFmtByte
},
2711 { "uint8", DevFmtUByte
},
2712 { "int16", DevFmtShort
},
2713 { "uint16", DevFmtUShort
},
2714 { "int32", DevFmtInt
},
2715 { "uint32", DevFmtUInt
},
2716 { "float32", DevFmtFloat
},
2720 for(i
= 0;i
< COUNTOF(typelist
);i
++)
2722 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
2724 device
->FmtType
= typelist
[i
].type
;
2725 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
2729 if(i
== COUNTOF(typelist
))
2730 ERR("Unsupported sample-type: %s\n", fmt
);
2732 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
2733 if((device
->Flags
&DEVICE_FORMAT_REQUEST
) != DEVICE_FORMAT_REQUEST
&&
2734 ConfigValueStr(NULL
, "format", &fmt
))
2736 static const struct {
2737 const char name
[32];
2738 enum DevFmtChannels channels
;
2739 enum DevFmtType type
;
2741 { "AL_FORMAT_MONO32", DevFmtMono
, DevFmtFloat
},
2742 { "AL_FORMAT_STEREO32", DevFmtStereo
, DevFmtFloat
},
2743 { "AL_FORMAT_QUAD32", DevFmtQuad
, DevFmtFloat
},
2744 { "AL_FORMAT_51CHN32", DevFmtX51
, DevFmtFloat
},
2745 { "AL_FORMAT_61CHN32", DevFmtX61
, DevFmtFloat
},
2746 { "AL_FORMAT_71CHN32", DevFmtX71
, DevFmtFloat
},
2748 { "AL_FORMAT_MONO16", DevFmtMono
, DevFmtShort
},
2749 { "AL_FORMAT_STEREO16", DevFmtStereo
, DevFmtShort
},
2750 { "AL_FORMAT_QUAD16", DevFmtQuad
, DevFmtShort
},
2751 { "AL_FORMAT_51CHN16", DevFmtX51
, DevFmtShort
},
2752 { "AL_FORMAT_61CHN16", DevFmtX61
, DevFmtShort
},
2753 { "AL_FORMAT_71CHN16", DevFmtX71
, DevFmtShort
},
2755 { "AL_FORMAT_MONO8", DevFmtMono
, DevFmtByte
},
2756 { "AL_FORMAT_STEREO8", DevFmtStereo
, DevFmtByte
},
2757 { "AL_FORMAT_QUAD8", DevFmtQuad
, DevFmtByte
},
2758 { "AL_FORMAT_51CHN8", DevFmtX51
, DevFmtByte
},
2759 { "AL_FORMAT_61CHN8", DevFmtX61
, DevFmtByte
},
2760 { "AL_FORMAT_71CHN8", DevFmtX71
, DevFmtByte
}
2764 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
2765 for(i
= 0;i
< COUNTOF(formats
);i
++)
2767 if(strcasecmp(fmt
, formats
[i
].name
) == 0)
2769 if(!(device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2770 device
->FmtChans
= formats
[i
].channels
;
2771 if(!(device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2772 device
->FmtType
= formats
[i
].type
;
2773 device
->Flags
|= DEVICE_FORMAT_REQUEST
;
2777 if(i
== COUNTOF(formats
))
2778 ERR("Unsupported format: %s\n", fmt
);
2780 #undef DEVICE_FORMAT_REQUEST
2782 if(ConfigValueUInt(NULL
, "frequency", &device
->Frequency
))
2784 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
2785 if(device
->Frequency
< MIN_OUTPUT_RATE
)
2786 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
2787 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
2790 ConfigValueUInt(NULL
, "periods", &device
->NumUpdates
);
2791 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
2793 ConfigValueUInt(NULL
, "period_size", &device
->UpdateSize
);
2794 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
2796 ConfigValueUInt(NULL
, "sources", &device
->MaxNoOfSources
);
2797 if(device
->MaxNoOfSources
== 0) device
->MaxNoOfSources
= 256;
2799 ConfigValueUInt(NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
2800 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 4;
2802 ConfigValueUInt(NULL
, "sends", &device
->NumAuxSends
);
2803 if(device
->NumAuxSends
> MAX_SENDS
) device
->NumAuxSends
= MAX_SENDS
;
2805 ConfigValueInt(NULL
, "cf_level", &device
->Bs2bLevel
);
2807 device
->NumStereoSources
= 1;
2808 device
->NumMonoSources
= device
->MaxNoOfSources
- device
->NumStereoSources
;
2810 // Find a playback device to open
2812 if((err
=ALCdevice_OpenPlayback(device
, deviceName
)) != ALC_NO_ERROR
)
2815 DeleteCriticalSection(&device
->Mutex
);
2817 alcSetError(NULL
, err
);
2822 if(DefaultEffect
.type
!= AL_EFFECT_NULL
)
2824 device
->DefaultSlot
= (ALeffectslot
*)(device
+1);
2825 if(InitEffectSlot(device
->DefaultSlot
) != AL_NO_ERROR
)
2827 device
->DefaultSlot
= NULL
;
2828 ERR("Failed to initialize the default effect slot\n");
2830 else if(InitializeEffect(device
, device
->DefaultSlot
, &DefaultEffect
) != AL_NO_ERROR
)
2832 ALeffectState_Destroy(device
->DefaultSlot
->EffectState
);
2833 device
->DefaultSlot
= NULL
;
2834 ERR("Failed to initialize the default effect\n");
2839 device
->next
= DeviceList
;
2840 } while(!CompExchangePtr((XchgPtr
*)&DeviceList
, device
->next
, device
));
2842 TRACE("Created device %p, \"%s\"\n", device
, device
->DeviceName
);
2848 * Closes the given device.
2850 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*Device
)
2852 ALCdevice
*volatile*list
;
2857 while(*list
&& *list
!= Device
)
2858 list
= &(*list
)->next
;
2860 if(!*list
|| (*list
)->Type
== Capture
)
2862 alcSetError(*list
, ALC_INVALID_DEVICE
);
2867 *list
= (*list
)->next
;
2870 while((ctx
=Device
->ContextList
) != NULL
)
2872 WARN("Releasing context %p\n", ctx
);
2873 ReleaseContext(ctx
, Device
);
2875 if((Device
->Flags
&DEVICE_RUNNING
))
2876 ALCdevice_StopPlayback(Device
);
2877 Device
->Flags
&= ~DEVICE_RUNNING
;
2879 ALCdevice_DecRef(Device
);
2885 /************************************************
2886 * ALC capture functions
2887 ************************************************/
2888 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
2890 ALCdevice
*device
= NULL
;
2895 if(!CaptureBackend
.name
)
2897 alcSetError(NULL
, ALC_INVALID_VALUE
);
2903 alcSetError(NULL
, ALC_INVALID_VALUE
);
2907 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
2910 device
= calloc(1, sizeof(ALCdevice
));
2913 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
2918 device
->Funcs
= &CaptureBackend
.Funcs
;
2920 device
->Connected
= ALC_TRUE
;
2921 device
->Type
= Capture
;
2922 InitializeCriticalSection(&device
->Mutex
);
2924 InitUIntMap(&device
->BufferMap
, ~0);
2925 InitUIntMap(&device
->EffectMap
, ~0);
2926 InitUIntMap(&device
->FilterMap
, ~0);
2928 device
->DeviceName
= NULL
;
2930 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
2931 device
->Frequency
= frequency
;
2933 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
2934 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
2936 DeleteCriticalSection(&device
->Mutex
);
2938 alcSetError(NULL
, ALC_INVALID_ENUM
);
2942 device
->UpdateSize
= samples
;
2943 device
->NumUpdates
= 1;
2946 if((err
=ALCdevice_OpenCapture(device
, deviceName
)) != ALC_NO_ERROR
)
2949 DeleteCriticalSection(&device
->Mutex
);
2951 alcSetError(NULL
, err
);
2957 device
->next
= DeviceList
;
2958 } while(!CompExchangePtr((XchgPtr
*)&DeviceList
, device
->next
, device
));
2960 TRACE("Created device %p\n", device
);
2964 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*Device
)
2966 ALCdevice
*volatile*list
;
2970 while(*list
&& *list
!= Device
)
2971 list
= &(*list
)->next
;
2973 if(!*list
|| (*list
)->Type
!= Capture
)
2975 alcSetError(*list
, ALC_INVALID_DEVICE
);
2980 *list
= (*list
)->next
;
2983 ALCdevice_DecRef(Device
);
2988 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
2991 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Capture
)
2994 alcSetError(device
, ALC_INVALID_DEVICE
);
2995 if(device
) ALCdevice_DecRef(device
);
2998 if(device
->Connected
)
3000 if(!(device
->Flags
&DEVICE_RUNNING
))
3001 ALCdevice_StartCapture(device
);
3002 device
->Flags
|= DEVICE_RUNNING
;
3006 ALCdevice_DecRef(device
);
3009 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
3012 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Capture
)
3015 alcSetError(device
, ALC_INVALID_DEVICE
);
3016 if(device
) ALCdevice_DecRef(device
);
3019 if((device
->Flags
&DEVICE_RUNNING
))
3020 ALCdevice_StopCapture(device
);
3021 device
->Flags
&= ~DEVICE_RUNNING
;
3024 ALCdevice_DecRef(device
);
3027 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
3029 ALCenum err
= ALC_INVALID_DEVICE
;
3031 if((device
=VerifyDevice(device
)) != NULL
&& device
->Type
== Capture
)
3033 err
= ALC_INVALID_VALUE
;
3034 if(samples
>= 0 && ALCdevice_AvailableSamples(device
) >= (ALCuint
)samples
)
3035 err
= ALCdevice_CaptureSamples(device
, buffer
, samples
);
3038 if(err
!= ALC_NO_ERROR
)
3039 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
= calloc(1, 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
);