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 }
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(alGetSourcei64vSOFT
),
265 #define DECL(x) { #x, (x) }
266 static const ALCenums enumeration
[] = {
271 DECL(ALC_MAJOR_VERSION
),
272 DECL(ALC_MINOR_VERSION
),
273 DECL(ALC_ATTRIBUTES_SIZE
),
274 DECL(ALC_ALL_ATTRIBUTES
),
275 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
276 DECL(ALC_DEVICE_SPECIFIER
),
277 DECL(ALC_ALL_DEVICES_SPECIFIER
),
278 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
279 DECL(ALC_EXTENSIONS
),
283 DECL(ALC_MONO_SOURCES
),
284 DECL(ALC_STEREO_SOURCES
),
285 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
286 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
287 DECL(ALC_CAPTURE_SAMPLES
),
290 DECL(ALC_EFX_MAJOR_VERSION
),
291 DECL(ALC_EFX_MINOR_VERSION
),
292 DECL(ALC_MAX_AUXILIARY_SENDS
),
294 DECL(ALC_FORMAT_CHANNELS_SOFT
),
295 DECL(ALC_FORMAT_TYPE_SOFT
),
298 DECL(ALC_STEREO_SOFT
),
300 DECL(ALC_5POINT1_SOFT
),
301 DECL(ALC_6POINT1_SOFT
),
302 DECL(ALC_7POINT1_SOFT
),
305 DECL(ALC_UNSIGNED_BYTE_SOFT
),
306 DECL(ALC_SHORT_SOFT
),
307 DECL(ALC_UNSIGNED_SHORT_SOFT
),
309 DECL(ALC_UNSIGNED_INT_SOFT
),
310 DECL(ALC_FLOAT_SOFT
),
313 DECL(ALC_INVALID_DEVICE
),
314 DECL(ALC_INVALID_CONTEXT
),
315 DECL(ALC_INVALID_ENUM
),
316 DECL(ALC_INVALID_VALUE
),
317 DECL(ALC_OUT_OF_MEMORY
),
325 DECL(AL_SOURCE_RELATIVE
),
326 DECL(AL_CONE_INNER_ANGLE
),
327 DECL(AL_CONE_OUTER_ANGLE
),
337 DECL(AL_ORIENTATION
),
338 DECL(AL_REFERENCE_DISTANCE
),
339 DECL(AL_ROLLOFF_FACTOR
),
340 DECL(AL_CONE_OUTER_GAIN
),
341 DECL(AL_MAX_DISTANCE
),
343 DECL(AL_SAMPLE_OFFSET
),
344 DECL(AL_SAMPLE_RW_OFFSETS_SOFT
),
345 DECL(AL_BYTE_OFFSET
),
346 DECL(AL_BYTE_RW_OFFSETS_SOFT
),
347 DECL(AL_SOURCE_TYPE
),
350 DECL(AL_UNDETERMINED
),
351 DECL(AL_METERS_PER_UNIT
),
352 DECL(AL_DIRECT_CHANNELS_SOFT
),
354 DECL(AL_DIRECT_FILTER
),
355 DECL(AL_AUXILIARY_SEND_FILTER
),
356 DECL(AL_AIR_ABSORPTION_FACTOR
),
357 DECL(AL_ROOM_ROLLOFF_FACTOR
),
358 DECL(AL_CONE_OUTER_GAINHF
),
359 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
360 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
361 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
363 DECL(AL_SOURCE_STATE
),
369 DECL(AL_BUFFERS_QUEUED
),
370 DECL(AL_BUFFERS_PROCESSED
),
372 DECL(AL_FORMAT_MONO8
),
373 DECL(AL_FORMAT_MONO16
),
374 DECL(AL_FORMAT_MONO_FLOAT32
),
375 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
376 DECL(AL_FORMAT_STEREO8
),
377 DECL(AL_FORMAT_STEREO16
),
378 DECL(AL_FORMAT_STEREO_FLOAT32
),
379 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
380 DECL(AL_FORMAT_MONO_IMA4
),
381 DECL(AL_FORMAT_STEREO_IMA4
),
382 DECL(AL_FORMAT_QUAD8_LOKI
),
383 DECL(AL_FORMAT_QUAD16_LOKI
),
384 DECL(AL_FORMAT_QUAD8
),
385 DECL(AL_FORMAT_QUAD16
),
386 DECL(AL_FORMAT_QUAD32
),
387 DECL(AL_FORMAT_51CHN8
),
388 DECL(AL_FORMAT_51CHN16
),
389 DECL(AL_FORMAT_51CHN32
),
390 DECL(AL_FORMAT_61CHN8
),
391 DECL(AL_FORMAT_61CHN16
),
392 DECL(AL_FORMAT_61CHN32
),
393 DECL(AL_FORMAT_71CHN8
),
394 DECL(AL_FORMAT_71CHN16
),
395 DECL(AL_FORMAT_71CHN32
),
396 DECL(AL_FORMAT_REAR8
),
397 DECL(AL_FORMAT_REAR16
),
398 DECL(AL_FORMAT_REAR32
),
399 DECL(AL_FORMAT_MONO_MULAW
),
400 DECL(AL_FORMAT_MONO_MULAW_EXT
),
401 DECL(AL_FORMAT_STEREO_MULAW
),
402 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
403 DECL(AL_FORMAT_QUAD_MULAW
),
404 DECL(AL_FORMAT_51CHN_MULAW
),
405 DECL(AL_FORMAT_61CHN_MULAW
),
406 DECL(AL_FORMAT_71CHN_MULAW
),
407 DECL(AL_FORMAT_REAR_MULAW
),
408 DECL(AL_FORMAT_MONO_ALAW_EXT
),
409 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
412 DECL(AL_MONO16_SOFT
),
413 DECL(AL_MONO32F_SOFT
),
414 DECL(AL_STEREO8_SOFT
),
415 DECL(AL_STEREO16_SOFT
),
416 DECL(AL_STEREO32F_SOFT
),
418 DECL(AL_QUAD16_SOFT
),
419 DECL(AL_QUAD32F_SOFT
),
421 DECL(AL_REAR16_SOFT
),
422 DECL(AL_REAR32F_SOFT
),
423 DECL(AL_5POINT1_8_SOFT
),
424 DECL(AL_5POINT1_16_SOFT
),
425 DECL(AL_5POINT1_32F_SOFT
),
426 DECL(AL_6POINT1_8_SOFT
),
427 DECL(AL_6POINT1_16_SOFT
),
428 DECL(AL_6POINT1_32F_SOFT
),
429 DECL(AL_7POINT1_8_SOFT
),
430 DECL(AL_7POINT1_16_SOFT
),
431 DECL(AL_7POINT1_32F_SOFT
),
434 DECL(AL_STEREO_SOFT
),
437 DECL(AL_5POINT1_SOFT
),
438 DECL(AL_6POINT1_SOFT
),
439 DECL(AL_7POINT1_SOFT
),
442 DECL(AL_UNSIGNED_BYTE_SOFT
),
444 DECL(AL_UNSIGNED_SHORT_SOFT
),
446 DECL(AL_UNSIGNED_INT_SOFT
),
448 DECL(AL_DOUBLE_SOFT
),
450 DECL(AL_UNSIGNED_BYTE3_SOFT
),
456 DECL(AL_INTERNAL_FORMAT_SOFT
),
457 DECL(AL_BYTE_LENGTH_SOFT
),
458 DECL(AL_SAMPLE_LENGTH_SOFT
),
459 DECL(AL_SEC_LENGTH_SOFT
),
466 DECL(AL_INVALID_NAME
),
467 DECL(AL_INVALID_ENUM
),
468 DECL(AL_INVALID_VALUE
),
469 DECL(AL_INVALID_OPERATION
),
470 DECL(AL_OUT_OF_MEMORY
),
477 DECL(AL_DOPPLER_FACTOR
),
478 DECL(AL_DOPPLER_VELOCITY
),
479 DECL(AL_DISTANCE_MODEL
),
480 DECL(AL_SPEED_OF_SOUND
),
481 DECL(AL_SOURCE_DISTANCE_MODEL
),
482 DECL(AL_DEFERRED_UPDATES_SOFT
),
484 DECL(AL_INVERSE_DISTANCE
),
485 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
486 DECL(AL_LINEAR_DISTANCE
),
487 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
488 DECL(AL_EXPONENT_DISTANCE
),
489 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
491 DECL(AL_FILTER_TYPE
),
492 DECL(AL_FILTER_NULL
),
493 DECL(AL_FILTER_LOWPASS
),
495 DECL(AL_FILTER_HIGHPASS
),
496 DECL(AL_FILTER_BANDPASS
),
499 DECL(AL_LOWPASS_GAIN
),
500 DECL(AL_LOWPASS_GAINHF
),
502 DECL(AL_EFFECT_TYPE
),
503 DECL(AL_EFFECT_NULL
),
504 DECL(AL_EFFECT_REVERB
),
505 DECL(AL_EFFECT_EAXREVERB
),
507 DECL(AL_EFFECT_CHORUS
),
508 DECL(AL_EFFECT_DISTORTION
),
510 DECL(AL_EFFECT_ECHO
),
512 DECL(AL_EFFECT_FLANGER
),
513 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
514 DECL(AL_EFFECT_VOCAL_MORPHER
),
515 DECL(AL_EFFECT_PITCH_SHIFTER
),
517 DECL(AL_EFFECT_RING_MODULATOR
),
519 DECL(AL_EFFECT_AUTOWAH
),
520 DECL(AL_EFFECT_COMPRESSOR
),
521 DECL(AL_EFFECT_EQUALIZER
),
523 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
524 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
526 DECL(AL_EAXREVERB_DENSITY
),
527 DECL(AL_EAXREVERB_DIFFUSION
),
528 DECL(AL_EAXREVERB_GAIN
),
529 DECL(AL_EAXREVERB_GAINHF
),
530 DECL(AL_EAXREVERB_GAINLF
),
531 DECL(AL_EAXREVERB_DECAY_TIME
),
532 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
533 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
534 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
535 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
536 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
537 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
538 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
539 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
540 DECL(AL_EAXREVERB_ECHO_TIME
),
541 DECL(AL_EAXREVERB_ECHO_DEPTH
),
542 DECL(AL_EAXREVERB_MODULATION_TIME
),
543 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
544 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
545 DECL(AL_EAXREVERB_HFREFERENCE
),
546 DECL(AL_EAXREVERB_LFREFERENCE
),
547 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
548 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
550 DECL(AL_REVERB_DENSITY
),
551 DECL(AL_REVERB_DIFFUSION
),
552 DECL(AL_REVERB_GAIN
),
553 DECL(AL_REVERB_GAINHF
),
554 DECL(AL_REVERB_DECAY_TIME
),
555 DECL(AL_REVERB_DECAY_HFRATIO
),
556 DECL(AL_REVERB_REFLECTIONS_GAIN
),
557 DECL(AL_REVERB_REFLECTIONS_DELAY
),
558 DECL(AL_REVERB_LATE_REVERB_GAIN
),
559 DECL(AL_REVERB_LATE_REVERB_DELAY
),
560 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
561 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
562 DECL(AL_REVERB_DECAY_HFLIMIT
),
565 DECL(AL_ECHO_LRDELAY
),
566 DECL(AL_ECHO_DAMPING
),
567 DECL(AL_ECHO_FEEDBACK
),
568 DECL(AL_ECHO_SPREAD
),
570 DECL(AL_RING_MODULATOR_FREQUENCY
),
571 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
572 DECL(AL_RING_MODULATOR_WAVEFORM
),
574 DECL(AL_DEDICATED_GAIN
),
580 static const ALCchar alcNoError
[] = "No Error";
581 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
582 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
583 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
584 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
585 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
588 /************************************************
590 ************************************************/
592 /* Enumerated device names */
593 static const ALCchar alcDefaultName
[] = "OpenAL Soft\0";
594 static ALCchar
*alcAllDevicesList
;
595 static ALCchar
*alcCaptureDeviceList
;
596 /* Sizes only include the first ending null character, not the second */
597 static size_t alcAllDevicesListSize
;
598 static size_t alcCaptureDeviceListSize
;
600 /* Default is always the first in the list */
601 static ALCchar
*alcDefaultAllDevicesSpecifier
;
602 static ALCchar
*alcCaptureDefaultDeviceSpecifier
;
604 /* Default context extensions */
605 static const ALchar alExtList
[] =
606 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
607 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
608 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
609 "AL_LOKI_quadriphonic AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data "
610 "AL_SOFTX_deferred_updates AL_SOFT_direct_channels AL_SOFT_loop_points";
612 static volatile ALCenum LastNullDeviceError
= ALC_NO_ERROR
;
614 /* Thread-local current context */
615 static pthread_key_t LocalContext
;
616 /* Process-wide current context */
617 static ALCcontext
*volatile GlobalContext
= NULL
;
619 /* Mixing thread piority level */
624 enum LogLevel LogLevel
= LogWarning
;
626 enum LogLevel LogLevel
= LogError
;
629 /* Flag to trap ALC device errors */
630 static ALCboolean TrapALCError
= ALC_FALSE
;
632 /* One-time configuration init control */
633 static pthread_once_t alc_config_once
= PTHREAD_ONCE_INIT
;
635 /* Default effect that applies to sources that don't have an effect on send 0 */
636 static ALeffect DefaultEffect
;
639 /************************************************
641 ************************************************/
642 static const ALCchar alcNoDeviceExtList
[] =
643 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
644 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
645 static const ALCchar alcExtensionList
[] =
646 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
647 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
648 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
649 static const ALCint alcMajorVersion
= 1;
650 static const ALCint alcMinorVersion
= 1;
652 static const ALCint alcEFXMajorVersion
= 1;
653 static const ALCint alcEFXMinorVersion
= 0;
656 /************************************************
658 ************************************************/
659 static ALCdevice
*volatile DeviceList
= NULL
;
661 static CRITICAL_SECTION ListLock
;
663 static void LockLists(void)
665 EnterCriticalSection(&ListLock
);
667 static void UnlockLists(void)
669 LeaveCriticalSection(&ListLock
);
672 /************************************************
673 * Library initialization
674 ************************************************/
676 static void alc_init(void);
677 static void alc_deinit(void);
678 static void alc_deinit_safe(void);
680 UIntMap TlsDestructor
;
682 #ifndef AL_LIBTYPE_STATIC
683 BOOL APIENTRY
DllMain(HINSTANCE hModule
,DWORD ul_reason_for_call
,LPVOID lpReserved
)
687 // Perform actions based on the reason for calling.
688 switch(ul_reason_for_call
)
690 case DLL_PROCESS_ATTACH
:
691 /* Pin the DLL so we won't get unloaded until the process terminates */
692 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
693 (WCHAR
*)hModule
, &hModule
);
694 InitUIntMap(&TlsDestructor
, ~0);
698 case DLL_THREAD_DETACH
:
699 LockUIntMapRead(&TlsDestructor
);
700 for(i
= 0;i
< TlsDestructor
.size
;i
++)
702 void *ptr
= pthread_getspecific(TlsDestructor
.array
[i
].key
);
703 void (*callback
)(void*) = (void(*)(void*))TlsDestructor
.array
[i
].value
;
707 UnlockUIntMapRead(&TlsDestructor
);
710 case DLL_PROCESS_DETACH
:
715 ResetUIntMap(&TlsDestructor
);
720 #elif defined(_MSC_VER)
721 #pragma section(".CRT$XCU",read)
722 static void alc_constructor(void);
723 static void alc_destructor(void);
724 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
726 static void alc_constructor(void)
728 atexit(alc_destructor
);
732 static void alc_destructor(void)
736 #elif defined(HAVE_GCC_DESTRUCTOR)
737 static void alc_init(void) __attribute__((constructor
));
738 static void alc_deinit(void) __attribute__((destructor
));
740 #error "No static initialization available on this platform!"
743 #elif defined(HAVE_GCC_DESTRUCTOR)
745 static void alc_init(void) __attribute__((constructor
));
746 static void alc_deinit(void) __attribute__((destructor
));
749 #error "No global initialization available on this platform!"
752 static void ReleaseThreadCtx(void *ptr
);
753 static void alc_init(void)
759 str
= getenv("__ALSOFT_HALF_ANGLE_CONES");
760 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
763 str
= getenv("__ALSOFT_REVERSE_Z");
764 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
767 pthread_key_create(&LocalContext
, ReleaseThreadCtx
);
768 InitializeCriticalSection(&ListLock
);
772 static void alc_initconfig(void)
774 const char *devs
, *str
;
779 str
= getenv("ALSOFT_LOGLEVEL");
782 long lvl
= strtol(str
, NULL
, 0);
783 if(lvl
>= NoLog
&& lvl
<= LogRef
)
787 str
= getenv("ALSOFT_LOGFILE");
790 FILE *logfile
= fopen(str
, "wat");
791 if(logfile
) LogFile
= logfile
;
792 else ERR("Failed to open log file '%s'\n", str
);
799 capfilter
|= CPU_CAP_SSE
;
802 capfilter
|= CPU_CAP_NEON
;
804 if(ConfigValueStr(NULL
, "disable-cpu-exts", &str
))
806 if(strcasecmp(str
, "all") == 0)
811 const char *next
= str
;
816 next
= strchr(str
, ',');
818 while(isspace(str
[0]))
820 if(!str
[0] || str
[0] == ',')
823 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
824 if(strncasecmp(str
, "sse", len
) == 0)
825 capfilter
&= ~CPU_CAP_SSE
;
826 else if(strncasecmp(str
, "neon", len
) == 0)
827 capfilter
&= ~CPU_CAP_NEON
;
829 WARN("Invalid CPU extension \"%s\"\n", str
);
833 FillCPUCaps(capfilter
);
842 ConfigValueInt(NULL
, "rt-prio", &RTPrioLevel
);
844 if(ConfigValueStr(NULL
, "resampler", &str
))
846 if(strcasecmp(str
, "point") == 0 || strcasecmp(str
, "none") == 0)
847 DefaultResampler
= PointResampler
;
848 else if(strcasecmp(str
, "linear") == 0)
849 DefaultResampler
= LinearResampler
;
850 else if(strcasecmp(str
, "cubic") == 0)
851 DefaultResampler
= CubicResampler
;
856 n
= strtol(str
, &end
, 0);
857 if(*end
== '\0' && (n
== PointResampler
|| n
== LinearResampler
|| n
== CubicResampler
))
858 DefaultResampler
= n
;
860 WARN("Invalid resampler: %s\n", str
);
864 str
= getenv("ALSOFT_TRAP_ERROR");
865 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
867 TrapALError
= AL_TRUE
;
868 TrapALCError
= AL_TRUE
;
872 str
= getenv("ALSOFT_TRAP_AL_ERROR");
873 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
874 TrapALError
= AL_TRUE
;
875 TrapALError
= GetConfigValueBool(NULL
, "trap-al-error", TrapALError
);
877 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
878 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
879 TrapALCError
= ALC_TRUE
;
880 TrapALCError
= GetConfigValueBool(NULL
, "trap-alc-error", TrapALCError
);
883 if(ConfigValueFloat("reverb", "boost", &valf
))
884 ReverbBoost
*= powf(10.0f
, valf
/ 20.0f
);
886 EmulateEAXReverb
= GetConfigValueBool("reverb", "emulate-eax", AL_FALSE
);
888 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
889 ConfigValueStr(NULL
, "drivers", &devs
))
893 const char *next
= devs
;
894 int endlist
, delitem
;
899 next
= strchr(devs
, ',');
901 delitem
= (devs
[0] == '-');
902 if(devs
[0] == '-') devs
++;
904 if(!devs
[0] || devs
[0] == ',')
911 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
912 for(n
= i
;BackendList
[n
].Init
;n
++)
914 if(len
== strlen(BackendList
[n
].name
) &&
915 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
920 BackendList
[n
] = BackendList
[n
+1];
922 } while(BackendList
[n
].Init
);
926 struct BackendInfo Bkp
= BackendList
[n
];
929 BackendList
[n
] = BackendList
[n
-1];
932 BackendList
[n
] = Bkp
;
943 BackendList
[i
].name
= NULL
;
944 BackendList
[i
].Init
= NULL
;
945 BackendList
[i
].Deinit
= NULL
;
946 BackendList
[i
].Probe
= NULL
;
950 for(i
= 0;BackendList
[i
].Init
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
952 if(!BackendList
[i
].Init(&BackendList
[i
].Funcs
))
954 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
958 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
959 if(BackendList
[i
].Funcs
.OpenPlayback
&& !PlaybackBackend
.name
)
961 PlaybackBackend
= BackendList
[i
];
962 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
964 if(BackendList
[i
].Funcs
.OpenCapture
&& !CaptureBackend
.name
)
966 CaptureBackend
= BackendList
[i
];
967 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
970 BackendLoopback
.Init(&BackendLoopback
.Funcs
);
972 if(ConfigValueStr(NULL
, "excludefx", &str
))
975 const char *next
= str
;
979 next
= strchr(str
, ',');
981 if(!str
[0] || next
== str
)
984 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
985 for(n
= 0;EffectList
[n
].name
;n
++)
987 if(len
== strlen(EffectList
[n
].name
) &&
988 strncmp(EffectList
[n
].name
, str
, len
) == 0)
989 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
994 InitEffect(&DefaultEffect
);
995 str
= getenv("ALSOFT_DEFAULT_REVERB");
996 if((str
&& str
[0]) || ConfigValueStr(NULL
, "default-reverb", &str
))
997 LoadReverbPreset(str
, &DefaultEffect
);
999 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
1002 /************************************************
1003 * Library deinitialization
1004 ************************************************/
1005 static void alc_cleanup(void)
1009 free(alcAllDevicesList
); alcAllDevicesList
= NULL
;
1010 alcAllDevicesListSize
= 0;
1011 free(alcCaptureDeviceList
); alcCaptureDeviceList
= NULL
;
1012 alcCaptureDeviceListSize
= 0;
1014 free(alcDefaultAllDevicesSpecifier
);
1015 alcDefaultAllDevicesSpecifier
= NULL
;
1016 free(alcCaptureDefaultDeviceSpecifier
);
1017 alcCaptureDefaultDeviceSpecifier
= NULL
;
1019 if((dev
=ExchangePtr((XchgPtr
*)&DeviceList
, NULL
)) != NULL
)
1024 } while((dev
=dev
->next
) != NULL
);
1025 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1029 static void alc_deinit_safe(void)
1037 DeleteCriticalSection(&ListLock
);
1038 pthread_key_delete(LocalContext
);
1040 if(LogFile
!= stderr
)
1045 static void alc_deinit(void)
1051 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1052 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1054 for(i
= 0;BackendList
[i
].Deinit
;i
++)
1055 BackendList
[i
].Deinit();
1056 BackendLoopback
.Deinit();
1062 /************************************************
1063 * Device enumeration
1064 ************************************************/
1065 static void ProbeList(ALCchar
**list
, size_t *listsize
, enum DevProbe type
)
1074 if(type
== ALL_DEVICE_PROBE
&& PlaybackBackend
.Probe
)
1075 PlaybackBackend
.Probe(type
);
1076 else if(type
== CAPTURE_DEVICE_PROBE
&& CaptureBackend
.Probe
)
1077 CaptureBackend
.Probe(type
);
1081 static void ProbeAllDevicesList(void)
1082 { ProbeList(&alcAllDevicesList
, &alcAllDevicesListSize
, ALL_DEVICE_PROBE
); }
1083 static void ProbeCaptureDeviceList(void)
1084 { ProbeList(&alcCaptureDeviceList
, &alcCaptureDeviceListSize
, CAPTURE_DEVICE_PROBE
); }
1087 static void AppendList(const ALCchar
*name
, ALCchar
**List
, size_t *ListSize
)
1089 size_t len
= strlen(name
);
1095 temp
= realloc(*List
, (*ListSize
) + len
+ 2);
1098 ERR("Realloc failed to add %s!\n", name
);
1103 memcpy((*List
)+(*ListSize
), name
, len
+1);
1105 (*List
)[*ListSize
] = 0;
1108 #define DECL_APPEND_LIST_FUNC(type) \
1109 void Append##type##List(const ALCchar *name) \
1110 { AppendList(name, &alc##type##List, &alc##type##ListSize); }
1112 DECL_APPEND_LIST_FUNC(AllDevices
)
1113 DECL_APPEND_LIST_FUNC(CaptureDevice
)
1115 #undef DECL_APPEND_LIST_FUNC
1118 /************************************************
1119 * Device format information
1120 ************************************************/
1121 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1125 case DevFmtByte
: return "Signed Byte";
1126 case DevFmtUByte
: return "Unsigned Byte";
1127 case DevFmtShort
: return "Signed Short";
1128 case DevFmtUShort
: return "Unsigned Short";
1129 case DevFmtInt
: return "Signed Int";
1130 case DevFmtUInt
: return "Unsigned Int";
1131 case DevFmtFloat
: return "Float";
1133 return "(unknown type)";
1135 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1139 case DevFmtMono
: return "Mono";
1140 case DevFmtStereo
: return "Stereo";
1141 case DevFmtQuad
: return "Quadraphonic";
1142 case DevFmtX51
: return "5.1 Surround";
1143 case DevFmtX51Side
: return "5.1 Side";
1144 case DevFmtX61
: return "6.1 Surround";
1145 case DevFmtX71
: return "7.1 Surround";
1147 return "(unknown channels)";
1150 ALuint
BytesFromDevFmt(enum DevFmtType type
)
1154 case DevFmtByte
: return sizeof(ALbyte
);
1155 case DevFmtUByte
: return sizeof(ALubyte
);
1156 case DevFmtShort
: return sizeof(ALshort
);
1157 case DevFmtUShort
: return sizeof(ALushort
);
1158 case DevFmtInt
: return sizeof(ALint
);
1159 case DevFmtUInt
: return sizeof(ALuint
);
1160 case DevFmtFloat
: return sizeof(ALfloat
);
1164 ALuint
ChannelsFromDevFmt(enum DevFmtChannels chans
)
1168 case DevFmtMono
: return 1;
1169 case DevFmtStereo
: return 2;
1170 case DevFmtQuad
: return 4;
1171 case DevFmtX51
: return 6;
1172 case DevFmtX51Side
: return 6;
1173 case DevFmtX61
: return 7;
1174 case DevFmtX71
: return 8;
1179 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1180 enum DevFmtType
*type
)
1182 static const struct {
1184 enum DevFmtChannels channels
;
1185 enum DevFmtType type
;
1187 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1188 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1189 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1191 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1192 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1193 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1195 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1196 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1197 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1199 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1200 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1201 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1203 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1204 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1205 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1207 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1208 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1209 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1213 for(i
= 0;i
< COUNTOF(list
);i
++)
1215 if(list
[i
].format
== format
)
1217 *chans
= list
[i
].channels
;
1218 *type
= list
[i
].type
;
1226 static ALCboolean
IsValidALCType(ALCenum type
)
1231 case ALC_UNSIGNED_BYTE_SOFT
:
1232 case ALC_SHORT_SOFT
:
1233 case ALC_UNSIGNED_SHORT_SOFT
:
1235 case ALC_UNSIGNED_INT_SOFT
:
1236 case ALC_FLOAT_SOFT
:
1242 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1247 case ALC_STEREO_SOFT
:
1249 case ALC_5POINT1_SOFT
:
1250 case ALC_6POINT1_SOFT
:
1251 case ALC_7POINT1_SOFT
:
1258 /************************************************
1259 * Miscellaneous ALC helpers
1260 ************************************************/
1262 /* SetDefaultWFXChannelOrder
1264 * Sets the default channel order used by WaveFormatEx.
1266 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1268 switch(device
->FmtChans
)
1270 case DevFmtMono
: device
->DevChannels
[0] = FrontCenter
; break;
1272 case DevFmtStereo
: device
->DevChannels
[0] = FrontLeft
;
1273 device
->DevChannels
[1] = FrontRight
; break;
1275 case DevFmtQuad
: device
->DevChannels
[0] = FrontLeft
;
1276 device
->DevChannels
[1] = FrontRight
;
1277 device
->DevChannels
[2] = BackLeft
;
1278 device
->DevChannels
[3] = BackRight
; break;
1280 case DevFmtX51
: device
->DevChannels
[0] = FrontLeft
;
1281 device
->DevChannels
[1] = FrontRight
;
1282 device
->DevChannels
[2] = FrontCenter
;
1283 device
->DevChannels
[3] = LFE
;
1284 device
->DevChannels
[4] = BackLeft
;
1285 device
->DevChannels
[5] = BackRight
; break;
1287 case DevFmtX51Side
: device
->DevChannels
[0] = FrontLeft
;
1288 device
->DevChannels
[1] = FrontRight
;
1289 device
->DevChannels
[2] = FrontCenter
;
1290 device
->DevChannels
[3] = LFE
;
1291 device
->DevChannels
[4] = SideLeft
;
1292 device
->DevChannels
[5] = SideRight
; break;
1294 case DevFmtX61
: device
->DevChannels
[0] = FrontLeft
;
1295 device
->DevChannels
[1] = FrontRight
;
1296 device
->DevChannels
[2] = FrontCenter
;
1297 device
->DevChannels
[3] = LFE
;
1298 device
->DevChannels
[4] = BackCenter
;
1299 device
->DevChannels
[5] = SideLeft
;
1300 device
->DevChannels
[6] = SideRight
; break;
1302 case DevFmtX71
: device
->DevChannels
[0] = FrontLeft
;
1303 device
->DevChannels
[1] = FrontRight
;
1304 device
->DevChannels
[2] = FrontCenter
;
1305 device
->DevChannels
[3] = LFE
;
1306 device
->DevChannels
[4] = BackLeft
;
1307 device
->DevChannels
[5] = BackRight
;
1308 device
->DevChannels
[6] = SideLeft
;
1309 device
->DevChannels
[7] = SideRight
; break;
1313 /* SetDefaultChannelOrder
1315 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1317 void SetDefaultChannelOrder(ALCdevice
*device
)
1319 switch(device
->FmtChans
)
1321 case DevFmtX51
: device
->DevChannels
[0] = FrontLeft
;
1322 device
->DevChannels
[1] = FrontRight
;
1323 device
->DevChannels
[2] = BackLeft
;
1324 device
->DevChannels
[3] = BackRight
;
1325 device
->DevChannels
[4] = FrontCenter
;
1326 device
->DevChannels
[5] = LFE
;
1329 case DevFmtX71
: device
->DevChannels
[0] = FrontLeft
;
1330 device
->DevChannels
[1] = FrontRight
;
1331 device
->DevChannels
[2] = BackLeft
;
1332 device
->DevChannels
[3] = BackRight
;
1333 device
->DevChannels
[4] = FrontCenter
;
1334 device
->DevChannels
[5] = LFE
;
1335 device
->DevChannels
[6] = SideLeft
;
1336 device
->DevChannels
[7] = SideRight
;
1339 /* Same as WFX order */
1347 SetDefaultWFXChannelOrder(device
);
1353 * Stores the latest ALC device error
1355 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1360 /* DebugBreak() will cause an exception if there is no debugger */
1361 if(IsDebuggerPresent())
1363 #elif defined(SIGTRAP)
1369 device
->LastError
= errorCode
;
1371 LastNullDeviceError
= errorCode
;
1375 /* UpdateDeviceParams
1377 * Updates device parameters according to the attribute list (caller is
1378 * responsible for holding the list lock).
1380 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1382 ALCcontext
*context
;
1383 enum DevFmtChannels oldChans
;
1384 enum DevFmtType oldType
;
1389 // Check for attributes
1390 if(device
->Type
== Loopback
)
1396 GotAll
= GotFreq
|GotChans
|GotType
1398 ALCuint freq
, numMono
, numStereo
, numSends
;
1399 enum DevFmtChannels schans
;
1400 enum DevFmtType stype
;
1401 ALCuint attrIdx
= 0;
1406 WARN("Missing attributes for loopback device\n");
1407 return ALC_INVALID_VALUE
;
1410 numMono
= device
->NumMonoSources
;
1411 numStereo
= device
->NumStereoSources
;
1412 numSends
= device
->NumAuxSends
;
1413 schans
= device
->FmtChans
;
1414 stype
= device
->FmtType
;
1415 freq
= device
->Frequency
;
1417 while(attrList
[attrIdx
])
1419 if(attrList
[attrIdx
] == ALC_FORMAT_CHANNELS_SOFT
)
1421 ALCint val
= attrList
[attrIdx
+ 1];
1422 if(!IsValidALCChannels(val
) || !ChannelsFromDevFmt(val
))
1423 return ALC_INVALID_VALUE
;
1428 if(attrList
[attrIdx
] == ALC_FORMAT_TYPE_SOFT
)
1430 ALCint val
= attrList
[attrIdx
+ 1];
1431 if(!IsValidALCType(val
) || !BytesFromDevFmt(val
))
1432 return ALC_INVALID_VALUE
;
1437 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1439 freq
= attrList
[attrIdx
+ 1];
1440 if(freq
< MIN_OUTPUT_RATE
)
1441 return ALC_INVALID_VALUE
;
1445 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1447 numStereo
= attrList
[attrIdx
+ 1];
1448 if(numStereo
> device
->MaxNoOfSources
)
1449 numStereo
= device
->MaxNoOfSources
;
1451 numMono
= device
->MaxNoOfSources
- numStereo
;
1454 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
1455 numSends
= attrList
[attrIdx
+ 1];
1460 if(gotFmt
!= GotAll
)
1462 WARN("Missing format for loopback device\n");
1463 return ALC_INVALID_VALUE
;
1466 ConfigValueUInt(NULL
, "sends", &numSends
);
1467 numSends
= minu(MAX_SENDS
, numSends
);
1469 if((device
->Flags
&DEVICE_RUNNING
))
1470 ALCdevice_StopPlayback(device
);
1471 device
->Flags
&= ~DEVICE_RUNNING
;
1473 device
->Frequency
= freq
;
1474 device
->FmtChans
= schans
;
1475 device
->FmtType
= stype
;
1476 device
->NumMonoSources
= numMono
;
1477 device
->NumStereoSources
= numStereo
;
1478 device
->NumAuxSends
= numSends
;
1480 else if(attrList
&& attrList
[0])
1482 ALCuint freq
, numMono
, numStereo
, numSends
;
1483 ALCuint attrIdx
= 0;
1485 /* If a context is already running on the device, stop playback so the
1486 * device attributes can be updated. */
1487 if((device
->Flags
&DEVICE_RUNNING
))
1488 ALCdevice_StopPlayback(device
);
1489 device
->Flags
&= ~DEVICE_RUNNING
;
1491 freq
= device
->Frequency
;
1492 numMono
= device
->NumMonoSources
;
1493 numStereo
= device
->NumStereoSources
;
1494 numSends
= device
->NumAuxSends
;
1496 while(attrList
[attrIdx
])
1498 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1500 freq
= attrList
[attrIdx
+ 1];
1501 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1504 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1506 numStereo
= attrList
[attrIdx
+ 1];
1507 if(numStereo
> device
->MaxNoOfSources
)
1508 numStereo
= device
->MaxNoOfSources
;
1510 numMono
= device
->MaxNoOfSources
- numStereo
;
1513 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
1514 numSends
= attrList
[attrIdx
+ 1];
1519 ConfigValueUInt(NULL
, "frequency", &freq
);
1520 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
1522 ConfigValueUInt(NULL
, "sends", &numSends
);
1523 numSends
= minu(MAX_SENDS
, numSends
);
1525 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
1528 device
->Frequency
= freq
;
1529 device
->NumMonoSources
= numMono
;
1530 device
->NumStereoSources
= numStereo
;
1531 device
->NumAuxSends
= numSends
;
1534 if((device
->Flags
&DEVICE_RUNNING
))
1535 return ALC_NO_ERROR
;
1537 oldFreq
= device
->Frequency
;
1538 oldChans
= device
->FmtChans
;
1539 oldType
= device
->FmtType
;
1541 TRACE("Format pre-setup: %s%s, %s%s, %uhz%s, %u update size x%d\n",
1542 DevFmtChannelsString(device
->FmtChans
),
1543 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?" (requested)":"",
1544 DevFmtTypeString(device
->FmtType
),
1545 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?" (requested)":"",
1547 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?" (requested)":"",
1548 device
->UpdateSize
, device
->NumUpdates
);
1550 if(ALCdevice_ResetPlayback(device
) == ALC_FALSE
)
1551 return ALC_INVALID_DEVICE
;
1553 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
1555 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
1556 DevFmtChannelsString(device
->FmtChans
));
1557 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
1559 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
1561 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
1562 DevFmtTypeString(device
->FmtType
));
1563 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
1565 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
1567 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
1568 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
1571 TRACE("Format post-setup: %s, %s, %uhz, %u update size x%d\n",
1572 DevFmtChannelsString(device
->FmtChans
),
1573 DevFmtTypeString(device
->FmtType
), device
->Frequency
,
1574 device
->UpdateSize
, device
->NumUpdates
);
1576 aluInitPanning(device
);
1578 for(i
= 0;i
< MaxChannels
;i
++)
1580 device
->ClickRemoval
[i
] = 0.0f
;
1581 device
->PendingClicks
[i
] = 0.0f
;
1584 device
->Hrtf
= NULL
;
1585 if(device
->Type
!= Loopback
&& GetConfigValueBool(NULL
, "hrtf", AL_FALSE
))
1586 device
->Hrtf
= GetHrtf(device
);
1587 TRACE("HRTF %s\n", device
->Hrtf
?"enabled":"disabled");
1589 if(!device
->Hrtf
&& device
->Bs2bLevel
> 0 && device
->Bs2bLevel
<= 6)
1593 device
->Bs2b
= calloc(1, sizeof(*device
->Bs2b
));
1594 bs2b_clear(device
->Bs2b
);
1596 bs2b_set_srate(device
->Bs2b
, device
->Frequency
);
1597 bs2b_set_level(device
->Bs2b
, device
->Bs2bLevel
);
1598 TRACE("BS2B level %d\n", device
->Bs2bLevel
);
1603 device
->Bs2b
= NULL
;
1604 TRACE("BS2B disabled\n");
1607 device
->Flags
&= ~DEVICE_WIDE_STEREO
;
1608 if(device
->Type
!= Loopback
&& !device
->Hrtf
&& GetConfigValueBool(NULL
, "wide-stereo", AL_FALSE
))
1609 device
->Flags
|= DEVICE_WIDE_STEREO
;
1611 oldMode
= SetMixerFPUMode();
1613 context
= device
->ContextList
;
1618 context
->UpdateSources
= AL_FALSE
;
1619 LockUIntMapRead(&context
->EffectSlotMap
);
1620 for(pos
= 0;pos
< context
->EffectSlotMap
.size
;pos
++)
1622 ALeffectslot
*slot
= context
->EffectSlotMap
.array
[pos
].value
;
1624 if(ALeffectState_DeviceUpdate(slot
->EffectState
, device
) == AL_FALSE
)
1626 UnlockUIntMapRead(&context
->EffectSlotMap
);
1627 UnlockDevice(device
);
1628 RestoreFPUMode(oldMode
);
1629 return ALC_INVALID_DEVICE
;
1631 slot
->NeedsUpdate
= AL_FALSE
;
1632 ALeffectState_Update(slot
->EffectState
, device
, slot
);
1634 UnlockUIntMapRead(&context
->EffectSlotMap
);
1636 LockUIntMapRead(&context
->SourceMap
);
1637 for(pos
= 0;pos
< context
->SourceMap
.size
;pos
++)
1639 ALsource
*source
= context
->SourceMap
.array
[pos
].value
;
1640 ALuint s
= device
->NumAuxSends
;
1641 while(s
< MAX_SENDS
)
1643 if(source
->Send
[s
].Slot
)
1644 DecrementRef(&source
->Send
[s
].Slot
->ref
);
1645 source
->Send
[s
].Slot
= NULL
;
1646 source
->Send
[s
].Gain
= 1.0f
;
1647 source
->Send
[s
].GainHF
= 1.0f
;
1650 source
->NeedsUpdate
= AL_FALSE
;
1651 ALsource_Update(source
, context
);
1653 UnlockUIntMapRead(&context
->SourceMap
);
1655 context
= context
->next
;
1657 if(device
->DefaultSlot
)
1659 ALeffectslot
*slot
= device
->DefaultSlot
;
1661 if(ALeffectState_DeviceUpdate(slot
->EffectState
, device
) == AL_FALSE
)
1663 UnlockDevice(device
);
1664 RestoreFPUMode(oldMode
);
1665 return ALC_INVALID_DEVICE
;
1667 slot
->NeedsUpdate
= AL_FALSE
;
1668 ALeffectState_Update(slot
->EffectState
, device
, slot
);
1670 UnlockDevice(device
);
1671 RestoreFPUMode(oldMode
);
1673 if(ALCdevice_StartPlayback(device
) == ALC_FALSE
)
1674 return ALC_INVALID_DEVICE
;
1675 device
->Flags
|= DEVICE_RUNNING
;
1677 return ALC_NO_ERROR
;
1682 * Frees the device structure, and destroys any objects the app failed to
1683 * delete. Called once there's no more references on the device.
1685 static ALCvoid
FreeDevice(ALCdevice
*device
)
1687 TRACE("%p\n", device
);
1689 if(device
->DefaultSlot
)
1691 ALeffectState_Destroy(device
->DefaultSlot
->EffectState
);
1692 device
->DefaultSlot
->EffectState
= NULL
;
1695 if(device
->BufferMap
.size
> 0)
1697 WARN("(%p) Deleting %d Buffer(s)\n", device
, device
->BufferMap
.size
);
1698 ReleaseALBuffers(device
);
1700 ResetUIntMap(&device
->BufferMap
);
1702 if(device
->EffectMap
.size
> 0)
1704 WARN("(%p) Deleting %d Effect(s)\n", device
, device
->EffectMap
.size
);
1705 ReleaseALEffects(device
);
1707 ResetUIntMap(&device
->EffectMap
);
1709 if(device
->FilterMap
.size
> 0)
1711 WARN("(%p) Deleting %d Filter(s)\n", device
, device
->FilterMap
.size
);
1712 ReleaseALFilters(device
);
1714 ResetUIntMap(&device
->FilterMap
);
1717 device
->Bs2b
= NULL
;
1719 free(device
->DeviceName
);
1720 device
->DeviceName
= NULL
;
1722 DeleteCriticalSection(&device
->Mutex
);
1728 void ALCdevice_IncRef(ALCdevice
*device
)
1731 ref
= IncrementRef(&device
->ref
);
1732 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
1735 void ALCdevice_DecRef(ALCdevice
*device
)
1738 ref
= DecrementRef(&device
->ref
);
1739 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
1740 if(ref
== 0) FreeDevice(device
);
1745 * Checks if the device handle is valid, and increments its ref count if so.
1747 static ALCdevice
*VerifyDevice(ALCdevice
*device
)
1749 ALCdevice
*tmpDevice
;
1755 tmpDevice
= DeviceList
;
1756 while(tmpDevice
&& tmpDevice
!= device
)
1757 tmpDevice
= tmpDevice
->next
;
1760 ALCdevice_IncRef(tmpDevice
);
1768 * Initializes context fields
1770 static ALvoid
InitContext(ALCcontext
*Context
)
1774 //Initialise listener
1775 Context
->Listener
.Gain
= 1.0f
;
1776 Context
->Listener
.MetersPerUnit
= 1.0f
;
1777 Context
->Listener
.Position
[0] = 0.0f
;
1778 Context
->Listener
.Position
[1] = 0.0f
;
1779 Context
->Listener
.Position
[2] = 0.0f
;
1780 Context
->Listener
.Velocity
[0] = 0.0f
;
1781 Context
->Listener
.Velocity
[1] = 0.0f
;
1782 Context
->Listener
.Velocity
[2] = 0.0f
;
1783 Context
->Listener
.Forward
[0] = 0.0f
;
1784 Context
->Listener
.Forward
[1] = 0.0f
;
1785 Context
->Listener
.Forward
[2] = -1.0f
;
1786 Context
->Listener
.Up
[0] = 0.0f
;
1787 Context
->Listener
.Up
[1] = 1.0f
;
1788 Context
->Listener
.Up
[2] = 0.0f
;
1789 for(i
= 0;i
< 4;i
++)
1791 for(j
= 0;j
< 4;j
++)
1792 Context
->Listener
.Matrix
[i
][j
] = ((i
==j
) ? 1.0f
: 0.0f
);
1796 Context
->LastError
= AL_NO_ERROR
;
1797 Context
->UpdateSources
= AL_FALSE
;
1798 Context
->ActiveSourceCount
= 0;
1799 InitUIntMap(&Context
->SourceMap
, Context
->Device
->MaxNoOfSources
);
1800 InitUIntMap(&Context
->EffectSlotMap
, Context
->Device
->AuxiliaryEffectSlotMax
);
1803 Context
->DistanceModel
= AL_INVERSE_DISTANCE_CLAMPED
;
1804 Context
->SourceDistanceModel
= AL_FALSE
;
1805 Context
->DopplerFactor
= 1.0f
;
1806 Context
->DopplerVelocity
= 1.0f
;
1807 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
1808 Context
->DeferUpdates
= AL_FALSE
;
1810 Context
->ExtensionList
= alExtList
;
1816 * Cleans up the context, and destroys any remaining objects the app failed to
1817 * delete. Called once there's no more references on the context.
1819 static ALCvoid
FreeContext(ALCcontext
*context
)
1821 TRACE("%p\n", context
);
1823 if(context
->SourceMap
.size
> 0)
1825 ERR("(%p) Deleting %d Source(s)\n", context
, context
->SourceMap
.size
);
1826 ReleaseALSources(context
);
1828 ResetUIntMap(&context
->SourceMap
);
1830 if(context
->EffectSlotMap
.size
> 0)
1832 ERR("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context
, context
->EffectSlotMap
.size
);
1833 ReleaseALAuxiliaryEffectSlots(context
);
1835 ResetUIntMap(&context
->EffectSlotMap
);
1837 context
->ActiveSourceCount
= 0;
1838 free(context
->ActiveSources
);
1839 context
->ActiveSources
= NULL
;
1840 context
->MaxActiveSources
= 0;
1842 context
->ActiveEffectSlotCount
= 0;
1843 free(context
->ActiveEffectSlots
);
1844 context
->ActiveEffectSlots
= NULL
;
1845 context
->MaxActiveEffectSlots
= 0;
1847 ALCdevice_DecRef(context
->Device
);
1848 context
->Device
= NULL
;
1850 //Invalidate context
1851 memset(context
, 0, sizeof(ALCcontext
));
1857 * Removes the context reference from the given device and removes it from
1858 * being current on the running thread or globally.
1860 static void ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
1862 ALCcontext
*volatile*tmp_ctx
;
1864 if(pthread_getspecific(LocalContext
) == context
)
1866 WARN("%p released while current on thread\n", context
);
1867 pthread_setspecific(LocalContext
, NULL
);
1868 ALCcontext_DecRef(context
);
1871 if(CompExchangePtr((XchgPtr
*)&GlobalContext
, context
, NULL
))
1872 ALCcontext_DecRef(context
);
1875 tmp_ctx
= &device
->ContextList
;
1878 if(CompExchangePtr((XchgPtr
*)tmp_ctx
, context
, context
->next
))
1880 tmp_ctx
= &(*tmp_ctx
)->next
;
1882 UnlockDevice(device
);
1884 ALCcontext_DecRef(context
);
1887 void ALCcontext_IncRef(ALCcontext
*context
)
1890 ref
= IncrementRef(&context
->ref
);
1891 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
1894 void ALCcontext_DecRef(ALCcontext
*context
)
1897 ref
= DecrementRef(&context
->ref
);
1898 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
1899 if(ref
== 0) FreeContext(context
);
1902 static void ReleaseThreadCtx(void *ptr
)
1904 WARN("%p current for thread being destroyed\n", ptr
);
1905 ALCcontext_DecRef(ptr
);
1910 * Checks that the given context is valid, and increments its reference count.
1912 static ALCcontext
*VerifyContext(ALCcontext
*context
)
1920 ALCcontext
*tmp_ctx
= dev
->ContextList
;
1923 if(tmp_ctx
== context
)
1925 ALCcontext_IncRef(tmp_ctx
);
1929 tmp_ctx
= tmp_ctx
->next
;
1941 * Returns the currently active context for this thread, and adds a reference
1942 * without locking it.
1944 ALCcontext
*GetContextRef(void)
1946 ALCcontext
*context
;
1948 context
= pthread_getspecific(LocalContext
);
1950 ALCcontext_IncRef(context
);
1954 context
= GlobalContext
;
1956 ALCcontext_IncRef(context
);
1964 /************************************************
1965 * Standard ALC functions
1966 ************************************************/
1970 * Return last ALC generated error code for the given device
1972 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
1976 if(VerifyDevice(device
))
1978 errorCode
= ExchangeInt(&device
->LastError
, ALC_NO_ERROR
);
1979 ALCdevice_DecRef(device
);
1982 errorCode
= ExchangeInt(&LastNullDeviceError
, ALC_NO_ERROR
);
1988 /* alcSuspendContext
1992 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*Context
)
1997 /* alcProcessContext
2001 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*Context
)
2009 * Returns information about the device, and error strings
2011 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2013 const ALCchar
*value
= NULL
;
2021 case ALC_INVALID_ENUM
:
2022 value
= alcErrInvalidEnum
;
2025 case ALC_INVALID_VALUE
:
2026 value
= alcErrInvalidValue
;
2029 case ALC_INVALID_DEVICE
:
2030 value
= alcErrInvalidDevice
;
2033 case ALC_INVALID_CONTEXT
:
2034 value
= alcErrInvalidContext
;
2037 case ALC_OUT_OF_MEMORY
:
2038 value
= alcErrOutOfMemory
;
2041 case ALC_DEVICE_SPECIFIER
:
2042 value
= alcDefaultName
;
2045 case ALC_ALL_DEVICES_SPECIFIER
:
2046 if(VerifyDevice(Device
))
2048 value
= Device
->DeviceName
;
2049 ALCdevice_DecRef(Device
);
2053 ProbeAllDevicesList();
2054 value
= alcAllDevicesList
;
2058 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2059 if(VerifyDevice(Device
))
2061 value
= Device
->DeviceName
;
2062 ALCdevice_DecRef(Device
);
2066 ProbeCaptureDeviceList();
2067 value
= alcCaptureDeviceList
;
2071 /* Default devices are always first in the list */
2072 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2073 value
= alcDefaultName
;
2076 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2077 if(!alcAllDevicesList
)
2078 ProbeAllDevicesList();
2080 Device
= VerifyDevice(Device
);
2082 free(alcDefaultAllDevicesSpecifier
);
2083 alcDefaultAllDevicesSpecifier
= strdup(alcAllDevicesList
?
2084 alcAllDevicesList
: "");
2085 if(!alcDefaultAllDevicesSpecifier
)
2086 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2088 value
= alcDefaultAllDevicesSpecifier
;
2089 if(Device
) ALCdevice_DecRef(Device
);
2092 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2093 if(!alcCaptureDeviceList
)
2094 ProbeCaptureDeviceList();
2096 Device
= VerifyDevice(Device
);
2098 free(alcCaptureDefaultDeviceSpecifier
);
2099 alcCaptureDefaultDeviceSpecifier
= strdup(alcCaptureDeviceList
?
2100 alcCaptureDeviceList
: "");
2101 if(!alcCaptureDefaultDeviceSpecifier
)
2102 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2104 value
= alcCaptureDefaultDeviceSpecifier
;
2105 if(Device
) ALCdevice_DecRef(Device
);
2108 case ALC_EXTENSIONS
:
2109 if(!VerifyDevice(Device
))
2110 value
= alcNoDeviceExtList
;
2113 value
= alcExtensionList
;
2114 ALCdevice_DecRef(Device
);
2119 Device
= VerifyDevice(Device
);
2120 alcSetError(Device
, ALC_INVALID_ENUM
);
2121 if(Device
) ALCdevice_DecRef(Device
);
2131 * Returns information about the device and the version of OpenAL
2133 ALC_API ALCvoid ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
,ALCenum param
,ALsizei size
,ALCint
*data
)
2135 device
= VerifyDevice(device
);
2137 if(size
== 0 || data
== NULL
)
2139 alcSetError(device
, ALC_INVALID_VALUE
);
2140 if(device
) ALCdevice_DecRef(device
);
2148 case ALC_MAJOR_VERSION
:
2149 *data
= alcMajorVersion
;
2151 case ALC_MINOR_VERSION
:
2152 *data
= alcMinorVersion
;
2155 case ALC_ATTRIBUTES_SIZE
:
2156 case ALC_ALL_ATTRIBUTES
:
2160 case ALC_MONO_SOURCES
:
2161 case ALC_STEREO_SOURCES
:
2162 case ALC_CAPTURE_SAMPLES
:
2163 case ALC_FORMAT_CHANNELS_SOFT
:
2164 case ALC_FORMAT_TYPE_SOFT
:
2165 alcSetError(NULL
, ALC_INVALID_DEVICE
);
2169 alcSetError(NULL
, ALC_INVALID_ENUM
);
2173 else if(device
->Type
== Capture
)
2177 case ALC_CAPTURE_SAMPLES
:
2179 /* Re-validate the device since it may have been closed */
2180 ALCdevice_DecRef(device
);
2181 if((device
=VerifyDevice(device
)) != NULL
)
2182 *data
= ALCdevice_AvailableSamples(device
);
2184 alcSetError(NULL
, ALC_INVALID_DEVICE
);
2189 *data
= device
->Connected
;
2193 alcSetError(device
, ALC_INVALID_ENUM
);
2197 else /* render device */
2201 case ALC_MAJOR_VERSION
:
2202 *data
= alcMajorVersion
;
2205 case ALC_MINOR_VERSION
:
2206 *data
= alcMinorVersion
;
2209 case ALC_EFX_MAJOR_VERSION
:
2210 *data
= alcEFXMajorVersion
;
2213 case ALC_EFX_MINOR_VERSION
:
2214 *data
= alcEFXMinorVersion
;
2217 case ALC_ATTRIBUTES_SIZE
:
2221 case ALC_ALL_ATTRIBUTES
:
2223 alcSetError(device
, ALC_INVALID_VALUE
);
2228 data
[i
++] = ALC_FREQUENCY
;
2229 data
[i
++] = device
->Frequency
;
2231 if(device
->Type
!= Loopback
)
2233 data
[i
++] = ALC_REFRESH
;
2234 data
[i
++] = device
->Frequency
/ device
->UpdateSize
;
2236 data
[i
++] = ALC_SYNC
;
2237 data
[i
++] = ALC_FALSE
;
2241 data
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
2242 data
[i
++] = device
->FmtChans
;
2244 data
[i
++] = ALC_FORMAT_TYPE_SOFT
;
2245 data
[i
++] = device
->FmtType
;
2248 data
[i
++] = ALC_MONO_SOURCES
;
2249 data
[i
++] = device
->NumMonoSources
;
2251 data
[i
++] = ALC_STEREO_SOURCES
;
2252 data
[i
++] = device
->NumStereoSources
;
2254 data
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
2255 data
[i
++] = device
->NumAuxSends
;
2262 *data
= device
->Frequency
;
2266 if(device
->Type
== Loopback
)
2267 alcSetError(device
, ALC_INVALID_DEVICE
);
2269 *data
= device
->Frequency
/ device
->UpdateSize
;
2273 if(device
->Type
== Loopback
)
2274 alcSetError(device
, ALC_INVALID_DEVICE
);
2279 case ALC_FORMAT_CHANNELS_SOFT
:
2280 if(device
->Type
!= Loopback
)
2281 alcSetError(device
, ALC_INVALID_DEVICE
);
2283 *data
= device
->FmtChans
;
2286 case ALC_FORMAT_TYPE_SOFT
:
2287 if(device
->Type
!= Loopback
)
2288 alcSetError(device
, ALC_INVALID_DEVICE
);
2290 *data
= device
->FmtType
;
2293 case ALC_MONO_SOURCES
:
2294 *data
= device
->NumMonoSources
;
2297 case ALC_STEREO_SOURCES
:
2298 *data
= device
->NumStereoSources
;
2301 case ALC_MAX_AUXILIARY_SENDS
:
2302 *data
= device
->NumAuxSends
;
2306 *data
= device
->Connected
;
2310 alcSetError(device
, ALC_INVALID_ENUM
);
2315 ALCdevice_DecRef(device
);
2319 /* alcIsExtensionPresent
2321 * Determines if there is support for a particular extension
2323 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
2325 ALCboolean bResult
= ALC_FALSE
;
2327 device
= VerifyDevice(device
);
2330 alcSetError(device
, ALC_INVALID_VALUE
);
2333 size_t len
= strlen(extName
);
2334 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
2337 if(strncasecmp(ptr
, extName
, len
) == 0 &&
2338 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
2343 if((ptr
=strchr(ptr
, ' ')) != NULL
)
2347 } while(isspace(*ptr
));
2352 ALCdevice_DecRef(device
);
2357 /* alcGetProcAddress
2359 * Retrieves the function address for a particular extension function
2361 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
2363 ALCvoid
*ptr
= NULL
;
2367 device
= VerifyDevice(device
);
2368 alcSetError(device
, ALC_INVALID_VALUE
);
2369 if(device
) ALCdevice_DecRef(device
);
2374 while(alcFunctions
[i
].funcName
&& strcmp(alcFunctions
[i
].funcName
, funcName
) != 0)
2376 ptr
= alcFunctions
[i
].address
;
2385 * Get the value for a particular ALC enumeration name
2387 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
2393 device
= VerifyDevice(device
);
2394 alcSetError(device
, ALC_INVALID_VALUE
);
2395 if(device
) ALCdevice_DecRef(device
);
2400 while(enumeration
[i
].enumName
&& strcmp(enumeration
[i
].enumName
, enumName
) != 0)
2402 val
= enumeration
[i
].value
;
2411 * Create and attach a context to the given device.
2413 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
2415 ALCcontext
*ALContext
;
2419 if(!(device
=VerifyDevice(device
)) || device
->Type
== Capture
|| !device
->Connected
)
2422 alcSetError(device
, ALC_INVALID_DEVICE
);
2423 if(device
) ALCdevice_DecRef(device
);
2427 device
->LastError
= ALC_NO_ERROR
;
2429 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
2432 alcSetError(device
, err
);
2433 if(err
== ALC_INVALID_DEVICE
)
2434 aluHandleDisconnect(device
);
2435 ALCdevice_DecRef(device
);
2439 ALContext
= calloc(1, sizeof(ALCcontext
));
2444 ALContext
->MaxActiveSources
= 256;
2445 ALContext
->ActiveSources
= malloc(sizeof(ALContext
->ActiveSources
[0]) *
2446 ALContext
->MaxActiveSources
);
2448 if(!ALContext
|| !ALContext
->ActiveSources
)
2450 if(!device
->ContextList
)
2452 ALCdevice_StopPlayback(device
);
2453 device
->Flags
&= ~DEVICE_RUNNING
;
2460 alcSetError(device
, ALC_OUT_OF_MEMORY
);
2461 ALCdevice_DecRef(device
);
2465 ALContext
->Device
= device
;
2466 ALCdevice_IncRef(device
);
2467 InitContext(ALContext
);
2470 ALContext
->next
= device
->ContextList
;
2471 } while(!CompExchangePtr((XchgPtr
*)&device
->ContextList
, ALContext
->next
, ALContext
));
2474 ALCdevice_DecRef(device
);
2476 TRACE("Created context %p\n", ALContext
);
2480 /* alcDestroyContext
2482 * Remove a context from its device
2484 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
2489 /* alcGetContextsDevice sets an error for invalid contexts */
2490 Device
= alcGetContextsDevice(context
);
2493 ReleaseContext(context
, Device
);
2494 if(!Device
->ContextList
)
2496 ALCdevice_StopPlayback(Device
);
2497 Device
->Flags
&= ~DEVICE_RUNNING
;
2504 /* alcGetCurrentContext
2506 * Returns the currently active context on the calling thread
2508 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
2510 ALCcontext
*Context
;
2512 Context
= pthread_getspecific(LocalContext
);
2513 if(!Context
) Context
= GlobalContext
;
2518 /* alcGetThreadContext
2520 * Returns the currently active thread-local context
2522 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
2524 ALCcontext
*Context
;
2525 Context
= pthread_getspecific(LocalContext
);
2530 /* alcMakeContextCurrent
2532 * Makes the given context the active process-wide context, and removes the
2533 * thread-local context for the calling thread.
2535 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
2537 /* context must be valid or NULL */
2538 if(context
&& !(context
=VerifyContext(context
)))
2540 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2543 /* context's reference count is already incremented */
2544 context
= ExchangePtr((XchgPtr
*)&GlobalContext
, context
);
2545 if(context
) ALCcontext_DecRef(context
);
2547 if((context
=pthread_getspecific(LocalContext
)) != NULL
)
2549 pthread_setspecific(LocalContext
, NULL
);
2550 ALCcontext_DecRef(context
);
2556 /* alcSetThreadContext
2558 * Makes the given context the active context for the current thread
2560 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
2564 /* context must be valid or NULL */
2565 if(context
&& !(context
=VerifyContext(context
)))
2567 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2570 /* context's reference count is already incremented */
2571 old
= pthread_getspecific(LocalContext
);
2572 pthread_setspecific(LocalContext
, context
);
2573 if(old
) ALCcontext_DecRef(old
);
2579 /* alcGetContextsDevice
2581 * Returns the device that a particular context is attached to
2583 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
2587 if(!(Context
=VerifyContext(Context
)))
2589 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2592 Device
= Context
->Device
;
2593 ALCcontext_DecRef(Context
);
2601 * Opens the named device.
2603 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
2611 if(!PlaybackBackend
.name
)
2613 alcSetError(NULL
, ALC_INVALID_VALUE
);
2617 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
2620 device
= calloc(1, sizeof(ALCdevice
)+sizeof(ALeffectslot
));
2623 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
2628 device
->Funcs
= &PlaybackBackend
.Funcs
;
2630 device
->Connected
= ALC_TRUE
;
2631 device
->Type
= Playback
;
2632 InitializeCriticalSection(&device
->Mutex
);
2633 device
->LastError
= ALC_NO_ERROR
;
2636 device
->Bs2b
= NULL
;
2637 device
->Bs2bLevel
= 0;
2638 device
->DeviceName
= NULL
;
2640 device
->ContextList
= NULL
;
2642 device
->MaxNoOfSources
= 256;
2643 device
->AuxiliaryEffectSlotMax
= 4;
2644 device
->NumAuxSends
= MAX_SENDS
;
2646 InitUIntMap(&device
->BufferMap
, ~0);
2647 InitUIntMap(&device
->EffectMap
, ~0);
2648 InitUIntMap(&device
->FilterMap
, ~0);
2651 device
->FmtChans
= DevFmtChannelsDefault
;
2652 device
->FmtType
= DevFmtTypeDefault
;
2653 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
2654 device
->NumUpdates
= 4;
2655 device
->UpdateSize
= 1024;
2657 if(ConfigValueStr(NULL
, "channels", &fmt
))
2659 static const struct {
2660 const char name
[16];
2661 enum DevFmtChannels chans
;
2663 { "mono", DevFmtMono
},
2664 { "stereo", DevFmtStereo
},
2665 { "quad", DevFmtQuad
},
2666 { "surround51", DevFmtX51
},
2667 { "surround61", DevFmtX61
},
2668 { "surround71", DevFmtX71
},
2672 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
2674 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
2676 device
->FmtChans
= chanlist
[i
].chans
;
2677 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
2681 if(i
== COUNTOF(chanlist
))
2682 ERR("Unsupported channels: %s\n", fmt
);
2684 if(ConfigValueStr(NULL
, "sample-type", &fmt
))
2686 static const struct {
2687 const char name
[16];
2688 enum DevFmtType type
;
2690 { "int8", DevFmtByte
},
2691 { "uint8", DevFmtUByte
},
2692 { "int16", DevFmtShort
},
2693 { "uint16", DevFmtUShort
},
2694 { "int32", DevFmtInt
},
2695 { "uint32", DevFmtUInt
},
2696 { "float32", DevFmtFloat
},
2700 for(i
= 0;i
< COUNTOF(typelist
);i
++)
2702 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
2704 device
->FmtType
= typelist
[i
].type
;
2705 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
2709 if(i
== COUNTOF(typelist
))
2710 ERR("Unsupported sample-type: %s\n", fmt
);
2712 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
2713 if((device
->Flags
&DEVICE_FORMAT_REQUEST
) != DEVICE_FORMAT_REQUEST
&&
2714 ConfigValueStr(NULL
, "format", &fmt
))
2716 static const struct {
2717 const char name
[32];
2718 enum DevFmtChannels channels
;
2719 enum DevFmtType type
;
2721 { "AL_FORMAT_MONO32", DevFmtMono
, DevFmtFloat
},
2722 { "AL_FORMAT_STEREO32", DevFmtStereo
, DevFmtFloat
},
2723 { "AL_FORMAT_QUAD32", DevFmtQuad
, DevFmtFloat
},
2724 { "AL_FORMAT_51CHN32", DevFmtX51
, DevFmtFloat
},
2725 { "AL_FORMAT_61CHN32", DevFmtX61
, DevFmtFloat
},
2726 { "AL_FORMAT_71CHN32", DevFmtX71
, DevFmtFloat
},
2728 { "AL_FORMAT_MONO16", DevFmtMono
, DevFmtShort
},
2729 { "AL_FORMAT_STEREO16", DevFmtStereo
, DevFmtShort
},
2730 { "AL_FORMAT_QUAD16", DevFmtQuad
, DevFmtShort
},
2731 { "AL_FORMAT_51CHN16", DevFmtX51
, DevFmtShort
},
2732 { "AL_FORMAT_61CHN16", DevFmtX61
, DevFmtShort
},
2733 { "AL_FORMAT_71CHN16", DevFmtX71
, DevFmtShort
},
2735 { "AL_FORMAT_MONO8", DevFmtMono
, DevFmtByte
},
2736 { "AL_FORMAT_STEREO8", DevFmtStereo
, DevFmtByte
},
2737 { "AL_FORMAT_QUAD8", DevFmtQuad
, DevFmtByte
},
2738 { "AL_FORMAT_51CHN8", DevFmtX51
, DevFmtByte
},
2739 { "AL_FORMAT_61CHN8", DevFmtX61
, DevFmtByte
},
2740 { "AL_FORMAT_71CHN8", DevFmtX71
, DevFmtByte
}
2744 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
2745 for(i
= 0;i
< COUNTOF(formats
);i
++)
2747 if(strcasecmp(fmt
, formats
[i
].name
) == 0)
2749 if(!(device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2750 device
->FmtChans
= formats
[i
].channels
;
2751 if(!(device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2752 device
->FmtType
= formats
[i
].type
;
2753 device
->Flags
|= DEVICE_FORMAT_REQUEST
;
2757 if(i
== COUNTOF(formats
))
2758 ERR("Unsupported format: %s\n", fmt
);
2760 #undef DEVICE_FORMAT_REQUEST
2762 if(ConfigValueUInt(NULL
, "frequency", &device
->Frequency
))
2764 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
2765 if(device
->Frequency
< MIN_OUTPUT_RATE
)
2766 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
2767 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
2770 ConfigValueUInt(NULL
, "periods", &device
->NumUpdates
);
2771 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
2773 ConfigValueUInt(NULL
, "period_size", &device
->UpdateSize
);
2774 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
2776 ConfigValueUInt(NULL
, "sources", &device
->MaxNoOfSources
);
2777 if(device
->MaxNoOfSources
== 0) device
->MaxNoOfSources
= 256;
2779 ConfigValueUInt(NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
2780 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 4;
2782 ConfigValueUInt(NULL
, "sends", &device
->NumAuxSends
);
2783 if(device
->NumAuxSends
> MAX_SENDS
) device
->NumAuxSends
= MAX_SENDS
;
2785 ConfigValueInt(NULL
, "cf_level", &device
->Bs2bLevel
);
2787 device
->NumStereoSources
= 1;
2788 device
->NumMonoSources
= device
->MaxNoOfSources
- device
->NumStereoSources
;
2790 // Find a playback device to open
2792 if((err
=ALCdevice_OpenPlayback(device
, deviceName
)) != ALC_NO_ERROR
)
2795 DeleteCriticalSection(&device
->Mutex
);
2797 alcSetError(NULL
, err
);
2802 if(DefaultEffect
.type
!= AL_EFFECT_NULL
)
2804 device
->DefaultSlot
= (ALeffectslot
*)(device
+1);
2805 if(InitEffectSlot(device
->DefaultSlot
) != AL_NO_ERROR
)
2807 device
->DefaultSlot
= NULL
;
2808 ERR("Failed to initialize the default effect slot\n");
2810 else if(InitializeEffect(device
, device
->DefaultSlot
, &DefaultEffect
) != AL_NO_ERROR
)
2812 ALeffectState_Destroy(device
->DefaultSlot
->EffectState
);
2813 device
->DefaultSlot
= NULL
;
2814 ERR("Failed to initialize the default effect\n");
2819 device
->next
= DeviceList
;
2820 } while(!CompExchangePtr((XchgPtr
*)&DeviceList
, device
->next
, device
));
2822 TRACE("Created device %p, \"%s\"\n", device
, device
->DeviceName
);
2828 * Closes the given device.
2830 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*Device
)
2832 ALCdevice
*volatile*list
;
2837 while(*list
&& *list
!= Device
)
2838 list
= &(*list
)->next
;
2840 if(!*list
|| (*list
)->Type
== Capture
)
2842 alcSetError(*list
, ALC_INVALID_DEVICE
);
2847 *list
= (*list
)->next
;
2850 while((ctx
=Device
->ContextList
) != NULL
)
2852 WARN("Releasing context %p\n", ctx
);
2853 ReleaseContext(ctx
, Device
);
2855 if((Device
->Flags
&DEVICE_RUNNING
))
2856 ALCdevice_StopPlayback(Device
);
2857 Device
->Flags
&= ~DEVICE_RUNNING
;
2859 ALCdevice_ClosePlayback(Device
);
2861 ALCdevice_DecRef(Device
);
2867 /************************************************
2868 * ALC capture functions
2869 ************************************************/
2870 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
2872 ALCdevice
*device
= NULL
;
2877 if(!CaptureBackend
.name
)
2879 alcSetError(NULL
, ALC_INVALID_VALUE
);
2885 alcSetError(NULL
, ALC_INVALID_VALUE
);
2889 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
2892 device
= calloc(1, sizeof(ALCdevice
));
2895 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
2900 device
->Funcs
= &CaptureBackend
.Funcs
;
2902 device
->Connected
= ALC_TRUE
;
2903 device
->Type
= Capture
;
2904 InitializeCriticalSection(&device
->Mutex
);
2906 InitUIntMap(&device
->BufferMap
, ~0);
2907 InitUIntMap(&device
->EffectMap
, ~0);
2908 InitUIntMap(&device
->FilterMap
, ~0);
2910 device
->DeviceName
= NULL
;
2912 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
2913 device
->Frequency
= frequency
;
2915 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
2916 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
2918 DeleteCriticalSection(&device
->Mutex
);
2920 alcSetError(NULL
, ALC_INVALID_ENUM
);
2924 device
->UpdateSize
= samples
;
2925 device
->NumUpdates
= 1;
2928 if((err
=ALCdevice_OpenCapture(device
, deviceName
)) != ALC_NO_ERROR
)
2931 DeleteCriticalSection(&device
->Mutex
);
2933 alcSetError(NULL
, err
);
2939 device
->next
= DeviceList
;
2940 } while(!CompExchangePtr((XchgPtr
*)&DeviceList
, device
->next
, device
));
2942 TRACE("Created device %p\n", device
);
2946 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*Device
)
2948 ALCdevice
*volatile*list
;
2952 while(*list
&& *list
!= Device
)
2953 list
= &(*list
)->next
;
2955 if(!*list
|| (*list
)->Type
!= Capture
)
2957 alcSetError(*list
, ALC_INVALID_DEVICE
);
2962 *list
= (*list
)->next
;
2965 ALCdevice_CloseCapture(Device
);
2967 ALCdevice_DecRef(Device
);
2972 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
2975 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Capture
)
2978 alcSetError(device
, ALC_INVALID_DEVICE
);
2979 if(device
) ALCdevice_DecRef(device
);
2982 if(device
->Connected
)
2984 if(!(device
->Flags
&DEVICE_RUNNING
))
2985 ALCdevice_StartCapture(device
);
2986 device
->Flags
|= DEVICE_RUNNING
;
2990 ALCdevice_DecRef(device
);
2993 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
2996 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Capture
)
2999 alcSetError(device
, ALC_INVALID_DEVICE
);
3000 if(device
) ALCdevice_DecRef(device
);
3003 if((device
->Flags
&DEVICE_RUNNING
))
3004 ALCdevice_StopCapture(device
);
3005 device
->Flags
&= ~DEVICE_RUNNING
;
3008 ALCdevice_DecRef(device
);
3011 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
3013 ALCenum err
= ALC_INVALID_DEVICE
;
3015 if((device
=VerifyDevice(device
)) != NULL
&& device
->Type
== Capture
)
3017 err
= ALC_INVALID_VALUE
;
3018 if(samples
>= 0 && ALCdevice_AvailableSamples(device
) >= (ALCuint
)samples
)
3019 err
= ALCdevice_CaptureSamples(device
, buffer
, samples
);
3022 if(err
!= ALC_NO_ERROR
)
3023 alcSetError(device
, err
);
3024 if(device
) ALCdevice_DecRef(device
);
3028 /************************************************
3029 * ALC loopback functions
3030 ************************************************/
3032 /* alcLoopbackOpenDeviceSOFT
3034 * Open a loopback device, for manual rendering.
3036 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
3042 /* Make sure the device name, if specified, is us. */
3043 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
3045 alcSetError(NULL
, ALC_INVALID_VALUE
);
3049 device
= calloc(1, sizeof(ALCdevice
));
3052 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3057 device
->Funcs
= &BackendLoopback
.Funcs
;
3059 device
->Connected
= ALC_TRUE
;
3060 device
->Type
= Loopback
;
3061 InitializeCriticalSection(&device
->Mutex
);
3062 device
->LastError
= ALC_NO_ERROR
;
3065 device
->Bs2b
= NULL
;
3066 device
->Bs2bLevel
= 0;
3067 device
->DeviceName
= NULL
;
3069 device
->ContextList
= NULL
;
3071 device
->MaxNoOfSources
= 256;
3072 device
->AuxiliaryEffectSlotMax
= 4;
3073 device
->NumAuxSends
= MAX_SENDS
;
3075 InitUIntMap(&device
->BufferMap
, ~0);
3076 InitUIntMap(&device
->EffectMap
, ~0);
3077 InitUIntMap(&device
->FilterMap
, ~0);
3080 device
->NumUpdates
= 0;
3081 device
->UpdateSize
= 0;
3083 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3084 device
->FmtChans
= DevFmtChannelsDefault
;
3085 device
->FmtType
= DevFmtTypeDefault
;
3087 ConfigValueUInt(NULL
, "sources", &device
->MaxNoOfSources
);
3088 if(device
->MaxNoOfSources
== 0) device
->MaxNoOfSources
= 256;
3090 ConfigValueUInt(NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
3091 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 4;
3093 ConfigValueUInt(NULL
, "sends", &device
->NumAuxSends
);
3094 if(device
->NumAuxSends
> MAX_SENDS
) device
->NumAuxSends
= MAX_SENDS
;
3096 device
->NumStereoSources
= 1;
3097 device
->NumMonoSources
= device
->MaxNoOfSources
- device
->NumStereoSources
;
3099 // Open the "backend"
3100 ALCdevice_OpenPlayback(device
, "Loopback");
3102 device
->next
= DeviceList
;
3103 } while(!CompExchangePtr((XchgPtr
*)&DeviceList
, device
->next
, device
));
3105 TRACE("Created device %p\n", device
);
3109 /* alcIsRenderFormatSupportedSOFT
3111 * Determines if the loopback device supports the given format for rendering.
3113 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
3115 ALCboolean ret
= ALC_FALSE
;
3117 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Loopback
)
3118 alcSetError(device
, ALC_INVALID_DEVICE
);
3120 alcSetError(device
, ALC_INVALID_VALUE
);
3123 if(IsValidALCType(type
) && BytesFromDevFmt(type
) > 0 &&
3124 IsValidALCChannels(channels
) && ChannelsFromDevFmt(channels
) > 0 &&
3125 freq
>= MIN_OUTPUT_RATE
)
3128 if(device
) ALCdevice_DecRef(device
);
3133 /* alcRenderSamplesSOFT
3135 * Renders some samples into a buffer, using the format last set by the
3136 * attributes given to alcCreateContext.
3138 ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
3140 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Loopback
)
3141 alcSetError(device
, ALC_INVALID_DEVICE
);
3142 else if(samples
< 0 || (samples
> 0 && buffer
== NULL
))
3143 alcSetError(device
, ALC_INVALID_VALUE
);
3145 aluMixData(device
, buffer
, samples
);
3146 if(device
) ALCdevice_DecRef(device
);