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 }
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
),
262 #define DECL(x) { #x, (x) }
263 static const ALCenums enumeration
[] = {
268 DECL(ALC_MAJOR_VERSION
),
269 DECL(ALC_MINOR_VERSION
),
270 DECL(ALC_ATTRIBUTES_SIZE
),
271 DECL(ALC_ALL_ATTRIBUTES
),
272 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
273 DECL(ALC_DEVICE_SPECIFIER
),
274 DECL(ALC_ALL_DEVICES_SPECIFIER
),
275 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
276 DECL(ALC_EXTENSIONS
),
280 DECL(ALC_MONO_SOURCES
),
281 DECL(ALC_STEREO_SOURCES
),
282 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
283 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
284 DECL(ALC_CAPTURE_SAMPLES
),
287 DECL(ALC_EFX_MAJOR_VERSION
),
288 DECL(ALC_EFX_MINOR_VERSION
),
289 DECL(ALC_MAX_AUXILIARY_SENDS
),
291 DECL(ALC_FORMAT_CHANNELS_SOFT
),
292 DECL(ALC_FORMAT_TYPE_SOFT
),
295 DECL(ALC_STEREO_SOFT
),
297 DECL(ALC_5POINT1_SOFT
),
298 DECL(ALC_6POINT1_SOFT
),
299 DECL(ALC_7POINT1_SOFT
),
302 DECL(ALC_UNSIGNED_BYTE_SOFT
),
303 DECL(ALC_SHORT_SOFT
),
304 DECL(ALC_UNSIGNED_SHORT_SOFT
),
306 DECL(ALC_UNSIGNED_INT_SOFT
),
307 DECL(ALC_FLOAT_SOFT
),
310 DECL(ALC_INVALID_DEVICE
),
311 DECL(ALC_INVALID_CONTEXT
),
312 DECL(ALC_INVALID_ENUM
),
313 DECL(ALC_INVALID_VALUE
),
314 DECL(ALC_OUT_OF_MEMORY
),
322 DECL(AL_SOURCE_RELATIVE
),
323 DECL(AL_CONE_INNER_ANGLE
),
324 DECL(AL_CONE_OUTER_ANGLE
),
334 DECL(AL_ORIENTATION
),
335 DECL(AL_REFERENCE_DISTANCE
),
336 DECL(AL_ROLLOFF_FACTOR
),
337 DECL(AL_CONE_OUTER_GAIN
),
338 DECL(AL_MAX_DISTANCE
),
340 DECL(AL_SAMPLE_OFFSET
),
341 DECL(AL_SAMPLE_RW_OFFSETS_SOFT
),
342 DECL(AL_BYTE_OFFSET
),
343 DECL(AL_BYTE_RW_OFFSETS_SOFT
),
344 DECL(AL_SOURCE_TYPE
),
347 DECL(AL_UNDETERMINED
),
348 DECL(AL_METERS_PER_UNIT
),
349 DECL(AL_DIRECT_CHANNELS_SOFT
),
351 DECL(AL_DIRECT_FILTER
),
352 DECL(AL_AUXILIARY_SEND_FILTER
),
353 DECL(AL_AIR_ABSORPTION_FACTOR
),
354 DECL(AL_ROOM_ROLLOFF_FACTOR
),
355 DECL(AL_CONE_OUTER_GAINHF
),
356 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
357 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
358 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
360 DECL(AL_SOURCE_STATE
),
366 DECL(AL_BUFFERS_QUEUED
),
367 DECL(AL_BUFFERS_PROCESSED
),
369 DECL(AL_FORMAT_MONO8
),
370 DECL(AL_FORMAT_MONO16
),
371 DECL(AL_FORMAT_MONO_FLOAT32
),
372 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
373 DECL(AL_FORMAT_STEREO8
),
374 DECL(AL_FORMAT_STEREO16
),
375 DECL(AL_FORMAT_STEREO_FLOAT32
),
376 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
377 DECL(AL_FORMAT_MONO_IMA4
),
378 DECL(AL_FORMAT_STEREO_IMA4
),
379 DECL(AL_FORMAT_QUAD8_LOKI
),
380 DECL(AL_FORMAT_QUAD16_LOKI
),
381 DECL(AL_FORMAT_QUAD8
),
382 DECL(AL_FORMAT_QUAD16
),
383 DECL(AL_FORMAT_QUAD32
),
384 DECL(AL_FORMAT_51CHN8
),
385 DECL(AL_FORMAT_51CHN16
),
386 DECL(AL_FORMAT_51CHN32
),
387 DECL(AL_FORMAT_61CHN8
),
388 DECL(AL_FORMAT_61CHN16
),
389 DECL(AL_FORMAT_61CHN32
),
390 DECL(AL_FORMAT_71CHN8
),
391 DECL(AL_FORMAT_71CHN16
),
392 DECL(AL_FORMAT_71CHN32
),
393 DECL(AL_FORMAT_REAR8
),
394 DECL(AL_FORMAT_REAR16
),
395 DECL(AL_FORMAT_REAR32
),
396 DECL(AL_FORMAT_MONO_MULAW
),
397 DECL(AL_FORMAT_MONO_MULAW_EXT
),
398 DECL(AL_FORMAT_STEREO_MULAW
),
399 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
400 DECL(AL_FORMAT_QUAD_MULAW
),
401 DECL(AL_FORMAT_51CHN_MULAW
),
402 DECL(AL_FORMAT_61CHN_MULAW
),
403 DECL(AL_FORMAT_71CHN_MULAW
),
404 DECL(AL_FORMAT_REAR_MULAW
),
405 DECL(AL_FORMAT_MONO_ALAW_EXT
),
406 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
409 DECL(AL_MONO16_SOFT
),
410 DECL(AL_MONO32F_SOFT
),
411 DECL(AL_STEREO8_SOFT
),
412 DECL(AL_STEREO16_SOFT
),
413 DECL(AL_STEREO32F_SOFT
),
415 DECL(AL_QUAD16_SOFT
),
416 DECL(AL_QUAD32F_SOFT
),
418 DECL(AL_REAR16_SOFT
),
419 DECL(AL_REAR32F_SOFT
),
420 DECL(AL_5POINT1_8_SOFT
),
421 DECL(AL_5POINT1_16_SOFT
),
422 DECL(AL_5POINT1_32F_SOFT
),
423 DECL(AL_6POINT1_8_SOFT
),
424 DECL(AL_6POINT1_16_SOFT
),
425 DECL(AL_6POINT1_32F_SOFT
),
426 DECL(AL_7POINT1_8_SOFT
),
427 DECL(AL_7POINT1_16_SOFT
),
428 DECL(AL_7POINT1_32F_SOFT
),
431 DECL(AL_STEREO_SOFT
),
434 DECL(AL_5POINT1_SOFT
),
435 DECL(AL_6POINT1_SOFT
),
436 DECL(AL_7POINT1_SOFT
),
439 DECL(AL_UNSIGNED_BYTE_SOFT
),
441 DECL(AL_UNSIGNED_SHORT_SOFT
),
443 DECL(AL_UNSIGNED_INT_SOFT
),
445 DECL(AL_DOUBLE_SOFT
),
447 DECL(AL_UNSIGNED_BYTE3_SOFT
),
453 DECL(AL_INTERNAL_FORMAT_SOFT
),
454 DECL(AL_BYTE_LENGTH_SOFT
),
455 DECL(AL_SAMPLE_LENGTH_SOFT
),
456 DECL(AL_SEC_LENGTH_SOFT
),
463 DECL(AL_INVALID_NAME
),
464 DECL(AL_INVALID_ENUM
),
465 DECL(AL_INVALID_VALUE
),
466 DECL(AL_INVALID_OPERATION
),
467 DECL(AL_OUT_OF_MEMORY
),
474 DECL(AL_DOPPLER_FACTOR
),
475 DECL(AL_DOPPLER_VELOCITY
),
476 DECL(AL_DISTANCE_MODEL
),
477 DECL(AL_SPEED_OF_SOUND
),
478 DECL(AL_SOURCE_DISTANCE_MODEL
),
479 DECL(AL_DEFERRED_UPDATES_SOFT
),
481 DECL(AL_INVERSE_DISTANCE
),
482 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
483 DECL(AL_LINEAR_DISTANCE
),
484 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
485 DECL(AL_EXPONENT_DISTANCE
),
486 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
488 DECL(AL_FILTER_TYPE
),
489 DECL(AL_FILTER_NULL
),
490 DECL(AL_FILTER_LOWPASS
),
492 DECL(AL_FILTER_HIGHPASS
),
493 DECL(AL_FILTER_BANDPASS
),
496 DECL(AL_LOWPASS_GAIN
),
497 DECL(AL_LOWPASS_GAINHF
),
499 DECL(AL_EFFECT_TYPE
),
500 DECL(AL_EFFECT_NULL
),
501 DECL(AL_EFFECT_REVERB
),
502 DECL(AL_EFFECT_EAXREVERB
),
504 DECL(AL_EFFECT_CHORUS
),
505 DECL(AL_EFFECT_DISTORTION
),
507 DECL(AL_EFFECT_ECHO
),
509 DECL(AL_EFFECT_FLANGER
),
510 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
511 DECL(AL_EFFECT_VOCAL_MORPHER
),
512 DECL(AL_EFFECT_PITCH_SHIFTER
),
514 DECL(AL_EFFECT_RING_MODULATOR
),
516 DECL(AL_EFFECT_AUTOWAH
),
517 DECL(AL_EFFECT_COMPRESSOR
),
518 DECL(AL_EFFECT_EQUALIZER
),
520 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
521 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
523 DECL(AL_EAXREVERB_DENSITY
),
524 DECL(AL_EAXREVERB_DIFFUSION
),
525 DECL(AL_EAXREVERB_GAIN
),
526 DECL(AL_EAXREVERB_GAINHF
),
527 DECL(AL_EAXREVERB_GAINLF
),
528 DECL(AL_EAXREVERB_DECAY_TIME
),
529 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
530 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
531 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
532 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
533 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
534 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
535 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
536 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
537 DECL(AL_EAXREVERB_ECHO_TIME
),
538 DECL(AL_EAXREVERB_ECHO_DEPTH
),
539 DECL(AL_EAXREVERB_MODULATION_TIME
),
540 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
541 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
542 DECL(AL_EAXREVERB_HFREFERENCE
),
543 DECL(AL_EAXREVERB_LFREFERENCE
),
544 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
545 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
547 DECL(AL_REVERB_DENSITY
),
548 DECL(AL_REVERB_DIFFUSION
),
549 DECL(AL_REVERB_GAIN
),
550 DECL(AL_REVERB_GAINHF
),
551 DECL(AL_REVERB_DECAY_TIME
),
552 DECL(AL_REVERB_DECAY_HFRATIO
),
553 DECL(AL_REVERB_REFLECTIONS_GAIN
),
554 DECL(AL_REVERB_REFLECTIONS_DELAY
),
555 DECL(AL_REVERB_LATE_REVERB_GAIN
),
556 DECL(AL_REVERB_LATE_REVERB_DELAY
),
557 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
558 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
559 DECL(AL_REVERB_DECAY_HFLIMIT
),
562 DECL(AL_ECHO_LRDELAY
),
563 DECL(AL_ECHO_DAMPING
),
564 DECL(AL_ECHO_FEEDBACK
),
565 DECL(AL_ECHO_SPREAD
),
567 DECL(AL_RING_MODULATOR_FREQUENCY
),
568 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
569 DECL(AL_RING_MODULATOR_WAVEFORM
),
571 DECL(AL_DEDICATED_GAIN
),
577 static const ALCchar alcNoError
[] = "No Error";
578 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
579 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
580 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
581 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
582 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
585 /************************************************
587 ************************************************/
589 /* Enumerated device names */
590 static const ALCchar alcDefaultName
[] = "OpenAL Soft\0";
591 static ALCchar
*alcAllDeviceList
;
592 static ALCchar
*alcCaptureDeviceList
;
593 /* Sizes only include the first ending null character, not the second */
594 static size_t alcAllDeviceListSize
;
595 static size_t alcCaptureDeviceListSize
;
597 /* Default is always the first in the list */
598 static ALCchar
*alcDefaultAllDeviceSpecifier
;
599 static ALCchar
*alcCaptureDefaultDeviceSpecifier
;
601 /* Default context extensions */
602 static const ALchar alExtList
[] =
603 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
604 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
605 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
606 "AL_LOKI_quadriphonic AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data "
607 "AL_SOFTX_deferred_updates AL_SOFT_direct_channels AL_SOFT_loop_points";
609 static volatile ALCenum LastNullDeviceError
= ALC_NO_ERROR
;
611 /* Thread-local current context */
612 static pthread_key_t LocalContext
;
613 /* Process-wide current context */
614 static ALCcontext
*volatile GlobalContext
= NULL
;
616 /* Mixing thread piority level */
621 enum LogLevel LogLevel
= LogWarning
;
623 enum LogLevel LogLevel
= LogError
;
626 /* Flag to trap ALC device errors */
627 static ALCboolean TrapALCError
= ALC_FALSE
;
629 /* One-time configuration init control */
630 static pthread_once_t alc_config_once
= PTHREAD_ONCE_INIT
;
632 /* Default effect that applies to sources that don't have an effect on send 0 */
633 static ALeffect DefaultEffect
;
636 /************************************************
638 ************************************************/
639 static const ALCchar alcNoDeviceExtList
[] =
640 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
641 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
642 static const ALCchar alcExtensionList
[] =
643 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
644 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
645 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
646 static const ALCint alcMajorVersion
= 1;
647 static const ALCint alcMinorVersion
= 1;
649 static const ALCint alcEFXMajorVersion
= 1;
650 static const ALCint alcEFXMinorVersion
= 0;
653 /************************************************
655 ************************************************/
656 static ALCdevice
*volatile DeviceList
= NULL
;
658 static CRITICAL_SECTION ListLock
;
660 static void LockLists(void)
662 EnterCriticalSection(&ListLock
);
664 static void UnlockLists(void)
666 LeaveCriticalSection(&ListLock
);
669 /************************************************
670 * Library initialization
671 ************************************************/
673 static void alc_init(void);
674 static void alc_deinit(void);
675 static void alc_deinit_safe(void);
677 UIntMap TlsDestructor
;
679 #ifndef AL_LIBTYPE_STATIC
680 BOOL APIENTRY
DllMain(HINSTANCE hModule
,DWORD ul_reason_for_call
,LPVOID lpReserved
)
684 // Perform actions based on the reason for calling.
685 switch(ul_reason_for_call
)
687 case DLL_PROCESS_ATTACH
:
688 /* Pin the DLL so we won't get unloaded until the process terminates */
689 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
690 (WCHAR
*)hModule
, &hModule
);
691 InitUIntMap(&TlsDestructor
, ~0);
695 case DLL_THREAD_DETACH
:
696 LockUIntMapRead(&TlsDestructor
);
697 for(i
= 0;i
< TlsDestructor
.size
;i
++)
699 void *ptr
= pthread_getspecific(TlsDestructor
.array
[i
].key
);
700 void (*callback
)(void*) = (void(*)(void*))TlsDestructor
.array
[i
].value
;
704 UnlockUIntMapRead(&TlsDestructor
);
707 case DLL_PROCESS_DETACH
:
712 ResetUIntMap(&TlsDestructor
);
717 #elif defined(_MSC_VER)
718 #pragma section(".CRT$XCU",read)
719 static void alc_constructor(void);
720 static void alc_destructor(void);
721 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
723 static void alc_constructor(void)
725 atexit(alc_destructor
);
729 static void alc_destructor(void)
733 #elif defined(HAVE_GCC_DESTRUCTOR)
734 static void alc_init(void) __attribute__((constructor
));
735 static void alc_deinit(void) __attribute__((destructor
));
737 #error "No static initialization available on this platform!"
740 #elif defined(HAVE_GCC_DESTRUCTOR)
742 static void alc_init(void) __attribute__((constructor
));
743 static void alc_deinit(void) __attribute__((destructor
));
746 #error "No global initialization available on this platform!"
749 static void ReleaseThreadCtx(void *ptr
);
750 static void alc_init(void)
756 str
= getenv("__ALSOFT_HALF_ANGLE_CONES");
757 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
760 str
= getenv("__ALSOFT_REVERSE_Z");
761 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
764 pthread_key_create(&LocalContext
, ReleaseThreadCtx
);
765 InitializeCriticalSection(&ListLock
);
769 static void alc_initconfig(void)
771 const char *devs
, *str
;
775 str
= getenv("ALSOFT_LOGLEVEL");
778 long lvl
= strtol(str
, NULL
, 0);
779 if(lvl
>= NoLog
&& lvl
<= LogRef
)
783 str
= getenv("ALSOFT_LOGFILE");
786 FILE *logfile
= fopen(str
, "wat");
787 if(logfile
) LogFile
= logfile
;
788 else ERR("Failed to open log file '%s'\n", str
);
800 ConfigValueInt(NULL
, "rt-prio", &RTPrioLevel
);
802 if(ConfigValueStr(NULL
, "resampler", &str
))
804 if(strcasecmp(str
, "point") == 0 || strcasecmp(str
, "none") == 0)
805 DefaultResampler
= PointResampler
;
806 else if(strcasecmp(str
, "linear") == 0)
807 DefaultResampler
= LinearResampler
;
808 else if(strcasecmp(str
, "cubic") == 0)
809 DefaultResampler
= CubicResampler
;
814 n
= strtol(str
, &end
, 0);
815 if(*end
== '\0' && (n
== PointResampler
|| n
== LinearResampler
|| n
== CubicResampler
))
816 DefaultResampler
= n
;
818 WARN("Invalid resampler: %s\n", str
);
822 str
= getenv("ALSOFT_TRAP_ERROR");
823 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
825 TrapALError
= AL_TRUE
;
826 TrapALCError
= AL_TRUE
;
830 str
= getenv("ALSOFT_TRAP_AL_ERROR");
831 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
832 TrapALError
= AL_TRUE
;
833 TrapALError
= GetConfigValueBool(NULL
, "trap-al-error", TrapALError
);
835 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
836 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
837 TrapALCError
= ALC_TRUE
;
838 TrapALCError
= GetConfigValueBool(NULL
, "trap-alc-error", TrapALCError
);
841 if(ConfigValueFloat("reverb", "boost", &valf
))
842 ReverbBoost
*= aluPow(10.0f
, valf
/ 20.0f
);
844 EmulateEAXReverb
= GetConfigValueBool("reverb", "emulate-eax", AL_FALSE
);
846 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
847 ConfigValueStr(NULL
, "drivers", &devs
))
851 const char *next
= devs
;
852 int endlist
, delitem
;
857 next
= strchr(devs
, ',');
859 delitem
= (devs
[0] == '-');
860 if(devs
[0] == '-') devs
++;
862 if(!devs
[0] || devs
[0] == ',')
869 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
870 for(n
= i
;BackendList
[n
].Init
;n
++)
872 if(len
== strlen(BackendList
[n
].name
) &&
873 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
878 BackendList
[n
] = BackendList
[n
+1];
880 } while(BackendList
[n
].Init
);
884 struct BackendInfo Bkp
= BackendList
[n
];
887 BackendList
[n
] = BackendList
[n
-1];
890 BackendList
[n
] = Bkp
;
901 BackendList
[i
].name
= NULL
;
902 BackendList
[i
].Init
= NULL
;
903 BackendList
[i
].Deinit
= NULL
;
904 BackendList
[i
].Probe
= NULL
;
908 for(i
= 0;BackendList
[i
].Init
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
910 if(!BackendList
[i
].Init(&BackendList
[i
].Funcs
))
912 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
916 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
917 if(BackendList
[i
].Funcs
.OpenPlayback
&& !PlaybackBackend
.name
)
919 PlaybackBackend
= BackendList
[i
];
920 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
922 if(BackendList
[i
].Funcs
.OpenCapture
&& !CaptureBackend
.name
)
924 CaptureBackend
= BackendList
[i
];
925 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
928 BackendLoopback
.Init(&BackendLoopback
.Funcs
);
930 if(ConfigValueStr(NULL
, "excludefx", &str
))
933 const char *next
= str
;
937 next
= strchr(str
, ',');
939 if(!str
[0] || next
== str
)
942 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
943 for(n
= 0;EffectList
[n
].name
;n
++)
945 if(len
== strlen(EffectList
[n
].name
) &&
946 strncmp(EffectList
[n
].name
, str
, len
) == 0)
947 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
952 InitEffect(&DefaultEffect
);
953 str
= getenv("ALSOFT_DEFAULT_REVERB");
954 if((str
&& str
[0]) || ConfigValueStr(NULL
, "default-reverb", &str
))
955 LoadReverbPreset(str
, &DefaultEffect
);
957 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
960 /************************************************
961 * Library deinitialization
962 ************************************************/
963 static void alc_cleanup(void)
967 free(alcAllDeviceList
); alcAllDeviceList
= NULL
;
968 alcAllDeviceListSize
= 0;
969 free(alcCaptureDeviceList
); alcCaptureDeviceList
= NULL
;
970 alcCaptureDeviceListSize
= 0;
972 free(alcDefaultAllDeviceSpecifier
);
973 alcDefaultAllDeviceSpecifier
= NULL
;
974 free(alcCaptureDefaultDeviceSpecifier
);
975 alcCaptureDefaultDeviceSpecifier
= NULL
;
977 if((dev
=ExchangePtr((XchgPtr
*)&DeviceList
, NULL
)) != NULL
)
982 } while((dev
=dev
->next
) != NULL
);
983 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
987 static void alc_deinit_safe(void)
995 DeleteCriticalSection(&ListLock
);
996 pthread_key_delete(LocalContext
);
998 if(LogFile
!= stderr
)
1003 static void alc_deinit(void)
1009 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1010 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1012 for(i
= 0;BackendList
[i
].Deinit
;i
++)
1013 BackendList
[i
].Deinit();
1014 BackendLoopback
.Deinit();
1020 /************************************************
1021 * Device enumeration
1022 ************************************************/
1023 static void ProbeList(ALCchar
**list
, size_t *listsize
, enum DevProbe type
)
1032 if(type
== ALL_DEVICE_PROBE
&& PlaybackBackend
.Probe
)
1033 PlaybackBackend
.Probe(type
);
1034 else if(type
== CAPTURE_DEVICE_PROBE
&& CaptureBackend
.Probe
)
1035 CaptureBackend
.Probe(type
);
1039 static void ProbeAllDeviceList(void)
1040 { ProbeList(&alcAllDeviceList
, &alcAllDeviceListSize
, ALL_DEVICE_PROBE
); }
1041 static void ProbeCaptureDeviceList(void)
1042 { ProbeList(&alcCaptureDeviceList
, &alcCaptureDeviceListSize
, CAPTURE_DEVICE_PROBE
); }
1045 static void AppendList(const ALCchar
*name
, ALCchar
**List
, size_t *ListSize
)
1047 size_t len
= strlen(name
);
1053 temp
= realloc(*List
, (*ListSize
) + len
+ 2);
1056 ERR("Realloc failed to add %s!\n", name
);
1061 memcpy((*List
)+(*ListSize
), name
, len
+1);
1063 (*List
)[*ListSize
] = 0;
1066 #define DECL_APPEND_LIST_FUNC(type) \
1067 void Append##type##List(const ALCchar *name) \
1068 { AppendList(name, &alc##type##List, &alc##type##ListSize); }
1070 DECL_APPEND_LIST_FUNC(AllDevice
)
1071 DECL_APPEND_LIST_FUNC(CaptureDevice
)
1073 #undef DECL_APPEND_LIST_FUNC
1076 /************************************************
1077 * Device format information
1078 ************************************************/
1079 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1083 case DevFmtByte
: return "Signed Byte";
1084 case DevFmtUByte
: return "Unsigned Byte";
1085 case DevFmtShort
: return "Signed Short";
1086 case DevFmtUShort
: return "Unsigned Short";
1087 case DevFmtInt
: return "Signed Int";
1088 case DevFmtUInt
: return "Unsigned Int";
1089 case DevFmtFloat
: return "Float";
1091 return "(unknown type)";
1093 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1097 case DevFmtMono
: return "Mono";
1098 case DevFmtStereo
: return "Stereo";
1099 case DevFmtQuad
: return "Quadraphonic";
1100 case DevFmtX51
: return "5.1 Surround";
1101 case DevFmtX51Side
: return "5.1 Side";
1102 case DevFmtX61
: return "6.1 Surround";
1103 case DevFmtX71
: return "7.1 Surround";
1105 return "(unknown channels)";
1108 ALuint
BytesFromDevFmt(enum DevFmtType type
)
1112 case DevFmtByte
: return sizeof(ALbyte
);
1113 case DevFmtUByte
: return sizeof(ALubyte
);
1114 case DevFmtShort
: return sizeof(ALshort
);
1115 case DevFmtUShort
: return sizeof(ALushort
);
1116 case DevFmtInt
: return sizeof(ALint
);
1117 case DevFmtUInt
: return sizeof(ALuint
);
1118 case DevFmtFloat
: return sizeof(ALfloat
);
1122 ALuint
ChannelsFromDevFmt(enum DevFmtChannels chans
)
1126 case DevFmtMono
: return 1;
1127 case DevFmtStereo
: return 2;
1128 case DevFmtQuad
: return 4;
1129 case DevFmtX51
: return 6;
1130 case DevFmtX51Side
: return 6;
1131 case DevFmtX61
: return 7;
1132 case DevFmtX71
: return 8;
1137 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1138 enum DevFmtType
*type
)
1140 static const struct {
1142 enum DevFmtChannels channels
;
1143 enum DevFmtType type
;
1145 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1146 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1147 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1149 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1150 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1151 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1153 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1154 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1155 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1157 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1158 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1159 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1161 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1162 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1163 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1165 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1166 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1167 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1171 for(i
= 0;i
< COUNTOF(list
);i
++)
1173 if(list
[i
].format
== format
)
1175 *chans
= list
[i
].channels
;
1176 *type
= list
[i
].type
;
1184 static ALCboolean
IsValidALCType(ALCenum type
)
1189 case ALC_UNSIGNED_BYTE_SOFT
:
1190 case ALC_SHORT_SOFT
:
1191 case ALC_UNSIGNED_SHORT_SOFT
:
1193 case ALC_UNSIGNED_INT_SOFT
:
1194 case ALC_FLOAT_SOFT
:
1200 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1205 case ALC_STEREO_SOFT
:
1207 case ALC_5POINT1_SOFT
:
1208 case ALC_6POINT1_SOFT
:
1209 case ALC_7POINT1_SOFT
:
1216 /************************************************
1217 * Miscellaneous ALC helpers
1218 ************************************************/
1220 /* SetDefaultWFXChannelOrder
1222 * Sets the default channel order used by WaveFormatEx.
1224 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1226 switch(device
->FmtChans
)
1228 case DevFmtMono
: device
->DevChannels
[0] = FRONT_CENTER
; break;
1230 case DevFmtStereo
: device
->DevChannels
[0] = FRONT_LEFT
;
1231 device
->DevChannels
[1] = FRONT_RIGHT
; break;
1233 case DevFmtQuad
: device
->DevChannels
[0] = FRONT_LEFT
;
1234 device
->DevChannels
[1] = FRONT_RIGHT
;
1235 device
->DevChannels
[2] = BACK_LEFT
;
1236 device
->DevChannels
[3] = BACK_RIGHT
; break;
1238 case DevFmtX51
: device
->DevChannels
[0] = FRONT_LEFT
;
1239 device
->DevChannels
[1] = FRONT_RIGHT
;
1240 device
->DevChannels
[2] = FRONT_CENTER
;
1241 device
->DevChannels
[3] = LFE
;
1242 device
->DevChannels
[4] = BACK_LEFT
;
1243 device
->DevChannels
[5] = BACK_RIGHT
; break;
1245 case DevFmtX51Side
: device
->DevChannels
[0] = FRONT_LEFT
;
1246 device
->DevChannels
[1] = FRONT_RIGHT
;
1247 device
->DevChannels
[2] = FRONT_CENTER
;
1248 device
->DevChannels
[3] = LFE
;
1249 device
->DevChannels
[4] = SIDE_LEFT
;
1250 device
->DevChannels
[5] = SIDE_RIGHT
; break;
1252 case DevFmtX61
: device
->DevChannels
[0] = FRONT_LEFT
;
1253 device
->DevChannels
[1] = FRONT_RIGHT
;
1254 device
->DevChannels
[2] = FRONT_CENTER
;
1255 device
->DevChannels
[3] = LFE
;
1256 device
->DevChannels
[4] = BACK_CENTER
;
1257 device
->DevChannels
[5] = SIDE_LEFT
;
1258 device
->DevChannels
[6] = SIDE_RIGHT
; break;
1260 case DevFmtX71
: device
->DevChannels
[0] = FRONT_LEFT
;
1261 device
->DevChannels
[1] = FRONT_RIGHT
;
1262 device
->DevChannels
[2] = FRONT_CENTER
;
1263 device
->DevChannels
[3] = LFE
;
1264 device
->DevChannels
[4] = BACK_LEFT
;
1265 device
->DevChannels
[5] = BACK_RIGHT
;
1266 device
->DevChannels
[6] = SIDE_LEFT
;
1267 device
->DevChannels
[7] = SIDE_RIGHT
; break;
1271 /* SetDefaultChannelOrder
1273 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1275 void SetDefaultChannelOrder(ALCdevice
*device
)
1277 switch(device
->FmtChans
)
1279 case DevFmtX51
: device
->DevChannels
[0] = FRONT_LEFT
;
1280 device
->DevChannels
[1] = FRONT_RIGHT
;
1281 device
->DevChannels
[2] = BACK_LEFT
;
1282 device
->DevChannels
[3] = BACK_RIGHT
;
1283 device
->DevChannels
[4] = FRONT_CENTER
;
1284 device
->DevChannels
[5] = LFE
;
1287 case DevFmtX71
: device
->DevChannels
[0] = FRONT_LEFT
;
1288 device
->DevChannels
[1] = FRONT_RIGHT
;
1289 device
->DevChannels
[2] = BACK_LEFT
;
1290 device
->DevChannels
[3] = BACK_RIGHT
;
1291 device
->DevChannels
[4] = FRONT_CENTER
;
1292 device
->DevChannels
[5] = LFE
;
1293 device
->DevChannels
[6] = SIDE_LEFT
;
1294 device
->DevChannels
[7] = SIDE_RIGHT
;
1297 /* Same as WFX order */
1305 SetDefaultWFXChannelOrder(device
);
1311 * Stores the latest ALC device error
1313 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1318 /* DebugBreak() will cause an exception if there is no debugger */
1319 if(IsDebuggerPresent())
1321 #elif defined(SIGTRAP)
1327 device
->LastError
= errorCode
;
1329 LastNullDeviceError
= errorCode
;
1333 /* UpdateDeviceParams
1335 * Updates device parameters according to the attribute list (caller is
1336 * responsible for holding the list lock).
1338 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1340 ALCcontext
*context
;
1341 enum DevFmtChannels oldChans
;
1342 enum DevFmtType oldType
;
1347 // Check for attributes
1348 if(device
->Type
== Loopback
)
1354 GotAll
= GotFreq
|GotChans
|GotType
1356 ALCuint freq
, numMono
, numStereo
, numSends
;
1357 enum DevFmtChannels schans
;
1358 enum DevFmtType stype
;
1359 ALCuint attrIdx
= 0;
1364 WARN("Missing attributes for loopback device\n");
1365 return ALC_INVALID_VALUE
;
1368 numMono
= device
->NumMonoSources
;
1369 numStereo
= device
->NumStereoSources
;
1370 numSends
= device
->NumAuxSends
;
1371 schans
= device
->FmtChans
;
1372 stype
= device
->FmtType
;
1373 freq
= device
->Frequency
;
1375 while(attrList
[attrIdx
])
1377 if(attrList
[attrIdx
] == ALC_FORMAT_CHANNELS_SOFT
)
1379 ALCint val
= attrList
[attrIdx
+ 1];
1380 if(!IsValidALCChannels(val
) || !ChannelsFromDevFmt(val
))
1381 return ALC_INVALID_VALUE
;
1386 if(attrList
[attrIdx
] == ALC_FORMAT_TYPE_SOFT
)
1388 ALCint val
= attrList
[attrIdx
+ 1];
1389 if(!IsValidALCType(val
) || !BytesFromDevFmt(val
))
1390 return ALC_INVALID_VALUE
;
1395 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1397 freq
= attrList
[attrIdx
+ 1];
1398 if(freq
< MIN_OUTPUT_RATE
)
1399 return ALC_INVALID_VALUE
;
1403 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1405 numStereo
= attrList
[attrIdx
+ 1];
1406 if(numStereo
> device
->MaxNoOfSources
)
1407 numStereo
= device
->MaxNoOfSources
;
1409 numMono
= device
->MaxNoOfSources
- numStereo
;
1412 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
1413 numSends
= attrList
[attrIdx
+ 1];
1418 if(gotFmt
!= GotAll
)
1420 WARN("Missing format for loopback device\n");
1421 return ALC_INVALID_VALUE
;
1424 ConfigValueUInt(NULL
, "sends", &numSends
);
1425 numSends
= minu(MAX_SENDS
, numSends
);
1427 if((device
->Flags
&DEVICE_RUNNING
))
1428 ALCdevice_StopPlayback(device
);
1429 device
->Flags
&= ~DEVICE_RUNNING
;
1431 device
->Frequency
= freq
;
1432 device
->FmtChans
= schans
;
1433 device
->FmtType
= stype
;
1434 device
->NumMonoSources
= numMono
;
1435 device
->NumStereoSources
= numStereo
;
1436 device
->NumAuxSends
= numSends
;
1438 else if(attrList
&& attrList
[0])
1440 ALCuint freq
, numMono
, numStereo
, numSends
;
1441 ALCuint attrIdx
= 0;
1443 /* If a context is already running on the device, stop playback so the
1444 * device attributes can be updated. */
1445 if((device
->Flags
&DEVICE_RUNNING
))
1446 ALCdevice_StopPlayback(device
);
1447 device
->Flags
&= ~DEVICE_RUNNING
;
1449 freq
= device
->Frequency
;
1450 numMono
= device
->NumMonoSources
;
1451 numStereo
= device
->NumStereoSources
;
1452 numSends
= device
->NumAuxSends
;
1454 while(attrList
[attrIdx
])
1456 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1458 freq
= attrList
[attrIdx
+ 1];
1459 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1462 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1464 numStereo
= attrList
[attrIdx
+ 1];
1465 if(numStereo
> device
->MaxNoOfSources
)
1466 numStereo
= device
->MaxNoOfSources
;
1468 numMono
= device
->MaxNoOfSources
- numStereo
;
1471 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
1472 numSends
= attrList
[attrIdx
+ 1];
1477 ConfigValueUInt(NULL
, "frequency", &freq
);
1478 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
1480 ConfigValueUInt(NULL
, "sends", &numSends
);
1481 numSends
= minu(MAX_SENDS
, numSends
);
1483 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
1486 device
->Frequency
= freq
;
1487 device
->NumMonoSources
= numMono
;
1488 device
->NumStereoSources
= numStereo
;
1489 device
->NumAuxSends
= numSends
;
1492 if((device
->Flags
&DEVICE_RUNNING
))
1493 return ALC_NO_ERROR
;
1495 oldFreq
= device
->Frequency
;
1496 oldChans
= device
->FmtChans
;
1497 oldType
= device
->FmtType
;
1499 TRACE("Format pre-setup: %s%s, %s%s, %uhz%s, %u update size x%d\n",
1500 DevFmtChannelsString(device
->FmtChans
),
1501 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?" (requested)":"",
1502 DevFmtTypeString(device
->FmtType
),
1503 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?" (requested)":"",
1505 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?" (requested)":"",
1506 device
->UpdateSize
, device
->NumUpdates
);
1508 if(ALCdevice_ResetPlayback(device
) == ALC_FALSE
)
1509 return ALC_INVALID_DEVICE
;
1511 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
1513 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
1514 DevFmtChannelsString(device
->FmtChans
));
1515 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
1517 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
1519 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
1520 DevFmtTypeString(device
->FmtType
));
1521 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
1523 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
1525 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
1526 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
1529 TRACE("Format post-setup: %s, %s, %uhz, %u update size x%d\n",
1530 DevFmtChannelsString(device
->FmtChans
),
1531 DevFmtTypeString(device
->FmtType
), device
->Frequency
,
1532 device
->UpdateSize
, device
->NumUpdates
);
1534 aluInitPanning(device
);
1536 for(i
= 0;i
< MAXCHANNELS
;i
++)
1538 device
->ClickRemoval
[i
] = 0.0f
;
1539 device
->PendingClicks
[i
] = 0.0f
;
1542 device
->Hrtf
= NULL
;
1543 if(device
->Type
!= Loopback
&& GetConfigValueBool(NULL
, "hrtf", AL_FALSE
))
1544 device
->Hrtf
= GetHrtf(device
);
1545 TRACE("HRTF %s\n", device
->Hrtf
?"enabled":"disabled");
1547 if(!device
->Hrtf
&& device
->Bs2bLevel
> 0 && device
->Bs2bLevel
<= 6)
1551 device
->Bs2b
= calloc(1, sizeof(*device
->Bs2b
));
1552 bs2b_clear(device
->Bs2b
);
1554 bs2b_set_srate(device
->Bs2b
, device
->Frequency
);
1555 bs2b_set_level(device
->Bs2b
, device
->Bs2bLevel
);
1556 TRACE("BS2B level %d\n", device
->Bs2bLevel
);
1561 device
->Bs2b
= NULL
;
1562 TRACE("BS2B disabled\n");
1565 device
->Flags
&= ~DEVICE_DUPLICATE_STEREO
;
1566 switch(device
->FmtChans
)
1576 if(GetConfigValueBool(NULL
, "stereodup", AL_TRUE
))
1577 device
->Flags
|= DEVICE_DUPLICATE_STEREO
;
1580 TRACE("Stereo duplication %s\n", (device
->Flags
&DEVICE_DUPLICATE_STEREO
)?"enabled":"disabled");
1582 oldMode
= SetMixerFPUMode();
1584 context
= device
->ContextList
;
1589 context
->UpdateSources
= AL_FALSE
;
1590 LockUIntMapRead(&context
->EffectSlotMap
);
1591 for(pos
= 0;pos
< context
->EffectSlotMap
.size
;pos
++)
1593 ALeffectslot
*slot
= context
->EffectSlotMap
.array
[pos
].value
;
1595 if(ALeffectState_DeviceUpdate(slot
->EffectState
, device
) == AL_FALSE
)
1597 UnlockUIntMapRead(&context
->EffectSlotMap
);
1598 UnlockDevice(device
);
1599 RestoreFPUMode(oldMode
);
1600 return ALC_INVALID_DEVICE
;
1602 slot
->NeedsUpdate
= AL_FALSE
;
1603 ALeffectState_Update(slot
->EffectState
, device
, slot
);
1605 UnlockUIntMapRead(&context
->EffectSlotMap
);
1607 LockUIntMapRead(&context
->SourceMap
);
1608 for(pos
= 0;pos
< context
->SourceMap
.size
;pos
++)
1610 ALsource
*source
= context
->SourceMap
.array
[pos
].value
;
1611 ALuint s
= device
->NumAuxSends
;
1612 while(s
< MAX_SENDS
)
1614 if(source
->Send
[s
].Slot
)
1615 DecrementRef(&source
->Send
[s
].Slot
->ref
);
1616 source
->Send
[s
].Slot
= NULL
;
1617 source
->Send
[s
].WetGain
= 1.0f
;
1618 source
->Send
[s
].WetGainHF
= 1.0f
;
1621 source
->NeedsUpdate
= AL_FALSE
;
1622 ALsource_Update(source
, context
);
1624 UnlockUIntMapRead(&context
->SourceMap
);
1626 context
= context
->next
;
1628 if(device
->DefaultSlot
)
1630 ALeffectslot
*slot
= device
->DefaultSlot
;
1632 if(ALeffectState_DeviceUpdate(slot
->EffectState
, device
) == AL_FALSE
)
1634 UnlockDevice(device
);
1635 RestoreFPUMode(oldMode
);
1636 return ALC_INVALID_DEVICE
;
1638 slot
->NeedsUpdate
= AL_FALSE
;
1639 ALeffectState_Update(slot
->EffectState
, device
, slot
);
1641 UnlockDevice(device
);
1642 RestoreFPUMode(oldMode
);
1644 if(ALCdevice_StartPlayback(device
) == ALC_FALSE
)
1645 return ALC_INVALID_DEVICE
;
1646 device
->Flags
|= DEVICE_RUNNING
;
1648 return ALC_NO_ERROR
;
1653 * Frees the device structure, and destroys any objects the app failed to
1654 * delete. Called once there's no more references on the device.
1656 static ALCvoid
FreeDevice(ALCdevice
*device
)
1658 TRACE("%p\n", device
);
1660 if(device
->DefaultSlot
)
1662 ALeffectState_Destroy(device
->DefaultSlot
->EffectState
);
1663 device
->DefaultSlot
->EffectState
= NULL
;
1666 if(device
->BufferMap
.size
> 0)
1668 WARN("(%p) Deleting %d Buffer(s)\n", device
, device
->BufferMap
.size
);
1669 ReleaseALBuffers(device
);
1671 ResetUIntMap(&device
->BufferMap
);
1673 if(device
->EffectMap
.size
> 0)
1675 WARN("(%p) Deleting %d Effect(s)\n", device
, device
->EffectMap
.size
);
1676 ReleaseALEffects(device
);
1678 ResetUIntMap(&device
->EffectMap
);
1680 if(device
->FilterMap
.size
> 0)
1682 WARN("(%p) Deleting %d Filter(s)\n", device
, device
->FilterMap
.size
);
1683 ReleaseALFilters(device
);
1685 ResetUIntMap(&device
->FilterMap
);
1688 device
->Bs2b
= NULL
;
1690 free(device
->DeviceName
);
1691 device
->DeviceName
= NULL
;
1693 DeleteCriticalSection(&device
->Mutex
);
1699 void ALCdevice_IncRef(ALCdevice
*device
)
1702 ref
= IncrementRef(&device
->ref
);
1703 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
1706 void ALCdevice_DecRef(ALCdevice
*device
)
1709 ref
= DecrementRef(&device
->ref
);
1710 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
1711 if(ref
== 0) FreeDevice(device
);
1716 * Checks if the device handle is valid, and increments its ref count if so.
1718 static ALCdevice
*VerifyDevice(ALCdevice
*device
)
1720 ALCdevice
*tmpDevice
;
1726 tmpDevice
= DeviceList
;
1727 while(tmpDevice
&& tmpDevice
!= device
)
1728 tmpDevice
= tmpDevice
->next
;
1731 ALCdevice_IncRef(tmpDevice
);
1739 * Initializes context fields
1741 static ALvoid
InitContext(ALCcontext
*Context
)
1745 //Initialise listener
1746 Context
->Listener
.Gain
= 1.0f
;
1747 Context
->Listener
.MetersPerUnit
= 1.0f
;
1748 Context
->Listener
.Position
[0] = 0.0f
;
1749 Context
->Listener
.Position
[1] = 0.0f
;
1750 Context
->Listener
.Position
[2] = 0.0f
;
1751 Context
->Listener
.Velocity
[0] = 0.0f
;
1752 Context
->Listener
.Velocity
[1] = 0.0f
;
1753 Context
->Listener
.Velocity
[2] = 0.0f
;
1754 Context
->Listener
.Forward
[0] = 0.0f
;
1755 Context
->Listener
.Forward
[1] = 0.0f
;
1756 Context
->Listener
.Forward
[2] = -1.0f
;
1757 Context
->Listener
.Up
[0] = 0.0f
;
1758 Context
->Listener
.Up
[1] = 1.0f
;
1759 Context
->Listener
.Up
[2] = 0.0f
;
1760 for(i
= 0;i
< 4;i
++)
1762 for(j
= 0;j
< 4;j
++)
1763 Context
->Listener
.Matrix
[i
][j
] = ((i
==j
) ? 1.0f
: 0.0f
);
1767 Context
->LastError
= AL_NO_ERROR
;
1768 Context
->UpdateSources
= AL_FALSE
;
1769 Context
->ActiveSourceCount
= 0;
1770 InitUIntMap(&Context
->SourceMap
, Context
->Device
->MaxNoOfSources
);
1771 InitUIntMap(&Context
->EffectSlotMap
, Context
->Device
->AuxiliaryEffectSlotMax
);
1774 Context
->DistanceModel
= AL_INVERSE_DISTANCE_CLAMPED
;
1775 Context
->SourceDistanceModel
= AL_FALSE
;
1776 Context
->DopplerFactor
= 1.0f
;
1777 Context
->DopplerVelocity
= 1.0f
;
1778 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
1779 Context
->DeferUpdates
= AL_FALSE
;
1781 Context
->ExtensionList
= alExtList
;
1787 * Cleans up the context, and destroys any remaining objects the app failed to
1788 * delete. Called once there's no more references on the context.
1790 static ALCvoid
FreeContext(ALCcontext
*context
)
1792 TRACE("%p\n", context
);
1794 if(context
->SourceMap
.size
> 0)
1796 ERR("(%p) Deleting %d Source(s)\n", context
, context
->SourceMap
.size
);
1797 ReleaseALSources(context
);
1799 ResetUIntMap(&context
->SourceMap
);
1801 if(context
->EffectSlotMap
.size
> 0)
1803 ERR("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context
, context
->EffectSlotMap
.size
);
1804 ReleaseALAuxiliaryEffectSlots(context
);
1806 ResetUIntMap(&context
->EffectSlotMap
);
1808 context
->ActiveSourceCount
= 0;
1809 free(context
->ActiveSources
);
1810 context
->ActiveSources
= NULL
;
1811 context
->MaxActiveSources
= 0;
1813 context
->ActiveEffectSlotCount
= 0;
1814 free(context
->ActiveEffectSlots
);
1815 context
->ActiveEffectSlots
= NULL
;
1816 context
->MaxActiveEffectSlots
= 0;
1818 ALCdevice_DecRef(context
->Device
);
1819 context
->Device
= NULL
;
1821 //Invalidate context
1822 memset(context
, 0, sizeof(ALCcontext
));
1828 * Removes the context reference from the given device and removes it from
1829 * being current on the running thread or globally.
1831 static void ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
1833 ALCcontext
*volatile*tmp_ctx
;
1835 if(pthread_getspecific(LocalContext
) == context
)
1837 WARN("%p released while current on thread\n", context
);
1838 pthread_setspecific(LocalContext
, NULL
);
1839 ALCcontext_DecRef(context
);
1842 if(CompExchangePtr((XchgPtr
*)&GlobalContext
, context
, NULL
))
1843 ALCcontext_DecRef(context
);
1846 tmp_ctx
= &device
->ContextList
;
1849 if(CompExchangePtr((XchgPtr
*)tmp_ctx
, context
, context
->next
))
1851 tmp_ctx
= &(*tmp_ctx
)->next
;
1853 UnlockDevice(device
);
1855 ALCcontext_DecRef(context
);
1858 void ALCcontext_IncRef(ALCcontext
*context
)
1861 ref
= IncrementRef(&context
->ref
);
1862 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
1865 void ALCcontext_DecRef(ALCcontext
*context
)
1868 ref
= DecrementRef(&context
->ref
);
1869 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
1870 if(ref
== 0) FreeContext(context
);
1873 static void ReleaseThreadCtx(void *ptr
)
1875 WARN("%p current for thread being destroyed\n", ptr
);
1876 ALCcontext_DecRef(ptr
);
1881 * Checks that the given context is valid, and increments its reference count.
1883 static ALCcontext
*VerifyContext(ALCcontext
*context
)
1891 ALCcontext
*tmp_ctx
= dev
->ContextList
;
1894 if(tmp_ctx
== context
)
1896 ALCcontext_IncRef(tmp_ctx
);
1900 tmp_ctx
= tmp_ctx
->next
;
1912 * Returns the currently active context for this thread, and adds a reference
1913 * without locking it.
1915 ALCcontext
*GetContextRef(void)
1917 ALCcontext
*context
;
1919 context
= pthread_getspecific(LocalContext
);
1921 ALCcontext_IncRef(context
);
1925 context
= GlobalContext
;
1927 ALCcontext_IncRef(context
);
1935 /************************************************
1936 * Standard ALC functions
1937 ************************************************/
1941 * Return last ALC generated error code for the given device
1943 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
1947 if(VerifyDevice(device
))
1949 errorCode
= ExchangeInt(&device
->LastError
, ALC_NO_ERROR
);
1950 ALCdevice_DecRef(device
);
1953 errorCode
= ExchangeInt(&LastNullDeviceError
, ALC_NO_ERROR
);
1959 /* alcSuspendContext
1963 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*Context
)
1968 /* alcProcessContext
1972 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*Context
)
1980 * Returns information about the device, and error strings
1982 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
1984 const ALCchar
*value
= NULL
;
1992 case ALC_INVALID_ENUM
:
1993 value
= alcErrInvalidEnum
;
1996 case ALC_INVALID_VALUE
:
1997 value
= alcErrInvalidValue
;
2000 case ALC_INVALID_DEVICE
:
2001 value
= alcErrInvalidDevice
;
2004 case ALC_INVALID_CONTEXT
:
2005 value
= alcErrInvalidContext
;
2008 case ALC_OUT_OF_MEMORY
:
2009 value
= alcErrOutOfMemory
;
2012 case ALC_DEVICE_SPECIFIER
:
2013 value
= alcDefaultName
;
2016 case ALC_ALL_DEVICES_SPECIFIER
:
2017 if(VerifyDevice(Device
))
2019 value
= Device
->DeviceName
;
2020 ALCdevice_DecRef(Device
);
2024 ProbeAllDeviceList();
2025 value
= alcAllDeviceList
;
2029 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2030 if(VerifyDevice(Device
))
2032 value
= Device
->DeviceName
;
2033 ALCdevice_DecRef(Device
);
2037 ProbeCaptureDeviceList();
2038 value
= alcCaptureDeviceList
;
2042 /* Default devices are always first in the list */
2043 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2044 value
= alcDefaultName
;
2047 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2048 if(!alcAllDeviceList
)
2049 ProbeAllDeviceList();
2051 Device
= VerifyDevice(Device
);
2053 free(alcDefaultAllDeviceSpecifier
);
2054 alcDefaultAllDeviceSpecifier
= strdup(alcAllDeviceList
?
2055 alcAllDeviceList
: "");
2056 if(!alcDefaultAllDeviceSpecifier
)
2057 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2059 value
= alcDefaultAllDeviceSpecifier
;
2060 if(Device
) ALCdevice_DecRef(Device
);
2063 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2064 if(!alcCaptureDeviceList
)
2065 ProbeCaptureDeviceList();
2067 Device
= VerifyDevice(Device
);
2069 free(alcCaptureDefaultDeviceSpecifier
);
2070 alcCaptureDefaultDeviceSpecifier
= strdup(alcCaptureDeviceList
?
2071 alcCaptureDeviceList
: "");
2072 if(!alcCaptureDefaultDeviceSpecifier
)
2073 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2075 value
= alcCaptureDefaultDeviceSpecifier
;
2076 if(Device
) ALCdevice_DecRef(Device
);
2079 case ALC_EXTENSIONS
:
2080 if(!VerifyDevice(Device
))
2081 value
= alcNoDeviceExtList
;
2084 value
= alcExtensionList
;
2085 ALCdevice_DecRef(Device
);
2090 Device
= VerifyDevice(Device
);
2091 alcSetError(Device
, ALC_INVALID_ENUM
);
2092 if(Device
) ALCdevice_DecRef(Device
);
2102 * Returns information about the device and the version of OpenAL
2104 ALC_API ALCvoid ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
,ALCenum param
,ALsizei size
,ALCint
*data
)
2106 device
= VerifyDevice(device
);
2108 if(size
== 0 || data
== NULL
)
2110 alcSetError(device
, ALC_INVALID_VALUE
);
2111 if(device
) ALCdevice_DecRef(device
);
2119 case ALC_MAJOR_VERSION
:
2120 *data
= alcMajorVersion
;
2122 case ALC_MINOR_VERSION
:
2123 *data
= alcMinorVersion
;
2126 case ALC_ATTRIBUTES_SIZE
:
2127 case ALC_ALL_ATTRIBUTES
:
2131 case ALC_MONO_SOURCES
:
2132 case ALC_STEREO_SOURCES
:
2133 case ALC_CAPTURE_SAMPLES
:
2134 case ALC_FORMAT_CHANNELS_SOFT
:
2135 case ALC_FORMAT_TYPE_SOFT
:
2136 alcSetError(NULL
, ALC_INVALID_DEVICE
);
2140 alcSetError(NULL
, ALC_INVALID_ENUM
);
2144 else if(device
->Type
== Capture
)
2148 case ALC_CAPTURE_SAMPLES
:
2150 /* Re-validate the device since it may have been closed */
2151 ALCdevice_DecRef(device
);
2152 if((device
=VerifyDevice(device
)) != NULL
)
2153 *data
= ALCdevice_AvailableSamples(device
);
2155 alcSetError(NULL
, ALC_INVALID_DEVICE
);
2160 *data
= device
->Connected
;
2164 alcSetError(device
, ALC_INVALID_ENUM
);
2168 else /* render device */
2172 case ALC_MAJOR_VERSION
:
2173 *data
= alcMajorVersion
;
2176 case ALC_MINOR_VERSION
:
2177 *data
= alcMinorVersion
;
2180 case ALC_EFX_MAJOR_VERSION
:
2181 *data
= alcEFXMajorVersion
;
2184 case ALC_EFX_MINOR_VERSION
:
2185 *data
= alcEFXMinorVersion
;
2188 case ALC_ATTRIBUTES_SIZE
:
2192 case ALC_ALL_ATTRIBUTES
:
2194 alcSetError(device
, ALC_INVALID_VALUE
);
2199 data
[i
++] = ALC_FREQUENCY
;
2200 data
[i
++] = device
->Frequency
;
2202 if(device
->Type
!= Loopback
)
2204 data
[i
++] = ALC_REFRESH
;
2205 data
[i
++] = device
->Frequency
/ device
->UpdateSize
;
2207 data
[i
++] = ALC_SYNC
;
2208 data
[i
++] = ALC_FALSE
;
2212 data
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
2213 data
[i
++] = device
->FmtChans
;
2215 data
[i
++] = ALC_FORMAT_TYPE_SOFT
;
2216 data
[i
++] = device
->FmtType
;
2219 data
[i
++] = ALC_MONO_SOURCES
;
2220 data
[i
++] = device
->NumMonoSources
;
2222 data
[i
++] = ALC_STEREO_SOURCES
;
2223 data
[i
++] = device
->NumStereoSources
;
2225 data
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
2226 data
[i
++] = device
->NumAuxSends
;
2233 *data
= device
->Frequency
;
2237 if(device
->Type
== Loopback
)
2238 alcSetError(device
, ALC_INVALID_DEVICE
);
2240 *data
= device
->Frequency
/ device
->UpdateSize
;
2244 if(device
->Type
== Loopback
)
2245 alcSetError(device
, ALC_INVALID_DEVICE
);
2250 case ALC_FORMAT_CHANNELS_SOFT
:
2251 if(device
->Type
!= Loopback
)
2252 alcSetError(device
, ALC_INVALID_DEVICE
);
2254 *data
= device
->FmtChans
;
2257 case ALC_FORMAT_TYPE_SOFT
:
2258 if(device
->Type
!= Loopback
)
2259 alcSetError(device
, ALC_INVALID_DEVICE
);
2261 *data
= device
->FmtType
;
2264 case ALC_MONO_SOURCES
:
2265 *data
= device
->NumMonoSources
;
2268 case ALC_STEREO_SOURCES
:
2269 *data
= device
->NumStereoSources
;
2272 case ALC_MAX_AUXILIARY_SENDS
:
2273 *data
= device
->NumAuxSends
;
2277 *data
= device
->Connected
;
2281 alcSetError(device
, ALC_INVALID_ENUM
);
2286 ALCdevice_DecRef(device
);
2290 /* alcIsExtensionPresent
2292 * Determines if there is support for a particular extension
2294 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
2296 ALCboolean bResult
= ALC_FALSE
;
2298 device
= VerifyDevice(device
);
2301 alcSetError(device
, ALC_INVALID_VALUE
);
2304 size_t len
= strlen(extName
);
2305 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
2308 if(strncasecmp(ptr
, extName
, len
) == 0 &&
2309 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
2314 if((ptr
=strchr(ptr
, ' ')) != NULL
)
2318 } while(isspace(*ptr
));
2323 ALCdevice_DecRef(device
);
2328 /* alcGetProcAddress
2330 * Retrieves the function address for a particular extension function
2332 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
2334 ALCvoid
*ptr
= NULL
;
2336 device
= VerifyDevice(device
);
2339 alcSetError(device
, ALC_INVALID_VALUE
);
2343 while(alcFunctions
[i
].funcName
&& strcmp(alcFunctions
[i
].funcName
,funcName
) != 0)
2345 ptr
= alcFunctions
[i
].address
;
2348 ALCdevice_DecRef(device
);
2355 * Get the value for a particular ALC enumeration name
2357 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
2363 device
= VerifyDevice(device
);
2364 alcSetError(device
, ALC_INVALID_VALUE
);
2365 if(device
) ALCdevice_DecRef(device
);
2370 while(enumeration
[i
].enumName
&& strcmp(enumeration
[i
].enumName
, enumName
) != 0)
2372 val
= enumeration
[i
].value
;
2381 * Create and attach a context to the given device.
2383 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
2385 ALCcontext
*ALContext
;
2389 if(!(device
=VerifyDevice(device
)) || device
->Type
== Capture
|| !device
->Connected
)
2392 alcSetError(device
, ALC_INVALID_DEVICE
);
2393 if(device
) ALCdevice_DecRef(device
);
2397 device
->LastError
= ALC_NO_ERROR
;
2399 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
2402 alcSetError(device
, err
);
2403 if(err
== ALC_INVALID_DEVICE
)
2404 aluHandleDisconnect(device
);
2405 ALCdevice_DecRef(device
);
2409 ALContext
= calloc(1, sizeof(ALCcontext
));
2414 ALContext
->MaxActiveSources
= 256;
2415 ALContext
->ActiveSources
= malloc(sizeof(ALContext
->ActiveSources
[0]) *
2416 ALContext
->MaxActiveSources
);
2418 if(!ALContext
|| !ALContext
->ActiveSources
)
2420 if(!device
->ContextList
)
2422 ALCdevice_StopPlayback(device
);
2423 device
->Flags
&= ~DEVICE_RUNNING
;
2430 alcSetError(device
, ALC_OUT_OF_MEMORY
);
2431 ALCdevice_DecRef(device
);
2435 ALContext
->Device
= device
;
2436 ALCdevice_IncRef(device
);
2437 InitContext(ALContext
);
2440 ALContext
->next
= device
->ContextList
;
2441 } while(!CompExchangePtr((XchgPtr
*)&device
->ContextList
, ALContext
->next
, ALContext
));
2444 ALCdevice_DecRef(device
);
2446 TRACE("Created context %p\n", ALContext
);
2450 /* alcDestroyContext
2452 * Remove a context from its device
2454 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
2459 /* alcGetContextsDevice sets an error for invalid contexts */
2460 Device
= alcGetContextsDevice(context
);
2463 ReleaseContext(context
, Device
);
2464 if(!Device
->ContextList
)
2466 ALCdevice_StopPlayback(Device
);
2467 Device
->Flags
&= ~DEVICE_RUNNING
;
2474 /* alcGetCurrentContext
2476 * Returns the currently active context on the calling thread
2478 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
2480 ALCcontext
*Context
;
2482 Context
= pthread_getspecific(LocalContext
);
2483 if(!Context
) Context
= GlobalContext
;
2488 /* alcGetThreadContext
2490 * Returns the currently active thread-local context
2492 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
2494 ALCcontext
*Context
;
2495 Context
= pthread_getspecific(LocalContext
);
2500 /* alcMakeContextCurrent
2502 * Makes the given context the active process-wide context, and removes the
2503 * thread-local context for the calling thread.
2505 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
2507 /* context must be valid or NULL */
2508 if(context
&& !(context
=VerifyContext(context
)))
2510 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2513 /* context's reference count is already incremented */
2514 context
= ExchangePtr((XchgPtr
*)&GlobalContext
, context
);
2515 if(context
) ALCcontext_DecRef(context
);
2517 if((context
=pthread_getspecific(LocalContext
)) != NULL
)
2519 pthread_setspecific(LocalContext
, NULL
);
2520 ALCcontext_DecRef(context
);
2526 /* alcSetThreadContext
2528 * Makes the given context the active context for the current thread
2530 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
2534 /* context must be valid or NULL */
2535 if(context
&& !(context
=VerifyContext(context
)))
2537 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2540 /* context's reference count is already incremented */
2541 old
= pthread_getspecific(LocalContext
);
2542 pthread_setspecific(LocalContext
, context
);
2543 if(old
) ALCcontext_DecRef(old
);
2549 /* alcGetContextsDevice
2551 * Returns the device that a particular context is attached to
2553 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
2557 if(!(Context
=VerifyContext(Context
)))
2559 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2562 Device
= Context
->Device
;
2563 ALCcontext_DecRef(Context
);
2571 * Opens the named device.
2573 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
2581 if(!PlaybackBackend
.name
)
2583 alcSetError(NULL
, ALC_INVALID_VALUE
);
2587 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
2590 device
= calloc(1, sizeof(ALCdevice
)+sizeof(ALeffectslot
));
2593 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
2598 device
->Funcs
= &PlaybackBackend
.Funcs
;
2600 device
->Connected
= ALC_TRUE
;
2601 device
->Type
= Playback
;
2602 InitializeCriticalSection(&device
->Mutex
);
2603 device
->LastError
= ALC_NO_ERROR
;
2606 device
->Bs2b
= NULL
;
2607 device
->Bs2bLevel
= 0;
2608 device
->DeviceName
= NULL
;
2610 device
->ContextList
= NULL
;
2612 device
->MaxNoOfSources
= 256;
2613 device
->AuxiliaryEffectSlotMax
= 4;
2614 device
->NumAuxSends
= MAX_SENDS
;
2616 InitUIntMap(&device
->BufferMap
, ~0);
2617 InitUIntMap(&device
->EffectMap
, ~0);
2618 InitUIntMap(&device
->FilterMap
, ~0);
2621 device
->FmtChans
= DevFmtChannelsDefault
;
2622 device
->FmtType
= DevFmtTypeDefault
;
2623 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
2624 device
->NumUpdates
= 4;
2625 device
->UpdateSize
= 1024;
2627 if(ConfigValueStr(NULL
, "channels", &fmt
))
2629 static const struct {
2630 const char name
[16];
2631 enum DevFmtChannels chans
;
2633 { "mono", DevFmtMono
},
2634 { "stereo", DevFmtStereo
},
2635 { "quad", DevFmtQuad
},
2636 { "surround51", DevFmtX51
},
2637 { "surround61", DevFmtX61
},
2638 { "surround71", DevFmtX71
},
2642 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
2644 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
2646 device
->FmtChans
= chanlist
[i
].chans
;
2647 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
2651 if(i
== COUNTOF(chanlist
))
2652 ERR("Unsupported channels: %s\n", fmt
);
2654 if(ConfigValueStr(NULL
, "sample-type", &fmt
))
2656 static const struct {
2657 const char name
[16];
2658 enum DevFmtType type
;
2660 { "int8", DevFmtByte
},
2661 { "uint8", DevFmtUByte
},
2662 { "int16", DevFmtShort
},
2663 { "uint16", DevFmtUShort
},
2664 { "int32", DevFmtInt
},
2665 { "uint32", DevFmtUInt
},
2666 { "float32", DevFmtFloat
},
2670 for(i
= 0;i
< COUNTOF(typelist
);i
++)
2672 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
2674 device
->FmtType
= typelist
[i
].type
;
2675 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
2679 if(i
== COUNTOF(typelist
))
2680 ERR("Unsupported sample-type: %s\n", fmt
);
2682 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
2683 if((device
->Flags
&DEVICE_FORMAT_REQUEST
) != DEVICE_FORMAT_REQUEST
&&
2684 ConfigValueStr(NULL
, "format", &fmt
))
2686 static const struct {
2687 const char name
[32];
2688 enum DevFmtChannels channels
;
2689 enum DevFmtType type
;
2691 { "AL_FORMAT_MONO32", DevFmtMono
, DevFmtFloat
},
2692 { "AL_FORMAT_STEREO32", DevFmtStereo
, DevFmtFloat
},
2693 { "AL_FORMAT_QUAD32", DevFmtQuad
, DevFmtFloat
},
2694 { "AL_FORMAT_51CHN32", DevFmtX51
, DevFmtFloat
},
2695 { "AL_FORMAT_61CHN32", DevFmtX61
, DevFmtFloat
},
2696 { "AL_FORMAT_71CHN32", DevFmtX71
, DevFmtFloat
},
2698 { "AL_FORMAT_MONO16", DevFmtMono
, DevFmtShort
},
2699 { "AL_FORMAT_STEREO16", DevFmtStereo
, DevFmtShort
},
2700 { "AL_FORMAT_QUAD16", DevFmtQuad
, DevFmtShort
},
2701 { "AL_FORMAT_51CHN16", DevFmtX51
, DevFmtShort
},
2702 { "AL_FORMAT_61CHN16", DevFmtX61
, DevFmtShort
},
2703 { "AL_FORMAT_71CHN16", DevFmtX71
, DevFmtShort
},
2705 { "AL_FORMAT_MONO8", DevFmtMono
, DevFmtByte
},
2706 { "AL_FORMAT_STEREO8", DevFmtStereo
, DevFmtByte
},
2707 { "AL_FORMAT_QUAD8", DevFmtQuad
, DevFmtByte
},
2708 { "AL_FORMAT_51CHN8", DevFmtX51
, DevFmtByte
},
2709 { "AL_FORMAT_61CHN8", DevFmtX61
, DevFmtByte
},
2710 { "AL_FORMAT_71CHN8", DevFmtX71
, DevFmtByte
}
2714 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
2715 for(i
= 0;i
< COUNTOF(formats
);i
++)
2717 if(strcasecmp(fmt
, formats
[i
].name
) == 0)
2719 if(!(device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2720 device
->FmtChans
= formats
[i
].channels
;
2721 if(!(device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2722 device
->FmtType
= formats
[i
].type
;
2723 device
->Flags
|= DEVICE_FORMAT_REQUEST
;
2727 if(i
== COUNTOF(formats
))
2728 ERR("Unsupported format: %s\n", fmt
);
2730 #undef DEVICE_FORMAT_REQUEST
2732 if(ConfigValueUInt(NULL
, "frequency", &device
->Frequency
))
2734 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
2735 if(device
->Frequency
< MIN_OUTPUT_RATE
)
2736 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
2737 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
2740 ConfigValueUInt(NULL
, "periods", &device
->NumUpdates
);
2741 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
2743 ConfigValueUInt(NULL
, "period_size", &device
->UpdateSize
);
2744 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
2746 ConfigValueUInt(NULL
, "sources", &device
->MaxNoOfSources
);
2747 if(device
->MaxNoOfSources
== 0) device
->MaxNoOfSources
= 256;
2749 ConfigValueUInt(NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
2750 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 4;
2752 ConfigValueUInt(NULL
, "sends", &device
->NumAuxSends
);
2753 if(device
->NumAuxSends
> MAX_SENDS
) device
->NumAuxSends
= MAX_SENDS
;
2755 ConfigValueInt(NULL
, "cf_level", &device
->Bs2bLevel
);
2757 device
->NumStereoSources
= 1;
2758 device
->NumMonoSources
= device
->MaxNoOfSources
- device
->NumStereoSources
;
2760 // Find a playback device to open
2762 if((err
=ALCdevice_OpenPlayback(device
, deviceName
)) != ALC_NO_ERROR
)
2765 DeleteCriticalSection(&device
->Mutex
);
2767 alcSetError(NULL
, err
);
2772 if(DefaultEffect
.type
!= AL_EFFECT_NULL
)
2774 device
->DefaultSlot
= (ALeffectslot
*)(device
+1);
2775 if(InitEffectSlot(device
->DefaultSlot
) != AL_NO_ERROR
)
2777 device
->DefaultSlot
= NULL
;
2778 ERR("Failed to initialize the default effect slot\n");
2780 else if(InitializeEffect(device
, device
->DefaultSlot
, &DefaultEffect
) != AL_NO_ERROR
)
2782 ALeffectState_Destroy(device
->DefaultSlot
->EffectState
);
2783 device
->DefaultSlot
= NULL
;
2784 ERR("Failed to initialize the default effect\n");
2789 device
->next
= DeviceList
;
2790 } while(!CompExchangePtr((XchgPtr
*)&DeviceList
, device
->next
, device
));
2792 TRACE("Created device %p, \"%s\"\n", device
, device
->DeviceName
);
2798 * Closes the given device.
2800 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*Device
)
2802 ALCdevice
*volatile*list
;
2807 while(*list
&& *list
!= Device
)
2808 list
= &(*list
)->next
;
2810 if(!*list
|| (*list
)->Type
== Capture
)
2812 alcSetError(*list
, ALC_INVALID_DEVICE
);
2817 *list
= (*list
)->next
;
2820 while((ctx
=Device
->ContextList
) != NULL
)
2822 WARN("Releasing context %p\n", ctx
);
2823 ReleaseContext(ctx
, Device
);
2825 if((Device
->Flags
&DEVICE_RUNNING
))
2826 ALCdevice_StopPlayback(Device
);
2827 Device
->Flags
&= ~DEVICE_RUNNING
;
2829 ALCdevice_ClosePlayback(Device
);
2831 ALCdevice_DecRef(Device
);
2837 /************************************************
2838 * ALC capture functions
2839 ************************************************/
2840 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
2842 ALCdevice
*device
= NULL
;
2847 if(!CaptureBackend
.name
)
2849 alcSetError(NULL
, ALC_INVALID_VALUE
);
2855 alcSetError(NULL
, ALC_INVALID_VALUE
);
2859 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
2862 device
= calloc(1, sizeof(ALCdevice
));
2865 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
2870 device
->Funcs
= &CaptureBackend
.Funcs
;
2872 device
->Connected
= ALC_TRUE
;
2873 device
->Type
= Capture
;
2874 InitializeCriticalSection(&device
->Mutex
);
2876 InitUIntMap(&device
->BufferMap
, ~0);
2877 InitUIntMap(&device
->EffectMap
, ~0);
2878 InitUIntMap(&device
->FilterMap
, ~0);
2880 device
->DeviceName
= NULL
;
2882 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
2883 device
->Frequency
= frequency
;
2885 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
2886 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
2888 DeleteCriticalSection(&device
->Mutex
);
2890 alcSetError(NULL
, ALC_INVALID_ENUM
);
2894 device
->UpdateSize
= samples
;
2895 device
->NumUpdates
= 1;
2898 if((err
=ALCdevice_OpenCapture(device
, deviceName
)) != ALC_NO_ERROR
)
2901 DeleteCriticalSection(&device
->Mutex
);
2903 alcSetError(NULL
, err
);
2909 device
->next
= DeviceList
;
2910 } while(!CompExchangePtr((XchgPtr
*)&DeviceList
, device
->next
, device
));
2912 TRACE("Created device %p\n", device
);
2916 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*Device
)
2918 ALCdevice
*volatile*list
;
2922 while(*list
&& *list
!= Device
)
2923 list
= &(*list
)->next
;
2925 if(!*list
|| (*list
)->Type
!= Capture
)
2927 alcSetError(*list
, ALC_INVALID_DEVICE
);
2932 *list
= (*list
)->next
;
2935 ALCdevice_CloseCapture(Device
);
2937 ALCdevice_DecRef(Device
);
2942 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
2945 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Capture
)
2948 alcSetError(device
, ALC_INVALID_DEVICE
);
2949 if(device
) ALCdevice_DecRef(device
);
2952 if(device
->Connected
)
2954 if(!(device
->Flags
&DEVICE_RUNNING
))
2955 ALCdevice_StartCapture(device
);
2956 device
->Flags
|= DEVICE_RUNNING
;
2960 ALCdevice_DecRef(device
);
2963 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
2966 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Capture
)
2969 alcSetError(device
, ALC_INVALID_DEVICE
);
2970 if(device
) ALCdevice_DecRef(device
);
2973 if((device
->Flags
&DEVICE_RUNNING
))
2974 ALCdevice_StopCapture(device
);
2975 device
->Flags
&= ~DEVICE_RUNNING
;
2978 ALCdevice_DecRef(device
);
2981 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
2983 ALCenum err
= ALC_INVALID_DEVICE
;
2985 if((device
=VerifyDevice(device
)) != NULL
&& device
->Type
== Capture
)
2987 err
= ALC_INVALID_VALUE
;
2988 if(samples
>= 0 && ALCdevice_AvailableSamples(device
) >= (ALCuint
)samples
)
2989 err
= ALCdevice_CaptureSamples(device
, buffer
, samples
);
2992 if(err
!= ALC_NO_ERROR
)
2993 alcSetError(device
, err
);
2994 if(device
) ALCdevice_DecRef(device
);
2998 /************************************************
2999 * ALC loopback functions
3000 ************************************************/
3002 /* alcLoopbackOpenDeviceSOFT
3004 * Open a loopback device, for manual rendering.
3006 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
3012 /* Make sure the device name, if specified, is us. */
3013 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
3015 alcSetError(NULL
, ALC_INVALID_VALUE
);
3019 device
= calloc(1, sizeof(ALCdevice
));
3022 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3027 device
->Funcs
= &BackendLoopback
.Funcs
;
3029 device
->Connected
= ALC_TRUE
;
3030 device
->Type
= Loopback
;
3031 InitializeCriticalSection(&device
->Mutex
);
3032 device
->LastError
= ALC_NO_ERROR
;
3035 device
->Bs2b
= NULL
;
3036 device
->Bs2bLevel
= 0;
3037 device
->DeviceName
= NULL
;
3039 device
->ContextList
= NULL
;
3041 device
->MaxNoOfSources
= 256;
3042 device
->AuxiliaryEffectSlotMax
= 4;
3043 device
->NumAuxSends
= MAX_SENDS
;
3045 InitUIntMap(&device
->BufferMap
, ~0);
3046 InitUIntMap(&device
->EffectMap
, ~0);
3047 InitUIntMap(&device
->FilterMap
, ~0);
3050 device
->NumUpdates
= 0;
3051 device
->UpdateSize
= 0;
3053 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3054 device
->FmtChans
= DevFmtChannelsDefault
;
3055 device
->FmtType
= DevFmtTypeDefault
;
3057 ConfigValueUInt(NULL
, "sources", &device
->MaxNoOfSources
);
3058 if(device
->MaxNoOfSources
== 0) device
->MaxNoOfSources
= 256;
3060 ConfigValueUInt(NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
3061 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 4;
3063 ConfigValueUInt(NULL
, "sends", &device
->NumAuxSends
);
3064 if(device
->NumAuxSends
> MAX_SENDS
) device
->NumAuxSends
= MAX_SENDS
;
3066 device
->NumStereoSources
= 1;
3067 device
->NumMonoSources
= device
->MaxNoOfSources
- device
->NumStereoSources
;
3069 // Open the "backend"
3070 ALCdevice_OpenPlayback(device
, "Loopback");
3072 device
->next
= DeviceList
;
3073 } while(!CompExchangePtr((XchgPtr
*)&DeviceList
, device
->next
, device
));
3075 TRACE("Created device %p\n", device
);
3079 /* alcIsRenderFormatSupportedSOFT
3081 * Determines if the loopback device supports the given format for rendering.
3083 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
3085 ALCboolean ret
= ALC_FALSE
;
3087 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Loopback
)
3088 alcSetError(device
, ALC_INVALID_DEVICE
);
3090 alcSetError(device
, ALC_INVALID_VALUE
);
3093 if(IsValidALCType(type
) && BytesFromDevFmt(type
) > 0 &&
3094 IsValidALCChannels(channels
) && ChannelsFromDevFmt(channels
) > 0 &&
3095 freq
>= MIN_OUTPUT_RATE
)
3098 if(device
) ALCdevice_DecRef(device
);
3103 /* alcRenderSamplesSOFT
3105 * Renders some samples into a buffer, using the format last set by the
3106 * attributes given to alcCreateContext.
3108 ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
3110 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Loopback
)
3111 alcSetError(device
, ALC_INVALID_DEVICE
);
3112 else if(samples
< 0 || (samples
> 0 && buffer
== NULL
))
3113 alcSetError(device
, ALC_INVALID_VALUE
);
3115 aluMixData(device
, buffer
, samples
);
3116 if(device
) ALCdevice_DecRef(device
);